目录
基于freertos的嵌入式系统开发(九)FreeRTOS的全局变量
freertos对全局变量加上互斥,主要是防止两个任务同时对这个全局变量修改和读取,导致任务之间的数据出现错误,所以一般都是要加上对应的互斥量的
当前TCB指针pxCurrentTCB
该指针指向当前运行任务的任务控制块,定义如下:
PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL;
该指针在任务建立、调度和删除等程序段都会用到,例如在恢复上下文宏中:
首先就要通过pxCurrentTCB 获取当前TCB的指针,然后从TCB中出栈各个寄存器的值,恢复到各个寄存器中,最后在恢复该任务的运行。
就绪任务列表pxReadyTasksList
就绪任务列表是一个 List_t 类型的数组,数组大小由系统配置的最大任务优先级的宏 configMAX_PRIORITIES 决定,目前在配置文件中默认定义为5。最大支持256个优先级,数组的下标就对应了任务的优先级,同一优先级的任务统一插入到就绪列表的同一条链表中,任务就绪列表定义:
PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ];
每个优先级,对应pxReadyTasksLists的一相,都有一条链表。例如在taskSELECT_HIGHEST_PRIORITY_TASK宏中:
#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() */
pxReadyTasksLists[ uxTopPriority ] 就是优先级为uxTopPriority 的就绪任务列表,所以,在小ram空间的处理器中,最大优先级不要设置的太大,越大对内存需求越多。
阻塞任务列表xDelayedTaskList1和xDelayedTaskList2
需要阻塞的任务都挂载到延时列表上,至于为什么需要xDelayedTaskList1和xDelayedTaskList2两个链表,主要是因为FreeRTOS内核时钟节拍xTickCount是TickType_t 类型的变量,而xTickCount存在溢出的情况,所以用两条列表交替使用来解决了时钟节拍溢出的问题
PRIVILEGED_DATA static List_t xDelayedTaskList1; //延时列表1
PRIVILEGED_DATA static List_t xDelayedTaskList2; //延时列表2
其中PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList; 指向延时没有溢出列表,而
PRIVILEGED_DATA static List_t * volatile pxOverflowDelayedTaskList; 则指向延时溢出列表
xTickCount 的定义如下:
PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;
例如在在32位系统中,TickType_t是一个32位无符号的整型数据,最大值是0xFFFFFFFF,当xTickCount 溢出时,只需要切换延时任务列表就可以了。
挂起任务列表xPendingReadyList
处于挂起态的任务,对调度器而言是不可见的,让一个任务进入挂起状态的唯一办法就是调用 vTaskSuspend()函数;而把一个挂起状态的任务恢复的唯一途径就是调用 vTaskResume() 或vTaskResumeFromISR()函数,我们看vTaskSuspend的部分实现代码:
其首先要做的就是进入临界区,将task从ready/delayed 的链表中移除,放入挂起链表,在任务挂起期间,就绪的任务暂时挂载到此列表上。待任务恢复以后,才可以将此列表中的任务移到就绪列表中,定义如下:
PRIVILEGED_DATA static List_t xPendingReadyList;
当任务调度器启动之后,如果某个任务调用了vTaskSuspend函数,就挂起了该任务,系统会将其添加到挂起态任务列表xPendingReadyList,此时任务进入挂起状态,直到调用vTaskResume函数解除。