FreeRTOS-tasks.c

FreeRTOS-tasks.c文件分析

typedef struct tskTaskControlBlock       /* 任务控制块 */

{

    volatile StackType_t * pxTopOfStack; /*任务栈顶指针 */

 

    ListItem_t xStateListItem;                  /*状态列表条目 */

    ListItem_t xEventListItem;                  /*事件列表条目 */

    UBaseType_t uxPriority;                     /*任务当前所处的优先级*/

    StackType_t * pxStack;                      /*< 堆栈指针,指向堆栈的起始地址 */

    char pcTaskName[ configMAX_TASK_NAME_LEN ]; /*< 任务名称*/

 

    #if ( configUSE_MUTEXES == 1 )

        UBaseType_t uxBasePriority; /*< 基本优先级,用来在互斥量优先级继承时保存原来的优先级。 */

        UBaseType_t uxMutexesHeld;   /*任务持有的互斥量数量*/

    #endif

} tskTCB;

 

PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL;  /*当前任务控制块指针*/

PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ]; /*< 各个优先级就绪任务列表 */

PRIVILEGED_DATA static List_t xDelayedTaskList1;                         /*< 延时任务列表1 */

PRIVILEGED_DATA static List_t xDelayedTaskList2;                         /*<  延时任务列表2*/

PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList;              /*< 指向当前延时任务列表的指针*/

PRIVILEGED_DATA static List_t * volatile pxOverflowDelayedTaskList;      /*< 指向溢出延时任务列表指针*/

PRIVILEGED_DATA static List_t xPendingReadyList;                         /*< 挂起就绪列表,用于挂载调度器被挂起时的需要进入就绪的任务*/

 

PRIVILEGED_DATA static List_t xTasksWaitingTermination; /*< 待终结任务列表,记录被删除但是内存没来得及释放的任务*/

PRIVILEGED_DATA static volatile UBaseType_t uxDeletedTasksWaitingCleanUp = ( UBaseType_t ) 0U;  /*待清除任务的个数*/

 

PRIVILEGED_DATA static List_t xSuspendedTaskList; /*< 挂起任务列表 */

 

PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U;  /*当前系统中的任务数量*/

PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;  /*系统tick值*/

PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY;   /*最高的就绪优先级*/

PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE;  /*调度器状态*/

PRIVILEGED_DATA static volatile TickType_t xPendedTicks = ( TickType_t ) 0U;  /*挂起的tick数*/

PRIVILEGED_DATA static volatile BaseType_t xYieldPending = pdFALSE;   /*请求执行调度标志*/

PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0; /*延时任务列表1和2切换次数,或者说延时列表溢出次数。*/

PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U;   /**/

PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = ( TickType_t ) 0U; /* 延时任务列表中下一个被唤醒任务的时间点。*/

PRIVILEGED_DATA static TaskHandle_t xIdleTaskHandle = NULL;       /*空闲任务句柄*/

 

PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) pdFALSE; /*调度器被挂起次数*/

 

BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,

                            const char * const pcName, /* */

                            const configSTACK_DEPTH_TYPE usStackDepth,

                            void * const pvParameters,

                            UBaseType_t uxPriority,

                            TaskHandle_t * const pxCreatedTask )

功能:创建任务

参数:

  1. pxTaskCode 任务指针
  2. pcName 任务名称
  3. usStackDepth 任务堆栈大小,单位4 bytes
  4. pvParameters 任务参数
  5. uxPriority 任务优先级
  6. pxCreatedTask 被创建的任务句柄

返回值:成功时返回1,否则返回负数表示错误

 

void vTaskDelete( TaskHandle_t xTaskToDelete )

功能:删除任务

参数:

  1. xTaskToDelete 任务句柄

 

void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime,

                          const TickType_t xTimeIncrement )

功能:延时指定的时间

参数:

  1. pxPreviousWakeTime 输出型参数,记录上次被唤醒时间
  2. xTimeIncrement 延时时长

 

void vTaskDelay( const TickType_t xTicksToDelay )

功能:延时

参数:

  1. xTicksToDelay 延时时间

 

eTaskState eTaskGetState( TaskHandle_t xTask )

功能:获取任务运行状态

参数:

  1. xTask 任务句柄

返回值:任务状态,包括:运行态,就绪态,阻塞态、挂起态、删除态

 

UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask )

功能:获取任务的优先级

参数:

  1. xTask 任务句柄

返回值:任务优先级

 

UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask )

功能:中断上下文获取任务优先级

参数:

  1. xTask 任务句柄

返回值:任务优先级

 

void vTaskPrioritySet( TaskHandle_t xTask,

                           UBaseType_t uxNewPriority )

功能:设置任务优先级

参数:

  1. xTask 任务句柄
  2. uxNewPriority 新的优先级

 

void vTaskSuspend( TaskHandle_t xTaskToSuspend )

功能:挂起任务

参数:

  1. xTaskToSuspend 任务句柄

 

void vTaskResume( TaskHandle_t xTaskToResume )

功能:恢复被挂起的任务

参数:

  1. 任务句柄

 

BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )

功能:中断上下文恢复被挂起的任务

参数:

  1. 任务句柄

 

void vTaskStartScheduler( void )

功能:启动调度器

 

void vTaskEndScheduler( void )

功能:结束调度器

 

void vTaskSuspendAll( void )

功能:挂起所有任务,或者说挂起调度器

 

BaseType_t xTaskResumeAll( void )

