下面我们详细的介绍这个数据结构的主要成员:
指针pxTopOfStack必须位于结构体的第一项,指向当前堆栈的栈顶,对于向下增长的堆栈,pxTopOfStack总是指向最后一个入栈的项目。
如果使用MPU,xMPUSettings必须位于结构体的第二项,用于MPU设置。
接下来是状态列表项xStateListItem和事件列表项xEventListItem,我们在上一章介绍列表和列表项的文章中提到过:列表被FreeRTOS调度器使用,用于跟踪任务,处于就绪、挂起、延时的任务,都会被挂接到各自的列表中。调度器就是通过把任务TCB中的状态列表项xStateListItem和事件列表项xEventListItem挂接到不同的列表中来实现上述过程的。在task.c中,定义了一些静态列表变量,其中有就绪、阻塞、挂起列表,例如当某个任务处于就绪态时,调度器就将这个任务TCB的xStateListItem列表项挂接到就绪列表。事件列表项也与之类似,当队列满的情况下,任务因入队操作而阻塞时,就会将事件列表项挂接到队列的等待入队列表上。
uxPriority用于保存任务的优先级,0为最低优先级。任务创建时,指定的任务优先级就被保存到该变量中。
指针pxStack指向堆栈的起始位置,任务创建时会分配指定数目的任务堆栈,申请堆栈内存函数返回的指针就被赋给该变量。很多刚接触FreeRTOS的人会分不清指针pxTopOfStack和pxStack的区别,这里简单说一下:pxTopOfStack指向当前堆栈栈顶,随着进栈出栈,pxTopOfStack指向的位置是会变化的;pxStack指向当前堆栈的起始位置,一经分配后,堆栈起始位置就固定了,不会被改变了。那么为什么需要pxStack变量呢,这是因为随着任务的运行,堆栈可能会溢出,在堆栈向下增长的系统中,这个变量可用于检查堆栈是否溢出;如果在堆栈向上增长的系统中,要想确定堆栈是否溢出,还需要另外一个变量pxEndOfStack来辅助诊断是否堆栈溢出,后面会讲到这个变量。
字符数组pcTaskName用于保存任务的描述或名字,在任务创建时,由参数指定。名字的长度由宏configMAX_TASK_NAME_LEN(位于FreeRTOSConfig.h中)指定,包含字符串结束标志。
如果堆栈向上生长(portSTACK_GROWTH > 0),指针pxEndOfStack指向堆栈尾部,用于检验堆栈是否溢出。freertos 任务
变量uxCriticalNesting用于保存临界区嵌套深度,初始值为0。
接下来两个变量用于可视化追踪,仅当宏configUSE_TRACE_FACILITY(位于FreeRTOSConfig.h中)为1时有效。变量uxTCBNumber存储一个数值,在创建任务时由内核自动分配数值(通常每创建一个任务,值增加1),每个任务的uxTCBNumber值都不同,主要用于调试。变量uxTaskNumber用于存储一个特定值,与变量uxTCBNumber不同,uxTaskNumber的数值不是由内核分配的,而是通过API函数vTaskSetTaskNumber()来设置的,数值由函数参数指定。
如果使用互斥量(configUSE_MUTEXES == 1),任务优先级被临时提高时,变量uxBasePriority用来保存任务原来的优先级。
变量ucStaticAllocationFlags也需要说明一下,我们前面说过任务创建API函数xTaskCreate()只能使用动态内存分配的方式创建任务堆栈和任务TCB,如果要使用静态变量实现任务堆栈和任务TCB就需要使用函数xTaskGenericCreate()来实现。如果任务堆栈或任务TCB由静态数组和静态变量实现,则将该变量设置为pdTRUE(任务堆栈空间由静态数组变量实现时为0x01,任务TCB由静态变量实现时为0x02,任务堆栈和任务TCB都由静态变量实现时为0x03),如果堆栈是动态分配的,则将该变量设置为pdFALSE。
到这里任务TCB的数据结构就讲完了,下面我们用一个例子来讲述任务创建的过程,为方便起见,假设被创建的任务叫“任务A”,任务函数为vTask_A():
TaskHandle_t xHandle;
xTaskCreate(vTask_A,”Task A”,120,NULL,1,&xHandle);
这里创建了一个任务,任务优先级为1,由于硬件平台是32为架构,所以指定了120*4=480字节的任务堆栈,向任务函数vTask_A()传递的参数为空(NULL),任务句柄由变量xHandle保存。当这个语句执行后,任务A被创建并加入就绪任务列表,我们这章的主要目的,就是看看这个语句在执行过程中,发生了什么事情。
如果上面的步骤都正确执行,并且调度器也开始工作,则判断当前任务的优先级是否大于新创建的任务优先级。如果新创建的任务优先级更高,则调用taskYIELD_IF_USING_PREEMPTION()强制进行一次上下文切换,切换后,新创建的任务将获得CPU控制权,精简后的代码如下所示。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-33582-3.html
美国人说
许多女人一生嫁过数个男人
~