FreeRTOS内核时钟不对的问题解决

李肖遥

共 3458字,需浏览 7分钟

 ·

2022-06-27 21:12

    关注、星标公众号,直达精彩内容

来源:技术让梦想更伟大

问题

在使用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_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配置问题,检查每一步配置是否更改相关时钟频率,无须关注其它问题。

版权声明:本文来源网络,免费传达知识,版权归原作者所有。如涉及作品版权问题,请联系我进行删除。

‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧  END  ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧

关注我的微信公众号,回复“加群”按规则加入技术交流群。


点击“阅读原文”查看更多分享,欢迎点分享、收藏、点赞、在看。

浏览 19
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报