功能:恢复所有任务,或者说恢复调度器

返回值:是否进行过调度,执行过调度返回1,否则返回0

 

TickType_t xTaskGetTickCount( void )

功能:获取当前tick值

返回值:tick值

 

TickType_t xTaskGetTickCountFromISR( void )

功能:中断上下文获取tick值

返回值:tick值

 

UBaseType_t uxTaskGetNumberOfTasks( void )

功能:获取系统中的任务数量

返回值:任务数量

 

char * pcTaskGetName( TaskHandle_t xTaskToQuery )

功能:获取任务名

参数:

  1. xTaskToQuery  任务句柄

返回值:任务名

 

void vTaskStepTick( const TickType_t xTicksToJump )

功能:补偿tick值

参数:

  1. xTicksToJump 补偿的tick数

 

BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp )

功能:补偿被挂起的tick,实际似乎没有被用到

参数:

  1. xTicksToCatchUp tick数

返回值:是否进行过调度,执行过调度返回1,否则返回0

 

BaseType_t xTaskIncrementTick( void )

功能:tick值加1,在systick中断处理中会调用此函数

返回值:是否需要进行任务调度,需要进行任务调度返回1,否则返回0

 

void vTaskSwitchContext( void )

功能:切换任务上下文,更新最高就绪优先级和当前任务控制块指针。重点是

              更新当前任务控制块指针,因为在PendSV中断处理函数中进行上下文切换时会:

             1. 保存当前任务的上下文

             2. 调用此函数,更新当前任务控制块指针

             3. 还原当前任务控制块指针指向任务的上下文

 

void vTaskPlaceOnEventList( List_t * const pxEventList,

                            const TickType_t xTicksToWait )

功能:把当前任务放到某事件列表,例如用在任务等待某信号量,等待时间是xTicksToWait。

参数:

  1. pxEventList 所放的事件列表
  2. xTicksToWait 任务延时时间

 

void vTaskPlaceOnUnorderedEventList( List_t * pxEventList,

                                     const TickType_t xItemValue,

                                     const TickType_t xTicksToWait )

功能:把当前任务放到某无序事件列表

参数:

  1. pxEventList 事件列表
  2. xItemValue  条目值 通常是任务的最大优先级-任务的优先级
  3. xTicksToWait 任务延时时间

 

void vTaskPlaceOnEventListRestricted( List_t * const pxEventList,

                                          TickType_t xTicksToWait,

                                          const BaseType_t xWaitIndefinitely )

功能:把当前任务放到事件列表,用于timer.c文件中

参数:

  1. pxEventList 事件列表
  2. xTicksToWait 任务延时时间
  3. xWaitIndefinitely 是否允许无限期超时

 

BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )

功能:从事件列表中移除一个任务

参数:pxEventList 事件列表

返回值:是否需要进行任务调度,如果是返回1,否则返回0

 

void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem,

                                        const TickType_t xItemValue )

功能:把某任务从事件列表里移除

参数:

  1. pxEventListItem 待删除条目
  2. xItemValue 条目值,通常是最高优先级-任务优先级

 

void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut )

功能:设置TimeOut结构,主要是记录当前tick值和延时列表溢出次数

参数:

  1. pxTimeOut  被设置的结果

 

void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut )

功能:类似于vTaskSetTimeOutState

 

BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut,

                                 TickType_t * const pxTicksToWait )

功能:检查pxTimeOut  记录的时间是否超时

参数:

  1. pxTimeOut 被判断的数据结构
  2. pxTicksToWait 还剩多长时间超时

返回值:超时返回1,否则返回0

 

void vTaskMissedYield( void )

功能:请求执行一次调度

 

eSleepModeStatus eTaskConfirmSleepModeStatus( void )

功能:判断系统能否允许进入休眠状态

返回值:eStandardSleep:允许进入休眠态;

                  eAbortSleep:禁止进入休眠态;

                  eNoTasksWaitingTimeout:可以无限期进入休眠

 

configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask )

功能:获取任务还剩多少堆栈空间,单位4 bytes

参数:

  1. xTask 任务句柄

返回值:剩余的堆栈空间大小

TaskHandle_t xTaskGetCurrentTaskHandle( void )

功能:获取当前任务句柄

返回值:当前任务句柄

 

BaseType_t xTaskGetSchedulerState( void )

功能:获取调度器状态

返回值:taskSCHEDULER_NOT_STARTED:调度器未启动

                  taskSCHEDULER_RUNNING:调度器正在运行

                   taskSCHEDULER_SUSPENDED:调度器被挂起

 

BaseType_t xTaskPriorityInherit( TaskHandle_t const pxMutexHolder )

功能:互斥量持有者任务继承当前任务的优先级(一般来说就是等待互斥量且优先级高的任务)

参数:

  1. pxMutexHolder 互斥量持有者

返回值:发生了继承返回1,否则返回0。

 

BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder )

功能:剥夺任务继承的优先级,重新设置为它原来的优先级

参数:

  1. pxMutexHolder 互斥量持有者

返回值:发生了还原返回1,否则返回0

 

void vTaskPriorityDisinheritAfterTimeout( TaskHandle_t const pxMutexHolder,

                                              UBaseType_t uxHighestPriorityWaitingTask )

功能:剥夺任务继承的优先级,重新设置为它原来的优先级,用于timer.c文件中。

 

TickType_t uxTaskResetEventItemValue( void )

功能:重置当前任务的事件条目值

返回值:之前用的事件条目值

 

