4、task.c解析
task.c中包含任务创建、任务调度、delay等等接口,很多需要仿真才能弄清楚里面的机制,文章里只能尽可能详细地描述每一个流程。
4.1 宏和数据结构
源码中有涉及的几个宏和数据结构需要先说明一下,其中几个宏是之前讲链表时遗漏的,在这里再补充一下。
4.1.1 链表中遗漏的宏
1 // 设置链表项的持有者 2 #define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner ) ( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) ) 3 // 获取链表项的持有者 4 #define listGET_LIST_ITEM_OWNER( pxListItem ) ( ( pxListItem )->pvOwner ) 5 // 设置链表项的值 6 #define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) ( ( pxListItem )->xItemValue = ( xValue ) ) 7 // 获取链表项的值 8 #define listGET_LIST_ITEM_VALUE( pxListItem ) ( ( pxListItem )->xItemValue ) 9 // 获取链表的第一项的值 10 #define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext->xItemValue ) 11 // 获取链表的第一项 12 #define listGET_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext ) 13 // 获取链表项的下一项 14 #define listGET_NEXT( pxListItem ) ( ( pxListItem )->pxNext ) 15 // 获取链表用于标记尾部的项 16 #define listGET_END_MARKER( pxList ) ( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) ) 17 // 该链表是否为空 18 #define listLIST_IS_EMPTY( pxList ) ( ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) ? pdTRUE : pdFALSE ) 19 // 该链表的总项数 20 #define listCURRENT_LIST_LENGTH( pxList ) ( ( pxList )->uxNumberOfItems ) 21 // 获取链表的第一项的持有者 22 #define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( ( &( ( pxList )->xListEnd ) )->pxNext->pvOwner ) 23 // 该链表是否持有此项 24 #define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( ( pxListItem )->pxContainer == ( pxList ) ) ? ( pdTRUE ) : ( pdFALSE ) ) 25 // 获取持有该链表项的链表 26 #define listLIST_ITEM_CONTAINER( pxListItem ) ( ( pxListItem )->pxContainer ) 27 // 该链表是否已初始化 28 #define listLIST_IS_INITIALISED( pxList ) ( ( pxList )->xListEnd.xItemValue == portMAX_DELAY )
4.1.2 TCB结构体
下面的结构体经过简化以后的样子,去除的那些成员变量在需要使用的时候再去理解就可以,这里先把最基础和常用的几个放出来。
1 typedef struct tskTaskControlBlock 2 { 3 /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */ 4 /* 指向放在任务栈上的最后一项的位置。这必须是TCB结构的第一个成员。 */ 5 volatile StackType_t * pxTopOfStack; 6 7 /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */ 8 /* 任务的状态链表项,表示该任务的状态(就绪、阻塞、挂起)。 */ 9 ListItem_t xStateListItem; 10 /*< Used to reference a task from an event list. */ 11 /* 任务的事件链表项。 */ 12 ListItem_t xEventListItem; 13 /*< The priority of the task. 0 is the lowest priority. */ 14 /* 任务的优先级,0的优先级最低。 */ 15 UBaseType_t uxPriority; 16 /*< Points to the start of the stack. */ 17 /* 指向栈的起始位置。 */ 18 StackType_t * pxStack; 19 /*< Descriptive name given to the task when created. Facilitates debugging only. */ 20 /* 描述任务的名字。 */ 21 char pcTaskName[ configMAX_TASK_NAME_LEN ]; 22 23 #if ( configUSE_TRACE_FACILITY == 1 ) 24 /*< Stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */ 25 /* 存储每次创建TCB时递增的数字。它允许调试器确定何时删除任务,然后重新创建。 */ 26 UBaseType_t uxTCBNumber; 27 /*< Stores a number specifically for use by third party trace code. */ 28 /* 存储专门供第三方跟踪代码使用的数字。 */ 29 UBaseType_t uxTaskNumber; 30 #endif 31 32 #if ( configUSE_MUTEXES == 1 ) 33 /*< The priority last assigned to the task - used by the priority inheritance mechanism. */ 34 /* 上次分配给任务的优先级-由优先级继承机制使用。 */ 35 UBaseType_t uxBasePriority; 36 UBaseType_t uxMutexesHeld; 37 #endif 38 39 #if ( configGENERATE_RU