FreeRTOS任务切换
一、PendSV 异常
PendSV(Pended Service Call,可挂起服务调用),PendSV的中断优先级是可以编程的,用户可以根据实际的需求,对其进行配置。PendSV 与 SVC 不同,PendSV 的中断是非实时的,即 PendSV 的中断可以在更高优先级的中断中触发,但是在更高优先级中断结束后才执行。
任务切换概念:在典型的 RTOS 中,任务的处理时间被分为多个时间片,OS 内核的执行可以有两种触发方式,一种是通过在应用任务中通过 SVC 指令触发,例如在应用任务在等待某个时间发生而需要停止的时候,那么就可以通过 SVC 指令来触发 OS内核的执行,以切换到其他任务;第二种方式是,SysTick 周期性的中断,来触发 OS 内核的执行。
二、PendSV 中断服务函数
????????FreeRTOS 在 PendSV 的中断中,完成任务切换,PendSV 的中断服务函数由 FreeRTOS 编
写,将 PendSV 的中断服务函数定义成函数 xPortPendSVHandler()。
? ? ? ? 针 对 ARM Cortex-M3 和 针 对 ARM Cortex-M4 和 ARM Cortex-M7 内 核 的 函 数xPortPendSVHandler()稍有不同,其主要原因在于 ARM Cortex-M4 和 ARM Cortex-M7 内核具有
浮点单元,因此在进行任务切换的时候,还需考虑是否保护和恢复浮点寄存器的值
任务切换的大概内容:(1)保存上文。(2)恢复下文。
具体流程如下:
- 触发任务切换异常(PendSV中断)后,硬件自动使用PSP堆栈指针将寄存器xPSR、PC、LR、R12、R3-R0压入任务对战
- 进入异常后,CPU使用MSP。
- 寄存器R11-R4,通过软件使用PSP压栈。
- 进入临界区。
- 调用
vTaskSwitchContext()
函数找出下一个要执行的任务更新到pxCurrentTCB
。 - 退出临界。
- 通过
pxCurrentTCB
获取到新的任务栈顶。 - 使用新的任务栈顶指针出栈R11-R4。
- 更新当前任务栈顶指针到PSP。
- 退出异常,硬件使用PSP出栈xPSR、PC、LR、R12、R3-R0。
- 进入新的任务了。
? ?
三、FreeRTOS 确定下一个要运行的任务
在 PendSV 的中断服务函数中,调用了函数 vTaskSwitchContext()来确定写一个要运行的任务。
四、PendSV 异常何时触发
调用函数 portYIELD()
#define portYIELD() \
{ \
/* 设置中断控制状态寄存器,以触发 PendSV 异常 */ \
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
\
__dsb( portSY_FULL_READ_WRITE ); \
__isb( portSY_FULL_READ_WRITE ); \
}
五、溢出检查
任务切换时会对任务栈进行检查,是否溢出。taskCHECK_FOR_STACK_OVERFLOW();
有两种方案可检查栈溢出,可同时使用:(以堆栈向下生长为例)
-
方案1:检查任务栈顶指针。如果任务上文压栈后,任务栈顶
pxCurrentTCB->pxTopOfStack
比栈起始pxCurrentTCB->pxStack
还小,说明已经栈溢出了。 -
方案2:栈起始内容检查。初始化时,把任务栈其实
pxCurrentTCB->pxStack
一部分栈内存初始化为特定的值。在每次任务切换时,检查下这几个值是否为原有值,如果不是,说明被踩栈了;如果不是,可初步判断任务栈安全(不能绝对判断当前任务栈安全)
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!