TaskHandle_t pvTaskIncrementMutexHeldCount( void )

功能:增加当前任务持有的互斥锁数量

返回值:当前任务句柄

 

重点分析

BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,

                            const char * const pcName, /**/

                            const configSTACK_DEPTH_TYPE usStackDepth,

                            void * const pvParameters,

                            UBaseType_t uxPriority,

                            TaskHandle_t * const pxCreatedTask )

    {

        TCB_t * pxNewTCB;

        BaseType_t xReturn;

 

                StackType_t * pxStack;

 

                /* 申请堆栈空间*/

                pxStack = pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation is the stack. */

 

                if( pxStack != NULL )

                {

                    /* 申请任务控制块空间 */

                    pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); /*lint !e9087 !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack, and the first member of TCB_t is always a pointer to the task's stack. */

 

                    if( pxNewTCB != NULL )

                    {

                        /* Store the stack location in the TCB. */

                        pxNewTCB->pxStack = pxStack;

                    }

                    else

                    {

                        vPortFree( pxStack );

                    }

                }

                else

                {

                    pxNewTCB = NULL;

                }

        if( pxNewTCB != NULL )

        {

            prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );

            prvAddNewTaskToReadyList( pxNewTCB );

            xReturn = pdPASS;

        }

        else

        {

            xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;

        }

 

        return xReturn;

    }

 

static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,

                                  const char * const pcName, /* */

                                  const uint32_t ulStackDepth,

                                  void * const pvParameters,

                                  UBaseType_t uxPriority,

                                  TaskHandle_t * const pxCreatedTask,

                                  TCB_t * pxNewTCB,

                                  const MemoryRegion_t * const xRegions )

{

    StackType_t * pxTopOfStack;

    UBaseType_t x;

 

    #if ( tskSET_NEW_STACKS_TO_KNOWN_VALUE == 1 )

        {

            /* 初始化堆栈 */

            ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) ulStackDepth * sizeof( StackType_t ) );

        }

    #endif /* tskSET_NEW_STACKS_TO_KNOWN_VALUE */

    

        {

                        /* 初始化栈顶*/

            pxTopOfStack = &( pxNewTCB->pxStack[ ulStackDepth - ( uint32_t ) 1 ] );

            pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); /**/            

        }

 

    if( pcName != NULL )

    {       /*设置任务名称*/

        for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )

        {

            pxNewTCB->pcTaskName[ x ] = pcName[ x ];

            if( pcName[ x ] == ( char ) 0x00 )

            {

                break;

            }

            else

            {

                mtCOVERAGE_TEST_MARKER();

            }

        }

 

        pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0';

    }

    else

    {

        pxNewTCB->pcTaskName[ 0 ] = 0x00;

    }

 

    /* 检查任务优先级*/

    if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES )

    {

        uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;

    }

    else

    {

        mtCOVERAGE_TEST_MARKER();

    }

 

        /*设置任务优先级*/

    pxNewTCB->uxPriority = uxPriority;

    #if ( configUSE_MUTEXES == 1 )

        {

            pxNewTCB->uxBasePriority = uxPriority;   /*设置任务基础优先级*/

            pxNewTCB->uxMutexesHeld = 0;             /*任务的持有的互斥锁为0*/

        }

    #endif /* configUSE_MUTEXES */

 

          /*初始化状态列表条目和事件列表条目*/

    vListInitialiseItem( &( pxNewTCB->xStateListItem ) );

    vListInitialiseItem( &( pxNewTCB->xEventListItem ) );

 

         /*设置事件列表条目的拥有者*/

    listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB );

         /*设置事件列表条目值,是最大优先级-任务优先级。因为任务优先级数值越小优先级越低,用最大优先级

            减当前优先级后,大的优先级数值会变小,这样当条目插入到列表时就会处在列表前面。*/

    listSET_LIST_ITEM_VALUE( &( pxNewTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); 

    listSET_LIST_ITEM_OWNER( &( pxNewTCB->xEventListItem ), pxNewTCB );

 

        {  

       /*初始化堆栈,把任务回调指针和参数压入堆栈,并把相关寄存器默认值压入堆栈*/

       pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );

    }   /*记录任务句柄*/

    if( pxCreatedTask != NULL )

    {

        *pxCreatedTask = ( TaskHandle_t ) pxNewTCB;

    }

    else

    {

        mtCOVERAGE_TEST_MARKER();

    }

}

 

添加新任务到就绪列表

static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )

