任务切换
受博客限制,如果您想获得更好的阅读体验,请前往https://github.com/Nrusher/FreeRTOS-Book或者https://gitee.com/nrush/FreeRTOS-Book下载PDF版本阅读,如果您觉得本文不错也可前往star,以示对作者的鼓励。如发现问题欢迎交流。
任务切换的目的是保证当前具有最高优先级的就绪任务获得处理器的使用权。在进行任务切换时,首先需要找到具有最高优先级的就绪任务,如果该任务不是当前正在运行的任务,需要先保存当前运行任务的堆栈,并将具有最高优先级的就绪任务堆栈恢复到处理器的堆栈中进行运行。
寻找拥有最高优先级的就绪任务
如何寻找具有最高优先级的就绪任务?根据本章前文对结构体和变量的以及任务创建过程的分析可知,所有的就绪任务都是挂载在一个链表数组pxReadyTasksLists中的,链表数组的下标代表了任务的优先级,同一个链表下挂接的任务具有相同的优先级,在任务切换过程中,它们将轮流的获得处理器的使用权。如此一来只需要在向pxReadyTasksLists添加或删除任务时,记录变动任务后处于就绪态任务的最高优先级即可获得待运行的任务。最高优先级被记录在uxTopReadyPriority这一变量中,宏函数taskRECORD_READY_PRIORITY( uxPriority )实现了在添加任务时记录最高优先级这一过程,
// 记录最高先级的就绪任务的优先级
#define taskRECORD_READY_PRIORITY( uxPriority )\
{ \
if( ( uxPriority ) > uxTopReadyPriority ) \
{ \
uxTopReadyPriority = ( uxPriority ); \
} \
} /* taskRECORD_READY_PRIORITY */
根据最高优先级获得要运行任务的过程由宏函数taskSELECT_HIGHEST_PRIORITY_TASK()实现,寻找到的拥有最高优先级的待运行任务会被存储到pxCurrentTCB变量中,其具体实现如下
#define taskSELECT_HIGHEST_PRIORITY_TASK() \
{ \
UBaseType_t uxTopPriority = uxTopReadyPriority; \
\
/* step1 */ \
while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopPriority ] ) ) ) \
{
\
configASSERT( uxTopPriority ); \
--uxTopPriority; \
} \
\
/* step2 */ \
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) );\
uxTopReadyPriority = uxTopPriority; \
} /* taskSELECT_HIGHEST_PRIORITY_TASK */
插入操作导致的就绪任务优先级变动由taskRECORD_READY_PRIORITY( uxPriority )进行了处理,删除任务导致的任务优先级变化则在taskSELECT_HIGHEST_PRIORITY_TASK()中的step1被处理了。step2中listGET_OWNER_OF_NEXT_ENTRY()函数在分析链表时已经进行解析,其会循环遍历链表中的每一个任务,因此最高优先级下的所有任务会平均的共享处理器的使用权。
以上所说的是通用版本的做法,除此方法外,FreeRTOS还提供了一套经过优化的,用来记录和寻找最高优先级的方法。对于crotex-m3为内核的平台,其借助特殊指令clz(从最高位开始,计算一个整型变量0的个数),实现bit map方法,以此提高程序运行的效率,在优化版本下,上述函数的代码如下
// 经过特殊优化的方法,依赖硬件
// 这里不在使用数值大小来表示最高优先级,而是使用每一位表示是否有该优先级的任务处于就绪态,对于cortex-m3有32位,如
// 0000 0000 0000 0000 0000 0000 0000 0001 表示第0级有就绪态的任务
#de

本文深入探讨了FreeRTOS操作系统在cortex-m3平台上的任务切换机制,详细解析了任务切换的目的、过程及关键函数,包括如何寻找最高优先级的就绪任务、任务切换的触发方式以及具体的汇编级代码实现。
最低0.47元/天 解锁文章
1640





