PenSV异常
1、任务切换的具体过程在PenSV中断服务函数里
2、ICSR寄存器bit28置1,则引起PenSV中断
#define portYIELD()
{
/* Set a PendSV to request a context switch. /
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
/ Barriers are normally not required but do ensure the code is completely
within the specified behaviour for the architecture. */
__dsb( portSY_FULL_READ_WRITE );
__isb( portSY_FULL_READ_WRITE );
}
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
3、任务切换场合:
1.执行系统调用,如:taskYIELD() vTaskDelay->portYIELD_WITHIN_API();
2.systick中断服务函数里:
SysTick_Handler->xPortSysTickHandler->portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
PendSV_Handler
FREERTOS_CONFIG_H中
#define xPortPendSVHandler PendSV_Handler
__asm void xPortPendSVHandler( void )
{
extern uxCriticalNesting;
extern pxCurrentTCB;
extern vTaskSwitchContext;
PRESERVE8
mrs r0, psp
isb
/* Get the location of the current TCB. */
ldr r3, =pxCurrentTCB
ldr r2, [r3]
/* Is the task using the FPU context? If so, push high vfp registers. */
tst r14, #0x10
it eq
vstmdbeq r0!, {s16-s31}
/* Save the core registers. */
stmdb r0!, {r4-r11, r14}
/* Save the new top of stack into the first member of the TCB. */
str r0, [r2]
stmdb sp!, {r3}
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
msr basepri, r0
dsb
isb
bl vTaskSwitchContext
mov r0, #0
msr basepri, r0
ldmia sp!