{

    taskENTER_CRITICAL();

    {       

        uxCurrentNumberOfTasks++;

                          

        if( pxCurrentTCB == NULL )

        {

            pxCurrentTCB = pxNewTCB;

 

            if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )

            {

                 prvInitialiseTaskLists();

            }

            else

            {

                mtCOVERAGE_TEST_MARKER();

            }

        }

        else

        {

            if( xSchedulerRunning == pdFALSE )

            {

                if( pxCurrentTCB->uxPriority <= pxNewTCB->uxPriority )

                {

                    pxCurrentTCB = pxNewTCB;

                }

                else

                {

                    mtCOVERAGE_TEST_MARKER();

                }

            }

            else

            {

                mtCOVERAGE_TEST_MARKER();

            }

        }

 

        uxTaskNumber++;

 

        traceTASK_CREATE( pxNewTCB );

 

        prvAddTaskToReadyList( pxNewTCB );

 

        portSETUP_TCB( pxNewTCB );

    }

    taskEXIT_CRITICAL();

 

    if( xSchedulerRunning != pdFALSE )

    {

        if( pxCurrentTCB->uxPriority < pxNewTCB->uxPriority )

        {

            taskYIELD_IF_USING_PREEMPTION();

        }

        else

        {

            mtCOVERAGE_TEST_MARKER();

        }

    }

    else

    {

        mtCOVERAGE_TEST_MARKER();

    }

}

 

 

 

 

    void vTaskDelete( TaskHandle_t xTaskToDelete )

    {

        TCB_t * pxTCB;

 

        taskENTER_CRITICAL();

        {

            pxTCB = prvGetTCBFromHandle( xTaskToDelete );

 

            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();

            }

 

            uxTaskNumber++;

 

            if( pxTCB == pxCurrentTCB )

            {

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

                ++uxDeletedTasksWaitingCleanUp;

                traceTASK_DELETE( pxTCB );

                portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending );

            }

            else

            {

                --uxCurrentNumberOfTasks;

                traceTASK_DELETE( pxTCB );

                prvDeleteTCB( pxTCB );

                prvResetNextTaskUnblockTime();

            }

        }

        taskEXIT_CRITICAL();

 

        if( xSchedulerRunning != pdFALSE )

        {

            if( pxTCB == pxCurrentTCB )

            {

                configASSERT( uxSchedulerSuspended == 0 );

                portYIELD_WITHIN_API();

            }

            else

            {

                mtCOVERAGE_TEST_MARKER();

            }

        }

    }

 

    eTaskState eTaskGetState( TaskHandle_t xTask )

    {

        eTaskState eReturn;

        List_t const * pxStateList, * pxDelayedList, * pxOverflowedDelayedList;

        const TCB_t * const pxTCB = xTask;

 

        configASSERT( pxTCB );

 

        if( pxTCB == pxCurrentTCB )

        {

            eReturn = eRunning;

        }

        else

        {

            taskENTER_CRITICAL();

            {

                pxStateList = listLIST_ITEM_CONTAINER( &( pxTCB->xStateListItem ) );

                pxDelayedList = pxDelayedTaskList;

                pxOverflowedDelayedList = pxOverflowDelayedTaskList;

            }

            taskEXIT_CRITICAL();

 

            if( ( pxStateList == pxDelayedList ) || ( pxStateList == pxOverflowedDelayedList ) )

            {

                eReturn = eBlocked;

            }

 

            #if ( INCLUDE_vTaskSuspend == 1 )

                else if( pxStateList == &xSuspendedTaskList )

                {

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

                    {

                         eReturn = eSuspended;                   

                   }

                    else

                    {

                        eReturn = eBlocked;

                    }

                }

            #endif /* if ( INCLUDE_vTaskSuspend == 1 ) */

 

            #if ( INCLUDE_vTaskDelete == 1 )

                else if( ( pxStateList == &xTasksWaitingTermination ) || ( pxStateList == NULL ) )

                {

                    eReturn = eDeleted;

                }

            #endif

 

            else 

            {

                eReturn = eReady;

            }

        }

 

        return eReturn;

    }

 

 

    void vTaskPrioritySet( TaskHandle_t xTask,

                           UBaseType_t uxNewPriority )

    {

        TCB_t * pxTCB;

        UBaseType_t uxCurrentBasePriority, uxPriorityUsedOnEntry;

        BaseType_t xYieldRequired = pdFALSE;

 

        configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) );

 

        if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES )

        {

            uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;

        }

        else

        {

            mtCOVERAGE_TEST_MARKER();

        }

 

        taskENTER_CRITICAL();

        {

            pxTCB = prvGetTCBFromHandle( xTask );

            traceTASK_PRIORITY_SET( pxTCB, uxNewPriority );

            uxCurrentBasePriority = pxTCB->uxBasePriority;

            if( uxCurrentBasePriority != uxNewPriority )

            {

                if( uxNewPriority > uxCurrentBasePriority )

                {

                    if( pxTCB != pxCurrentTCB )

                    {

                        if( uxNewPriority >= pxCurrentTCB->uxPriority )

                        {

                            xYieldRequired = pdTRUE;

                        }

                        else

                        {

                            mtCOVERAGE_TEST_MARKER();

                        }

                    }

                    else

                    {

                    }

                }

                else if( pxTCB == pxCurrentTCB )

                {

                    xYieldRequired = pdTRUE;

                }

                else

                {

                }

                uxPriorityUsedOnEntry = pxTCB->uxPriority;

 

                    {

                        if( pxTCB->uxBasePriority == pxTCB->uxPriority )

                        {

                            pxTCB->uxPriority = uxNewPriority;

                        }

                        else

                        {

                            mtCOVERAGE_TEST_MARKER();

                        }

                        pxTCB->uxBasePriority = uxNewPriority;

                    }

          

                if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )

                {

                    listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxNewPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */

                }

                else

                {

                    mtCOVERAGE_TEST_MARKER();

                }

 

                if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )

                {

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

                    {

                        portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority );

                    }

                    else

                    {

                        mtCOVERAGE_TEST_MARKER();

                    }

 

                    prvAddTaskToReadyList( pxTCB );

                }

                else

                {

                    mtCOVERAGE_TEST_MARKER();

                }

 

                if( xYieldRequired != pdFALSE )

                {

                    taskYIELD_IF_USING_PREEMPTION();

                }

                else

                {

                    mtCOVERAGE_TEST_MARKER();

                }

 

                ( void ) uxPriorityUsedOnEntry;

            }

        }

        taskEXIT_CRITICAL();

    }

 

 

 void vTaskSuspend( TaskHandle_t xTaskToSuspend )

    {

        TCB_t * pxTCB;

 

        taskENTER_CRITICAL();

        {

            pxTCB = prvGetTCBFromHandle( xTaskToSuspend );

 

            traceTASK_SUSPEND( pxTCB );

            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();

        }

 

        if( pxTCB == pxCurrentTCB )

        {

            if( xSchedulerRunning != pdFALSE )

            {

                configASSERT( uxSchedulerSuspended == 0 );

                portYIELD_WITHIN_API();

            }

            else

            {

                if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks ) /**/

                {

                    pxCurrentTCB = NULL;

                }

                else

                {

                    vTaskSwitchContext();

                }

            }

        }

        else

        {

            mtCOVERAGE_TEST_MARKER();

        }

    }

 

 

 

 

