天天看點

[RTOS]關于STM32F4移植uCOSIII使用FPU會HardFault

首先必須要謝謝正點原子的uCOS開發手冊V3.0,介紹的很詳細,大神就是大神

然後呢,這幾天就在看的時候發現移植uCOSIII出現了開啟FPU的時候就會HardFault,然後上網搜了一下,果然這個問題爛大街了已經,然後我也稍微研究了一下,發現出問題的是uCOS官方的檔案不符合浮點寄存器的入棧和出棧順序,然後呢,經過兩個小時的尋找解決方案,最終還是在安富萊電子的uCOSIII教程1-11期中找到了解決方案,出現問題的點有兩個: 一個是 CPU_STK *OSTaskStkInit(), 另一個是 PendSV中斷。其餘的地方按照原子哥的方法修改,然後融合到一起就沒問題了。

以下解決方案是基于uCOSIII 3.04版本,其他版本自行測試

  具體的移植方法是:

1,按照原子哥的方法移植到編譯沒有錯誤為止,然後試一下,添加一個列印浮點數的任務,Debug一下試試會不會死在

/**
  * @brief  This function handles Hard Fault exception.
  * @param  None
  * @retval None
  */
void HardFault_Handler(void)
{
  /* Go to infinite loop when Hard Fault exception occurs */
  while (1)
  {
  }
}
           

其實根本不用試,這是必須的。

2,找到OSTaskStkInit(在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                                                     */

		*--p_stk = (CPU_STK)0xFFFFFFFDUL;

    return (p_stk);
}

           

3,找到PendSV_Handler(在os_cpu_a.asm),改為以下代碼

PendSV_Handler
    CPSID   I                                                   ; Prevent interruption during context switch
    MRS     R0, PSP                                             ; PSP is process stack pointer
    CBZ     R0, PendSVHandler_nosave                    		; Skip register save the first time

	CBZ R0, PendSVHandler_nosave 								; Skip register save the first time
	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
	
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
	CPSIE I
	BX LR 														; Exception return will restore remaining context
	END		
           

這個時候再編譯下,排錯,然後下載下傳試下應該就可以了

繼續閱讀