54chenjq 发表于 2015-9-27 16:43
上下文切换中有没有对与浮点运算有关的寄存器进行压栈和出栈的处理,没有这些代码是不是会出错?
从代码上看确实是有对浮点寄存器的进栈和出栈的处理,堆栈初始化的时候浮点寄存器进栈,位于os_cpu_c.c文件中:
CPU_STK *OSTaskStkInit (OS_TASK_PTR p_task,
void *p_arg,
CPU_STK *p_stk_base,
CPU_STK *p_stk_limit,
CPU_STK_SIZE stk_size,
OS_OPT opt)
{
CPU_STK *p_stk;
(void)opt; /* Prevent compiler warning */
p_stk = &p_stk_base[stk_size]; /* Load stack pointer */
/* Align the stack to 8-bytes. */
p_stk = (CPU_STK *)((CPU_STK)(p_stk) & 0xFFFFFFF8);
/* Registers stacked as if auto-saved on exception */
*--p_stk = (CPU_STK)0x01000000u; /* xPSR */
*--p_stk = (CPU_STK)p_task; /* Entry Point */
*--p_stk = (CPU_STK)OS_TaskReturn; /* R14 (LR) */
*--p_stk = (CPU_STK)0x12121212u; /* R12 */
*--p_stk = (CPU_STK)0x03030303u; /* R3 */
*--p_stk = (CPU_STK)0x02020202u; /* R2 */
*--p_stk = (CPU_STK)p_stk_limit; /* R1 */
*--p_stk = (CPU_STK)p_arg; /* R0 : argument */
/* Remaining registers saved on process stack */
*--p_stk = (CPU_STK)0x11111111u; /* R11 */
*--p_stk = (CPU_STK)0x10101010u; /* R10 */
*--p_stk = (CPU_STK)0x09090909u; /* R9 */
*--p_stk = (CPU_STK)0x08080808u; /* R8 */
*--p_stk = (CPU_STK)0x07070707u; /* R7 */
*--p_stk = (CPU_STK)0x06060606u; /* R6 */
*--p_stk = (CPU_STK)0x05050505u; /* R5 */
*--p_stk = (CPU_STK)0x04040404u; /* R4 */
#if (OS_CPU_ARM_FP_EN == DEF_ENABLED)
if ((opt & OS_OPT_TASK_SAVE_FP) != (OS_OPT)0) {
*--p_stk = (CPU_STK)0x02000000u; /* FPSCR */
/* Initialize S0-S31 floating point registers */
*--p_stk = (CPU_STK)0x41F80000u; /* S31 */
*--p_stk = (CPU_STK)0x41F00000u; /* S30 */
*--p_stk = (CPU_STK)0x41E80000u; /* S29 */
*--p_stk = (CPU_STK)0x41E00000u; /* S28 */
*--p_stk = (CPU_STK)0x41D80000u; /* S27 */
*--p_stk = (CPU_STK)0x41D00000u; /* S26 */
*--p_stk = (CPU_STK)0x41C80000u; /* S25 */
*--p_stk = (CPU_STK)0x41C00000u; /* S24 */
*--p_stk = (CPU_STK)0x41B80000u; /* S23 */
*--p_stk = (CPU_STK)0x41B00000u; /* S22 */
*--p_stk = (CPU_STK)0x41A80000u; /* S21 */
*--p_stk = (CPU_STK)0x41A00000u; /* S20 */
*--p_stk = (CPU_STK)0x41980000u; /* S19 */
*--p_stk = (CPU_STK)0x41900000u; /* S18 */
*--p_stk = (CPU_STK)0x41880000u; /* S17 */
*--p_stk = (CPU_STK)0x41800000u; /* S16 */
*--p_stk = (CPU_STK)0x41700000u; /* S15 */
*--p_stk = (CPU_STK)0x41600000u; /* S14 */
*--p_stk = (CPU_STK)0x41500000u; /* S13 */
*--p_stk = (CPU_STK)0x41400000u; /* S12 */
*--p_stk = (CPU_STK)0x41300000u; /* S11 */
*--p_stk = (CPU_STK)0x41200000u; /* S10 */
*--p_stk = (CPU_STK)0x41100000u; /* S9 */
*--p_stk = (CPU_STK)0x41000000u; /* S8 */
*--p_stk = (CPU_STK)0x40E00000u; /* S7 */
*--p_stk = (CPU_STK)0x40C00000u; /* S6 */
*--p_stk = (CPU_STK)0x40A00000u; /* S5 */
*--p_stk = (CPU_STK)0x40800000u; /* S4 */
*--p_stk = (CPU_STK)0x40400000u; /* S3 */
*--p_stk = (CPU_STK)0x40000000u; /* S2 */
*--p_stk = (CPU_STK)0x3F800000u; /* S1 */
*--p_stk = (CPU_STK)0x00000000u; /* S0 */
}
#endif
return (p_stk);
}复制代码然后上下文切换里面似乎也有对于FPU寄存器的进栈与出栈操作,也位于os_cpu_c.c文件中
void OSTaskSwHook (void)
{
#if OS_CFG_TASK_PROFILE_EN > 0u
CPU_TS ts;
#endif
#ifdef CPU_CFG_INT_DIS_MEAS_EN
CPU_TS int_dis_time;
#endif
#if (OS_CPU_ARM_FP_EN == DEF_ENABLED)
if ((OSTCBCurPtr->Opt & OS_OPT_TASK_SAVE_FP) != (OS_OPT)0) {
OS_CPU_FP_Reg_Push(OSTCBCurPtr->StkPtr);
}
if ((OSTCBHighRdyPtr->Opt & OS_OPT_TASK_SAVE_FP) != (OS_OPT)0) {
OS_CPU_FP_Reg_Pop(OSTCBHighRdyPtr->StkPtr);
}
#endif
#if OS_CFG_APP_HOOKS_EN > 0u
if (OS_AppTaskSwHookPtr != (OS_APP_HOOK_VOID)0) {
(*OS_AppTaskSwHookPtr)();
}
#endif
#if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u))
TRACE_OS_TASK_SWITCHED_IN(OSTCBHighRdyPtr); /* Record the event. */
#endif
#if OS_CFG_TASK_PROFILE_EN > 0u
ts = OS_TS_GET();
if (OSTCBCurPtr != OSTCBHighRdyPtr) {
OSTCBCurPtr->CyclesDelta = ts - OSTCBCurPtr->CyclesStart;
OSTCBCurPtr->CyclesTotal += (OS_CYCLES)OSTCBCurPtr->CyclesDelta;
}
OSTCBHighRdyPtr->CyclesStart = ts;
#endif
#ifdef CPU_CFG_INT_DIS_MEAS_EN
int_dis_time = CPU_IntDisMeasMaxCurReset(); /* Keep track of per-task interrupt disable time */
if (OSTCBCurPtr->IntDisTimeMax < int_dis_time) {
OSTCBCurPtr->IntDisTimeMax = int_dis_time;
}
#endif
#if OS_CFG_SCHED_LOCK_TIME_MEAS_EN > 0u
/* Keep track of per-task scheduler lock time */
if (OSTCBCurPtr->SchedLockTimeMax < OSSchedLockTimeMaxCur) {
OSTCBCurPtr->SchedLockTimeMax = OSSchedLockTimeMaxCur;
}
OSSchedLockTimeMaxCur = (CPU_TS)0; /* Reset the per-task value */
#endif
}复制代码OS_CPU_FP_Reg_Push和OS_CPU_FP_Reg_Pop是用汇编语言写的,位于os_cpu_a.asm中:
#ifdef __ARMVFP__
OS_CPU_FP_Reg_Push
MRS R1, PSP ; PSP is process stack pointer
CBZ R1, OS_CPU_FP_nosave ; Skip FP register save the first time
VMRS R1, FPSCR
STR R1, [R0, #-4]!
VSTMDB R0!, {S0-S31}
LDR R1, =OSTCBCurPtr
LDR R2, [R1]
STR R0, [R2]
OS_CPU_FP_nosave
BX LR
#endif
#ifdef __ARMVFP__
OS_CPU_FP_Reg_Pop
VLDMIA R0!, {S0-S31}
LDMIA R0!, {R1}
VMSR FPSCR, R1
LDR R1, =OSTCBHighRdyPtr
LDR R2, [R1]
STR R0, [R2]
BX LR
#endif
复制代码