3-FreeRTOS原理剖析:任务挂起和恢复

函数 描述
vTaskSuspend() 挂起一个任务,使任务处于挂起态
vTaskSuspendAll() 调度锁关闭函数,即禁止调度器调用,相当于将所有的任务挂起
vTaskResume() 释放一个挂起的任务
xTaskResumeAll() 调度锁开启函数,即恢复调度器调用,同时将列表xPendingReadyList 中的任务插入到对应的就绪表中,可与函数vTaskSuspendAll()配合,使用在一个临界区太长而不适合简单地关中断的代码段
xTaskResumeFromISR() 在中断函数中使用,释放一个挂起的任务

任务挂起中其它重要的API函数(介绍过的函数不列出,请参考前面的文章):

函数 描述
prvTaskIsTaskSuspended() 判断任务是否挂起,内部调用函数

2. 任务的挂起函数vTaskSuspend()

任务函数挂起功能是将任务插入挂起列表中,此时任务处于挂起态,调度器不能对该任务进行调度。使用此函数必须将INCLUDE_vTaskSuspend设置为1,在FreeRTOSConfig.h中定义,函数原型如下:

/********************************************************

参数:xTaskToSuspend :需要挂起任务的句柄,若为NULL,则挂起任务本身

返回:无

*********************************************************/
void vTaskSuspend( TaskHandle_t xTaskToSuspend )

函数代码如下:

void vTaskSuspend( TaskHandle_t xTaskToSuspend )

{

    TCB_t *pxTCB;



    taskENTER_CRITICAL();    /* 进入临界状态 */
    {

        /* 等到挂起任务的TCB,若参数为NULL,则挂起任务为当前正在运行的任务(即自己删除自己) */

        pxTCB = prvGetTCBFromHandle( xTaskToSuspend );



        traceTASK_SUSPEND( pxTCB );



        /*

         * 删除任务的状态信息,不让任务的状态列表项挂接到任何一个列表上

         * 不同优先级的任务放在不同任务就绪列表,用一个32位变量表示就绪位,相应Bit位为1表示对应就绪表中有任务

         * 如返回值为0,则说明该任务优先级下,任务就绪表只有它一个任务,删除了该任务,就无其他任务

         */

        if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )

        {

            /* 清除相应的就绪标志位,防止调度器调用 */

            taskRESET_READY_PRIORITY( pxTCB->uxPriority );
        }

        else

        {

            mtCOVERAGE_TEST_MARKER();

        }



        /* 判断任务是否存在事件(如信号量,队列),若存在,则将事件从相应的列表中删除 */

        if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
        {

            ( void ) uxListRemove( &( pxTCB->xEventListItem ) );

        }

        else

        {

            mtCOVERAGE_TEST_MARKER();

        }
        /* 将任务的状态列表项插入挂起列表的末尾 */

        vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) );

    }

    taskEXIT_CRITICAL();    /* 退出临界状态 */



    /* 如果任务调度器正在运行 */

    if( xSchedulerRunning != pdFALSE )
    {

        taskENTER_CRITICAL();    /* 进入临界状态 */
        {

            /* 重置下一个任务的解锁时间,防止下一个解锁任务为刚刚挂起的任务 */

            prvResetNextTaskUnblockTime();

        }

        taskEXIT_CRITICAL();    /* 退出临界状态 */

    }

    else
    {

        mtCOVERAGE_TEST_MARKER();

    }


    /* 如果TCB为当前正在运行的任务 */

    if( pxTCB == pxCurrentTCB )
    {

        /* 如果任务调度器正在运行 */

        if( xSchedulerRunning != pdFALSE )

        {

            configASSERT( uxSchedulerSuspended == 0 );

            

            /* 执行一次任务切换,如果需要挂起的任务是正在运行的任务,已经将它放在挂起列表中,就会切换到其它任务 */

            portYIELD_WITHIN_API();    

        }
        else    /* 如果任务调度器关闭 */
        {

            /* 如果就绪列表的任务数量等于任务总数量,一般不会执行这里,因为至少会有一个空闲任务 */

            if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks )

            {

                pxCurrentTCB = NULL;    /* 当前运行的任务TCB执行NULL */

            }

            else

            {

                vTaskSwitchContext();    /* 获取下一个任务(分析任务切换时具体说明) */

            }

        }

    }

    else
    {

        mtCOVERAGE_TEST_MARKER();

    }

}

说明:

  • 若函数带入的任务句柄为N

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小吴的嵌入式笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值