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

【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核应该都可以
 
andykim 回答时间:2014-4-30 14:25:24

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

好经验,谢谢楼主分享。

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

相似技术帖

官网相关资源

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