ucosii for m4 带fpu
本帖最后由 BSF_RL 于 2012-7-29 00:22 编辑在网上买了块STM32F4 discovery的板子,想把ucosii移植到上面跑跑。在网上收罗一遍,M4上移植ucosii的比较少,m4和m3差不太多就把M3的移植接口用来植m4,移植完后,下载到硬件运行程序尽然死掉了,费劲跟踪出错的地方,在跟踪的过程中发现堆栈出问题了。我在我们的BBS上看到了有位已经在m4上移植了ucosii,但是不支持FPU,我下载下来参考一下,其工程中把FPU关闭了,我查看我的工程,FPU是使能的,于是我也把FPU关闭,运行程序,led闪烁起来了,这说明M3的移植接口适用于M4,但是使能FPU为什么就不行了呢!继续跟踪单步调试,最后终于找到原因了,在使能FPU后,M4自动入栈和出栈的寄存器多了18个,如果按照M3的结构,其堆栈必定冲破栈底,这就是为什么会死掉的原因所在,但这18个寄存器到底是什么,我在网上没有找到资料,发了一个贴也没有人回答这时我突然想到RT-Thread,在哪个realthouch不是用的是M4的么,下个工程看看他是怎么处理的,下面就是cpuport.c中的定义的结构体
struct exception_stack_frame
{
rt_uint32_t r0;
rt_uint32_t r1;
rt_uint32_t r2;
rt_uint32_t r3;
rt_uint32_t r12;
rt_uint32_t lr;
rt_uint32_t pc;
rt_uint32_t psr;
#if USE_FPU
/* FPU register */
rt_uint32_t S0;
rt_uint32_t S1;
rt_uint32_t S2;
rt_uint32_t S3;
rt_uint32_t S4;
rt_uint32_t S5;
rt_uint32_t S6;
rt_uint32_t S7;
rt_uint32_t S8;
rt_uint32_t S9;
rt_uint32_t S10;
rt_uint32_t S11;
rt_uint32_t S12;
rt_uint32_t S13;
rt_uint32_t S14;
rt_uint32_t S15;
rt_uint32_t FPSCR;
rt_uint32_t NO_NAME;
#endif
};
struct stack_frame
{
/* r4 ~ r11 register */
rt_uint32_t r4;
rt_uint32_t r5;
rt_uint32_t r6;
rt_uint32_t r7;
rt_uint32_t r8;
rt_uint32_t r9;
rt_uint32_t r10;
rt_uint32_t r11;
#if USE_FPU
/* FPU register s16 ~ s31 */
rt_uint32_t s16;
rt_uint32_t s17;
rt_uint32_t s18;
rt_uint32_t s19;
rt_uint32_t s20;
rt_uint32_t s21;
rt_uint32_t s22;
rt_uint32_t s23;
rt_uint32_t s24;
rt_uint32_t s25;
rt_uint32_t s26;
rt_uint32_t s27;
rt_uint32_t s28;
rt_uint32_t s29;
rt_uint32_t s30;
rt_uint32_t s31;
#endif
struct exception_stack_frame exception_stack_frame;
};
看了上面的代码心中的疑惑明了了。
依据TH-thread的代码修改UCOSII的移植接口
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 */
stk++;
/* Registers stacked as if auto-saved on exception */
#if USE_FPU
*(--stk)= (INT32U)0xaa; /* R? : argument */
*(--stk)= (INT32U)0xa; /* FPSCR : argument */
*(--stk)= (INT32U)0x15; /* S15 : argument */
*(--stk)= (INT32U)0x14; /* S14 : argument */
*(--stk)= (INT32U)0x13; /* S13 : argument */
*(--stk)= (INT32U)0x12; /* S12 : argument */
*(--stk)= (INT32U)0x11; /* S11 : argument */
*(--stk)= (INT32U)0x10; /* S10 : argument */
*(--stk)= (INT32U)0x9; /* S9 : argument */
*(--stk)= (INT32U)0x8; /* S8 : argument */
*(--stk)= (INT32U)0x7; /* S7 : argument */
*(--stk)= (INT32U)0x6; /* S6 : argument */
*(--stk)= (INT32U)0x5; /* S5 : argument */
*(--stk)= (INT32U)0x4; /* S4 : argument */
*(--stk)= (INT32U)0x3; /* S3 : argument */
*(--stk)= (INT32U)0x2; /* S2 : argument */
*(--stk)= (INT32U)0x1; /* S1 : argument */
*(--stk)= (INT32U)0x0; /* S0 : argument */
#endif
*(--stk)= (INT32U)0x01000000uL; /* xPSR */
*(--stk)= (INT32U)task; /* Entry Point */
*(--stk)= (INT32U)OS_TaskReturn; /* R14 (LR) */
*(--stk)= (INT32U)0x12121212uL; /* R12 */
*(--stk)= (INT32U)0x03030303uL; /* R3 */
*(--stk)= (INT32U)0x02020202uL; /* R2 */
*(--stk)= (INT32U)0x01010101uL; /* R1 */
*(--stk)= (INT32U)p_arg; /* R0 : argument */
/* Remaining registers saved on process stack */
*(--stk)= (INT32U)0x11111111uL; /* R11 */
*(--stk)= (INT32U)0x10101010uL; /* R10 */
*(--stk)= (INT32U)0x09090909uL; /* R9 */
*(--stk)= (INT32U)0x08080808uL; /* R8 */
*(--stk)= (INT32U)0x07070707uL; /* R7 */
*(--stk)= (INT32U)0x06060606uL; /* R6 */
*(--stk)= (INT32U)0x05050505uL; /* R5 */
*(--stk)= (INT32U)0x04040404uL; /* R4 */
#if USE_FPU
/* FPU register s16 ~ s31 */
*(--stk)= (INT32U)0x31uL; /* S31 */
*(--stk)= (INT32U)0x30uL; /* S30 */
*(--stk)= (INT32U)0x29uL; /* S29 */
*(--stk)= (INT32U)0x28uL; /* S28 */
*(--stk)= (INT32U)0x27uL; /* S27 */
*(--stk)= (INT32U)0x26uL; /* S26 */
*(--stk)= (INT32U)0x25uL; /* S25 */
*(--stk)= (INT32U)0x24uL; /* S24 */
*(--stk)= (INT32U)0x23uL; /* S23 */
*(--stk)= (INT32U)0x22uL; /* S22 */
*(--stk)= (INT32U)0x21uL; /* S21 */
*(--stk)= (INT32U)0x20uL; /* S20 */
*(--stk)= (INT32U)0x19uL; /* S19 */
*(--stk)= (INT32U)0x18uL; /* S18 */
*(--stk)= (INT32U)0x17uL; /* S17 */
*(--stk)= (INT32U)0x16uL; /* S16 */
#endif
return (stk);
}
这只是堆栈初始化部分,最重要的部分是任务切换部分,任务切换我觉得就是保护现场,和恢复现场,可是汇编不会,还那样 参考下rt-thread
OS_CPU_PendSVHandler
CPSID I ; Prevent interruption during context switch
MRS R0, PSP ; PSP is process stack pointer
CBZ R0, OS_CPU_PendSVHandler_nosave ; Skip register save the first time
SUBS R0, R0, #0x20 ; Save remaining regs r4-11 on process stack
STM R0, {R4-R11}
IF {FPU} != "SoftVFP"
VSTMFDr0!, {d8 - d15} ; push FPU register s16~s31
ENDIF
LDR R1, =OSTCBCur ; OSTCBCur->OSTCBStkPtr = SP;
LDR R1,
STR R0, ; R0 is SP of process being switched out
; At this point, entire context of process has been saved
OS_CPU_PendSVHandler_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,
STRB R2,
LDR R0, =OSTCBCur ; OSTCBCur= OSTCBHighRdy;
LDR R1, =OSTCBHighRdy
LDR R2,
STR R2,
LDR R0, ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr;
IF {FPU} != "SoftVFP"
VLDMFDr0!, {d8 - d15} ; pop FPU register s16~s31
ENDIF
LDM R0, {R4-R11} ; Restore r4-11 from new process stack
ADDS R0, R0, #0x20
MSR PSP, R0 ; Load PSP with new process SP
ORR LR, LR, #0x04 ; Ensure exception return uses process stack
CPSIE I
BX LR ; Exception return will restore remaining context
END
我有些不明白的是IF {FPU} != "SoftVFP" 是怎么来的?
下面奉上工程 mdk的如有不对的地方请指正!
{:smile:}谢谢,分享 楼主的STM32是F407VG系列吗? 我正准备搞个最小系统板玩玩,以前搞过STM32F103。 STM32F4 discovery这个我就感觉挺好的 主要便宜啊 用rlarm吧,对于stm32来说,比ucos好太多了。 i55x 发表于 2012-8-5 09:44 static/image/common/back.gif
用rlarm吧,对于stm32来说,比ucos好太多了。
好多了?有啥优势呢? 不知楼主的疑问解决了没有! 有编译通过的吗?我用MDK4.72A编译,开启FPU有运行异常。 感谢楼主分享
页:
[1]