【FreeRTOS复盘】3-FreeRTOS系统的时钟节拍和延时函数

发布时间 2023-06-27 09:38:45作者: FBshark

参考文章1:《FreeRTOS的学习(六)——系统时钟》

参考文章2:【FreeRTOS】04 系统的时钟节拍和延时函数

 

原理

reeRTOS使用裸机自带的滴答定时器中断,使用其主频或者外部频率作为时钟基准。由于定时器的功能作为FreeRTOS的核心,所以正常情况下必须是一个一直运行着的中断,那么就意味着FreeRTOS庞大的代码量也必须与此中断相互配合,保证实时性和可靠性,因此滴答定时器的中断时间必然是不能太短的,否则将大大影响FreeRTOS的实时性。我们直接来看配置的代码:

 1 void delay_init()
 2 {
 3     u32 reload;
 4     SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);//选择内部时钟  HCLK
 5     fac_us=SystemCoreClock/1000000;                //不论是否使用OS,fac_us都需要使用
 7     reload=SystemCoreClock/configTICK_RATE_HZ;            //根据configTICK_RATE_HZ设定溢出时间
 8                                                 //reload为24位寄存器,最大值:16777216,在72M下,约合0.233s左右    
 9     fac_ms=1000/configTICK_RATE_HZ;                //代表OS可以延时的最少单位       
10 
11     SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;       //开启SYSTICK中断
12     SysTick->LOAD=reload;                         //每1/configTICK_RATE_HZ秒中断一次    
13     SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;       //开启SYSTICK    
14 }

通过控制SysTick寄存器的几个地址可以实现开启中断,设定中断频率,开启/关闭SysTick的功能。
其中,reload作为中断的频率,其计算过程较为重要,需要根据系统时钟设定。本人使用的是stm32f103,系统主频为72M,那么也就意味着,stm32在1s内可以计数72M个。那么只要控制reload的值,每次计数结束后产生一次中断就可以了。所以引入configTICK_RATE_HZ的变量,用于方便调整滴答定时器的中断频率。具体的计算相对简单,可自行尝试。

FreeRTOS通过全局变量xTickCount的计数以及在SysTick的中断函数里的操作与逻辑之间形成了联系。下面给出了**SysTick_Handler()**的中断内部函数:

1 void SysTick_Handler(void)
2 {
3     if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//判断系统是否已经运行
4     {
5         xPortSysTickHandler();
6     }
7 }
 1 void xPortSysTickHandler( void )
 2 {
 3     //执行SysTick_Handler中断函数时,为了保证在freertos中属于最低优先级的此中断能顺利执行,
 4     //故要关闭FreeRTOS的所有可管理中断,保证系统计数时不被打断。
 5     vPortRaiseBASEPRI();  //关中断
 6     {
 7         if( xTaskIncrementTick() != pdFALSE )  //判断返回值,如果为pdTURE就要进行一次上下文切换
 8         {
 9             portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
10         }
11     }
12     vPortClearBASEPRIFromISR();  //开中断
13 }

 

为了保证计数的正常执行,需要先关闭系统中断,但是值得注意的是,FreeRTOS系统可关闭的中断都是系统级的,一般还有优先级在5以上的几个中断不受其管理,具体可见之前写的中断机制相关内容。那么也就不可避免地,计数会被这种情况打断,至少目前为止,以我学习到的内容来考虑,使用了RTOS就不太适合使用其他高优先级的大段大段主体内容的中断函数了,会对RTOS的运行产生极大的影响。所以系统外的高优先级中断一般都是短且对实时性要求高的,用于诸如一些紧急情况,需要紧急处理的。

系统的滴答定时器中断像是定时检查的功能,主要是列表溢出检查,任务唤醒检查,是否唤醒的任务要进行调度或者抢占式任务要进行调度等功能。

应用

操作系统的时钟节拍,是用于系统计时的;有了时钟节拍这个计时器,操作系统就能知道时间过去了多少周期,便于处理延时、超时等等与时间相关的操作。

一般情况下,时钟节拍是一个定时器中断,周期性地进入中断更新计数器,以计数器的值去指示走过了多少节拍。

时钟节拍的周期需要依据具体任务的特点来确定,一般为1ms~100ms。如果实时性要求高,需要任务响应较快,则节拍设置得短一些;如果实时性要求低,可以设置得长一些。如果设置的节拍短,那么系统对时间的控制更精确,比如设置成1ms,那么延时的精度可以达到最小1ms;设置成10ms节拍,系统就无法实现1ms的延时;但是,时钟节拍设置得越短,则系统自身的开销会越大。

FreeRTOS的时钟节拍可以在keil工程中的FreeRTOSConfig.h文件中设置:

 

图中设置成了1000Hz,也就是1ms一个节拍。

 

在使用cubemx生成keil工程时,也可以在这里修改,最后同样会体现在生成的FreeRTOSConfig.h文件中: