9.1 PendSV 异常
PendSV(可挂起的系统调用)异常对 OS 操作非常重要,其优先级可以通过编程设置。可以 通过将中断控制和壮态寄存器 ICSR 的 bit28,也就是 PendSV 的挂起位置 1 来触发 PendSV 中 断。与 SVC 异常不同,它是不精确的,因此它的挂起状态可在更高优先级异常处理内设置,且会在高优先级处理完成后执行。
若将 PendSV 设置为最低的异常优先级,可以让 PendSV 异常处理在所有其他 中断处理完成后执行,这对于上下文切换非常有用
上下文切换被触发的场合可以是:
⚫ 执行一个系统调用
⚫ 系统滴答定时器(SysTick)中断
在 OS 中,任务调度器决定是否应该执行上下文切换,如图 9.1.1 中任务切换都是由 SysTick 中断中执行,每次它都会决定切换到一个不同的任务中。
若中断请求(IRQ)在 SysTick 异常前产生,则 SysTick 异常可能会抢占 IRQ 的处理,在这种 情况下,OS 不应该执行上下文切换,否则中断请求 IRQ 处理就会被延迟,而且在真实系统中 延迟时间还往往不可预知——任何有一丁点实时要求的系统都决不能容忍这种事。对于 CortexM3 和 Cortex-M4 处理器,当存在活跃的异常服务时,设计默认不允许返回到线程模式,若存在 活跃中断服务,且 OS 试图返回到线程模式,则将触发用法 fault
在一些 OS 设计中,要解决这个问题,可以在运行中断服务时不执行上下文切换,此时可 以检查栈帧中的压栈 xPSR 或 NVIC 中的中断活跃壮态寄存器。不过,系统的性能可能会受到 影响,特别时当中断源在 SysTick 中断前后持续产生请求时,这样上下文切换可能就没有执行的机会了。
为了解决这个问题,PendSV 异常将上下文切换请求延迟到所有其他 IRQ 处理都已经完成后,此时需要将 PendSV 设置为最低优先级。若 OS 需要执行上下文切换,他会设置 PendSV 的挂起状态,并在 PendSV 异常内执行上下文切换。
9.2 FreeRTOS 任务切换场合
上下文(任务)切换被触发的场合:● 可以执行一个系统调用 ● 系统滴答定时器(SysTick)中断。
执行系统调用
执行系统调用就是执行 FreeRTOS系统提供的相关API函数,比如任务切换函数 taskYIELD(), FreeRTOS 有些 API 函数也会调用函数 taskYIELD(),这些 API 函数都会导致任务切换,这些 API 函数和任务切换函数 taskYIELD()都统称为系统调用。
系统滴答定时器(SysTick)中断
FreeRTOS 中滴答定时器(SysTick)中断服务函数中也会进行任务切换,滴答定时器中断服务函数如下:
在滴答定时器中断服务函数中调用了 FreeRTOS 的 API 函数 xPortSysTickHandler(),此函数 源码如下:
void xPortSysTickHandler( void )
{
vPortRaiseBASEPRI(); (1)
{
if( xTaskIncrementTick() != pdFALSE ) //增加时钟计数器 xTickCount 的值
{
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; (2)
}
}
vPortClearBASEPRIFromISR(); (3)
}
(1)、关闭中断
(2)、通过向中断控制和壮态寄存器 ICSR 的 bit28 写入 1 挂起 PendSV 来启动 PendSV 中 断。
这样就可以在 PendSV 中断服务函数中进行任务切换了。
(3)、开启中断
标签:函数,FreeRTOS,第九章,中断,PendSV,切换,SysTick,上下文 From: https://blog.csdn.net/qq_45150278/article/details/143484042