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

【安富莱STM32F407之uCOS-III教程】第10章 μCOS-III在高版本MDK...

[复制链接]
baiyongbin2009 发布时间:2014-12-23 19:27
本帖最后由 baiyongbin2009 于 2014-12-23 19:30 编辑 9 r) [. b5 V/ z* v( `6 R  l5 o. {& ?
; J: D  y$ |& w( c
特别说明:
4 L8 s. S; p4 R; y: z$ e1.  本教程是安富莱电子原创。/ {/ t  [' j! e0 g1 S! n8 m( h
2.  安富莱STM32F407开发板资料已经全部开源,开源地址:地址链接

" Z! y% T1 X9 ?3 O2 A3.  当前共配套300多个实例,4套用户手册。& t9 u) Q0 `, `# E( R# e7 q
+ z  I" v* G+ |' U0 M" f7 i" F
第10章  μCOS-III在高版本MDK开启FPU方案
$ M5 }0 {* a* O& z3 Y
    由于官方提供的μCOS-III移植工程中对于浮点寄存器的入栈和出栈处理是错误的,所以网上就流传了各种修正版本。但是这些修正的代码只能在MDK4.7以下版本中可以正常的运行,MDK4.7及其以上的版本无法正常运行。本期教程为此而生。本期教程提供的方案只有任务使用了浮点寄存器(也就是做了浮点运算)才需要将其入栈,没有使用浮点寄存器的任务不需要进行入栈,认识到这点很重要。此方案在MDK4.54、4.73、5.10以及IAR6.3、6.7上面测试均通过。
    10.1 官方移植方案
    10.2 开启FPU解决方案
    10.3 开启FPU的优劣
    10.4 总结
- y' I7 H* [" d' m
10.1  官方移植方案
    官方提供的移植工程里面,只有IAR工程里面才有浮点寄存器的入栈和出栈处理函数,MDK工程里面是没有的。下面这个是os_cpu_c.c文件夹中的函数:
  1. /*
    # K# j/ `$ R# e1 t
  2. *********************************************************************************************************
    1 U! b' Y& r8 K- g* [, j
  3. *                                        INITIALIZE A TASK'S STACK& X* R' w4 J7 k. O; K2 S! \
  4. *+ U5 w* n6 w3 O
  5. * Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the
    , R3 _4 B; V' s  n9 w) M
  6. *              stack frame of the task being created.  This function is highly processor specific.0 V  r% x* W# E8 q8 A
  7. *% P- q4 O$ \; y) D: d$ I: h' v
  8. * Arguments  : task          is a pointer to the task code
    ) [8 \, M' _! u8 x6 F
  9. *
    ! M2 G% f4 b& T* B
  10. *              p_arg         is a pointer to a user supplied data area that will be passed to the task
    4 h& R$ _5 k& Y/ e
  11. *                            when the task first executes.! R8 Z1 {7 ~' L2 [
  12. *
    " P) \/ C! @; w0 {. A3 J9 W6 }* I
  13. *              ptos          is a pointer to the top of stack.  It is assumed that 'ptos' points to
    : s6 k2 M& y/ Y; K% J  o
  14. *                            a 'free' entry on the task stack.  If OS_STK_GROWTH is set to 1 then
    ; A2 R1 `* V2 w% Q7 j
  15. *                            'ptos' will contain the HIGHEST valid address of the stack.  Similarly, if
    ( ~" H$ F; y4 \' X
  16. *                            OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address/ m& h5 X4 m6 O$ ^; w
  17. *                            of the stack.: w4 \4 E5 e9 J! s! r
  18. *: {$ r/ q5 l; N) K( f' B
  19. *              opt           specifies options that can be used to alter the behavior of OSTaskStkInit().
    ' r+ q, U( B9 X3 W9 r3 Y
  20. *                            (see uCOS_II.H for OS_TASK_OPT_xxx).8 X9 X* O/ B1 T& D. V
  21. *  _9 [6 s; n$ G. E2 Y
  22. * Returns    : Always returns the location of the new top-of-stack once the processor registers have
    ! C0 Z" L. N2 @2 ]' |
  23. *              been placed on the stack in the proper order.
    8 |% P6 h, h* B9 f) B0 H% H
  24. ** _2 w" I: b" Z5 L/ Y. x
  25. * Note(s)    : (1) Interrupts are enabled when task starts executing.
    3 T8 y8 \% p! _% Q6 q
  26. *8 j1 ^( c; \8 z3 w3 i" m
  27. *              (2) All tasks run in Thread mode, using process stack.6 N6 _4 i; [7 d2 B; F' p. C. _
  28. *( }1 f" F9 N% w5 y; B( k
  29. *              (3) There are two different stack frames depending on whether the Floating-Point(FP)" d% _/ \% X2 v, l+ m& r
  30. *                  co-processor is enabled or not.8 y# Y6 S( Z5 {$ O
  31. *& X" n- P1 |; T; ]2 C
  32. *                  (a) The stack frame shown in the diagram is used when the FP co-processor is not present and+ R; r1 W! D1 D5 _. _3 M* X5 y
  33. *                      OS_TASK_OPT_SAVE_FP is disabled. In this case, the FP registers and FP Status Control8 i  w* Z0 c8 `+ ?' f. K
  34. *                      register are not saved in the stack frame.. E5 |; O8 E( y, U
  35. *
    7 `7 |' h5 H9 U* M# @
  36. *                  (b) If the FP co-processor is present but the OS_TASK_OPT_SAVE_FP is not set, then the stack6 D- z( O8 g! l3 m, V
  37. *                      frame is saved as shown in diagram (a). Moreover, if OS_TASK_OPT_SAVE_FP is set, then the/ D# d% a4 h$ U' ^* e
  38. *                      FP registers and FP Status Control register are saved in the stack frame.: b6 a5 A8 q1 C, V: J4 ~( s
  39. *  g7 D+ ~; |+ o. b* `
  40. *                      (1) When enabling the FP co-processor, make sure to clear bits ASPEN and LSPEN in the
    + D! [# \1 K- M, k# m
  41. *                          Floating-Point Context Control Register (FPCCR).
      Q  c3 N6 G1 a4 a& r" k. E
  42. *
复制代码
*                   +------------+      +------------+
*                    |            |       |            |
*                   +------------+      +------------+
*                    |    xPSR   |       |    xPSR   |
*                    +------------+       +------------+      
*                    |Return Addr|       |Return Addr |
*                   +------------+      +------------+
*                    |  LR(R14)  |       |   LR(R14) |
*                   +------------+      +------------+
*                    |    R12    |       |     R12   |
*                   +------------+      +------------+
*                    |    R3     |       |     R3    |
*                    +------------+       +------------+
*                    |    R2     |       |     R0    |
*                   +------------+      +------------+
*                    |    R1     |       |     R1    |
*                   +------------+       +------------+
*                    |    R0     |       |     R0    |
*                   +------------+      +------------+
*                    |    R11    |       |     R11   |
*                   +------------+      +------------+
*                    |    R10    |       |     R10   |
*                   +------------+      +------------+
*                    |    R9     |       |     R9    |
*                   +------------+      +------------+
*                    |    R8     |       |     R8    |
*                   +------------+      +------------+
*                    |    R7     |       |     R7    |
*                   +------------+      +------------+
*                    |    R6     |       |     R6    |
*                    +------------+       +------------+
*                    |    R5     |       |     R5    |
*                   +------------+      +------------+
*                    |    R4     |       |     R4    |
*                   +------------+       +------------+
*                         (a)             |  FPSCR    |
*                                        +------------+
*                                        |     S31    |
*                                        +------------+
*                                                .
*                                               .
*                                               .
*                                        +------------+
*                                        |     S1     |
                                          +------------+
*                                        |     S0     |
*                                        +------------+
*                                             (b)
# ~2 K' P: ]/ A6 P: ]
9 r& F0 a$ H& x' l: _8 ]

. F& q4 K; W9 \' a+ V' X! G8 V, F
赞 收藏 评论6 发布时间:2014-12-23 19:27

举报

6个回答
baiyongbin2009 回答时间:2014-12-23 19:32:50
本帖最后由 baiyongbin2009 于 2014-12-23 19:36 编辑 ( W% z9 ]4 i: n1 ?2 Y" w) i

2 I  V0 U) d" v7 R: p% a5 T(续)10.1  官方移植方案
  1. */ d  Y2 n- X6 w. b
  2. *             (4) The SP must be 8-byte aligned in conforming to the Procedure Call Standard for the ARM architecture
    . I' Q% F9 T# z9 Q
  3. *
    9 A+ F' ~$ }8 I' t! @
  4. *                    (a) Section 2.1 of the  ABI for the ARM Architecture Advisory Note. SP must be 8-byte aligned
    5 t( H% |: E+ P3 d2 @
  5. *                        on entry to AAPCS-Conforming functions states : 7 |) _) I* L' s& H! D& }
  6. *                    
    ; q7 w" ]' P& e3 C3 d
  7. *                        The Procedure Call Standard for the ARM Architecture [AAPCS] requires primitive
      S- z4 r, Z  ]/ n( ?: x' f
  8. *                        data types to be naturally aligned according to their sizes (for size = 1, 2, 4, 8 bytes). ! P" e$ f, t: ^0 _- p, Z* U, k
  9. *                        Doing otherwise creates more problems than it solves.
    3 y9 L1 C$ s4 w% i5 o  ~
  10. *3 P2 A( R* E( a3 G* F9 a
  11. *                        In return for preserving the natural alignment of data, conforming code is permitted
    0 b. b6 i8 K" B
  12. *                        to rely on that alignment. To support aligning data allocated on the stack, the stack 2 U5 g4 j2 J8 T$ p% B8 v% w* v
  13. *                        pointer (SP) is required to be 8-byte aligned on entry to a conforming function. In 2 v( ]# y# n! y
  14. *                        practice this requirement is met if:* N' q' C7 G3 r2 Y# A; R7 Z- d
  15. *
    / G  D/ s0 w1 }0 v) r
  16. *                           (1) At each call site, the current size of the calling function抯 stack frame is a multiple of 8 bytes.$ ]! @! O; h% v( z( L
  17. *                               This places an obligation on compilers and assembly language programmers." M: e% J1 l" B
  18. *4 F) {; ^  t1 F. E* i0 H4 s
  19. *                           (2) SP is a multiple of 8 when control first enters a program.
    3 S4 a8 P- j5 d2 P6 T
  20. *                               This places an obligation on authors of low level OS, RTOS, and runtime library " Q& ]8 A4 F: F' f2 j
  21. *                               code to align SP at all points at which control first enters & \" m0 G8 q: w. h$ g
  22. *                               a body of (AAPCS-conforming) code. & E2 t. ~8 H- s  M5 v8 @
  23. *              
    8 Q6 G' z6 N3 y2 p( A) Q0 D1 A
  24. *                       In turn, this requires the value of SP to be aligned to 0 modulo 8:2 c! S* r" D. _, Y
  25. */ [. m# E$ \- l& p! s' C
  26. *                           (3) By exception handlers, before calling AAPCS-conforming code.
    * g' ^1 ]/ P- N9 o$ _& e
  27. *
    ' I- r' {0 r* g$ t, I/ `  b+ n
  28. *                           (4) By OS/RTOS/run-time system code, before giving control to an application.
    " X3 K! ^4 p* E
  29. *6 N; m) H/ X- |( g) G8 R5 C
  30. *                 (b) Section 2.3.1 corrective steps from the the SP must be 8-byte aligned on entry 3 q0 H; a  z+ }+ F. d3 ^
  31. *                     to AAPCS-conforming functions advisory note also states.
    * Q2 q, U# F8 a$ I" A9 `
  32. * # A* T6 E  j( P0 H3 M' h
  33. *                     " This requirement extends to operating systems and run-time code for all architecture versions
    ! E1 c3 z# ^( s
  34. *                       prior to ARMV7 and to the A, R and M architecture profiles thereafter. Special considerations
    7 P/ A6 R: o! P6 r3 Y0 k
  35. *                       associated with ARMV7M are discussed in ?.3.3"5 a) ^1 l; O9 C7 G" H3 q
  36. * % B  W9 H- l; k, |
  37. *                     (1) Even if the SP 8-byte aligment is not a requirement for the ARMv7M profile, the stack is aligned1 z) Y* Q' ~. P# Y
  38. *                         to 8-byte boundaries to support legacy execution enviroments.
    $ s# E3 u$ i2 n
  39. *
    3 q! B6 P  _. ~% ?% k$ V
  40. *                 (c) Section 5.2.1.2 from the Procedure Call Standard for the ARM ! |  T# Z. x: J& X* Q
  41. *                     architecture states :  "The stack must also conform to the following # J# }. f( r1 q! ~$ ?6 T
  42. *                     constraint at a public interface:
    : ]( p8 h# F5 S/ |- C2 {* Q
  43. *
    5 Z0 l- G; |/ z4 u! `
  44. *                     (1) SP mod 8 = 0. The stack must be double-word aligned"* m: T% M. q2 Q, n- L3 z
  45. *
    : L& K* t& k4 D! M! y
  46. *                 (d) From the ARM Technical Support Knowledge Base. 8 Byte stack aligment.2 z; f5 q7 C) ^1 i1 K4 ?
  47. *
    0 W; g4 Z% @  ?3 V! t& q7 u# V9 W) b: z
  48. *                     "8 byte stack alignment is a requirement of the ARM Architecture Procedure - A+ K: Y; }' `: C" y3 f2 a; O
  49. *                      Call Standard [AAPCS]. This specifies that functions must maintain an 8 byte # k* y$ O. J0 b6 g
  50. *                      aligned stack address (e.g. 0x00, 0x08, 0x10, 0x18, 0x20) on all external
    0 f; e1 U. E8 Z2 x' _& Z
  51. *                      interfaces. In practice this requirement is met if:. M: U; ]+ d, h7 L; x$ c. y8 E' Y  {
  52. *4 ]3 d3 S1 }+ I+ j
  53. *                      (1) At each external interface, the current stack pointer 4 M* L; ~$ W3 B1 s% U. T. z
  54. *                          is a multiple of 8 bytes.: e% c$ c9 B, D1 d4 ]
  55. *
    , p. g; ?) B: p# w6 Z% E
  56. *                      (2) Your OS maintains 8 byte stack alignment on its external interfaces
    1 ^" {: X  E# {. C" J" U
  57. *                          e.g. on task switches"  `7 R* U  ]9 X' @2 r3 h- S
  58. *
    2 X! q  ?" [" o) h7 H
  59. **********************************************************************************************************5 d) C" j8 p+ j
