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

【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支持。  N- B5 H1 {& _5 \
首先,为了便于控制是否使用FPU,定义一个宏 USE_FPU。需要使用FPU时在MDK的工程选项中定义这个宏,要在”C/C++“和”Asm“选项卡中都定义,这样无论C代码还是汇编代码中都可以使用这个宏了。需要注意的是,预定义宏__TARGET_FPU_VFP只能在C文件中使用,汇编文件中不能使用。2 ]6 w' I. X5 k1 n1 U8 H, g
然后,在CPU初始化代码中设置FPU。在官方移植中,设置代码已经有了,但被注释掉了,只要取消注释即可,然后再设置代码前后添加条件编译:4 O, L, E" u, H- N% y
                IF  EF: USE_FPU
; ?8 z" i' B7 u* S3 t: h                               
5 o# A/ C1 v; O) N$ y;Enable FPU" v' k) M! h+ {" \/ `
;Use reset settings: automatic lazy FPU state preservation
* J- t" Q- \1 V; W8 M  j                LDR     R0, =0xE000ED88           ; Enable CP10,CP11
  K# |" k% A% l  {1 f8 d% Q                LDR     R1,[R0]# |, A$ _9 y% I, f7 q9 {" s2 A- F
- i- {( P5 W* J1 A9 W
<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()函数代码如下:( f# j5 f* Q5 _) ^
CPU_STK  *OSTaskStkInit (OS_TASK_PTR    p_task,, N& t1 U" b" e) U2 k% X
void          *p_arg," @0 c) d8 \7 A. P6 K& X
CPU_STK       *p_stk_base,
& t" }& ], M' s& u' X; j8 H: cCPU_STK       *p_stk_limit,8 \. p2 p& S9 q! i" a: a  \- P
CPU_STK_SIZE   stk_size,
* L, o% P/ f+ mOS_OPT         opt)
/ K: F/ p, q' L* f, G; P) |{
( J  K2 c; h5 ^7 l$ GCPU_STK  *p_stk;
1 H( ?2 J% t# m0 `; H% W# B8 g  U6 P% d' h/ C1 J5 H
(void)opt;                                              /* Prevent compiler warning                               */
, H7 f+ B- q+ t  Sp_stk = &p_stk_base[stk_size];                          /* Load stack pointer                                     */
  ?5 n( G1 \, E( H6 V5 C/* Align the stack to 8-bytes.                            */. s& e* [+ C- V! E' c% x; ]
p_stk = (CPU_STK *)((CPU_STK)(p_stk) & 0xFFFFFFF8);
7 _3 c; I" B+ N; l/* Registers stacked as if auto-saved on exception        */$ V: k1 h" R6 }1 B3 B  B1 _# J) ^
#ifdef  USE_FPU* B6 u/ n$ ~& T
*--p_stk = (CPU_STK)0xABCD1234u;                                                /* Reserved                                               */
/ }/ @3 S+ |% p5 A* I' H*--p_stk = (CPU_STK)0x00000000u;                                                /* FPSCR                                                  */
2 R1 A# @8 \! }& o*--p_stk = (CPU_STK)0x7FC01515u;                                                /* S15                                                    */
9 [+ N' u9 Q% t4 N6 y) G5 Q*--p_stk = (CPU_STK)0x7FC01414u;                                                /* S14                                                    */
  q6 J2 N9 u/ [0 t. v*--p_stk = (CPU_STK)0x7FC01313u;                                                /* S13                                                    */- w( H; r% k2 ~! r' w
*--p_stk = (CPU_STK)0x7FC01212u;                                                /* S12                                                    */
( s( ]$ b" A$ t* E*--p_stk = (CPU_STK)0x7FC01111u;                                                /* S11                                                    */3 l' M# L: k$ X8 h$ A$ P
*--p_stk = (CPU_STK)0x7FC01010u;                                                /* S10                                                    */. N' U8 G( [5 Y% H7 M
*--p_stk = (CPU_STK)0x7FC00909u;                                                /* S9                                                     */5 e/ v5 K% k1 a5 g1 P# [- T  K
*--p_stk = (CPU_STK)0x7FC00808u;                                                /* S8                                                     */# d* K& v! ^+ j& i
*--p_stk = (CPU_STK)0x7FC00707u;                                                /* S7                                                     */
1 K8 A9 s1 R) r8 p: u4 G. D' I*--p_stk = (CPU_STK)0x7FC00606u;                                                /* S6                                                     */
" `+ q. Z6 a2 T4 P( O5 V& }*--p_stk = (CPU_STK)0x7FC00505u;                                                /* S5                                                     */
3 S  U# R# G- A- u0 z+ l. O. U*--p_stk = (CPU_STK)0x7FC00404u;                                                /* S4                                                     */# |, A4 r: d+ D$ P
*--p_stk = (CPU_STK)0x7FC00303u;                                                /* S3                                                     */& m0 F3 E5 H) s& i5 Y; V3 E  Y
*--p_stk = (CPU_STK)0x7FC00202u;                                                /* S2                                                     */
: s, ]. S8 L( i4 e7 [*--p_stk = (CPU_STK)0x7FC00101u;                                                /* S1                                                     */+ M9 n9 \* {6 {! q" r
*--p_stk = (CPU_STK)0x7FC00000u;                                                /* S0                                                     */
8 M) U% u4 n. f#endif  /* USE_FPU */

% \# e0 }  U5 I/ L& a$ }*--p_stk = (CPU_STK)0x01000000u;                        /* xPSR                                                   */: G. H+ c& v! A8 [# e( {+ Z
*--p_stk = (CPU_STK)p_task;                             /* Entry Point                                            */- y, C" }/ ~% _0 _( X. V$ `' d
*--p_stk = (CPU_STK)OS_TaskReturn;                      /* R14 (LR)                                               */
' N% ^7 _+ b& u8 ?* r9 Y*--p_stk = (CPU_STK)0x12121212u;                        /* R12                                                    */3 \7 E8 e5 _! o4 s  H
*--p_stk = (CPU_STK)0x03030303u;                        /* R3                                                     */
" \. d& b! a/ `8 c9 A*--p_stk = (CPU_STK)0x02020202u;                        /* R2                                                     */
) ?  ?+ D) h" k$ R& B& \' x, \*--p_stk = (CPU_STK)p_stk_limit;                        /* R1                                                     */: A( z/ c: ~8 u8 u/ p
*--p_stk = (CPU_STK)p_arg;                              /* R0 : argument                                          */' f. S( h" e; R
/* Remaining registers saved on process stack             */; C9 D/ v$ S( I
#ifdef  USE_FPU7 c0 T9 v( _: V, Y
*--p_stk = (CPU_STK)0x7FC03131u;                                                /* S31                                                    */
" S5 I* j$ k& ]+ t*--p_stk = (CPU_STK)0x7FC03030u;                                                /* S30                                                    */
+ s0 y: [2 f" h3 T/ J, r*--p_stk = (CPU_STK)0x7FC02929u;                                                /* S29                                                    */
2 j+ j# w7 D2 e( v) ?5 p. e- V*--p_stk = (CPU_STK)0x7FC02828u;                                                /* S28                                                    */( k+ `5 y/ q# W1 P9 C9 F' `
*--p_stk = (CPU_STK)0x7FC02727u;                                                /* S27                                                    */. n, z2 C9 K  d7 I* k; V& N: c
*--p_stk = (CPU_STK)0x7FC02626u;                                                /* S26                                                    */4 S& H5 _# \9 Q; D  V& u9 a1 ~* _
*--p_stk = (CPU_STK)0x7FC02525u;                                                /* S25                                                    */
" a2 a8 B! S3 l4 C& b/ F*--p_stk = (CPU_STK)0x7FC02424u;                                                /* S24                                                    */
! M( V7 H3 g, `" M3 k& U+ z& `*--p_stk = (CPU_STK)0x7FC02323u;                                                /* S23                                                    */
/ j& }0 o" z; x. g; \! ^/ z4 N*--p_stk = (CPU_STK)0x7FC02222u;                                                /* S22                                                    */) z+ [, L/ E: M( N
*--p_stk = (CPU_STK)0x7FC02121u;                                                /* S21                                                    */
5 W& {7 X' o  W. J5 h, H*--p_stk = (CPU_STK)0x7FC02020u;                                                /* S20                                                    */
  u( f" {& B0 `* T. j*--p_stk = (CPU_STK)0x7FC01919u;                                                /* S19                                                    */) ^  O& W! K& ^* Z3 J
*--p_stk = (CPU_STK)0x7FC01818u;                                                /* S18                                                    */0 t/ G* {; ^$ J  S: T& v/ x0 Z* _
*--p_stk = (CPU_STK)0x7FC01717u;                                                /* S17                                                    */: ^& i/ O+ `7 y6 ^. P
*--p_stk = (CPU_STK)0x7FC01616u;                                                /* S16                                                        */$ \$ S1 P  d; Z; i1 q: y
#endif  /* USE_FPU */
# p) j" s9 P( R
*--p_stk = (CPU_STK)0x11111111u;                        /* R11                                                    */
! H' X  v  R' @0 p*--p_stk = (CPU_STK)0x10101010u;                        /* R10                                                    */  X( x$ M' o0 q) _
*--p_stk = (CPU_STK)0x09090909u;                        /* R9                                                     */, _! T$ P3 H+ v1 D8 D% d' a
*--p_stk = (CPU_STK)0x08080808u;                        /* R8                                                     */+ u0 @$ }+ b4 a  q+ V; [
*--p_stk = (CPU_STK)0x07070707u;                        /* R7                                                     */3 X* @) h+ ?4 Z/ e! J: r) P6 j
*--p_stk = (CPU_STK)0x06060606u;                        /* R6                                                     */# L$ ?9 M! D. L5 H% Z% y
*--p_stk = (CPU_STK)0x05050505u;                        /* R5                                                     */
& I6 Z/ _" l0 l$ T! i! ~8 r" j*--p_stk = (CPU_STK)0x04040404u;                        /* R4                                                     */0 a: @- b6 _- j& E$ @( b
return (p_stk);; q# Y. ]& ?2 \! v) S
}  f. C% ~% N) d9 ^, x" |' S
其中红色代码是新添加的处理浮点寄存器的代码。特别注意注释为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子程序代码如下:( G1 h! l; V- K. q9 _% e
OS_CPU_PendSVHandler
8 B, [# e0 ~7 c+ X! G    CPSID   I                                                   ; Prevent interruption during context switch- X' O$ m0 E1 u$ X( [+ H1 K
    MRS     R0, PSP                                             ; PSP is process stack pointer/ B) T# X- K, d# X6 W
    CBZ     R0, OS_CPU_PendSVHandler_nosave                     ; Skip register save the first time
, i9 z3 q: J$ G- H+ m+ B+ B4 D' l        % y7 ^; Y1 H1 L( e" c1 o* B: N1 a
        IF  EF: USE_FPU
" n- V2 Z" o4 U& p6 j6 h4 e       
* F8 z( s! v  Z( E. s8 A& r2 r0 s        VMRS    R1, FPSCR             ; Dummy read access to force FPU state preservation and FPSCR clear' ?1 f8 r1 i+ i' R9 h! u" x
        SUBS    R0, R0, #0x40        ; Save remaining FP regs s16-s31 on process stack1 J- ?8 y$ B* X( ^2 z. b1 p) v
        VSTM      R0, {D8-D15}* @. t; K5 s% S: `1 D; Q4 j
       
* v  d( }( P" C2 E( ]        ENDIF4 _) d/ K# |' u) I
 # ?0 V1 f6 K: h; p4 Y
    SUBS    R0, R0, #0x20                                       ; Save remaining regs r4-11 on process stack! [% ~8 T# ^: n+ y. |
    STM     R0, {R4-R11}
( O2 D- F& |. z0 e: y ) M. {( f3 d7 `! e- S
    LDR     R1, =OSTCBCurPtr                                    ; OSTCBCurPtr->OSTCBStkPtr = SP;* k, q( F6 j; m
    LDR     R1, [R1]: ^4 Y3 a! r+ o
    STR     R0, [R1]                                            ; R0 is SP of process being switched out) q$ j/ K* X0 h, \" n
 7 e$ _- u; z/ v3 y7 I5 w
     ; At this point, entire context of process has been saved
) q2 b( L, K4 X( @" e  e& V$ wOS_CPU_PendSVHandler_nosave
3 h3 L# R4 u' T9 ^/ B5 h    PUSH    {R14}                                               ; Save LR exc_return value% R5 K0 o$ ^9 E3 J
    LDR     R0, =OSTaskSwHook                                   ; OSTaskSwHook();
" b; z% P$ a/ k' ^- `; u    BLX     R0
$ u: z9 I5 a! R1 n5 z6 ~    POP     {R14}7 G! C* c3 a# J" N2 @6 j: }5 u# f
 
) u+ p! D7 m/ h6 s, b+ M0 p    LDR     R0, =OSPrioCur                                      ; OSPrioCur   = OSPrioHighRdy;
) U, C' A' T3 ^* w. Q    LDR     R1, =OSPrioHighRdy! D5 q% i7 B$ E2 }" m  T
    LDRB    R2, [R1]
6 Y: y2 d7 f+ k  W# c/ `    STRB    R2, [R0]9 Y( a, E! Z$ P& `2 w2 M
 ! }- x7 [& t5 S' l. A, V& q
    LDR     R0, =OSTCBCurPtr                                    ; OSTCBCurPtr = OSTCBHighRdyPtr;
! \4 x1 F. |5 H2 X: m5 L    LDR     R1, =OSTCBHighRdyPtr
5 j# i& U, ]6 n. `9 _# n    LDR     R2, [R1]
4 k: s. q% F+ P2 Q+ b$ C    STR     R2, [R0]
5 s( u" ~# E0 ~" x 
$ U" F. Q7 G& L; A    LDR     R0, [R2]                                            ; R0 is new process SP; SP = OSTCBHighRdyPtr->StkPtr;
6 A# r/ @  o" }/ M) I    LDM     R0, {R4-R11}                                        ; Restore r4-11 from new process stack
% t) w( C  \9 e! @: U4 R! v    ADDS    R0, R0, #0x20
4 ?$ ~% A4 I$ T5 \5 d( R        * Z$ j  k) o8 B* V3 R& |
        IF  EF: USE_FPU( ^9 u/ ~2 p' B2 ~: A
       
% q8 k$ |& z0 Z. K        VLDM      R0, {D8-D15}                        ; Restore s16-s31 from new process stack
* D! M4 m- ]9 j4 G3 n. s8 d' ?, z        ADDS       R0, R0, #0x40) {, d- m7 J. b( j$ L: x! b' E
        4 B: ~/ G! r& O# G8 e" t- b
        ENDIF8 y4 l9 k2 P1 _1 I' o
       
. x9 _; ]% Z" F, _% `( }    MSR     PSP, R0                                             ; Load PSP with new process SP
) u4 k8 v* ~4 ?" S    ORR     LR, LR, #0x04                                       ; Ensure exception return uses process stack; N$ V; c' W- I% o0 S) p
        8 q% Q2 s7 t" O1 M2 s& w* ]4 k' Z
        IF  EF: USE_FPU
' K/ n1 T4 H0 R4 B: @" N- ~9 N. s* _        9 |9 C; ^: C# h( A2 _
        AND         LR, LR, #0xFFFFFFEF             ; Clear LR to ensure FPU state restore
! W4 w! b! |1 q! ~1 d* D        LDR     R0, =0xE000EF34                         ; Clear FPCCR (LSPACT) to ensure FPU state restore. H+ v3 [9 M3 ~' r  O- o2 l7 M
        LDR     R1, [R0]- Q7 r1 r, P+ h7 V, G7 P
        AND     R1, R1, #0xFFFFFFFE
9 N$ k, O+ Z) n, t        STR     R1, [R0]
5 }+ F4 d7 H( v- J ) E5 G9 W7 J4 B
        ENDIF
: u& e4 l' M, @/ k0 c0 o  c        ' R, D! b$ Q5 U1 o  ?; _
        CPSIE   I6 r% a: c3 Q. F# J! E- z* p) k- E
BX      LR                                                  ; Exception return will restore remaining context
1 m$ g9 |  A1 k: y+ O其中红色代码是新添加的处理浮点寄存器的代码。几点说明:9 ~* @0 s$ ?% Q! |
1)根据FPCCR的设置值(就是复位值ASPEN=1, LSPEN=1),如果发生PendSV异常时CONTROL.FPCA=1,在进入PendSV异常处理函数时,硬件会自动在任务栈保留浮点寄存器占用的空间,首先通过读FPSCR寄存器让硬件自动保存浮点寄存器S0~S15和浮点状态寄存器FPSCR到任务栈,然后手动保存其余的浮点寄存器S16~S31。  X: E" @% K  s2 k
2)在退出PendSV异常处理函数前,清除LR第4位并清除FPCCR寄存器第0位(LSPACT),目的是让硬件在退出PendSV异常处理函数时自动从任务栈恢复浮点寄存器S0~S15和浮点状态寄存器FPSCR。这样如果新任务是第一次运行,则可实现从任务栈加载浮点寄存器初值,否则是从任务栈加载以前保存的值,并且可以保证每个任务运行时都有CONTROL.FPCA=1。. F* o0 A% U* y' U" l- T
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发表:
/ H$ N: D1 s! ]. S谢谢,在F407VG上通过# }* u7 ^- f- f6 o: `; }- b
 
5 [/ e  r$ L9 x' K) [只要是Cortex-M4核应该都可以
% \0 E1 i) Q; b$ a/ d 
A.K. 回答时间:2014-4-30 14:25:24

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

好经验,谢谢楼主分享。

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版