FreeRTOS时间管理--两个延时列表分析

FreeRTOS的任务调度一般使用系统滴答时钟,每次系统节拍时钟发生中断后加1,用来记录系统节拍时钟中断的次数,内核会将所有阻塞的任务跟这个变量比较,以判断是否超时,若超时意味着等待时间到达,可以执行。

变量xTickCount的数据类型跟具体硬件有关,32位架构硬件一般是无符号32位变量、8位或16位架构一般是无符号16位变量。即便是32位变量,xTickCount累加到0xFFFFFFFF后也会溢出。因此,在程序中要判断变量xTickCount是否溢出。如果溢出(xTickCount为0),则调用宏taskSWITCH_DELAYED_LISTS()交换延时列表指针和溢出延时列表指针。

taskSWITCH_DELAYED_LISTS()                          
{                                                                                                   
    List_t *pxTemp;                                                                                 

    configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) );                                     

    pxTemp = pxDelayedTaskList;                                                                     
    pxDelayedTaskList = pxOverflowDelayedTaskList;                                                  
    pxOverflowDelayedTaskList = pxTemp;                                                             
    xNumOfOverflows++;                                                                              
    prvResetNextTaskUnblockTime();                                                                  
}

为了解决xTickCount溢出问题,FreeRTOS使用了两个延时列表:xDelayedTaskList1和xDelayedTaskList2。并使用延时列表指针pxDelayedTaskList和溢出延时列表指针pxOverflowDelayedTaskList分别指向上面的延时列表1和延时列表2(在创建任务时将延时列表指针指向延时列表)。
Note:上面的两个延时列表指针变量和两个延时列表变量都是在tasks.c中定义的静态局部变量。

例如使用API延时函数vTaskDelay( xTicksToDelay ) 将任务延时xTicksToDelay个系统节拍周期,延时函数会以当前的系统节拍中断次数xTickCount为参考,这个值加上参数规定的延时时间xTicksToDelay,即xTickCount+ xTicksToDelay,就是下次唤醒任务的时间。xTickCount+xTicksToDelay会被记录到任务TCB中,随着任务一起挂接到延时列表。如果内核判断出xTickCount+ xTicksToDelay溢出(大于32位可以表示的最大值),就将当前任务挂接到列表指针pxOverflowDelayedTaskList指向的列表中,否则就挂接到列表指针pxDelayedTaskList指向的列表中。任务按照延时时间,顺序的插入到延时列表中。

xTimeToWake = xTickCount + xTicksToWait;

listSET_LIST_ITEM_VALUE(&(pxCurrentTCB->xStateListItem), xTimeToWake);

/*时间值已经溢出*/
if (xTimeToWake < xTickCount)
{                                                                                                                 
    vListInsert(pxOverflowDelayedTaskList, &(pxCurrentTCB->xStateListItem));
}
else
{
    vListInsert(pxDelayedTaskList, &(pxCurrentTCB->xStateListItem));

    if (xTimeToWake < xNextTaskUnblockTime)
    {
        xNextTaskUnblockTime = xTimeToWake;
    }
    else
    {
        mtCOVERAGE_TEST_MARKER();
    }
}

所以当系统节拍中断次数计数器xTickCount溢出时,必须将延时列表指针pxDelayedTaskList和溢出延时列表指针pxOverflowDelayedTaskList交换以便正确处理延时的任务。

猜你喜欢

转载自blog.csdn.net/yk150915/article/details/79114298