绵阳网站开发公司,深圳闭环转运,html5视频网站模板,WordPress hitokoto任务控制块结构体
任务控制块是 FreeRTOS 中用于描述和管理任务的数据结构#xff0c;包含了任务的状态、优先级、堆栈等信息。
TCB_t的全称为Task Control Block#xff0c;也就是任务控制块#xff0c;这个结构体包含了一个任务所有的信息#xff0c;它的定义以及相关变…任务控制块结构体
任务控制块是 FreeRTOS 中用于描述和管理任务的数据结构包含了任务的状态、优先级、堆栈等信息。
TCB_t的全称为Task Control Block也就是任务控制块这个结构体包含了一个任务所有的信息它的定义以及相关变量的解释如下
typedef struct tskTaskControlBlock {// 这里栈顶指针必须位于TCB第一项是为了便于上下文切换操作详见xPortPendSVHandler中任务切换的操作。volatile StackType_t *pxTopOfStack; // MPU相关暂时不讨论#if ( portUSING_MPU_WRAPPERS 1 )xMPU_SETTINGS xMPUSettings; #endif// 表示任务状态不同的状态会挂接在不同的状态链表下ListItem_t xStateListItem; // 事件链表项会挂接到不同事件链表下ListItem_t xEventListItem; // 任务优先级数值越大优先级越高UBaseType_t uxPriority; // 指向堆栈起始位置这只是单纯的一个分配空间的地址可以用来检测堆栈是否溢出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; #endif// 跟踪调试用的变量#if ( configUSE_TRACE_FACILITY 1 )UBaseType_t uxTCBNumber; UBaseType_t uxTaskNumber; #endif// 任务优先级被临时提高时保存任务原本的优先级#if ( configUSE_MUTEXES 1 )UBaseType_t uxBasePriority; UBaseType_t uxMutexesHeld;#endif// 任务的一个标签值可以由用户自定义它的意义例如可以传入一个函数指针可以用来做Hook 函数调用#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// 运行时间变量#if( configGENERATE_RUN_TIME_STATS 1 )uint32_t ulRunTimeCounter; #endif// 支持NEWLIB的一个变量#if ( configUSE_NEWLIB_REENTRANT 1 )struct _reent xNewLib_reent;#endif// 任务通知功能需要用到的变量#if( configUSE_TASK_NOTIFICATIONS 1 )// 任务通知的值 volatile uint32_t ulNotifiedValue;// 任务通知的状态volatile uint8_t ucNotifyState;#endif// 用来标记这个任务的栈是不是静态分配的#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE ! 0 ) uint8_t ucStaticallyAllocated; #endif// 延时是否被打断#if( INCLUDE_xTaskAbortDelay 1 )uint8_t ucDelayAborted;#endif// 错误标识#if( configUSE_POSIX_ERRNO 1 )int iTaskErrno;#endif} tskTCB;typedef tskTCB TCB_t;栈顶指针必须为TCB结构体的第一项原因是栈顶指针与我们的任务上下文保存、任务切换和任务恢复等操作息息相关。
每个任务都有自己的任务控制块类似身份证。
TCB结构体中portSTACK_GROWTH0表示栈是向上生长0表示栈是向下生长我们STM32的栈是高地址往低地址存储是向下生长的而堆是低地址往高地址生长是向上生长的。 任务句柄 任务句柄Task Handle是在 FreeRTOS 中用于标识和引用任务的数据类型。每个创建的任务都会分配一个唯一的任务句柄通过该句柄可以对任务进行操作和管理。
任务句柄是一个指向任务控制块Task Control BlockTCB的指针。 使用任务句柄可以通过 FreeRTOS 提供的 API 函数对任务进行操作例如挂起suspend、恢复resume、删除delete任务或者查询任务的状态等。另外任务句柄还可以用于任务通信和同步的机制例如向任务发送信号量或消息。 在创建任务时通过调用 FreeRTOS 提供的任务创建函数例如 xTaskCreate()可以获取到相应任务的句柄。你可以将该句柄保存在一个变量中以便后续对该任务进行操作或引用。
任务句柄提供了一种有效的方式来管理和操作 FreeRTOS 中的任务。通过使用任务句柄可以方便地对任务进行控制和监视。 任务栈
图解 任务创建 static void prvInitialiseNewTask(…) 这个函数用于创建新的任务其中的 “prv” 表示该函数是一个私有函数只用于内部处理和初始化新任务的操作。对于外部使用者来说应该使用公开的 API 函数来创建和管理任务而不是直接调用 “prvInitialiseNewTask”。 这个函数被 TaskHandle_t xTaskCreateStatic() 函数调用 函数源代码如下
static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, /* 任务入口 */const char * const pcName, /* 任务名称字符串形式 */const uint32_t ulStackDepth, /* 任务栈大小单位为字 */void * const pvParameters, /* 任务形参 */TaskHandle_t * const pxCreatedTask, /* 任务句柄 */TCB_t *pxNewTCB ) /* 任务控制块指针 */{StackType_t *pxTopOfStack; //栈顶UBaseType_t x; /* 获取栈顶地址 */pxTopOfStack pxNewTCB-pxStack ( ulStackDepth - ( uint32_t ) 1 );//pxTopOfStack ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );/* 向下做8字节对齐 */pxTopOfStack ( StackType_t * ) ( ( ( uint32_t ) pxTopOfStack ) ( ~( ( uint32_t ) 0x0007 ) ) ); /* 将任务的名字存储在TCB中 */for( x ( UBaseType_t ) 0; x ( UBaseType_t ) configMAX_TASK_NAME_LEN; x ){pxNewTCB-pcTaskName[ x ] pcName[ x ];if( pcName[ x ] 0x00 ){break;}}/* 任务名字的长度不能超过configMAX_TASK_NAME_LEN */pxNewTCB-pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] \0;/* 初始化TCB中的xStateListItem节点 */vListInitialiseItem( ( pxNewTCB-xStateListItem ) );/* 设置xStateListItem节点的拥有者 */listSET_LIST_ITEM_OWNER( ( pxNewTCB-xStateListItem ), pxNewTCB );/* 初始化任务栈 */pxNewTCB-pxTopOfStack pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters ); /* 让任务句柄指向任务控制块 */if( ( void * ) pxCreatedTask ! NULL ){ *pxCreatedTask ( TaskHandle_t ) pxNewTCB;}
}初始化任务栈 StackType_t *pxPortInitialiseStack(…) 详细存储见下图 初始化任务栈的作用是保存当前上下文的任务信息以供我们后续任务切换所使用。 总结
任务控制块是存储任务信息的载体每个任务都有对应自己的任务控制块我们在创建完任务之后生成了任务对应的任务控制块我们所定义的对应任务句柄在任务创建完成之后就会指向我们的任务控制块相当于我们可以通过任务句柄间接去控制和管理我们的任务而任务栈则是一些寄存器的载体任务栈通过栈顶地址的加减去存储一些寄存器信息进而去设置任务的模式以及一些任务切换时所需要的信息例如将任务栈中的PC寄存器存储了该任务的函数指针在进行任务切换时就可以调出PC寄存器存储的信息进而找到相应的任务函数去执行任务栈也为该任务预留了一些寄存器的空间方便后面的使用。