你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【MCU实战经验】向μC/OS-III在STM32F4xx上的移植中添加FPU支持

[复制链接]
erabby 发布时间:2014-4-28 00:19
因项目需要使用STM32F417的硬件浮点单元,但当时Micrium的官方移植µC/OS-III V3.03.01 (2013/01/23)不支持FPU,因此需要修改代码添加FPU支持。
首先,为了便于控制是否使用FPU,定义一个宏 USE_FPU。需要使用FPU时在MDK的工程选项中定义这个宏,要在”C/C++“”Asm“选项卡中都定义,这样无论C代码还是汇编代码中都可以使用这个宏了。需要注意的是,预定义宏__TARGET_FPU_VFP只能在C文件中使用,汇编文件中不能使用。
然后,在CPU初始化代码中设置FPU。在官方移植中,设置代码已经有了,但被注释掉了,只要取消注释即可,然后再设置代码前后添加条件编译:
                IF  EF: USE_FPU
                               
;Enable FPU
;Use reset settings: automatic lazy FPU state preservation
                LDR     R0, =0xE000ED88           ; Enable CP10,CP11
                LDR     R1,[R0]

<span lang="EN-US" style="font-size: 9pt; font-family: Arial, sans-serif;">                ORR     R1,R1,#(0xF
收藏 评论6 发布时间:2014-4-28 00:19

举报

6个回答
erabby 回答时间:2014-4-28 00:20:11

RE:【MCU实战经验】向μC/OS-III在STM32F4xx上的移植中添加FPU支持

下一步,修改os_cpu_c.c文件中的OSTaskStkInit()函数,创建任务时在任务栈中设置浮点寄存器的初值。修改后的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                                     */
/* Align the stack to 8-bytes.                            */
p_stk = (CPU_STK *)((CPU_STK)(p_stk) & 0xFFFFFFF8);
/* Registers stacked as if auto-saved on exception        */
#ifdef  USE_FPU
*--p_stk = (CPU_STK)0xABCD1234u;                                                /* Reserved                                               */
*--p_stk = (CPU_STK)0x00000000u;                                                /* FPSCR                                                  */
*--p_stk = (CPU_STK)0x7FC01515u;                                                /* S15                                                    */
*--p_stk = (CPU_STK)0x7FC01414u;                                                /* S14                                                    */
*--p_stk = (CPU_STK)0x7FC01313u;                                                /* S13                                                    */
*--p_stk = (CPU_STK)0x7FC01212u;                                                /* S12                                                    */
*--p_stk = (CPU_STK)0x7FC01111u;                                                /* S11                                                    */
*--p_stk = (CPU_STK)0x7FC01010u;                                                /* S10                                                    */
*--p_stk = (CPU_STK)0x7FC00909u;                                                /* S9                                                     */
*--p_stk = (CPU_STK)0x7FC00808u;                                                /* S8                                                     */
*--p_stk = (CPU_STK)0x7FC00707u;                                                /* S7                                                     */
*--p_stk = (CPU_STK)0x7FC00606u;                                                /* S6                                                     */
*--p_stk = (CPU_STK)0x7FC00505u;                                                /* S5                                                     */
*--p_stk = (CPU_STK)0x7FC00404u;                                                /* S4                                                     */
*--p_stk = (CPU_STK)0x7FC00303u;                                                /* S3                                                     */
*--p_stk = (CPU_STK)0x7FC00202u;                                                /* S2                                                     */
*--p_stk = (CPU_STK)0x7FC00101u;                                                /* S1                                                     */
*--p_stk = (CPU_STK)0x7FC00000u;                                                /* S0                                                     */
#endif  /* USE_FPU */

*--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             */
#ifdef  USE_FPU
*--p_stk = (CPU_STK)0x7FC03131u;                                                /* S31                                                    */
*--p_stk = (CPU_STK)0x7FC03030u;                                                /* S30                                                    */
*--p_stk = (CPU_STK)0x7FC02929u;                                                /* S29                                                    */
*--p_stk = (CPU_STK)0x7FC02828u;                                                /* S28                                                    */
*--p_stk = (CPU_STK)0x7FC02727u;                                                /* S27                                                    */
*--p_stk = (CPU_STK)0x7FC02626u;                                                /* S26                                                    */
*--p_stk = (CPU_STK)0x7FC02525u;                                                /* S25                                                    */
*--p_stk = (CPU_STK)0x7FC02424u;                                                /* S24                                                    */
*--p_stk = (CPU_STK)0x7FC02323u;                                                /* S23                                                    */
*--p_stk = (CPU_STK)0x7FC02222u;                                                /* S22                                                    */
*--p_stk = (CPU_STK)0x7FC02121u;                                                /* S21                                                    */
*--p_stk = (CPU_STK)0x7FC02020u;                                                /* S20                                                    */
*--p_stk = (CPU_STK)0x7FC01919u;                                                /* S19                                                    */
*--p_stk = (CPU_STK)0x7FC01818u;                                                /* S18                                                    */
*--p_stk = (CPU_STK)0x7FC01717u;                                                /* S17                                                    */
*--p_stk = (CPU_STK)0x7FC01616u;                                                /* S16                                                        */
#endif  /* USE_FPU */

