下面是任务站的初始化程序,对于该程序我有一个疑问,希望知道的同学可以帮助我(假设所有的预编条件都满足)
疑问用红的写出
OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt)
{
OS_STK *stk;
(void)opt; /* 'opt' is not used, prevent warning */
stk = ptos; /* Load stack pointer */
#if (__FPU_PRESENT==1)&&(__FPU_USED==1)
*(--stk) = (INT32U)0x00000000L; //No Name Register
*(--stk) = (INT32U)0x00001000L; //FPSCR
*(--stk) = (INT32U)0x00000015L; //s15
*(--stk) = (INT32U)0x00000014L; //s14
*(--stk) = (INT32U)0x00000013L; //s13
*(--stk) = (INT32U)0x00000012L; //s12
*(--stk) = (INT32U)0x00000011L; //s11
*(--stk) = (INT32U)0x00000010L; //s10
*(--stk) = (INT32U)0x00000009L; //s9
*(--stk) = (INT32U)0x00000008L; //s8
*(--stk) = (INT32U)0x00000007L; //s7
*(--stk) = (INT32U)0x00000006L; //s6
*(--stk) = (INT32U)0x00000005L; //s5
*(--stk) = (INT32U)0x00000004L; //s4
*(--stk) = (INT32U)0x00000003L; //s3
*(--stk) = (INT32U)0x00000002L; //s2
*(--stk) = (INT32U)0x00000001L; //s1
*(--stk) = (INT32U)0x00000000L; //s0
#endif
/* Registers stacked as if auto-saved on exception */
*(stk) = (INT32U)0x01000000L; /* xPSR */
请问该数据是否覆盖s0的数据,*(--stk) 应该是先减1,然后向该地址存入数据,那么相邻的这两句不就是使用同一个地址吗。
*(--stk) = (INT32U)task; /* Entry Point */
*(--stk) = (INT32U)OS_TaskReturn; /* R14 (LR) (init value will cause fault if ever used)*/
*(--stk) = (INT32U)0x12121212L; /* R12 */
*(--stk) = (INT32U)0x03030303L; /* R3 */
*(--stk) = (INT32U)0x02020202L; /* R2 */
*(--stk) = (INT32U)0x01010101L; /* R1 */
*(--stk) = (INT32U)p_arg; /* R0 : argument */
#if (__FPU_PRESENT==1)&&(__FPU_USED==1)
*(--stk) = (INT32U)0x00000031L; //s31
*(--stk) = (INT32U)0x00000030L; //s30
*(--stk) = (INT32U)0x00000029L; //s29
*(--stk) = (INT32U)0x00000028L; //s28
*(--stk) = (INT32U)0x00000027L; //s27
*(--stk) = (INT32U)0x00000026L; //s26
*(--stk) = (INT32U)0x00000025L; //s25
*(--stk) = (INT32U)0x00000024L; //s24
*(--stk) = (INT32U)0x00000023L; //s23
*(--stk) = (INT32U)0x00000022L; //s22
*(--stk) = (INT32U)0x00000021L; //s21
*(--stk) = (INT32U)0x00000020L; //s20
*(--stk) = (INT32U)0x00000019L; //s19
*(--stk) = (INT32U)0x00000018L; //s18
*(--stk) = (INT32U)0x00000017L; //s17
*(--stk) = (INT32U)0x00000016L; //s16
#endif
/* Remaining registers saved on process stack */
*(--stk) = (INT32U)0x11111111L; /* R11 */
*(--stk) = (INT32U)0x10101010L; /* R10 */
*(--stk) = (INT32U)0x09090909L; /* R9 */
*(--stk) = (INT32U)0x08080808L; /* R8 */
*(--stk) = (INT32U)0x07070707L; /* R7 */
*(--stk) = (INT32U)0x06060606L; /* R6 */
*(--stk) = (INT32U)0x05050505L; /* R5 */
*(--stk) = (INT32U)0x04040404L; /* R4 */
return (stk);
}
下面的函数存在PenSV中断中,该函数就是任务切换的根本
PendSV_Handler
CPSID I ; Prevent interruption during context switch
MRS R0, PSP ; PSP is process stack pointer
CBZ R0, PendSV_Handler_Nosave ; Skip register save the first time
;Is the task using the FPU context? If so, push high vfp registers.
TST R14, #0x10
IT EQ
VSTMDBEQ R0!, {S16-S31}
SUBS R0, R0, #0x20 ; Save remaining regs r4-11 on process stack
STM R0, {R4-R11}
LDR R1, =OSTCBCur ; OSTCBCur->OSTCBStkPtr = SP;
LDR R1, [R1]
STR R0, [R1] ; R0 is SP of process being switched out
在此为什么要保存上一个任务的PSP到R0中
PendSV_Handler_Nosave
PUSH {R14} ; Save LR exc_return value
LDR R0, =OSTaskSwHook ; OSTaskSwHook();
BLX R0
POP {R14}
LDR R0, =OSPrioCur ; OSPrioCur = OSPrioHighRdy;
LDR R1, =OSPrioHighRdy
LDRB R2, [R1]
STRB R2, [R0]
LDR R0, =OSTCBCur ; OSTCBCur = OSTCBHighRdy;
LDR R1, =OSTCBHighRdy
LDR R2, [R1]
STR R2, [R0]
上面我可以看懂,是通过全局变量得到一个任务的堆栈段,然后把SP指针放在R0寄存其中,现在的R0就是上面OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt)函数返回的stk(最后一个语句 return(stk);)
LDR R0, [R2] ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr;
LDM R0, {R4-R11} ; Restore r4-11 from new process stack
该指令执行完成之后R0的内容应该保持不变,这样才可以保证后面FPU寄存器数据恢复正确(问 分析的是否正确)
ADDS R0, R0, #0x20
;Is the task using the FPU context? If so, push high vfp registers.
TST R14, #0x10
IT EQ
VLDMIAEQ R0!, {S16-S31}
该指令执行完成之后R0的内容应该变化,R0应该指向堆栈段中任务上次R0寄存器中的内容(问 分析的是否正确)
MSR PSP, R0 ; Load PSP with new process SP
uC/OS II在STM32F4上使不使用双堆栈?堆栈指针不是在中断返回指令下自动恢复吗?此处为什么还要手动恢复?
ORR LR, LR, #0x04 ; Ensure exception return uses process stack
CPSIE I
BX LR ; Exception return will restore remaining context
此处不是该使用中断返回指令吗,M4内核的中断返回指令和跳转指令一样吗?该指令会自动恢复R0-R4、S0-S16、PC、SP、xPSR吗?
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
谢谢了,豁然开朗!!
最后再说说,这些文件应该是STM32官方移植时候写的,难道他们没有察觉这个错误吗,答案肯定是肯定的,他们知道,但是他们为什么还要让这样的错误出现在程序里,我看了几遍代码后明白,这样可以在兼容M3内核和M4内核不使用FPU的同时,节省4字节的RAM空间,这样的解决使我觉得 、、、、,全世界的工程师也许都有强迫症吧、、、、
但是我觉他们是不是该把这样的错误注明在程序里呢、、、、,也许他们觉得我们应该足够聪明,不会被这点小问题难道、、、、、
一周热门 更多>