xTaskIncrementTick
操作系统的运行是由系统节拍时钟驱动的。
系统每次节拍中断服务程序中主要任务由函数 xTaskIncrementTick 完成。
在任务调度器没有挂起的情况下( xTaskIncrementTick != pdFALSE ),该函数主要完成 :
* 判断节拍计数器xTickCount 是否溢出, 溢出轮换延时函数队列
* 判断是否有阻塞任务超时,取出插入就绪链表
* 同优先级任务时间片轮
而当任务调度器被挂起时, 该函数累加挂起时间计数器 uxPendedTicks, 调用用户钩子函数, 此时,正在运行的任务不会被切换, 一直运行。
当恢复调度时, 系统会先重复调用 xTaskIncrementTick 补偿 (uxPendedTicks次)。
不管, 系统调度器是否挂起, 每次节拍中断都会调用用户的钩子函数
vApplicationTickHook
。 由于函数是中断中调用,不要在里面处理太复杂的事情!!
在FreeRTOS中,我们知道系统延时和阻塞时间都是以系统节拍时钟周期为单位。在配置文件FreeRTOSConfig.h,改变宏configCPU_CLOCK_HZ的值,可以改变系统节拍时钟的中断频率,也间接的改变了系统节拍时钟周期(T=1/f)。
设置宏configCPU_CLOCK_HZ为100,则系统节拍时钟周期为10ms,设置宏configCPU_CLOCK_HZ为1000,则系统节拍时钟周期为1ms。
系统节拍中断服务程序会调用函数xTaskIncrementTick()来完成主要工作,如果该函数返回值为真(不等于pdFALSE),说明处于就绪态任务的优先级比当前运行的任务优先级高。这会触发一次PendSV中断,进行上下文切换。
BaseType_t xTaskIncrementTick( void )
{
TCB_t * pxTCB;
TickType_t xItemValue;
BaseType_t xSwitchRequired = pdFALSE;
/* Called by the portable layer each time a tick interrupt occurs.
Increments the tick then checks to see if the new tick value will cause any
tasks to be unblocked. */
/*在每个时钟到的时候检查,是否会有任务需要解锁(是否有就绪态的任务需要执行)*/
traceTASK_INCREMENT_TICK( xTickCount );//空的定义
//系统维护一个计数uxSchedulerSuspended,当它大于0时候表示禁止调度,等于0则打开调度(允许调度)。
if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )//允许调度
{
/* Minor optimisation. The tick count cannot change in this
block. */
const TickType_t xConstTickCount = xTickCount + 1;/* 系统节拍计数器xTickCount 加1*/
/* Increment the RTOS tick, switching the delayed and overflowed
delayed lists if it wraps to 0. */
xTickCount = xConstTickCount;
if( xConstTickCount == ( TickType_t ) 0U )/* 系统节拍计数器xTickCount 是否溢出*/
{
taskSWITCH_DELAYED_LISTS();
}
else