PendSV异常
问题:
- 怎么触发PendSV异常?
- 何时使用MSP何时切换PSP?
- PendSV如何实现上下文切换?
1. 触发PendSV异常
在RTOS内核中,任务切换的原理是:手动触发PendSV异常,在PendSV异常服务函数中实现任务切换。
freeRTOS有两种方式触发PendSV异常,一种是通过调用portYIELD()
, 另一种是在Systick_Handler()
中时基增加出现上下文切换请求。
触发PendSV异常的方法在task.h
中的
#define portYIELD() \
{ \
\
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
}
以及port.c
中的
void xPortSysTickHandler( void )
{
portDISABLE_INTERRUPTS();
{
if( xTaskIncrementTick() != pdFALSE )
{
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
}
}
portENABLE_INTERRUPTS();
}
在portmacro.h
中定义了中断控制状态寄存器:portNVIC_INT_CTRL_REG
= 0xe000ed04。
其Bit 28 为PENDSVSET: portNVIC_PENDSVSET_BIT
:PendSV悬起位
![image-20211112215504221](https://img-blog.csdnimg.cn/img_convert/001c1bb5dd5c08add00de971746ea89d.png)
因此,只要在portYIELD()
或者xPortSysTickHandler()
中调用了:
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
执行后就会进入PendSV异常,在PendSV中断服务函数中实现上下文切换。
2. 堆栈指针的切换
异常(PendSV异常)发生时,R14保存异常返回标志,包括返回后进入任务模式还是处理模式、使用PSP还是MSP。
在PendSV异常保存上文时,通过向 R14 寄存器最后 4 位按位或上 0x0D,使得硬件在退出时使用进程堆栈指针 PSP 完成出栈操作,并在异常返回后进入任务模式、返回 Thumb 状态。然后将R14压入任务堆栈,一遍下次切换回该任务时获取R14的内容。
PendSV异常切换到下文时会将新任务堆栈中的R14读取出来,由于上文将R14做了保存,此时R14=0xFFFFFFFD,表示异常返回后进入任务模式,使用PSP作为堆栈指针出栈,出栈完毕后PSP指向任务栈栈顶。
3. PendSV中断实现上下文切换
在 stm32 中 PendSV 的异常服务函数名为 PendSV_Handler,在stm32xxxx_it.c中为弱定义,直接重定义函数即可。
在PendSV异常中执行四个步骤:
- 关闭中断
- 保存上文
- 加载下文
- 打开中断
__asm volatile void xPortPendSVHandler( void )
{
extern pxCurrentTCB;
extern vTaskSwitchContext;
PRESERVE8
mrs r0, psp
isb
ldr r3, =pxCurrentTCB
ldr r2, [r3]
stmdb r0!, {r4-r11}
str r0, [r2]
stmdb sp!, {r3, r14}
mov r0, %0
msr basepri, r0
bl vTaskSwitchContext
mov r0, #0
msr basepri, r0
ldmia sp!, {r3, r14}
ldr r1, [r3]
ldr r0, [r1]
ldmia r0!, {r4-r11}
msr psp, r0
isb
bx r14
nop
}
汇编代码流程如下:
![CSDN图片](https://img-blog.csdn.net/20160515192425451?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
图1:
![图1](https://img-blog.csdnimg.cn/img_convert/0c64ea2bc3c6ad984add3885fef82512.png)
图2:
![图2](https://img-blog.csdnimg.cn/img_convert/f6c59ecd56827c193c8eace9c099ef5e.png)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)