复制代码
  e9 R  L$ p) f! D% ]% Y
+ n( p: l4 N$ e- P) R% W

$ X8 l1 j/ m# m0 G5 o6 p
baiyongbin2009 回答时间:2014-12-23 19:38:02
(续)10.1  官方移植方案
# p) I& w$ B( R  Y# y7 R' g, }
  1. */: y# R+ ^0 k! g. s: ?. h1 a
  2. 3 u  y) B5 @# k7 b) ]. _" c
  3. OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt)
    ) w) B) g% L5 i% Z- i; t: B1 t
  4. {
    $ ^/ w7 J7 d5 @$ Q4 F
  5. OS_STK *p_stk;( P% Q0 K- u- L/ _. B6 c

  6.   r" t1 H8 m8 a3 [$ _0 [

  7. 6 ]. K3 R2 x( S5 T  [( q
  8. p_stk = ptos + 1u; /* Load stack pointer */& `5 Y7 n2 C. g; H& }" B
  9. /* Align the stack to 8-bytes. */% O5 q' T* T+ K0 p* p
  10. p_stk = (OS_STK *)((OS_STK)(p_stk) & 0xFFFFFFF8u);
    & [5 {, g& T5 d* a0 o4 v, J
  11. /* Registers stacked as if auto-saved on exception */& m' a* t- m. v+ b& p
  12. *(--p_stk) = (OS_STK)0x01000000uL; /* xPSR */
    : P8 O% N3 J& N# J% z: h
  13. *(--p_stk) = (OS_STK)task; /* Entry Point */
    . q, K$ t5 P  N  ^5 p5 V! q- m0 j/ Q
  14. *(--p_stk) = (OS_STK)OS_TaskReturn; /* R14 (LR) */
    % s" X$ u0 K4 f6 q. a. a
  15. *(--p_stk) = (OS_STK)0x12121212uL; /* R12 */
    - x4 i# W5 c* B( W" M2 m. `0 Z0 p# _
  16. *(--p_stk) = (OS_STK)0x03030303uL; /* R3 */
    % z4 a) s+ U: ^! i
  17. *(--p_stk) = (OS_STK)0x02020202uL; /* R2 */; f* v3 E- w" C5 |6 N3 c5 Q
  18. *(--p_stk) = (OS_STK)0x01010101uL; /* R1 */
    ' r' c$ G& J  k
  19. *(--p_stk) = (OS_STK)p_arg; /* R0 : argument */
    + f5 Y$ t8 D1 Q* ?5 F5 }8 I% u
  20. 1 L% N+ _& r# Y( P' p( C/ M4 k3 e
  21. /* Remaining registers saved on process stack */
    ; W7 O  O1 V( y; e+ E5 b3 C
  22. *(--p_stk) = (OS_STK)0x11111111uL; /* R11 */# T! c% j. G/ u7 Z
  23. *(--p_stk) = (OS_STK)0x10101010uL; /* R10 */  k# b+ z) B! L# ^
  24. *(--p_stk) = (OS_STK)0x09090909uL; /* R9 */# \3 p7 e" v; U4 B! p
  25. *(--p_stk) = (OS_STK)0x08080808uL; /* R8 */. T7 |# h; m+ A
  26. *(--p_stk) = (OS_STK)0x07070707uL; /* R7 */
    5 m, l1 R* ^% m( R7 _( q' T  a
  27. *(--p_stk) = (OS_STK)0x06060606uL; /* R6 */+ d- V. h6 D( f3 T% Y
  28. *(--p_stk) = (OS_STK)0x05050505uL; /* R5 */" |7 P5 C' `- E/ @9 M9 E
  29. *(--p_stk) = (OS_STK)0x04040404uL; /* R4 */
    8 N5 M/ x1 S" ?$ u! p

  30. 8 g  S# Q; ~% G( X+ \" H
  31. #if (OS_CPU_ARM_FP_EN > 0u)
    ; [+ K+ u% D) j7 D
  32. if ((opt & OS_TASK_OPT_SAVE_FP) != (INT16U)0) {
      V; b; I5 B' j3 r3 d) z6 Q
  33. *--p_stk = (OS_STK)0x02000000u; /* FPSCR */; X) r5 w. l  c; `; m
  34. /* Initialize S0-S31 floating point registers */5 n" L) @* l2 Y, x( \4 c
  35. *--p_stk = (OS_STK)0x41F80000u; /* S31 */5 r# p" h7 O: Q& t
  36. *--p_stk = (OS_STK)0x41F00000u; /* S30 */
      H% {( K* C5 E3 u# S; l' H  ^
  37. *--p_stk = (OS_STK)0x41E80000u; /* S29 */
    ' P, I+ u  P! N. B
  38. *--p_stk = (OS_STK)0x41E00000u; /* S28 */2 P7 O* U/ j9 A% n
  39. *--p_stk = (OS_STK)0x41D80000u; /* S27 */
    - ?( m7 K1 n0 S8 a1 z8 |
  40. *--p_stk = (OS_STK)0x41D00000u; /* S26 */
    9 A+ W3 l! W9 H5 k
  41. *--p_stk = (OS_STK)0x41C80000u; /* S25 */
    $ E% y4 ^/ F! y! Z9 O# t
  42. *--p_stk = (OS_STK)0x41C00000u; /* S24 */
    . P. N0 ]" O& u' ?
  43. *--p_stk = (OS_STK)0x41B80000u; /* S23 */
    # a4 ^+ x9 v, ~4 q% {) @5 x
  44. *--p_stk = (OS_STK)0x41B00000u; /* S22 */- \- B$ V% p7 p* p. B7 y
  45. *--p_stk = (OS_STK)0x41A80000u; /* S21 */
    " I) s& M. R! B( I
  46. *--p_stk = (OS_STK)0x41A00000u; /* S20 */
    - }3 v! U0 o7 \5 |* e" A
  47. *--p_stk = (OS_STK)0x41980000u; /* S19 */0 |5 c: }- i+ F3 P# E" I& H
  48. *--p_stk = (OS_STK)0x41900000u; /* S18 */6 _8 f! y+ r# @: X" @
  49. *--p_stk = (OS_STK)0x41880000u; /* S17 */
    9 x; R9 N: _) A* S% i. \; X
  50. *--p_stk = (OS_STK)0x41800000u; /* S16 */' X( z$ ]5 E  E2 m& c
  51. *--p_stk = (OS_STK)0x41700000u; /* S15 */- s4 f* b0 A6 H5 L1 Z! ^' N3 X
  52. *--p_stk = (OS_STK)0x41600000u; /* S14 */) J, ^! ?% _/ T( t6 K" x
  53. *--p_stk = (OS_STK)0x41500000u; /* S13 */, f. i% a2 b0 \2 C% m. z5 v
  54. *--p_stk = (OS_STK)0x41400000u; /* S12 */
    # k2 q% Y5 g# B# g, t" g
  55. *--p_stk = (OS_STK)0x41300000u; /* S11 */6 X( d. R* W3 y; X
  56. *--p_stk = (OS_STK)0x41200000u; /* S10 */
    " d" `" D: {) n. @1 @( v
  57. *--p_stk = (OS_STK)0x41100000u; /* S9 */" Y6 @1 `8 S0 s3 Q
  58. *--p_stk = (OS_STK)0x41000000u; /* S8 */5 H' z% h1 J! E# X0 h' T
  59. *--p_stk = (OS_STK)0x40E00000u; /* S7 */
    ! `  @3 c& @) Z8 v5 l& k/ L
  60. *--p_stk = (OS_STK)0x40C00000u; /* S6 */
    8 L: g# k. Q$ w  a- U
  61. *--p_stk = (OS_STK)0x40A00000u; /* S5 */: ^0 P9 B# a+ l( Y) {
  62. *--p_stk = (OS_STK)0x40800000u; /* S4 */' G2 d/ c( s3 z! h7 j5 K# M
  63. *--p_stk = (OS_STK)0x40400000u; /* S3 */. r' k" J, e  [  ^
  64. *--p_stk = (OS_STK)0x40000000u; /* S2 */4 _8 n. m- U& Y7 M
  65. *--p_stk = (OS_STK)0x3F800000u; /* S1 */4 o" |/ V  V' Z  |! |% T) w3 D3 a6 D2 f
  66. *--p_stk = (OS_STK)0x00000000u; /* S0 */, A  ~+ c# j$ Q
  67. }7 E( Y: j' P# z% h* c/ L" O
  68. #endif # R; X0 g1 g3 M8 R
  69. " T: l  T: ?6 F6 h. {& c- M
  70. return (p_stk);
    ) V8 h. a' E7 x, E; ?. V
  71. }
复制代码
    官方提供的这个堆栈初始化是错误的的,为什么是错误的?因为这个不符合浮点寄存器的入栈和出栈顺序。还有一部分代码在os_cpu_a.asm文件中,内容如下:
  1. #ifdef __ARMVFP__ ( u' t4 A+ S2 ?1 Z" `( s! p$ v
  2.     PUBLIC  OS_CPU_FP_Reg_Push7 d# v2 Z# y; x* j" |# f
  3.     PUBLIC  OS_CPU_FP_Reg_Pop: a* X% }0 J2 x
  4. #endif   
    - x) `- ~, E6 D4 G. r4 e2 X
  5. : P8 K1 o5 B. }! l  @/ t
  6. ;********************************************************************************************************
    ' v$ A3 H: k. q0 T; F+ x
  7. ;                                               EQUATES7 H; l! ]8 P( p
  8. ;********************************************************************************************************: U' n- Q% C- {) L. K- W
  9. % F1 j7 B6 U: x" ]+ S
  10. NVIC_INT_CTRL   EQU     0xE000ED04                              ; Interrupt control state register.
    # X& s" S: j2 i- ?$ q
  11. NVIC_SYSPRI14   EQU     0xE000ED22                              ; System priority register (priority 14).% l6 [' t3 d* N  r
  12. NVIC_PENDSV_PRI EQU           0xFF                              ; PendSV priority value (lowest).; k) P2 r7 ~1 x" I0 J
  13. NVIC_PENDSVSET  EQU     0x10000000                              ; Value to trigger PendSV exception.* K% x: A: s  \% @  H7 c0 B

  14. 1 V4 u; o' T2 R- |- b7 @$ h
  15. " e! m6 z: L* ?' d; g3 A
  16. ;********************************************************************************************************
    5 t( Z; Y$ R2 r2 B  `% D/ z. m
  17. ;                                     CODE GENERATION DIRECTIVES
    ( w; G$ U! |2 U5 I
  18. ;********************************************************************************************************
    / a) U, G! ^1 a, o4 E
  19. 6 ~4 `9 C5 k% x. s2 Z
  20.     RSEG CODE:CODE:NOROOT(2)
    6 n; M; x* o$ v6 q! L$ {. x0 q
  21.     THUMB" V: F/ r- H% `
  22. 7 B) J4 K& w; Z" O- F) d# x! V& }6 i! t5 e+ A
  23. #ifdef __ARMVFP__
    6 o+ k+ Y. h: H9 V5 [) n9 k
  24. ;********************************************************************************************************& G$ D0 `  G0 J% B  H2 T. |
  25. ;                                   FLOATING POINT REGISTERS PUSH2 N; i& _. k' p- w/ @; O
  26. ;                             void  OS_CPU_FP_Reg_Push (OS_STK  *stkPtr)2 A9 B" H, P( `: u
  27. ;
    ; P1 x) k' g7 F" L5 o
  28. ; Note(s) : 1) This function saves S0-S31, and FPSCR registers of the Floating Point Unit.
    + _) V; s# i4 _+ P) X  C
  29. ;# Y/ V; S  c( k& ~1 ?  q! K8 j3 ?
  30. ;           2) Pseudo-code is:
    0 @+ ^- b* [" ?: {
  31. ;              a) Get FPSCR register value;
    ' z! P  L( P# P- f  r) }
  32. ;              b) Push value on process stack;
    $ g6 t) b: B, D8 T, |9 j
  33. ;              c) Push remaining regs S0-S31 on process stack;
    5 E' z. R( t0 C/ q9 f6 S1 m3 z
  34. ;              d) Update OSTCBCur->OSTCBStkPtr;$ \% p5 ^6 b' L$ V1 J% z
  35. ;********************************************************************************************************" [7 R1 p6 K+ V7 e
  36. # x, r7 o6 w% h( ]/ T# X
  37. OS_CPU_FP_Reg_Push# D# X+ `' S5 z, j) b
  38.     MRS     R1, PSP                                             ; PSP is process stack pointer4 \3 G# [7 ?/ u
  39.     CBZ     R1, OS_CPU_FP_nosave                                ; Skip FP register save the first time& z' T! J& L% p7 p2 I) {9 V# r
  40.    
    ; A% k5 I: z  n' p  r
  41.     VMRS    R1, FPSCR
    2 J8 Q0 {3 P6 e0 ?/ m6 P$ G
  42.     STR R1, [R0, #-4]!- k; ^5 Q1 K# T1 X* m' y! D. }+ @7 I
  43.     VSTMDB  R0!, {S0-S31}
    % ?8 c, B) w  U" h4 l' l
  44.     LDR     R1, =OSTCBCur, [+ ~3 g3 x, K2 {, l( t9 O* n
  45.     LDR     R2, [R1]" {4 |. D: l3 a4 s  c7 u0 b# n/ B
  46.     STR     R0, [R2]& N0 `3 l; r- O5 Q) P: \1 @
  47. OS_CPU_FP_nosave   
    % |2 x& P' Y' W2 |/ W8 U' ^
  48.     BX      LR
    9 N7 x5 b' h4 R( ?( x* r

  49. ' \+ ]" r4 x, A, Y7 s; ?
  50. ;********************************************************************************************************
    + O9 ]4 r  H+ `1 `
  51. ;                                   FLOATING POINT REGISTERS POP
    $ e' o9 ~' b+ K8 p. j& u
  52. ;                             void  OS_CPU_FP_Reg_Pop (OS_STK  *stkPtr)
    ; i: v& u0 d/ j$ h
  53. ;
    ( e2 g! l- ~7 a% }
  54. ; Note(s) : 1) This function restores S0-S31, and FPSCR registers of the Floating Point Unit.- q& a( \- t1 O, w/ ?( M2 D- M
  55. ;' R/ |8 k" e3 H% x. X
  56. ;           2) Pseudo-code is:
    ! O6 x! G3 Z: q/ F% t$ ^# h
  57. ;              a) Restore regs S0-S31 of new process stack;
    & b, M( }! B/ q6 H! I6 Q
  58. ;              b) Restore FPSCR reg value
    / P- y0 E. Y8 E- z/ t1 z. o
  59. ;              c) Update OSTCBHighRdy->OSTCBStkPtr pointer of new proces stack;
    0 @: @* B- U( w( f  ~8 `
  60. ;********************************************************************************************************4 z& Q! `& P( ~3 T
  61. + ]) U, f5 ?5 f! r5 J
  62. OS_CPU_FP_Reg_Pop. O5 o! W9 C4 W  k8 h. [# V
  63.     VLDMIA  R0!, {S0-S31}6 J+ N* T9 V7 \' I
  64.     LDMIA   R0!, {R1}" m2 Q" f5 j' E, N
  65.     VMSR    FPSCR, R1   
    % z( T. L* B6 A# A
  66.     LDR     R1, =OSTCBHighRdy/ z! F) @. r. t, o3 ]2 \
  67.     LDR     R2, [R1]! J  G; \( `, f0 j6 _9 G9 Z
  68.     STR     R0, [R2]
    8 Y  M: B0 u" ^5 L; k& u
  69.     BX      LR
    * o+ M3 H  [) E7 V
  70. #endif
复制代码
    如果不理解为什么这个浮点寄存的入栈和出栈是错误的,需要认真学习一下第5章:任务切换设计。第5章对于这个问题有深入的讲解。

! i/ w3 \4 x+ k# c- D2 i6 @4 M% d, r
baiyongbin2009 回答时间:2014-12-23 19:42:38
本帖最后由 baiyongbin2009 于 2014-12-23 19:48 编辑 1 ?, Z3 `4 a+ P& i) Y
, A( z. s4 p) C( A- E$ [
10.2  开启FPU解决方案
    为了解决FPU的问题,有两个函数需要修改:一个是CPU_STK  *OSTaskStkInit(),另一个是PendSV中断。
10.2.1      修改函数CPU_STK  *OSTaskStkInit()
    函数所在的位置如下:
10.1.png

/ u8 c0 l% L' c
    下面是修改后的内容:
  1. CPU_STK  *OSTaskStkInit (OS_TASK_PTR    p_task,
    , ~2 ^5 p0 F: I: J7 b( j
  2.                          void          *p_arg,
    - V0 M9 O$ s/ ~" k4 Y
  3.                          CPU_STK       *p_stk_base,  N5 s  W: A- A8 x
  4.                          CPU_STK       *p_stk_limit,
    8 [  `3 o, Q' `) P$ K; a
  5.                          CPU_STK_SIZE   stk_size,
    8 s  ~2 t" u. x) |( F( _
  6.                          OS_OPT         opt)
    7 Z! ~' x( B& y
  7. {
    1 A8 b( k6 V% Q
  8.     CPU_STK  *p_stk;
      Q# b  d- f; ^1 o- ]3 H5 ?& H
  9. # V' t& j# O. Y
  10. 1 Q( J/ q2 @9 w( Z
  11.     (void)opt;                                              /* Prevent compiler warning                               */
    ( K# k* k6 [2 B5 g

  12. + X2 {3 |) V0 D7 ]7 A2 J
  13.     p_stk = &p_stk_base[stk_size];                          /* Load stack pointer                                     */+ K5 j) k% u( m! K3 C  v
  14.                                                             /* Align the stack to 8-bytes.                            */
    1 U% O3 `/ R8 @+ O& B
  15.     p_stk = (CPU_STK *)((CPU_STK)(p_stk) & 0xFFFFFFF8);/ q7 |( Q3 t/ u; ^6 ]: w: E/ g
  16.                                                             /* Registers stacked as if auto-saved on exception        */# ]/ j7 w9 J5 U( m4 W" L' E. B

  17. # l, a% z% `# g+ {, B4 g' k* t* b. V
  18. *--p_stk = (CPU_STK)0x01000000u;                        /* xPSR                                                 */
    ; x) o+ k$ X# w1 N5 x
  19.     *--p_stk = (CPU_STK)p_task;                             /* Entry Point                                            */. {  N' X7 T" S# m) A' E, t9 T
  20.     *--p_stk = (CPU_STK)OS_TaskReturn;                      /* R14 (LR)                                               */
    ! U' C0 V# @! f: p$ J( Q
  21.     *--p_stk = (CPU_STK)0x12121212u;                        /* R12                                                    */' r0 b0 [  c0 {& Q8 C+ V% P6 S
  22.     *--p_stk = (CPU_STK)0x03030303u;                        /* R3                                                     */
    0 M  \9 e) z6 t" q7 I
  23.     *--p_stk = (CPU_STK)0x02020202u;                        /* R2                                                     */! I8 \) k# f; C+ U/ N
  24.     *--p_stk = (CPU_STK)p_stk_limit;                        /* R1                                                     */. x5 l! h$ O6 `+ {
  25.     *--p_stk = (CPU_STK)p_arg;                              /* R0 : argument                                          */8 S, J( l. U) u2 d
  26.                                                             /* Remaining registers saved on process stack             */
    ) I; J/ j0 H; g# [/ {* d/ u
  27.     *--p_stk = (CPU_STK)0x11111111u;                        /* R11                                                    */% l& u( ]6 e/ V# V% s
  28.     *--p_stk = (CPU_STK)0x10101010u;                        /* R10                                                    */6 I- ^4 D2 A0 i- Z% I
  29.     *--p_stk = (CPU_STK)0x09090909u;                        /* R9                                                     */: s  ]7 h+ C+ b+ Q0 ^
  30.     *--p_stk = (CPU_STK)0x08080808u;                        /* R8                                                     */+ {$ ]% T4 Y6 p- L0 ]
  31.     *--p_stk = (CPU_STK)0x07070707u;                        /* R7                                                     */- m+ \# G1 u4 G% I
  32.     *--p_stk = (CPU_STK)0x06060606u;                        /* R6                                                     */
    * w. g, G% y1 _: c( U' s
  33.     *--p_stk = (CPU_STK)0x05050505u;                        /* R5                                                     */( X; \8 a' J# x& s
  34.     *--p_stk = (CPU_STK)0x04040404u;                        /* R4                                                     */
    : U+ H0 _4 v) z! d  Q
  35. 6 h( g6 J, i# Y) ?  X  d
  36.     *--p_stk = (CPU_STK)0xFFFFFFFDUL;                                                                                                                            (1)% S% O% E& T+ H7 ~
  37.      
    ! j' ^* i4 L& V  E
  38.       return (p_stk);  k* ~! U7 }% R, o0 d- R
  39. }
复制代码
1.     这句话最重要,这里是将EXC_RETURN也进行了入栈处理。关于EXC_RETURN在前面4.2.5 特殊功能寄存器讲解。这里要补充一点,对于M4内核,EXC_RETURN的bit4也是有意义的。
    当bit4 = 1时,8个寄存器自动入栈,还有8个寄存器需要手动入栈
    当bit4 = 0时,18个浮点寄存器+8个寄存器自动入栈,还有16个浮点寄存器+8个寄存器需要手动入栈。
这些寄存器在第4章和第5章有详细的讲解,这里就不再赘述了。
- j; k) Z! m) Y; [4 K$ M, d3 L* q* ?
10.2.png
, g' ~7 n! t5 h0 e4 P# B
& v, ~& k! j( A9 B. C. u

% q" B$ b: }% g3 u10.2.2      修改函数OS_CPU_PendSVHandler
    函数所在的位置如下:
10.3.png
* v7 `) j* E+ B$ p9 N3 k
    PendSV中断需要修改的地方如下:
  1. OS_CPU_PendSVHandler
    / P# b& u5 x( I# y4 K9 a4 m  m
  2.     CPSID   I                                                   ; Prevent interruption during context switch
    3 i( ]! x" k6 `3 F
  3.     MRS     R0, PSP                                             ; PSP is process stack pointer& ^# E3 O$ e) `' r2 I" P8 E" c
  4.     CBZ     R0, OS_CPU_PendSVHandler_nosave                     ; Skip register save the first time
    2 t5 g" T$ w! x: B5 o
  5. 7 K" E! s1 q* m( s: K% T
  6.     TST      LR, #0x10                                                                                                                                                (1)9 O, V7 c/ q5 D1 ?" P' B! {9 W( }
  7. IT       EQ
    7 v: @2 a1 F" \9 l0 \
  8. VSTMDBEQ R0!, {S16-S31}
    8 [- Y2 T, V7 A- x6 H
  9.    & S1 o6 Q, Z* X  }+ `9 g( T: |
  10. MOV      R3, LR                                                                                                                                                          (2)+ S1 e- Q7 u# E! k
  11. STMDB    R0!,{R3-R11}            
    6 f4 R# e- d2 a8 P

  12. ) B& T& ]3 W+ K
  13.     LDR     R1, =OSTCBCurPtr                                    ; OSTCBCurPtr->OSTCBStkPtr = SP;  p! n3 S5 O. E9 M. x
  14.     LDR     R1, [R1]
    + O) [( y3 U9 _6 h. g6 u
  15.     STR     R0, [R1]                                            ; R0 is SP of process being switched out
    , G7 l( [  w$ X; ^0 |1 g: B- V

  16. 8 P8 |% r% H# `' J2 [1 r0 u; _2 d
  17.                                                                 ; At this point, entire context of process has been saved" b( l* @3 G) i, [4 r+ D
  18. OS_CPU_PendSVHandler_nosave
    & i& y& F. z$ b! S7 z5 B9 E- W3 M. O
  19.     PUSH    {R14}                                               ; Save LR exc_return value1 b( c' e7 i, F+ [
  20.     LDR     R0, =OSTaskSwHook                                   ; OSTaskSwHook();
    6 Q8 n& c; R& q  X
  21.     BLX     R0
    1 }) |) h9 M5 [8 |" j6 |$ c
  22.     POP     {R14}$ `7 J( T. Z- F& |5 z: J. u
  23. 9 Z  h9 W# J$ L
  24.     LDR     R0, =OSPrioCur                                      ; OSPrioCur   = OSPrioHighRdy;8 i, O& |+ M0 i' R$ j9 s
  25.     LDR     R1, =OSPrioHighRdy
    9 H6 R+ _; h2 O/ z1 A0 ^% D* m
  26.     LDRB    R2, [R1]1 z. Q" ^' D6 E* z
  27.     STRB    R2, [R0]* r, s, D3 M5 k6 J+ X

  28. % _" f, j5 o9 B) s3 Q
  29.     LDR     R0, =OSTCBCurPtr                                    ; OSTCBCurPtr = OSTCBHighRdyPtr;: N; K: W* `, K4 }1 a5 R
  30.     LDR     R1, =OSTCBHighRdyPtr
    3 \2 U* [- t0 j& p$ `  {
  31.     LDR     R2, [R1]. }% H- L) h  q/ ?( z* g6 u
  32.     STR     R2, [R0]
    / ]+ r! _" u2 ?- F
  33.     LDR     R0, [R2]                                            ; R0 is new process SP; SP = OSTCBHighRdyPtr->StkPtr;7 f) D0 q+ U9 `/ h6 f, r
  34. 9 q1 D# C8 Y3 \0 f9 ]
  35. ; `  D; ?: a  f3 M
  36.     LDMIA    R0!,{R3-R11}                                                                                                                                                  (3)
    / \( v6 P9 g% o+ L: O4 i7 \
  37. MOV      LR, R3% h0 B# w% T$ W  I" W( ~
  38.          
    * k* |% [3 L$ k# i$ X3 _$ H
  39. TST      LR, #0x10                                                                                                                                                                (4)
    0 J0 W6 g( M- H. Z1 b3 M) C
  40. IT       EQ" ?- z- z+ G+ e* E: ^& p
  41. VLDMIAEQ R0!, {S16-S31}           
    0 E2 V# Z* ?/ e: ~# w. S( N
  42.    : D! W1 {- U3 D# x
  43.     MSR     PSP, R0                                             ; Load PSP with new process SP' `- [( ]# [! m- l, b8 y
  44.    7 a' L! s# n/ Y, K, h
  45.     CPSIE   I1 ?% i$ h. ~3 O. r
  46.     BX      LR                                                  ; Exception return will restore remaining context' E- \+ N. C+ K& D4 x# D9 f
  47. ) z" U4 J! D+ N4 w
  48.     END
复制代码
1.     通过检测EXC_RETURN(LR)的bit4来看这个任务是否使用了浮点寄存器,如果使用了需要将剩余的16个浮点寄存器入栈。
TST   LR,  #0x10:
    TST指令通常与EQ,NE条件码配合使用。当所有测试位均为0时,EQ有效。而只要有一个测试位不为0,则NE有效。这里LR和0x10的值按位作逻辑“与”操作。
IT  EQ :
    这里IT指令就是IF-THEN的缩写。IF‐THEN(IT)指令围起一个块,里面最多有4条指令,它里面的指令可以条件执行。 IT已经带了一个“T”,因此还可以最多再带3个“T”或者“E”。并且对T和E的顺序没有要求。其中T对应条件成立时执行的语句,E对应条件不成立时执行的语句。在If‐Then块中的指令必须加上条件后缀,且T对应的指令必须使用和IT指令中相同的条件,E对应的指令必须使用和IT指令中相反的条件。
    IT的使用形式总结如下:
IT<cond> ;围起1条指令的IF-THEN块
IT<x><cond> ;围起2条指令的IF-THEN块
IT<x><y>  <cond> ;围起3条指令的IF-THEN块
IT<x><y><z><cond> ;围起4条指令的IF-THEN块
    其中<x>,<y>, <z>的取值可以是“T”或者“E”。而<cond>则是在下表中列出的条件(AL除外)。
10.4.png

) ], q- m, X2 [) J$ c; X
0 W- B* {0 P3 \  z: Q1 [- f9 N; [1 Z1 n
baiyongbin2009 回答时间:2014-12-23 19:45:29
(续)10.2.2  修改函数OS_CPU_PendSVHandler
    这么说还不够形象,下面举一个简单的例子,用IT指令优化C伪代码:
if(R0==R1)
{
R3= R4 + R5;
R3= R3 / 2;
}
else
{
R3= R6 + R7;
R3= R3 / 2;
}
    可以写作:
CMP  R0, R1     ; 比较R0和R1
ITTEEEQ          ; 如果R0== R1, Then-Then-Else-Else
ADDEQR3,R4, R5  ; 相等时加法
ASREQR3,R3, #1   ; 相等时算术右移
ADDNER3,R6, R7  ; 不等时加法
ASRNER3,R3, #1   ; 不等时算术右移
有了上面这些基础知识后再看下面的指令。
VSTMDBEQ R0!, {S16-S31}:
    结合上面的IT EQ,这里的意思就是 if  LR & 0x10 == 0 then  VSTMDB R0!, {S16-S31}。也就是咱们前面所说的如果EXC_RETURN(LR)的bit4= 0就表示使用浮点寄存器了,这里需要入栈。
2.     这里比较好理解,只不过也将EXC_RETURN进行了入栈。
3.     参考上面的第二条,只不过这里是出栈。
4.     参考上面的第一条,只不过这里是出栈。
10.2.3      开启FPU
    修改了上面的两个地方后别忘了开启FPU:
10.5.png
                              
    通过上面这三部就完成了相关的修改。
& J# b0 \$ d+ e' L3 a8 z1 n1 Q
baiyongbin2009 回答时间:2014-12-23 19:46:53
10.3  开启FPU的优劣
    开启FPU的好处就是加快浮点运算的执行速度,缺点就是增加任务堆栈的大小,因为34个浮点寄存器也需要入栈。同时也增加了任务的切换时间。下面是在μCOS-III的GUI任务和启动任务中使用了浮点运算的对比(App Task GUI和App Task Start)。
    第一个截图是开启了FPU:
10.6.png
    第二个截图是没有开启FPU:
10.7.png
" b$ L# I7 J2 x/ U- N* Q" g
    特别对比下使用了浮点运行的两个任务。
10.4  总结        ) A/ w4 S0 o- b2 I  H9 T  g3 P6 Q
& s* z5 C" n; t3 s# \1 w
    本期教程提供的方案在MDK4.54、4.73、5.10以及IAR6.3、6.7上面测试均通过,用户只需按照上面讲的三个地方做修改即可。
) D- b% h; T# k% B9 Q3 V2 U
: u0 X6 S, i& d3 A9 ?/ s
) u( E7 \+ \9 z( Q3 {: `1 z
pjzmj2012 回答时间:2020-3-3 14:48:23
有ucosIII 3。06.02在S32 Design Studio下的教程吗

所属标签

相似技术帖

官网相关资源

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