12 FreeRTOS时间管理

1 延时函数介绍

函数描述

vTaskDelay()

相对延时

xTaskDelayUntil()

绝对延时

相对延时:指每次延时都是从执行函数vTaskDelay()开始,直到延时指定的时间结束

绝对延时:指将整个任务的运行周期看成一个整体,适用于需要按照一定频率运行的任务,如下图所示:

(1)为任务主体,也就是任务要真正要做的工作

(2)是任务函数中调用vTaskDealyUntil()对任务进行演示

(3)为其他任务在运行

xTimeIncrement即是绝对延时时间.

2 延时函数解析

void vTaskDelay( const TickType_t xTicksToDelay )
    {
        BaseType_t xAlreadyYielded = pdFALSE;

        if( xTicksToDelay > ( TickType_t ) 0U )  
        /*只有在延时时间大于0的时候,才需要进行任务阻塞*/
        {
            configASSERT( uxSchedulerSuspended == 0 );

            vTaskSuspendAll();  
            /*挂起任务调度器*/
            {
                traceTASK_DELAY();
                /*用于调试*/

                 prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE );
                /*将当前正在执行的任务移到阻塞列表*/
            }
            xAlreadyYielded = xTaskResumeAll();
            /*恢复任务调度器运行,调用此函数会返回是否需要进行任务切换*/
        }
        else
        {
            mtCOVERAGE_TEST_MARKER();
        }

        if( xAlreadyYielded == pdFALSE )
        /*根据返回值xAlreadyYielded判断需不需要进行任务切换*/
        {
            portYIELD_WITHIN_API();
            /*触发PendSV*/
        }
        else
        {
            mtCOVERAGE_TEST_MARKER();
        }
    }

#endif
static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait,
                                            const BaseType_t xCanBlockIndefinitely )
/*xTicksToWait为阻塞时间,xCanBlockIndefinitely是否无期限阻塞(阻塞时间为最大值) */
{
    TickType_t xTimeToWake;
    const TickType_t xConstTickCount = xTickCount;
    
    #if ( INCLUDE_xTaskAbortDelay == 1 )
    /*此宏用于开启任务延时中断功能*/
        {
            pxCurrentTCB->ucDelayAborted = pdFALSE;
            /*如果开启了任务延时中断功能,那么将任务的延时中断标志复位设置为假,
             *当任务延时被中断是,再将其设置为真*/
        }
    #endif

        if( uxListRemove( &( pxCurrentTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
        /*将当前任务从所在列表中移除,当前任务为调用了会触发阻塞的API函数的任务*/
    {
        
        portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); 
        /*如果将当前任务从所在就绪态任务列表中移除后,原本所在就绪态任务列表中每有其他任务
         *那么就将任务优先级记录中该任务的优先级清除*/
    }
    else
    {
        mtCOVERAGE_TEST_MARKER();
    }

    #if ( INCLUDE_vTaskSuspend == 1 )
    /*此宏用于启用任务挂起功能*/
     {
          if( ( xTicksToWait == portMAX_DELAY ) && ( xCanBlockIndefinitely != pdFALSE ) )
          /*如果阻塞时间为最大值并且允许任务被无期限阻塞,入参xCanBlockIndefintely用于定义
           *在入参xTicksToWait为最大值的情况下,是否将任务无期限阻塞,即任务挂起*/
            {
               listINSERT_END( &xSuspendedTaskList, &( pxCurrentTCB->xStateListItem ) );
               /*将任务添加到挂起任务列表中挂起,即将任务无期限阻塞*/
            }
            else
            {
                xTimeToWake = xConstTickCount + xTicksToWait;
				/*计算任务在未来被取消阻塞时,系统时钟节拍计数器的值,
                 * 计算出来的值可能会出现溢出的情况。但系统会有相应的处理机制,
                 *即两个阻塞态任务列表*/
                //记录时间,xConstTickCount为进入函数之前得到的时间,
                //xTicksToWait为延时时间,xTimeToWake为真正的延时时间

                listSET_LIST_ITEM_VALUE(&( pxCurrentTCB->xStateListItem ), xTimeToWake );
			    //将真正的延时时间写到列表项中,然后将这个值加载到阻塞列表中,
                //通过该值进行升序排列

                if( xTimeToWake < xConstTickCount )
                /*判断计算的值是否溢出*/
                {
                    
                    vListInsert( pxOverflowDelayedTaskList, 
                                 &( pxCurrentTCB->xStateListItem ) );
                    /*如果计算出来的值溢出,将任务添加到阻塞超时时间溢出列表*/
                }
                else
                {
                   vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
                    /*将任务添加到阻塞态任务列表*/

                    if( xTimeToWake < xNextTaskUnblockTime )
                    /*全局变量xNextTaskUnblockTime用于保存系统中
                     *最近要发生超时的系统节拍计数器的值*/
                    {
                        xNextTaskUnblockTime = xTimeToWake;
                        /*有新的任务阻塞,因此要更新xNextTaskUnblockTime*/
                    }
                    else
                    {
                        mtCOVERAGE_TEST_MARKER();
                    }
                }
            }
        }
    #else 
        {
            xTimeToWake = xConstTickCount + xTicksToWait;
            /*计算任务在未来被取消阻塞时,系统时钟节拍计数器的值,
             *计算出来的值可能会出现溢出的情况,但系统会有相应的处理机制,即两个阻塞态任务列表*/

            listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
            /*设置任务的状态列表项的值为计算出来的值,那么在 SysTick 中断服务函数中处理阻塞态任务            
             *列表时,就可以通过这个值,判断任务时候阻塞超时*/

            if( xTimeToWake < xConstTickCount )
            /*如果计算出来的值溢出*/
            {
                vListInsert(pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem));
                /*将任务添加到阻塞超时时间溢出列表*/
            }
            else
            {
                vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
                /* 将任务添加到阻塞态任务列表 */

                if( xTimeToWake < xNextTaskUnblockTime )
                /* 全局变量xNextTaskUnblockTime 用于保存系统中最近要发生超时的系统时
                 *钟节拍计数器的值 */
                {
                    xNextTaskUnblockTime = xTimeToWake;
                    /*有新的任务阻塞,因此要更新*/
                }
                else
                {
                    mtCOVERAGE_TEST_MARKER();
                }
            }

            ( void ) xCanBlockIndefinitely;
            /*不使用任务挂起功能,就不使用这个入参*/
        }
    #endif 
}

3 延时函数实验

1)实验设计:设计三个任务:start_task、task1、task2

2)三个任务功能如下:

start_task :用来创建task1和task2任务

task1 :用于展示相对延时函数vTaskDelay()的使用

task2: 用于展示绝对延时函数vTaskDelayUntil()的使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值