问题
在使用RTOS时,忽然发现RTOS的时钟出现异常,具体表现在使用vTaskDelay或vTaskDelayUntil函数时,发现延时时间的表现与预期相差甚远,大致为预期时间的10倍左右。
问题定位
经过长时间检查,发现问题出现在configSYSTICK_CLOCK_HZ的定义上。最初理解此宏的意义是:首先,它只适用于Cortex-M处理器;其次,如果Systick和系统时钟相同,就无需定义此宏;但如果两者不同,就需要将其定义为Systick的时钟频率。在移植代码时,采用了以下实现方式:
#define configCPU_CLOCK_HZ ( ( unsigned long ) 72000000 )
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
导致最终的问题。
问题分析
为什么一开始没有发现问题呢,因为一开始仅仅看到了下图,没有对整个设置Systick了解,
看着,觉得设定值没错,然后就是没有看下一句,也没有关注configSYSTICK_CLOCK_HZ这个
宏定义与不定义的区别。在确认问题来源时需要明白两个问题:
1.Systick的时钟是不是就是系统内核时钟,是否可以选择时钟频率
2.Systick是怎样切换系统时钟的
第一个问题
Systick的时钟不一定是系统时钟(AHB),找到CM内核可以看到Systick寄存器,中2位的类型,即可明确,有两种情况1是内核时钟,0是内核时钟的8分频
第二个问题
很显然第二个问题,自然就出来,通过更改位2即可改变
好,在明确以上两个问题后,我们来问RTOS是如何帮我们设置Systick的
/* Configure SysTick to interrupt at the requested rate. */
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
两句话,没毛病,第一句话设置装在数值,第二步骤设置控制即状态寄存器,好,先按照我原先出现问题情况翻译一下:
/* Configure SysTick to interrupt at the requested rate. */
0xE000_E014 = ( 72000000/ 1000) - 1UL;
0xE000_E010 = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
只关注到重装寄存器数据的正确性,忽略了控制与状态寄存器的配置,当关注到这个问题了自然就解决了,首先找下portNVIC_SYSTICK_CLK_BIT 定义
#ifndef configSYSTICK_CLOCK_HZ
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
/* Ensure the SysTick is clocked at the same frequency as the core. */
#define portNVIC_SYSTICK_CLK_BIT ( 1UL
#else
/* The way the SysTick is clocked is not modified in case it is not the same
as the core. */
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
#endif
看到了没,如果定义了configSYSTICK_CLOCK_HZ就会更改portNVIC_SYSTICK_CLK_BIT的数值,即使你保证了configSYSTICK_CLOCK_HZ和系统时钟频率是一样的也不行,会导致时钟源的时钟源发生改变,导致最终的问题。
解决办法
怎么样完美解决还是去官网看下这宏的本身官方解释:
取消定义configSYSTICK_CLOCK_HZ
Optional parameter for ARM Cortex-M ports only.
By default ARM Cortex-M ports generate the RTOS tick interrupt from the Cortex-M SysTick timer. Most Cortex-M MCUs run the SysTick timer at the same frequency as the MCU itself – when that is the case configSYSTICK_CLOCK_HZ is not needed and should be left undefined. If the SysTick timer is clocked at a different frequency to the MCU core then set configCPU_CLOCK_HZ to the MCU clock frequency, as normal, and configSYSTICK_CLOCK_HZ to the SysTick clock frequency.
大致意思就是仅对Cortex-M内核有效,其次就是如果Systick系统的时钟和内核一样那就不要去定定义这个宏,反之就定义这个宏,同时将其数值分频后的实际时钟频率。
那就很简单了,移除对其定义就好了。
总结
在RTOS中如果出现RTOS内核时钟不对,首先定位Systick配置问题,检查每一步配置是否更改相关时钟频率,无须关注其它问题。
以上就是良许教程网为各位朋友分享的Linu系统相关内容。想要了解更多Linux相关知识记得关注公众号“良许Linux”,或扫描下方二维码进行关注,更多干货等着你 !