void vTaskResume( TaskHandle_t xTaskToResume )

    {

        TCB_t * const pxTCB = xTaskToResume;

 

        configASSERT( xTaskToResume );

        if( ( pxTCB != pxCurrentTCB ) && ( pxTCB != NULL ) )

        {

            taskENTER_CRITICAL();

            {

                if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )

                {

                    traceTASK_RESUME( pxTCB );

 

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

                    prvAddTaskToReadyList( pxTCB );

 

                    if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )

                    {

                        taskYIELD_IF_USING_PREEMPTION();

                    }

                    else

                    {

                        mtCOVERAGE_TEST_MARKER();

                    }

                }

                else

                {

                    mtCOVERAGE_TEST_MARKER();

                }

            }

            taskEXIT_CRITICAL();

        }

        else

        {

            mtCOVERAGE_TEST_MARKER();

        }

    }

 

 

 

 

void vTaskStartScheduler( void )

{

    BaseType_t xReturn;

 

            xReturn = xTaskCreate( prvIdleTask,

                                   configIDLE_TASK_NAME,

                                   configMINIMAL_STACK_SIZE,

                                   ( void * ) NULL,

                                   portPRIVILEGE_BIT,  /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */

                                   &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */

   

    #if ( configUSE_TIMERS == 1 )

        {

            if( xReturn == pdPASS )

            {

                xReturn = xTimerCreateTimerTask();

            }

            else

            {

                mtCOVERAGE_TEST_MARKER();

            }

        }

    #endif /* configUSE_TIMERS */

 

    if( xReturn == pdPASS )

    {      

                portDISABLE_INTERRUPTS();

 

        xNextTaskUnblockTime = portMAX_DELAY;

        xSchedulerRunning = pdTRUE;

        xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;

 

        portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();

 

        traceTASK_SWITCHED_IN();

 

        if( xPortStartScheduler() != pdFALSE )

        {

 

        }

        else

        {

 

        }

    }

    else

    {

        configASSERT( xReturn != errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY );

    }

}

 

 

 

 

 

挂起调度器

void vTaskSuspendAll( void )

{

    portSOFTWARE_BARRIER();

 

    ++uxSchedulerSuspended;

 

    portMEMORY_BARRIER();

}

 

static TickType_t prvGetExpectedIdleTime( void )

    {

        TickType_t xReturn;

        UBaseType_t uxHigherPriorityReadyTasks = pdFALSE;

 

         if( uxTopReadyPriority > tskIDLE_PRIORITY )

         {

                uxHigherPriorityReadyTasks = pdTRUE;

         }

        if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )

        {

            xReturn = 0;

        }

        else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 )

        {

            xReturn = 0;

        }

        else if( uxHigherPriorityReadyTasks != pdFALSE )

        {

            xReturn = 0;

        }

        else

        {

            xReturn = xNextTaskUnblockTime - xTickCount;

        }

 

        return xReturn;

    }

 

 

 

 


BaseType_t xTaskResumeAll( void )

{

    TCB_t * pxTCB = NULL;

    BaseType_t xAlreadyYielded = pdFALSE;

 

    configASSERT( uxSchedulerSuspended );

 

    taskENTER_CRITICAL();

    {

        --uxSchedulerSuspended;

 

        if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )

        {

            if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U )

            {

                while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE )

                {

                    pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) ); /*liof e. */

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

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

                    prvAddTaskToReadyList( pxTCB );

 

                    if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )

                    {

                        xYieldPending = pdTRUE;

                    }

                    else

                    {

                        mtCOVERAGE_TEST_MARKER();

                    }

                }

 

                if( pxTCB != NULL )

                {

                    prvResetNextTaskUnblockTime();

                }

 

                {

                    TickType_t xPendedCounts = xPendedTicks; /* Non-volatile copy. */

 

                    if( xPendedCounts > ( TickType_t ) 0U )

                    {

                        do

                        {

                            if( xTaskIncrementTick() != pdFALSE )

                            {

                                xYieldPending = pdTRUE;

                            }

                            else

                            {

                                mtCOVERAGE_TEST_MARKER();

                            }

 

                            --xPendedCounts;

                        } while( xPendedCounts > ( TickType_t ) 0U );

 

                        xPendedTicks = 0;

                    }

                    else

                    {

                        mtCOVERAGE_TEST_MARKER();

                    }

                }

 

                if( xYieldPending != pdFALSE )

                {

                    #if ( configUSE_PREEMPTION != 0 )

                        {

                            xAlreadyYielded = pdTRUE;

                        }

                    #endif

                    taskYIELD_IF_USING_PREEMPTION();

                }

                else

                {

                    mtCOVERAGE_TEST_MARKER();

                }

            }

        }

        else

        {

            mtCOVERAGE_TEST_MARKER();

        }

    }

    taskEXIT_CRITICAL();

 

    return xAlreadyYielded;

}

 

 

 

 

 

 

 

 

 