*--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);
}
其中红色代码是新添加的处理浮点寄存器的代码。特别注意注释为Reserved的第2行红字,在任务栈中保存这个保留的32位字是必须的,其值没有特别要求,请参考ARMv7-M Architecture Reference Manual (DDI0403D)。
erabby 回答时间:2014-4-28 00:24:30

回复:【MCU实战经验】向μC/OS-III在STM32F4xx上的移植中添加FPU支持

 最后,修改os_cpu_a.asm文件中的OS_CPU_PendSVHandler子程序,任务切换时保存旧任务的浮点寄存器并加载新任务的浮点寄存器值。修改后的OS_CPU_PendSVHandler子程序代码如下:
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  EF: USE_FPU
       
        VMRS    R1, FPSCR             ; Dummy read access to force FPU state preservation and FPSCR clear
        SUBS    R0, R0, #0x40        ; Save remaining FP regs s16-s31 on process stack
        VSTM      R0, {D8-D15}
       
        ENDIF
 
    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
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;
    LDM     R0, {R4-R11}                                        ; Restore r4-11 from new process stack
    ADDS    R0, R0, #0x20
       
        IF  EF: USE_FPU
       
        VLDM      R0, {D8-D15}                        ; Restore s16-s31 from new process stack
        ADDS       R0, R0, #0x40
       
        ENDIF
       
    MSR     PSP, R0                                             ; Load PSP with new process SP
    ORR     LR, LR, #0x04                                       ; Ensure exception return uses process stack
       
        IF  EF: USE_FPU
       
        AND         LR, LR, #0xFFFFFFEF             ; Clear LR to ensure FPU state restore
        LDR     R0, =0xE000EF34                         ; Clear FPCCR (LSPACT) to ensure FPU state restore
        LDR     R1, [R0]
        AND     R1, R1, #0xFFFFFFFE
        STR     R1, [R0]
 
        ENDIF
       
        CPSIE   I
BX      LR                                                  ; Exception return will restore remaining context
其中红色代码是新添加的处理浮点寄存器的代码。几点说明:
1)根据FPCCR的设置值(就是复位值ASPEN=1, LSPEN=1),如果发生PendSV异常时CONTROL.FPCA=1,在进入PendSV异常处理函数时,硬件会自动在任务栈保留浮点寄存器占用的空间,首先通过读FPSCR寄存器让硬件自动保存浮点寄存器S0~S15和浮点状态寄存器FPSCR到任务栈,然后手动保存其余的浮点寄存器S16~S31
2)在退出PendSV异常处理函数前,清除LR4位并清除FPCCR寄存器第0位(LSPACT),目的是让硬件在退出PendSV异常处理函数时自动从任务栈恢复浮点寄存器S0~S15和浮点状态寄存器FPSCR。这样如果新任务是第一次运行,则可实现从任务栈加载浮点寄存器初值,否则是从任务栈加载以前保存的值,并且可以保证每个任务运行时都有CONTROL.FPCA=1
3)虽然使能了延迟保存浮点状态功能,但因为总是有CONTROL.FPCA=1,因此无论旧任务是否执行过浮点指令,在进入PendSV异常处理函数执行任务切换时,都会保存旧任务的浮点寄存器,加载新任务的浮点寄存器,没有利用延迟保存浮点状态功能可减小中断延迟的优势。
erabby 回答时间:2014-4-28 00:47:39

RE:【MCU实战经验】向μC/OS-III在STM32F4xx上的移植中添加FPU支持

以上代码在STM3241G-Eval评估板上测试通过,并且已经在产品中成功应用。
yw0238 回答时间:2014-4-28 11:39:39

回复:【MCU实战经验】向μC/OS-III在STM32F4xx上的移植中添加FPU支持

谢谢,在F407VG上通过
erabby 回答时间:2014-4-28 21:57:26

回复:【MCU实战经验】向μC/OS-III在STM32F4xx上的移植中添加FPU支持

回复第 5 楼 于2014-04-28 11:39:39发表:
谢谢,在F407VG上通过
 
只要是Cortex-M4核应该都可以
 
A.K. 回答时间:2014-4-30 14:25:24

RE:【MCU实战经验】向μC/OS-III在STM32F4xx上的移植中添加FPU支持

好经验,谢谢楼主分享。
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版