疑问1:
之所以要在切到异常模式,主要是为了SP指针的切换。复位之后使用MSP,但是要使用OS,必然会用到独立的任务栈,在异常处理中就可以从MSP切到PSP,这样切到任务执行时就使用任务的栈。当然,这里面有将任务栈数据出到CPU寄存器组。问题来了,理论上(我的认知),SVC中断中做的事我也可以使用一个我系统不会用的外部中断,然后软件写中断标志来触发,然后在中断处理来完成SVC中的事情,如果理论正确,为什么就一定要用SVC呢?
疑问2:
M4的FreeRTOS,任务创建的时候,会初始化栈区,如下
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
{
/* Simulate the stack frame as it would be created by a context switchinterrupt. */
/* Offset added to account for the way the MCU uses the stack on entry/exit
of interrupts, and to ensure alignment. */
/* 异常发生时,自动加载到CPU寄存器的内容 */
pxTopOfStack--;
*pxTopOfStack = portINITIAL_XPSR; /* xPSR xPSR的bit24必须置1*/
pxTopOfStack--;
*pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK; /* PC 即任务入口函数*/
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) prvTaskExitError; /* LR 函数返回地址*/
/* Save code space by skipping register initialisation. */
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 任务形参*/
/* A save method is being used that requires each task to maintain its own exec return value. */
pxTopOfStack--;
*pxTopOfStack = portINITIAL_EXEC_RETURN; //0xFFFF_FFF1 返回handler模式
//0xFFFF_FFF9 返回线程模式,并使用主堆栈(SP=MSP)
//0xFFFF_FFFD 返回线程模式,并使用线程堆栈(SP=PSP)
/* 异常发生时,手动加载到CPU寄存器的内容 */
pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. 默认初始化为0*/