BaseType_t xTaskIncrementTick( void )

{

    TCB_t * pxTCB;

    TickType_t xItemValue;

    BaseType_t xSwitchRequired = pdFALSE;

 

    traceTASK_INCREMENT_TICK( xTickCount );

 

    if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )

    {

        const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1;

 

        xTickCount = xConstTickCount;

 

        if( xConstTickCount == ( TickType_t ) 0U ) /**/

        {

            taskSWITCH_DELAYED_LISTS();

        }

        else

        {

            mtCOVERAGE_TEST_MARKER();

        }

 

        if( xConstTickCount >= xNextTaskUnblockTime )

        {

            for( ; ; )

            {

                if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )

                {

                    xNextTaskUnblockTime = portMAX_DELAY; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */

                    break;

                }

                else

                {

                    pxTCB = listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too.  Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */

                    xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) );

 

                    if( xConstTickCount < xItemValue )

                    {

                        xNextTaskUnblockTime = xItemValue;

                        break/*lint !e9011 Code structure here is deedmed easier to understand with multiple breaks. */

                    }

                    else

                    {

                        mtCOVERAGE_TEST_MARKER();

                    }

 

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

 

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

                    {

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

                    }

                    else

                    {

                        mtCOVERAGE_TEST_MARKER();

                    }

                    prvAddTaskToReadyList( pxTCB );

                    #if ( configUSE_PREEMPTION == 1 )

                        {

                            if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )

                            {

                                xSwitchRequired = pdTRUE;

                            }

                            else

                            {

                                mtCOVERAGE_TEST_MARKER();

                            }

                        }

                    #endif /* configUSE_PREEMPTION */

                }

            }

        }

        #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )

            {

                if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( UBaseType_t ) 1 )

                {

                    xSwitchRequired = pdTRUE;

                }

                else

                {

                    mtCOVERAGE_TEST_MARKER();

                }

            }

        #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */

 

        #if ( configUSE_PREEMPTION == 1 )

            {

                if( xYieldPending != pdFALSE )

                {

                    xSwitchRequired = pdTRUE;

                }

                else

                {

                    mtCOVERAGE_TEST_MARKER();

                }

            }

        #endif /* configUSE_PREEMPTION */

    }

    else

    {

        ++xPendedTicks;

    }

 

    return xSwitchRequired;

}

 

 

void vTaskSwitchContext( void )

{

    if( uxSchedulerSuspended != ( UBaseType_t ) pdFALSE )

    {

        xYieldPending = pdTRUE;

    }

    else

    {

        xYieldPending = pdFALSE;

        traceTASK_SWITCHED_OUT();

 

        /* 更新最高就绪优先级和当前任务控制块指针*/

        taskCHECK_FOR_STACK_OVERFLOW();

 

        taskSELECT_HIGHEST_PRIORITY_TASK(); /*lint !e9079 void * is used as this macro is used with timers and co-routines too.  Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */

        traceTASK_SWITCHED_IN();

    }

}

 

把当前任务放到事件列表

void vTaskPlaceOnEventList( List_t * const pxEventList,

                            const TickType_t xTicksToWait )

{

    configASSERT( pxEventList );

 

    /* 当前任务事件列表条目按优先级顺序插入到事件列表*/

    vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) );

         /*把当前任务添加到延时列表*/

    prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );

}

 

void vTaskPlaceOnUnorderedEventList( List_t * pxEventList,

                                     const TickType_t xItemValue,

                                     const TickType_t xTicksToWait )

{

    configASSERT( pxEventList );

 

    configASSERT( uxSchedulerSuspended != 0 );

 

    /*  设置事件列表条目值*/

    listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );

 

    /*把当前任务的事件列表条目插入到事件列表末尾。*/

    vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );

         /*把当前任务添加到延时列表*/

    prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );

}

 

void vTaskPlaceOnEventListRestricted( List_t * const pxEventList,

                                          TickType_t xTicksToWait,

                                          const BaseType_t xWaitIndefinitely )

    {

        configASSERT( pxEventList );

 

        /*把当前任务事件列表条目按照优先级顺序添加到事件列表 */

        vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );

 

        if( xWaitIndefinitely != pdFALSE )

        {

            xTicksToWait = portMAX_DELAY;

        }

        traceTASK_DELAY_UNTIL( ( xTickCount + xTicksToWait ) );

                  /*把当前任务添加到延时列表*/

        prvAddCurrentTaskToDelayedList( xTicksToWait, xWaitIndefinitely );

    }

 

BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )

{

    TCB_t * pxUnblockedTCB;

    BaseType_t xReturn;

 

    pxUnblockedTCB = listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); /* */

    configASSERT( pxUnblockedTCB );

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

 

    if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )

    {

        ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) );

        prvAddTaskToReadyList( pxUnblockedTCB );

 

        #if ( configUSE_TICKLESS_IDLE != 0 )

            {

                prvResetNextTaskUnblockTime();

            }

        #endif

    }

    else

    {

        vListInsertEnd( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );

    }

 

    if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )

    {

        xReturn = pdTRUE;

 

        xYieldPending = pdTRUE;

    }

    else

    {

        xReturn = pdFALSE;

    }

 

    return xReturn;

}

 

 

 

 

 

