FreeRTOS内核时钟不对的问题解决
FreeRTOS内核时钟不对的问题解决问题在使用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 << 2UL )
#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_HZOptional 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配置问题,检查每一步配置是否更改相关时钟频率,无须关注其它问题。
页:
[1]