FreeRTOS 笔记之⑧:任务延时列表的实现

目录

1. 任务延时列表的工作原理

2. 实现任务延时列表

2.1 定义任务延时列表

2.2 任务延时列表初始化

2.3 定义xNextTaskUnblockTime


在本章之前,为了实现任务的阻塞延时,在任务控制块中内置了一个延时变量xTicksToDelay。每当任务需要延时的时候,就初始化xTicksToDelay需要延时的时间,然后将任务挂起,这里的挂起只是将任务在优先级位图表uxTopReadyPriority中对应的位清零,并不会将任务从就绪列表中删除。当每次时基中断(SysTick中断)来临时,就扫描就绪列表中的每个任务的xTicksToDelay,如果xTicksToDelay大于0则递减一次,然后判断xTicksToDelay是否为0,如果为0则表示延时时间到,将该任务就绪(即将任务在优先级位图表uxTopReadyPriority中对应的位置位),然后进行任务切换。这种延时的缺点是,在每个时基中断中需要对所有任务都扫描一遍,费时,优点是容易理解。这种方法其实也是大多数人的常规操作。之所以先这样讲解是为了慢慢地过度到FreeRTOS任务延时列表的讲解。

1. 任务延时列表的工作原理

在FreeRTOS中,有一个任务延时列表(实际上有两个,为了方便讲解原理,我们假装合并为一个,其实两个的作用是一样的),当任务需要延时的时候,则先将任务挂起,即先将任务从就绪列表删除,然后插入到任务延时列表,同时更新下一个任务的解锁时刻变量:xNextTaskUnblockTime的值。

xNextTaskUnblockTime的值等于系统时基计数器的值xTickCount加上任务需要延时的值xTicksToDelay。当系统时基计数器xTickCount的值与xNextTaskUnblockTime相等时,就表示有任务延时到期了,需要将该任务就绪。与RT-Thread和μC/OS在解锁延时任务时要扫描定时器列表这种时间不确定性的方法相比,FreeRTOS这个xNextTaskUnblockTime全局变量设计的非常巧妙。

任务延时列表表维护着一条双向链表,每个节点代表了正在延时的任务,节点按照延时时间大小做升序排列。当每次时基中断(SysTick中断)来临时,就拿系统时基计数器的值xTickCount与下一个任务的解锁时刻变量xNextTaskUnblockTime的值相比较,如果相等,则表示有任务延时到期,需要将该任务就绪,否则只是单纯地更新系统时基计数器xTickCount的值,然后进行任务切换。

FreeRTOS 笔记之⑧:任务延时列表的实现_第1张图片

2. 实现任务延时列表

2.1 定义任务延时列表

任务延时列表在task.c中定义

static List_t xDelayedTaskList1;
static List_t xDelayedTaskList2;
static List_t * volatile pxDelayedTaskList;
static List_t * volatile pxOverflowDelayedTaskList;
  • FreeRTOS定义了两个任务延时列表,当系统时基计数器xTickCount没有溢出时,用一条列表,当xTickCount溢出后,用另外一条列表

  • 任务延时列表指针,指向xTickCount没有溢出时使用的那条列表

  • 任务延时列表指针,指向xTickCount溢出时使用的那条列表。

2.2 任务延时列表初始化

任务延时列表属于任务列表的一种,在prvInitialiseTaskLists()函数中初始化

/* 初始化任务相关的列表 */
void prvInitialiseTaskLists( void )
{
    UBaseType_t uxPriority;
    
    /* 初始化就绪列表 */
    for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ )
	{
		vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) );
	}
    
    vListInitialise( &xDelayedTaskList1 );
	vListInitialise( &xDelayedTaskList2 );
    
    pxDelayedTaskList = &xDelayedTaskList1;
	pxOverflowDelayedTaskList = &xDelayedTaskList2;
}

2.3 定义xNextTaskUnblockTime

xNextTaskUnblockTime是一个在task.c中定义的静态变量,用于表示下一个任务的解锁时刻。xNextTaskUnblockTime的值等于系统时基计数器的值xTickCount加上任务需要延时值xTicksToDelay。当系统时基计数器xTickCount的值与xNextTaskUnblockTime相等时,就表示有任务延时到期了,需要将该任务就绪。

xNextTaskUnblockTime在vTaskStartScheduler()函数中初始化为portMAX_DELAY(portMAX_DELAY是一个portmacro.h中定义的宏,默认为0xffffffffUL)

从上面原理提到可以知道xNextTaskUnblockTime 对于任务延时实现起到了很大的作用,也减少不定时扫描带了的不确定开销。具体实现,见官方源码。

你可能感兴趣的:(FreeRTOS,嵌入式开发)