void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem,

                                        const TickType_t xItemValue )

{

    TCB_t * pxUnblockedTCB;

 

    configASSERT( uxSchedulerSuspended != pdFALSE );

 

    /* 设置时间列表条目值*/

    listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );

 

    pxUnblockedTCB = listGET_LIST_ITEM_OWNER( pxEventListItem ); /**/

    configASSERT( pxUnblockedTCB );

                            /*把任务从事件列表删除*/

    ( void ) uxListRemove( pxEventListItem );

 

    #if ( configUSE_TICKLESS_IDLE != 0 )

        {

            /* 更新延时列表下个任务唤醒时间*/

            prvResetNextTaskUnblockTime();

        }

    #endif

 

    /* 把任务添加到就绪列表*/

    ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) );

    prvAddTaskToReadyList( pxUnblockedTCB );

 

          /*检查是否需要进行调度*/

    if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )

    {

        xYieldPending = pdTRUE;

    }

}

 

BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut,

                                 TickType_t * const pxTicksToWait )

{

    BaseType_t xReturn;

 

    configASSERT( pxTimeOut );

    configASSERT( pxTicksToWait );

 

    taskENTER_CRITICAL();

    {

        const TickType_t xConstTickCount = xTickCount;

        const TickType_t xElapsedTime = xConstTickCount - pxTimeOut->xTimeOnEntering;

 

        #if ( INCLUDE_vTaskSuspend == 1 )

            if( *pxTicksToWait == portMAX_DELAY )

            {

                xReturn = pdFALSE;

            }

            else

        #endif

 

        if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /**/

        {

            xReturn = pdTRUE;

            *pxTicksToWait = ( TickType_t ) 0;

        }

        else if( xElapsedTime < *pxTicksToWait ) 

        {

            *pxTicksToWait -= xElapsedTime;

            vTaskInternalSetTimeOutState( pxTimeOut );

            xReturn = pdFALSE;

        }

        else

        {

            *pxTicksToWait = ( TickType_t ) 0;

            xReturn = pdTRUE;

        }

    }

    taskEXIT_CRITICAL();

 

    return xReturn;

}

 

 

 

 

 

 

 

 

static portTASK_FUNCTION( prvIdleTask, pvParameters )

{

    ( void ) pvParameters;

    portALLOCATE_SECURE_CONTEXT( configMINIMAL_SECURE_STACK_SIZE );

 

    for( ; ; )

    {

        prvCheckTasksWaitingTermination();

 

        #if ( configUSE_TICKLESS_IDLE != 0 )

            {

                TickType_t xExpectedIdleTime;

 

                if (!gasMeter.noSleep)

                {

                    xExpectedIdleTime = prvGetExpectedIdleTime();

 

                    if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )

                    {

                        vTaskSuspendAll();

                        {

                            configASSERT( xNextTaskUnblockTime >= xTickCount );

                            xExpectedIdleTime = prvGetExpectedIdleTime();

                            configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING( xExpectedIdleTime );

 

                            if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )

                            {

                                traceLOW_POWER_IDLE_BEGIN();

                                portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );

                                traceLOW_POWER_IDLE_END();

                            }

                            else

                            {

                                mtCOVERAGE_TEST_MARKER();

                            }

                        }

                        ( void ) xTaskResumeAll();

                    }

                    else

                    {

                        mtCOVERAGE_TEST_MARKER();

                    }

                }

            }

        #endif /* configUSE_TICKLESS_IDLE */

    }

}

 

 

 

 

 

eSleepModeStatus eTaskConfirmSleepModeStatus( void )

    {

        const UBaseType_t uxNonApplicationTasks = 1;

        eSleepModeStatus eReturn = eStandardSleep;

 

        if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 )

        {

            eReturn = eAbortSleep;

        }

        else if( xYieldPending != pdFALSE )

        {

            eReturn = eAbortSleep;

        }

        else if( xPendedTicks != 0 )

        {

            eReturn = eAbortSleep;

        }

        else

        {

            if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) )

            {

                eReturn = eNoTasksWaitingTimeout;

            }

            else

            {

                mtCOVERAGE_TEST_MARKER();

            }

        }

 

        return eReturn;

    }

 

 

 

 

 

 

更新延时列表任务下一次唤醒时间

static void prvResetNextTaskUnblockTime( void )

