• STM32F303xC在UCOSIII下使用FPU总结


    总体来说,按照网上的教程差不多,但是有个别地方不太一样,下面分别说说。

    1.打开单片机的FPU

    在 system_stm32f30x.c 文件下找到函数 SystemInit ,注意头几行的条件判断(橙色)有没有,没有的话加上。

    void SystemInit(void)
    {
      /* FPU settings ------------------------------------------------------------*/
      #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
        SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));  /* set CP10 and CP11 Full Access */
      #endif
    
      /* Reset the RCC clock configuration to the default reset state ------------*/
      /* Set HSION bit */
      RCC->CR |= (uint32_t)0x00000001;
    
      /* Reset CFGR register */
      RCC->CFGR &= 0xF87FC00C;
    
      /* Reset HSEON, CSSON and PLLON bits */
      RCC->CR &= (uint32_t)0xFEF6FFFF;
    ...
    ...
    }

    2.在 stm32f30x.h 文件中 找到 宏定义 __FPU_PRESENT 并置1

    3.在  option for target -- C/C++ --Preoprocessor Symbols 加入__TARGET_FPU_VFP__FPU_PRESENT ; 在 option for target --target -- code generation -- Float Point Hardware 选择 SIngle Precision

    4.确保 core_cm4.h 中这里的条件编译 成功宏定义  __FPU_USED 为1

    #if defined ( __CC_ARM )
      #if defined __TARGET_FPU_VFP
        #if (__FPU_PRESENT == 1)
          #define __FPU_USED       1
        #else
          #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
          #define __FPU_USED       0
        #endif
      #else
        #define __FPU_USED         0
      #endif

    5.在 startup_stm32f303xc.s 文件中,添加橙色汇编代码以支持FPU,这部分代码,网络上有不同版本,正点原子也和我的不同,我是尝试了好多版本才试出来我这个是可以用的,具体原因不太清楚,以后再查吧。

    ; Reset handler
    Reset_Handler    PROC
                     EXPORT  Reset_Handler             [WEAK]
            IMPORT  SystemInit
            IMPORT  __main
                     
                     LDR     R0, =0xE000ED88    ; 使能浮点运算 CP10,CP11
                     LDR     R1,[R0]
                     ORR     R1,R1,#(0xF << 20)
                     STR     R1,[R0]
                     DSB
                     
                     LDR.W R0,=0xE000EF34
                     LDR R1,[R0]
                     AND R1,R1,#(0X3FFFFFFF)
                     STR R1,[R0]
                     ISB
                     
                     LDR     R0, =SystemInit  
                     BLX     R0                
                     LDR     R0, =__main
                     BX      R0
                     ENDP

    ok!这样单片机这边的FPU就可以使用了,接下去在UCOSIII中开启FPU支持。

    1.打开 os_cpu_c.c,找到函数 OSTaskStkInit,加入如下橙色代码

    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                                     */
    
        p_stk = (CPU_STK *)((CPU_STK)(p_stk) & 0xFFFFFFF8);         /* Align the stack to 8-bytes.                            */
    
    #if (__FPU_PRESENT==1)&&(__FPU_USED==1)         /* Registers stacked as if auto-saved on exception        */
        *(--p_stk) = (CPU_STK)0x00000000u; //No Name Register  
        *(--p_stk) = (CPU_STK)0x00001000u; //FPSCR
        *(--p_stk) = (CPU_STK)0x00000015u; //s15
        *(--p_stk) = (CPU_STK)0x00000014u; //s14
        *(--p_stk) = (CPU_STK)0x00000013u; //s13
        *(--p_stk) = (CPU_STK)0x00000012u; //s12
        *(--p_stk) = (CPU_STK)0x00000011u; //s11
        *(--p_stk) = (CPU_STK)0x00000010u; //s10
        *(--p_stk) = (CPU_STK)0x00000009u; //s9
        *(--p_stk) = (CPU_STK)0x00000008u; //s8
        *(--p_stk) = (CPU_STK)0x00000007u; //s7
        *(--p_stk) = (CPU_STK)0x00000006u; //s6
        *(--p_stk) = (CPU_STK)0x00000005u; //s5
        *(--p_stk) = (CPU_STK)0x00000004u; //s4
        *(--p_stk) = (CPU_STK)0x00000003u; //s3
        *(--p_stk) = (CPU_STK)0x00000002u; //s2
        *(--p_stk) = (CPU_STK)0x00000001u; //s1
        *(--p_stk) = (CPU_STK)0x00000000u; //s0
    #endif
        
        *(--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                                          */
    
    #if (__FPU_PRESENT==1)&&(__FPU_USED==1)
        *(--p_stk) = (CPU_STK)0x00000031u; //s31
        *(--p_stk) = (CPU_STK)0x00000030u; //s30
        *(--p_stk) = (CPU_STK)0x00000029u; //s29
        *(--p_stk) = (CPU_STK)0x00000028u; //s28
        *(--p_stk) = (CPU_STK)0x00000027u; //s27
        *(--p_stk) = (CPU_STK)0x00000026u; //s26
        *(--p_stk) = (CPU_STK)0x00000025u; //s25
        *(--p_stk) = (CPU_STK)0x00000024u; //s24
        *(--p_stk) = (CPU_STK)0x00000023u; //s23
        *(--p_stk) = (CPU_STK)0x00000022u; //s22
        *(--p_stk) = (CPU_STK)0x00000021u; //s21
        *(--p_stk) = (CPU_STK)0x00000020u; //s20
        *(--p_stk) = (CPU_STK)0x00000019u; //s19
        *(--p_stk) = (CPU_STK)0x00000018u; //s18
        *(--p_stk) = (CPU_STK)0x00000017u; //s17
        *(--p_stk) = (CPU_STK)0x00000016u; //s16
    #endif
                                                                    /* 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                                                     */
    
        return (p_stk);
    }

    2.打开 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
    
        ;Is the task using the FPU context? If so, push high vfp registers.
        SUBS    R0, R0, #0x40
        VSTM    R0, {S16-S31}
        
        SUBS    R0, R0, #0x20                                       ; Save remaining regs r4-11 on process stack
        STM     R0, {R4-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;
        LDM     R0, {R4-R11}                                        ; Restore r4-11 from new process stack
        ADDS    R0, R0, #0x20
       
       ;Is the task using the FPU context? If so, push high vfp registers.
        VLDM    R0, {S16-S31}
        ADDS    R0, R0, #0x40
        
        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

    现在,调试一下,看汇编窗口,乘法是带V开头的汇编指令,这样,就完成了!!!

  • 相关阅读:
    制作类似QQ截图软件
    XML文件与实体类的互相转换
    MFC中真彩工具条的制作方法
    MFC使用技巧集锦(1)(转载)
    抽象工厂模式与工厂方法模式区别
    VC数据库编程分析
    如何让工具条显示256色图像
    华为软件编程规范和范例
    设计模式总结性试题
    VC++中基于ADO操作ACCESS数据库,FLEXGRID控件的综合应用
  • 原文地址:https://www.cnblogs.com/sypspace/p/10463003.html
Copyright © 2020-2023  润新知