FreeRTOS实时操作系统支持时间片示例详解
目录
- 什么是时间片
- 时间片实现关键
- taskSELECT_HIGHEST_PRIORITY_TASK()
- taskRESET_READY_PRIORITY()
什么是时间片
时间片就是同一个优先级下可以有多个任务,每个任务轮流地享有相同的 CPU 时间, 享有 CPU 的时间我们叫时间片。在 RTOS 中,最小的时间单位为一个 tick,即 SysTick 的中断周期,与其说 FreeRTOS 支持时间片,倒不如说它的时间片就是正常的任务调度。
时间片实现关键
时间片实现关键在这两个宏。
taskRESET_READY_PRIORITY()、
taskSELECT_HIGHEST_PRIORITY_TASK()
taskSELECT_HIGHEST_PRIORITY_TASK()
系统在任务切换的时候总会从就绪列表中寻找优先级最高的任务来执行,寻找优先级
最高的任务这个功能由 taskSELECT_HIGHEST_PRIORITY_TASK()函数来实现,该函数在
task.c 中定义,如下
#define taskSELECT_HIGHEST_PRIORITY_TASK()\ {\ UBaseType_t uxTopPriority;\ /* 寻找就绪任务的最高优先级 */\ portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority );\ /* 获取优先级最高的就绪任务的 TCB,然后更新到 pxCurrentTCB */\ listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB,\ &( pxReadyTasksLists[ uxTopPriority ] ) );\ }
先寻找就绪任务的最高优先级。即根据优先级位图表uxTopReadyPriority
找到就绪任务的最高优先级,然后将优先级暂存在uxTopPriority
获取优先级最高的就绪任务的 TCB,然后更新到 pxCurrentTCB
。这里关键在更新到pxCurrentTCB
的宏listGET_OWNER_OF_NEXT_ENTRY
,如下
#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList )\ {\ List_t * const pxConstList = ( pxList );\ /* 节点索引指向链表第一个节点调整节点索引指针,指向下一个节点, 如果当前链表有 N 个节点,当第 N 次调用该函数时, pxIndex 则指向第 N 个节点 */\ ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;\ /* 当遍历完链表后, pxIndex 回指到根节点 */\ if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) )\ {\ ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;\ }\ /* 获取节点的 OWNER,即 TCB */\ ( pxTCB ) = ( pxConstList )->pxIndex->pvOwner;\ }
关键在下面这句,下面看图比较好说明
( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;
对于优先级2,当第一次执行listGET_OWNER_OF_NEXT_ENTRY后,pxIndex
指向Task1TCB->xStateListItem,所以pvOwner
取到的是Task1TCB
赋值给pxCurrentTCB
.
对于优先级2,当第二次执行listGET_OWNER_OF_NEXT_ENTRY前,注意此时pxIndex
指向Task1TCB->xStateListItem,所以( pxConstList )->pxIndex->pxNext;是Task2TCB->xStateListItem,所以这次pvOwner
取到的是Task2TCB
赋值给pxCurrentTCB
.
对于优先级2,当第三次执行listGET_OWNER_OF_NEXT_ENTRY前,注意此时pxIndex
指向Task2TCB->xStateListItem,这时符合上面的if
条件了,所以( pxConstList )->pxIndex->pxNext;是Task1TCB->xStateListItem,所以这次pvOwner
取到的是Task1TCB
赋值给pxCurrentTCB
.
这样就实现了同一优先级下的任务时间片轮流执行。
taskRESET_READY_PRIORITY()
#define taskRESET_READY_PRIORITY( uxPriority )\ {\ if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) )\ == ( UBaseType_t ) 0 )\ {\ portRESET_READY_PRIORITY( ( uxPriority ),\ ( uxTopReadyPriority ) );\ }\ }
taskRESET_READY_PRIORITY()函数的妙处在于清除优先级位图表uxTopReadyPriority
中相应的位时候,会先判断当前优先级链表下是否还有其它任务,如果有则不清零。 假设任务1会调用 vTaskDelay()
,会将自己挂起,只能是将任务1从就绪列表删除,不能将任务1在优先级位图表uxTopReadyPriority
中对应的位清0,因为该优先级下还有任务2,否则任务2将得不到执行.
以上就是FreeRTOS支持时间片示例详解的详细内容,更多关于FreeRTOS支持时间片的资料请关注我们其它相关文章!