FreeRTOS Task Management(2)- 任务控制块(TCB)
/* FreeRTOS Kernel V10.4.1 */
本文原文链接:https://www.cnblogs.com/yanpio/p/14873627.html
1 任务控制块(Task Control Block, TCB)
TCB
是每个任务所有操作的基础,因此有必要先了解一下TCB
的详细构成。部分变量会在之后用到时,再补充说明。
/*
* Task control block. A task control block (TCB) is allocated for each task,
* and stores task state information, including a pointer to the task's context
* (the task's run time environment, including register values)
*/
typedef struct tskTaskControlBlock
{
/* 栈顶<元素>指针,注意与 pxEndOfStack 的区别。 必须是结构体的第一个成员. */
volatile StackType_t * pxTopOfStack;
/* MPU 模块设置,必须是结构体的第二个成员 */
#if ( portUSING_MPU_WRAPPERS == 1 )
xMPU_SETTINGS xMPUSettings;
#endif
ListItem_t xStateListItem; /* 列表项指示任务当前的状态 (Ready, Blocked, Suspended ). */
ListItem_t xEventListItem; /* 用于在事件列表中. */
UBaseType_t uxPriority; /* 任务优先级(0为优先级最低). */
StackType_t * pxStack; /* 栈底指针,指向栈开始处. */
char pcTaskName[ configMAX_TASK_NAME_LEN ]; /* 任务名 */
/* 如果栈向上生长,则定义栈顶指针 */
#if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
StackType_t * pxEndOfStack;
#endif
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
UBaseType_t uxCriticalNesting; /* 保存临界区的栈深度. 在函数vTaskEnterCritical() 和 vTaskExitCritical()中会维护这个值*/
#endif
#if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxTCBNumber; /*TCB的编号,每次增加一个task,TCB的编号就会增加. */
UBaseType_t uxTaskNumber; /*task的编号,其值和uxTCBNumber相等,可用于调试追踪. */
#endif
#if ( configUSE_MUTEXES == 1 )
UBaseType_t uxBasePriority; /*上一次分配给该任务的优先级,用于优先级继承机制. */
UBaseType_t uxMutexesHeld; /* 持有的信号量 */
#endif
#if ( configUSE_APPLICATION_TASK_TAG == 1 )
TaskHookFunction_t pxTaskTag;
#endif
/* 存储一些私有的变量 */
#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
void * pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
#endif
/* task 运行的总时间 */
#if ( configGENERATE_RUN_TIME_STATS == 1 )
uint32_t ulRunTimeCounter;
#endif
/* See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html for additional information. */
#if ( configUSE_NEWLIB_REENTRANT == 1 )
struct _reent xNewLib_reent;
#endif
/* 任务通知相关变量 */
#if ( configUSE_TASK_NOTIFICATIONS == 1 )
volatile uint32_t ulNotifiedValue[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
volatile uint8_t ucNotifyState[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
#endif
/* FreeRTOS.h 中有关于 tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE 的详细注释。主要的作用是决定task创建的资源是动态还是静态分配内存. */
#if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
uint8_t ucStaticallyAllocated; /* 标记stack 和 TCB分配方式,在删除任务时,根据此标志来对应释放内存 */
#endif
/* delay 终止标志 */
#if ( INCLUDE_xTaskAbortDelay == 1 )
uint8_t ucDelayAborted;
#endif
/* error number*/
#if ( configUSE_POSIX_ERRNO == 1 )
int iTaskErrno;
#endif
} tskTCB;
2 相关全局变量
/* 当前TCB,task运行时,实质上就是对TCB进行操作 */
TCB_t * volatile pxCurrentTCB = NULL;
/* 不同的优先级有不同的ready list。处于ready状态的task会依据优先级,被添加到此list中 */
static List_t pxReadyTasksLists[ configMAX_PRIORITIES ];
/* task delay操作时, tick计数器不断累积,可能会发生溢出(循环计数,比如从0计数到100,满100后又重新从0开始计数)
* 因此,需要两个list来记录,xDelayedTaskList2用于计数溢出的task */
static List_t xDelayedTaskList1;
static List_t xDelayedTaskList2;
/* 分别指向上述两个不同的list */
static List_t * volatile pxDelayedTaskList;
static List_t * volatile pxOverflowDelayedTaskList;
/* 档调度器挂起时,处于ready状态的task被添加到该list中。等调度器恢复时,这些task会从该list中移出 */
static List_t xPendingReadyList;
/* task被删除后,其资源不会立刻进行释放。而是由idle task去处理这些资源释放的活。
* 而idle task 不一定立刻就能被调度器执行,因此需要将被删除任务的相关信息记录下来 */
#if ( INCLUDE_vTaskDelete == 1 )
/*任务被删除后,添加到此list中 */
static List_t xTasksWaitingTermination;
/* 等待清理内存的任务数量 */
static volatile UBaseType_t uxDeletedTasksWaitingCleanUp = ( UBaseType_t ) 0U;
#endif
/* 处于Suspend状态的task,会被添加到此list中 . */
#if ( INCLUDE_vTaskSuspend == 1 )
static List_t xSuspendedTaskList;
#endif
转载请说明出处,尊重原创,尊重劳动,谢谢!