学习RTOS(6)空闲任务与阻塞延时

RTOS 中的延时叫阻塞延时,即任务需要延时的时候,任务会放弃 CPU 的使用权, CPU 可以去干其它的事情,当任务延时时间到,重新获取 CPU 使用权,任务继续运行,这样就充分地利用了 CPU 的资源,而不是干等着。当任务需要延时,进入阻塞状态,那 CPU 又去干什么事情了?如果没有其它任务可以运行, RTOS 都会为 CPU 创建一个空闲任务,这个时候 CPU 就运行空闲任务。 在FreeRTOS 中,空闲任务是系统在【启动调度器】的时候创建的优先级最低的任务,空闲任务主体主要是做一些系统内存的清理工作。

定义空闲任务
在这里插入图片描述
在这里插入图片描述

代码清单 9-3(1) :获取空闲任务的内存,即将 pxIdleTaskTCBBuffer 和pxIdleTaskStackBuffer 这两个接下来要作为形参传到 xTaskCreateStatic()函数的指针分别指向空闲任务的 TCB 和栈的起始地址,这个操作由函数 vApplicationGetIdleTaskMemory()来实现,该函数需要用户自定义,目前我们在 main.c 中实现。
代码清单 9-3(2) : 调用 xTaskCreateStatic()函数创建空闲任务。
代码清单 9-3(3) :将空闲任务插入到就绪列表的开头。 在下一章我们会支持优先级,空闲任务默认的优先级是最低的,即排在就绪列表的开头。

实现阻塞延时

阻塞延时的阻塞是指任务调用该延时函数后, 任务会被剥离 CPU 使用权,然后进入阻塞状态,直到延时结束, 任务重新获取 CPU 使用权才可以继续运行。在任务阻塞的这段时间, CPU 可以去执行其它的任务,如果其它的任务也在延时状态,那么 CPU 就将运行空闲任务。阻塞延时函数在 task.c 中定义。
在这里插入图片描述

代码清单 9-5 (1): 获取当前任务的任务控制块。 pxCurrentTCB 是一个在 task.c 定义的全局指针,用于指向当前正在运行或者即将要运行的任务的任务控制块。
代码清单 9-5 (2): xTicksToDelay 是任务控制块的一个成员,用于记录任务需要延时的时间,单位为 SysTick 的中断周期。比如 SysTick 的中断周期为 10ms,调用 vTaskDelay( 2 )则完成 2*10ms 的延时。 xTicksToDelay 定义具体见代码清单 9-6 的加粗部分。
在这里插入图片描述

代码清单 9-5 (3):任务切换。 调用 tashYIELD()会产生 PendSV 中断,在 PendSV 中断服务函数中会调用上下文切换函数 vTaskSwitchContext(),该函数的作用是寻找最高优先级的就绪任务,然后更新 pxCurrentTCB。
在这里插入图片描述

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

xTaskIncrementTick()函数

更新系统时基,该函数在 task.c 中定义。
在这里插入图片描述

代码清单 9-9(1): 更新系统时基计数器 xTickCount, 加一操作。 xTickCount 是一个在port.c 中定义的全局变量, 在函数 vTaskStartScheduler()中调用 xPortStartScheduler()函数前初始化。
代码清单 9-9(2): 扫描就绪列表中所有任务的 xTicksToDelay,如果不为 0,则减 1。
代码清单 9-9(3): 执行一次任务切换。

SysTick 初始化函数
SysTick 的中断服务函数要想被顺利执行,则 SysTick 必须先初始化。 SysTick 初始化函数在 port.c 中定义。
在这里插入图片描述
在这里插入图片描述

代码清单 9-10(1):配置 SysTick 需要用到的寄存器和宏定义,在 port.c 中实现。
代 码 清 单 9-10(2) : SysTick 初 始 化 函 数 vPortSetupTimerInterrupt() , 在xPortStartScheduler()中被调用。
代码清单 9-10(2)-①:设置重装载寄存器的值, 决定 SysTick 的中断周期。从代码清单 9-10(1) 可 以知道:如果没有定义configSYSTICK_CLOCK_HZ 那 么configSYSTICK_CLOCK_HZ就等于configCPU_CLOCK_HZ ,configSYSTICK_CLOCK_HZ 确实没有定义,则 configSYSTICK_CLOCK_HZ 由在FreeRTOSConfig.h 中定义的 configCPU_CLOCK_HZ 决定, 同时 configTICK_RATE_HZ 也在FreeRTOSConfig.h 中定义。在这里插入图片描述

代码清单 9-12(1):系统时钟的大小,因为目前是软件仿真,需要配置成与system_ARMCM3.c(system_ARMCM4.c 或 system_ARMCM7.c)文件中的 SYSTEM_CLOCK的一样, 即等于 25M。如果有具体的硬件,则配置成与硬件的系统时钟一样。
代码清单 9-12(2): SysTick 每秒中断多少次,目前配置为 100,即每 10ms 中断一次。
代码清单 9-10(2)-②:设置系统定时器的时钟等于内核时钟,使能 SysTick 定时器中断,使能 SysTick 定时器。
在这里插入图片描述
在这里插入图片描述

6.320191 - 6.300191 = 20ms 和预期中的20ms中断一致。其实也就是时间切片,只不过我们是由习惯的软件操作,变成了硬件操作。
Hankin
2020.08.21

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值