任务的状态
- 运行态
- 就绪态
- 阻塞态(被动让出CPU)
- 挂起态(主动让出CPU)
就绪链表
就绪态,每个任务优先级对应一个链表,如下:
PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ] = {0}; /*< Prioritised ready tasks. */
xPortPendSVHandler 中断只会从高优先级链表取任务,最高优先级链表没有任务,则往低优先级链表取任务,其内调用如下宏:
#define taskSELECT_HIGHEST_PRIORITY_TASK() \ { \ UBaseType_t uxTopPriority; \ \ /* Find the highest priority list that contains ready tasks. */ \ portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \ configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \ listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \ } /* taskSELECT_HIGHEST_PRIORITY_TASK() */
如下可知,链表的成员变量 pxIndex 指向当前正在指向的任务。链表是一个循环链表,新插入的任务放在 pxIndex 的前面(保证后插入的任务后执行)。
#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \ { \ List_t * const pxConstList = ( pxList ); \ /* Increment the index to the next item and return the item, ensuring */ \ /* we don't return the marker used at the end of the list. */ \ ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) \ { \ ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ } \ ( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \ }
阻塞链表
当获取不到互斥锁,把当前任务从就绪链表移到阻塞链表
何时触发任务切换
tick中断
高优先级任务变为就绪态
- 释放信号量导致高优先级任务可以获得信号量
- 释放互斥锁导致高优先级任务可以获得互斥锁
- 创建了一个高优先级任务,且调度器已启动
- ......
当释放信号量,会把等待此信号量的任务从阻塞链表移到就绪链表,如果优先级大于当前正在执行的任务,则调用如下函数触发 xPortPendSVHandler 中断
#define taskYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API() #define portYIELD_WITHIN_API portYIELD #define portYIELD() \ { \ /* Set a PendSV to request a context switch. */ \ portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \ __DSB(); \ __ISB(); \ }
标签:链表,优先级,FreeRTOS,pxConstList,pxIndex,---,任务,任务调度,define From: https://www.cnblogs.com/god-of-death/p/17729120.html