{

          /*延时列表空无休止延时*/

    if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )

    {

        xNextTaskUnblockTime = portMAX_DELAY;

    }

    else  /*否则下一次唤醒时间是延时列表首任务唤醒时间*/

    {

        xNextTaskUnblockTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxDelayedTaskList );

    }

}

 

 BaseType_t xTaskPriorityInherit( TaskHandle_t const pxMutexHolder )

    {

        TCB_t * const pxMutexHolderTCB = pxMutexHolder;

        BaseType_t xReturn = pdFALSE;

 

        if( pxMutexHolder != NULL )

        {

            if( pxMutexHolderTCB->uxPriority < pxCurrentTCB->uxPriority )

            {

                if( ( listGET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )

                {

                    listSET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ); /* */

                }

                else

                {

                    mtCOVERAGE_TEST_MARKER();

                }

 

                if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxMutexHolderTCB->uxPriority ] ), &( pxMutexHolderTCB->xStateListItem ) ) != pdFALSE )

                {

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

                    {

                        portRESET_READY_PRIORITY( pxMutexHolderTCB->uxPriority, uxTopReadyPriority );

                    }

                    else

                    {

                        mtCOVERAGE_TEST_MARKER();

                    }

 

                    pxMutexHolderTCB->uxPriority = pxCurrentTCB->uxPriority;

                    prvAddTaskToReadyList( pxMutexHolderTCB );

                }

                else

                {

                    pxMutexHolderTCB->uxPriority = pxCurrentTCB->uxPriority;

                }

 

                traceTASK_PRIORITY_INHERIT( pxMutexHolderTCB, pxCurrentTCB->uxPriority );

 

                xReturn = pdTRUE;

            }

            else

            {

                if( pxMutexHolderTCB->uxBasePriority < pxCurrentTCB->uxPriority )

                {

                    xReturn = pdTRUE;

                }

                else

                {

                    mtCOVERAGE_TEST_MARKER();

                }

            }

        }

        else

        {

            mtCOVERAGE_TEST_MARKER();

        }

 

        return xReturn;

    }

 

 

BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder )

    {

        TCB_t * const pxTCB = pxMutexHolder;

        BaseType_t xReturn = pdFALSE;

 

        if( pxMutexHolder != NULL )

        {

            configASSERT( pxTCB == pxCurrentTCB );

            configASSERT( pxTCB->uxMutexesHeld );

            ( pxTCB->uxMutexesHeld )--;

 

            if( pxTCB->uxPriority != pxTCB->uxBasePriority )

            {

                if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 )

                {

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

                    {

                        portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority );

                    }

                    else

                    {

                        mtCOVERAGE_TEST_MARKER();

                    }

 

                    traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );

                    pxTCB->uxPriority = pxTCB->uxBasePriority;

 

                    listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxTCB->uxPriority ); /*/

                    prvAddTaskToReadyList( pxTCB );

 

                    xReturn = pdTRUE;

                }

                else

                {

                    mtCOVERAGE_TEST_MARKER();

                }

            }

            else

            {

                mtCOVERAGE_TEST_MARKER();

            }

        }

        else

        {

            mtCOVERAGE_TEST_MARKER();

        }

 

        return xReturn;

    }

 

 

 

 

 

把持有互斥量任务的优先级设置为任务的基础优先级或者最高等待任务的优先级。

void vTaskPriorityDisinheritAfterTimeout( TaskHandle_t const pxMutexHolder,

                                              UBaseType_t uxHighestPriorityWaitingTask )

    {

        TCB_t * const pxTCB = pxMutexHolder;

        UBaseType_t uxPriorityUsedOnEntry, uxPriorityToUse;

        const UBaseType_t uxOnlyOneMutexHeld = ( UBaseType_t ) 1;

 

        if( pxMutexHolder != NULL )

        {

            configASSERT( pxTCB->uxMutexesHeld );

 

            if( pxTCB->uxBasePriority < uxHighestPriorityWaitingTask )

            {

                uxPriorityToUse = uxHighestPriorityWaitingTask;

            }

            else

            {

                uxPriorityToUse = pxTCB->uxBasePriority;

            }

 

            if( pxTCB->uxPriority != uxPriorityToUse )

            {

                if( pxTCB->uxMutexesHeld == uxOnlyOneMutexHeld )

                {

                    configASSERT( pxTCB != pxCurrentTCB );

 

                    traceTASK_PRIORITY_DISINHERIT( pxTCB, uxPriorityToUse );

                    uxPriorityUsedOnEntry = pxTCB->uxPriority;

                    pxTCB->uxPriority = uxPriorityToUse;

 

                    if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )

                    {

                        listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriorityToUse ); /* */

                    }

                    else

                    {

                        mtCOVERAGE_TEST_MARKER();

                    }

 

                    if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )

                    {

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

                        {

                            portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority );

                        }

                        else

                        {

                            mtCOVERAGE_TEST_MARKER();

                        }

                        prvAddTaskToReadyList( pxTCB );

                    }

                    else

                    {

                        mtCOVERAGE_TEST_MARKER();

                    }

                }

                else

                {

                    mtCOVERAGE_TEST_MARKER();

                }

            }

            else

            {

                mtCOVERAGE_TEST_MARKER();

            }

        }

        else

        {

            mtCOVERAGE_TEST_MARKER();

        }

    }

 

 

static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait,

                                            const BaseType_t xCanBlockIndefinitely )

{

    TickType_t xTimeToWake;

    const TickType_t xConstTickCount = xTickCount;

 

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

    {

        portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); /**/

    }

    else

    {

        mtCOVERAGE_TEST_MARKER();

    }

 

    #if ( INCLUDE_vTaskSuspend == 1 )

        {

            if( ( xTicksToWait == portMAX_DELAY ) && ( xCanBlockIndefinitely != pdFALSE ) )

            {

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

            }

            else

            {

                xTimeToWake = xConstTickCount + xTicksToWait;

 

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

 

                if( xTimeToWake < xConstTickCount )

                {

                    vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );

                }

                else

                {

                    vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );

 

                    if( xTimeToWake < xNextTaskUnblockTime )

                    {

                        xNextTaskUnblockTime = xTimeToWake;

                    }

                    else

                    {

                        mtCOVERAGE_TEST_MARKER();

                    }

                }

            }

        }

}

 

posted @ 2022-08-08 20:44  明er  阅读(164)  评论(0)    收藏  举报