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)恢复下文。

具体流程如下:

  1. 触发任务切换异常(PendSV中断)后,硬件自动使用PSP堆栈指针将寄存器xPSR、PC、LR、R12、R3-R0压入任务对战
  2. 进入异常后,CPU使用MSP。
  3. 寄存器R11-R4,通过软件使用PSP压栈。
  4. 进入临界区。
  5. 调用vTaskSwitchContext()函数找出下一个要执行的任务更新到pxCurrentTCB
  6. 退出临界。
  7. 通过pxCurrentTCB获取到新的任务栈顶。
  8. 使用新的任务栈顶指针出栈R11-R4。
  9. 更新当前任务栈顶指针到PSP。
  10. 退出异常,硬件使用PSP出栈xPSR、PC、LR、R12、R3-R0。
  11. 进入新的任务了。

   
三、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. 方案1:检查任务栈顶指针。如果任务上文压栈后,任务栈顶pxCurrentTCB->pxTopOfStack比栈起始pxCurrentTCB->pxStack还小,说明已经栈溢出了。

  2. 方案2:栈起始内容检查。初始化时,把任务栈其实pxCurrentTCB->pxStack一部分栈内存初始化为特定的值。在每次任务切换时,检查下这几个值是否为原有值,如果不是,说明被踩栈了;如果不是,可初步判断任务栈安全(不能绝对判断当前任务栈安全)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值