首页 > 代码库 > stm32f407 官方ucos-iii 不支持FPU 导致haltfault错误的处理办法

stm32f407 官方ucos-iii 不支持FPU 导致haltfault错误的处理办法

由于官方提供的μCOS-III移植工程中对于浮点寄存器的入栈和出栈处理是错误的,所以网上就流传了
各种修正版本。但是这些修正的代码只能在 MDK4.7 以下版本中可以正常的运行,MDK4.7 及其以上的版

本无法正常运行。下面针对高版本的MDK进行修正处理


处理方法如下:


为了解决 FPU 的问题,有两个函数需要修改:一个是 CPU_STK  *OSTaskStkInit(),另一个是 PendSV
中断。 最后需要在工程选项中开启FPU的支持


修改函数CPU_STK  *OSTaskStkInit() 
函数所在的在:

uCOS-III\Ports\ARM-Cortex-M4\Generic\RealView\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                                          */ 
                                                        /* 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 ENABLE_FPU
    *--p_stk = (CPU_STK)0xFFFFFFFDUL;                                                                                 (1) 
 ;endif  
   return (p_stk); 
} 


1.  这句话最重要,这里是将 EXC_RETURN也进行了入栈处理。

修改函数OS_CPU_PendSVHandler 
函数所在的位置在:

uCOS-III\Ports\ARM-Cortex-M4\Generic\RealView\os_cpu_a.asm

修改后的内容

<pre name="code" class="cpp">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
 ;if enable the FPU

	TST LR, #0x10 
	IT EQ 
	VSTMDBEQ R0!, {S16-S31} 
	MOV R3, LR 
	STMDB R0!,{R3-R11}

    LDR     R1, =OSTCBCurPtr                                    ; OSTCBCurPtr->OSTCBStkPtr = SP;
    LDR     R1, [R1]
    STR     R0, [R1]                                            ; 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, [R1]
    STRB    R2, [R0]

    LDR     R0, =OSTCBCurPtr                                    ; OSTCBCurPtr = OSTCBHighRdyPtr;
    LDR     R1, =OSTCBHighRdyPtr
    LDR     R2, [R1]
    STR     R2, [R0]

    LDR     R0, [R2]                                            ; R0 is new process SP; SP = OSTCBHighRdyPtr->StkPtr;
	
	LDMIA R0!,{R3-R11} 
	MOV LR, R3 
	TST LR, #0x10
	IT EQ 
	VLDMIAEQ R0!, {S16-S31}
		
    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



1.  通过检测 EXC_RETURN(LR)的 bit4 来看这个任务是否使用
的 16 个浮点寄存器入栈。 

2.  这里比较好理解,只不过也将 EXC_RETURN进行了入栈。 
3.  参考上面的第二条,只不过这里是出栈。 
4.  参考上面的第一条,只不过这里是出栈。



开启FPU 
修改了上面的两个地方后别忘了开启 FPU: 





开启FPU的优劣
开启FPU的好处就是加快浮点运算的执行速度,缺点就是增加任务堆栈的大小,因为34个浮点寄存器也需要入栈。同时也增加了任务的切换时间