freertos空闲任务和阻塞延时

使用 RTOS 的很大优势就是榨干 CPU 的性能,永远不能让它闲着,任务如果需要延时也就不能再让 CPU 空等来实现延时的效果。RTOS 中的延时叫阻塞延时,即任务需要延时的时候,任务会放弃 CPU 的使用权,CPU 可以去干其它的事情,当任务延时时间到,重新获取 CPU 使用权,任务继续运行,这样就充分地利用了 CPU 的资源,而不是干等着。

当任务需要延时,进入阻塞状态,那 CPU 又去干什么事情了?如果没有其它任务可以运行,RTOS 都会为 CPU 创建一个空闲任务,这个时候 CPU 就运行空闲任务。在FreeRTOS 中,空闲任务是系统在【启动调度器】的时候创建的优先级最低的任务空闲任务主体主要是做一些系统内存的清理工作

一、实现空闲任务

1.1定义空闲任务栈

1 /* 定义空闲任务的栈 */
2 #define configMINIMAL_STACK_SIZE  ( ( unsigned short ) 128 ) (2)
3 StackType_t IdleTaskStack[configMINIMAL_STACK_SIZE]; (1)

1.2 定义空闲任务控制块

/* 定义空闲任务的任务控制块 */
2 TCB_t IdleTaskTCB;

1.3 创建空闲任务
空闲任务在调度器启动函数 vTaskStartScheduler()中创建

二、实现阻塞延时

2.1 vTaskDelay ()函数
阻塞延时的阻塞是指任务调用该延时函数后,任务会被剥离 CPU 使用权,然后进入阻塞状态,直到延时结束,任务重新获取 CPU 使用权才可以继续运行。在任务阻塞的这段时间,CPU 可以去执行其它的任务,如果其它的任务也在延时状态,那么 CPU 就将运行空闲任务。

1 void vTaskDelay( const TickType_t xTicksToDelay )
2 {
3 TCB_t *pxTCB = NULL;
4 
5 /* 获取当前任务的 TCB */
6 pxTCB = pxCurrentTCB; (1)
7 
8 /* 设置延时时间 */
9 pxTCB->xTicksToDelay = xTicksToDelay; (2)    //xTicksToDelay 是任务控制块的一个成员,用于记录任务需要延时的时间,单位为 SysTick 的中断周期
10 
11 /* 任务切换 */
12 taskYIELD(); (3)
13 }

2.2 修改 vTaskSwitchContext()函数,任务切换函数

 void vTaskSwitchContext( void ) 
16 { 
17 /* 如果当前任务是空闲任务,那么就去尝试执行任务 1 或者任务 2, 
18 看看他们的延时时间是否结束,如果任务的延时时间均没有到期, 
19 那就返回继续执行空闲任务 */ 
20 if ( pxCurrentTCB == &IdleTaskTCB ) (1) 
21 { 
22 if (Task1TCB.xTicksToDelay == 0) 
23 { 
24 pxCurrentTCB =&Task1TCB; 
25 } 
26 else if (Task2TCB.xTicksToDelay == 0) 
27 { 
28 pxCurrentTCB =&Task2TCB; 
29 } 
30 else 
31 { 
32 return; /* 任务延时均没有到期则返回,继续执行空闲任务 */ 
33 } 
34 } 
35 else /* 当前任务不是空闲任务则会执行到这里 */ (2) 
36 { 
37 /*如果当前任务是任务 1 或者任务 2 的话,检查下另外一个任务, 
38 如果另外的任务不在延时中,就切换到该任务 
39 否则,判断下当前任务是否应该进入延时状态, 
40 如果是的话,就切换到空闲任务。否则就不进行任何切换 */ 
41 if (pxCurrentTCB == &Task1TCB) 
42 { 
43 if (Task2TCB.xTicksToDelay == 0) 
44 { 
45 pxCurrentTCB =&Task2TCB; 
46 } 
47 else if (pxCurrentTCB->xTicksToDelay != 0) 
48 { 
49 pxCurrentTCB = &IdleTaskTCB;
50 } 
51 else 
52 { 
53 return; /* 返回,不进行切换,因为两个任务都处于延时中 */ 
54 } 
55 } 
56 else if (pxCurrentTCB == &Task2TCB) 
57 { 
58 if (Task1TCB.xTicksToDelay == 0) 
59 { 
60 pxCurrentTCB =&Task1TCB; 
61 } 
62 else if (pxCurrentTCB->xTicksToDelay != 0) 
63 { 
64 pxCurrentTCB = &IdleTaskTCB; 
65 } 
66 else 
67 { 
68 return; /* 返回,不进行切换,因为两个任务都处于延时中 */ 

代码清单 9-7(1):如果当前任务是空闲任务,那么就去尝试执行任务 1 或者任务 2,
看看他们的延时时间是否结束,如果任务的延时时间均没有到期,那就返回继续执行空闲
任务。

代码清单 9-7(2):如果当前任务是任务 1 或者任务 2 的话,检查下另外一个任务,如
果另外的任务不在延时中,就切换到该任务
。否则,判断下当前任务是否应该进入延时状
态,如果是的话,就切换到空闲任务,否则就不进行任何切换

三 、SysTick 中断服务函数

在任务上下文切换函数 vTaskSwitchContext ()中,会判断每个任务的任务控制块中的延时成员 xTicksToDelay 的值是否为 0,如果为 0就要将对应的任务就绪,如果不为 0 就继续延时。如果一个任务要延时,一开始 xTicksToDelay 肯定不为 0,当 xTicksToDelay 变为0 的时候表示延时结束,那么xTicksToDelay 是以什么周期在递减?在哪里递减?在FreeRTOS 中,这个周期由 SysTick 中断提供,操作系统里面的最小的时间单位就是SysTick 的中断周期。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值