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

【安富莱】【RTX操作系统教程】第18章 内存管理

[复制链接]
baiyongbin2009 发布时间:2016-2-3 13:27
【安富莱】【RTX操作系统教程】第18章     内存管理 【RTX操作系统教程】第18ç«  内存管理.pdf (969.74 KB, 下载次数: 45)
赞 收藏 评论8 发布时间:2016-2-3 13:27

举报

8个回答
baiyongbin2009 回答时间:2016-2-3 14:50:52
18.2  内存管理API函数
    使用如下7个函数可以实现RTX的内存管理:
_declare_box
_declare_box8
_init_box
_init_box8
_alloc_box
_calloc_box
_free_box
关于这7个函数的讲解及其使用方法可以看教程第3章3.3小节里面说的参考资料rlarm.chm文件
18.2.png
                              
这里我们重点的说一下函数_declare_box,_declare_box8,_init_box,_init_box8,_alloc_box和_free_box。
) ]8 k  c$ ^9 a3 `4 F
18.2.1  函数_declare_box
函数原型:
  1. #define _declare_box( \
    - m! D' m9 z; ?& ^3 U, L
  2.     pool,      \    /* 内存池变量名 */
    - q5 A4 F0 L* B5 E) u  F9 z
  3.     size,      \    /* 内存块大小,单位字节 */
      {9 y6 t7 c2 C2 K- p
  4.     cnt )      \    /* 内存池中内存块的个数 */
      {/ o3 c- f7 ~* l
  5.     U32 pool[((size+3)/4)*(cnt) + 3]
复制代码

+ C$ F& X" m- ~# _  _
函数描述:
函数_declare_box用于定义一块内存池。
(1)第1个参数填写内存池的变量名。
(2)第2个参数填写内存块的大小,单位字节。
(3)第3个参数填写内存池中内存块的个数。

5 q, Q: x; g  L4 N; F4 o$ v
使用这个函数要注意以下问题:
1.     宏定义中通过操作(size+3)/4保证了每个内存块大小是4字节的倍数,从而也就保证了每个内存块的首地址是4字节对齐的(4字节对齐的含义是地址对4求余等于0)。这里初学者也要注意数据类型的字节对齐问题。
    基本数据类型的字节对齐问题
    这个问题在MDK5安装目录里面的文档DUI0375G_02_mdk_armcc_user_guide.pdf里面有详细的说明,简单的说明,数据类型有几个字节,那么这个数据类型的变量就是几字节对齐,比如32位的int型有4个字节,那么此int型定义的变量就是4字节对齐,对于初学者要牢牢的记住这个知识点。
18.3.png
2.     内存池中额外定义的12个字节用于将内存块做指针链表,方便动态的申请和释放。
使用举例:
  1. #include <rtl.h>
      i9 n" C, \- Z; P5 t$ {
  2. 9 O/ t; ?: L0 d4 _, R$ f
  3. #define PoolBlocks           10; C% I- W. j6 G( l
  4. #define PoolPerBlockSize     8
    $ g" Q/ s$ O$ N$ i8 s/ u

  5. # ?- L! ^' d! a
  6. /* 声明一个内存池,10块,每块大小8字节 */4 z+ E. E& m3 w( f2 v
  7. _declare_box(mpool, PoolPerBlockSize, PoolBlocks);
复制代码
' J. a( o9 G6 h& n% z5 ~7 ^

4 b: i- n, b  }6 N9 ]+ C
18.2.2 函数_declare_box8
函数原型:
  1. #define _declare_box8( \$ f0 C+ h! c1 ^
  2.     pool,      \    /* 内存池变量名 */
    6 W1 P" c  t, y7 C5 H9 k7 i. D
  3.     size,      \    /* 内存块大小,单位字节 */
    9 i/ d3 Q/ R0 C( `( W* y. _9 J
  4.     cnt )      \    /* 内存池中内存块的个数 */
      |. s' E$ L$ N, U! r0 y# _
  5.     U64 pool[((size+7)/8)*(cnt) + 2]
复制代码
( Q. y5 O- H5 L
函数描述:
函数_declare_box用于定义一块内存池。
(1)第1个参数填写内存池的变量名。
(2)第2个参数填写内存块的大小,单位字节。
(3)第3个参数填写内存池中内存块的个数。

- }7 j+ l4 \# f7 P
使用这个函数要注意以下问题:
1.     宏定义中通过操作(size+7)/8保证了每个内存块大小是8字节的倍数,从而也就保证了每个内存块的首地址是8字节对齐的(8字节对齐的含义是地址对8求余等于0)。这里初学者也要注意数据类型的字节对齐问题。
2.     内存池中额外定义的16个字节用于将内存块做指针链表,方便动态的申请和释放。
使用举例:
  1. #include <rtl.h>" p* Z9 `( L. h" {0 w- y* B0 s. t- e8 B

  2. ! r, l) R7 n% _9 I" H. X& u( L& c
  3. #define PoolBlocks           10' a5 U" _" E' [+ b% j. N
  4. #define PoolPerBlockSize     8
    9 \6 Q+ J. g: p8 Y$ I9 O

  5. 4 o! U; A5 ?2 F$ @% U/ K/ c  E
  6. /* 声明一个内存池,10块,每块大小8字节 */& T' A' w- a% X& Q
  7. _declare_box8(mpool, PoolPerBlockSize, PoolBlocks);
复制代码

  z/ C5 p: z4 s: A9 Y: t+ H
% i8 U6 o5 V- |0 a; m- N
18.2.3 函数_init_box
函数原型:
  1. int _init_box  (
    & `" G  k9 O+ L& V8 ^0 a2 {/ l4 U; {
  2.     void* box_mem,       /* 内存池首地址 */
    6 T- p0 o4 H" J; @
  3.     U32   box_size,      /* 内存池大小,单位字节 */6 C) |; M! |9 Q* S- k; ^) c3 b
  4.     U32   blk_size );    /* 内存块大小,单位字节 */
复制代码
! G( F' P; |' b: }
函数描述:
函数_init_box用于内存池的初始化,初始化时用到的参数都是源自于_declare_box。
(1)第1个参数填写内存池的首地址。
(2)第2个参数填写内存池的大小,单位字节。
(3)第3个参数填写内存块大小,单位字节。
& Q, s! y$ O6 ?. ?; f% ]
使用这个函数要注意以下问题:
1.     强烈建议跟函数_declare_box一起使用。用户不要自己去初始化这个函数,用_declare_box声明的才是最保险的。
2.     如果用户没有使用函数_declare_box进行定义,那么要保证内存池首地址是4字节对齐的。
3.     如果用户没有使用函数_declare_box进行定义,那么要保证内存池的大小box_size至少有12个字节,因为这个12个字节是用于将内存块做成指针链表,方便动态申请和释放。
使用举例:
  1. #include <rtl.h>
    7 ]5 L! Z* r2 e7 I# Z
  2. - q& R9 V3 {$ y: a! c- i) q
  3. #define PoolBlocks           103 A, q3 _! L; Y: O" U3 X
  4. #define PoolPerBlockSize     8& ]) ^* {$ x5 f0 ?) |& o7 \

  5. , l* m1 t$ N# y  F
  6. /* 声明一个内存池,10块,每块大小8字节 */
    1 j+ {# v+ c) N' u
  7. _declare_box(mpool, PoolPerBlockSize, PoolBlocks);
    3 z( }4 E* H3 v4 a

  8. 6 ?, m: W, x! {% c0 ]$ U
  9. /*9 F- @. C8 ^+ K# ]: Z
  10. *********************************************************************************************************
    : l) t6 x: ~4 t3 y" k0 r& Q$ m
  11. *         函 数 名: AppObjCreate
    ) b8 \, y5 B. T- D( }" j, f$ t' F* A- p
  12. *         功能说明: 创建任务通信机制, v: t+ j5 e; ?/ J- M; c
  13. *         形    参: 无
    " a/ B: p5 \; S7 h9 S
  14. *         返 回 值: 无
    ) b: M3 J. Q! m( F+ W  l% A: R
  15. *********************************************************************************************************
    4 ]1 h3 o* H& |8 s4 R7 x( b4 i
  16. */5 b$ v: Y- a3 ^
  17. static void AppObjCreate (void)
    6 b2 b6 y/ k. [& l( o
  18. {        ! S/ F8 x  X1 p  k! T5 }
  19. /* 初始化内存池,4字节对齐,*/
    - c2 v$ D/ n6 k: n: Q
  20. _init_box (mpool, sizeof (mpool), PoolPerBlockSize);
    ) N* e0 @8 L  q6 G1 H" ]" }; i) c
  21. }
复制代码

$ ?1 m3 Z9 L$ L6 Z# B3 `; K; l  W3 K$ H% O
18.2.4 函数_init_box8
函数原型:
  1. int _init_box  (
    ! y5 g$ y$ g, u; I
  2.     void* box_mem,       /* 内存池首地址 */
    7 x3 c1 T$ u; C% {
  3.     U32   box_size,      /* 内存池大小,单位字节 */
    9 S& J0 b+ {1 [3 W7 Z5 V4 x
  4.     U32   blk_size );    /* 内存块大小,单位字节 */
复制代码

0 G5 f" ~9 j4 C8 j
函数描述:
函数_init_box8用于内存池的初始化,初始化时用到的参数都是源自于_declare_box8。
(1)第1个参数填写内存池的首地址。
(2)第2个参数填写内存池的大小,单位字节。
(3)第3个参数填写内存块大小,单位字节。
0 B' J/ r- q& p; z" r
使用这个函数要注意以下问题:
1.     强烈建议跟函数_declare_box8一起使用。用户不要自己去初始化这个函数,用_declare_box声明的才是最保险的。
2.     如果用户没有使用函数_declare_box8进行定义,那么要保证内存池首地址是8字节对齐的。
3.     如果用户没有使用函数_declare_box8进行定义,那么要保证内存池的大小box_size至少有16个字节,因为这个16个字节是用于将内存块做成指针链表,方便动态申请和释放。
使用举例:
  1. #include <rtl.h>9 _" @% v$ ?) O5 d

  2. 6 y$ {2 S3 o: z1 Y5 C5 l' A6 Y
  3. #define PoolBlocks           10) O) O1 O1 h0 F* n* o& `$ d
  4. #define PoolPerBlockSize     8
    $ k/ d. l" D/ n; b

  5. $ B2 o4 S- ^$ [$ i. X
  6. /* 声明一个内存池,10块,每块大小8字节 */9 s( l7 D7 Y7 \$ R( S& d  Y
  7. _declare_box8(mpool, PoolPerBlockSize, PoolBlocks);; @9 K9 W( m$ Q9 M$ k/ U9 N

  8. , ^8 p1 M- v' i5 I8 O: }
  9. /*
    0 e( Z7 y" p  @
  10. *********************************************************************************************************
    , V. c7 ^4 S4 {
  11. *         函 数 名: AppObjCreate
    4 X$ L; [) {! K+ i( n2 o; ^
  12. *         功能说明: 创建任务通信机制
    6 H% f- y# x6 e" ?
  13. *         形    参: 无0 O6 {( p; O8 c- b/ R, C  b0 D
  14. *         返 回 值: 无9 c# n: \& F# H& x, T) C# a, G
  15. *********************************************************************************************************
    . B/ z7 P* t' G' f9 G; |. ?
  16. */; _8 @: g# s$ n! N# v7 R3 ~6 P9 h
  17. static void AppObjCreate (void)1 `; n6 k& G1 u, u+ }
  18. {        6 a, B) \5 n5 l) a6 y, a% A6 Y, z
  19. /* 初始化内存池,4字节对齐,*/
    9 g: h4 U$ y. a1 q$ N( @' O+ O
  20. _init_box8 (mpool, sizeof (mpool), PoolPerBlockSize);
    + ]) f, K: D% |) M7 f3 s2 Z$ o0 [
  21. }
复制代码
, s$ Q8 R$ J& c# ]. T
0 z2 g: H/ s' S/ ]
18.2.5 函数_alloc_box
函数原型:
  1. void *_alloc_box (5 n; x) Z7 G* H8 Q1 g) ?% x4 x" f5 B9 N
  2.     void* box_mem );    /* 内存池的首地址 */
复制代码
- e7 e( L; \. ^. Q& a
函数描述:
函数_alloc_box用于从首地址是box_mem的内存池中申请一个内存块。
(1)第1个参数填写内存池的首地址。

+ o" u$ m' m1 C3 \
使用这个函数要注意以下问题:
1.     调用此函数前,一定要使用函数_init_box或者_init_box8进行初始化。
2.     函数_alloc_box支持重入,而且是线程安全的,也即是说用户可以没有限制的在主函数和中断中调用此函数。
使用举例:
  1. #include <rtl.h>
    ! e4 [4 I( M& N

  2. 1 P9 O8 B; S7 K6 j9 l
  3. #define PoolBlocks           10
    / [- O1 H9 H7 h/ h, y/ c
  4. #define PoolPerBlockSize     8- ~% K( w' i5 B7 u2 g: q( P
  5. % }1 |5 a/ ~( ~* `+ O- l. B
  6. /* 声明一个内存池,10块,每块大小8字节 */8 A) C& q# b7 ?1 ?: s, l- [$ X0 Q
  7. _declare_box(mpool, PoolPerBlockSize, PoolBlocks);+ l% v, f; H  A4 b# v/ o
  8.   w8 t+ U$ Z$ D5 ?9 G8 ^# T
  9. /*
    9 c3 U5 w0 d% K4 D- M  q* Z) L
  10. *********************************************************************************************************; q: J1 c! J# k* O+ E" P+ o1 w
  11. *         函 数 名: AppObjCreate
    + H& ~6 [/ k, |: ~' ~
  12. *         功能说明: 创建任务通信机制
    $ ?# L, t+ m6 Q" I! d
  13. *         形    参: 无+ [/ O' U, n* {2 g
  14. *         返 回 值: 无1 a$ N; B% }/ Q
  15. *********************************************************************************************************, M! W! n, d% P8 }9 p2 ?( d
  16. */
    2 Y4 E. Z1 W+ B2 Q: U
  17. static void AppObjCreate (void)
      o' d  \% }# k! }% ]; S* T1 p
  18. {        
    6 L- b5 }( p* }& S. K
  19. /* 初始化内存池,4字节对齐,*/
    + {1 [; m+ m' o0 ?# I$ f
  20. _init_box (mpool, sizeof (mpool), PoolPerBlockSize);
    0 N* d' o" b6 g* D/ g. N4 O
  21. }9 y2 |* p6 h: r' `- t
  22. 4 B: Q4 p& i* @4 b" o5 X% \5 d

  23. ' {7 p- N. W4 T% ^9 T) r' J
  24. /*
    - V) h: u7 E0 I* i% Y7 n: J$ Z9 E
  25. *********************************************************************************************************- \, |+ ]- n" [  g0 b
  26. *    函 数 名: AppTaskUserIF
    ) ?( B5 l& v; c8 D: B9 Y
  27. *    功能说明: 按键消息处理     
    / m2 {- c: A) {9 L  Y
  28. *    形    参: 无# A! Y. U( i& w: N
  29. *    返 回 值: 无( [8 E. U- h; q& G6 S' Z) n$ G# e
  30. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
    9 Q9 M( ?9 y+ z9 H/ s+ H
  31. *********************************************************************************************************
    6 z, h) o1 p  N- I4 i; u7 G7 X. ?
  32. */
    ! f7 U% I: W  F, ]& ]( d9 P
  33. __task void AppTaskUserIF(void)' w" z/ o( s7 x# F( Z- B
  34. {
    % [" r5 q; K4 {9 f
  35.      uint8_t  *pucMsg; . x5 C& B) T" T3 ]  h
  36.      uint8_t ucKeyCode, ucCount = 0;
    ! o& Q5 ]8 @0 Q% ]7 f  H9 v

  37. 0 V( g9 |8 t+ P9 }" m
  38.     while(1)
    0 E$ k/ o" J' F) @. W
  39.     {
    % |1 x  U8 s5 ~9 u( M& _% L
  40.          ucKeyCode = bsp_GetKey();
    % p% l/ }1 @& t9 G% N$ X$ G
  41.         
    4 V  y9 W$ o6 x. c  {6 f
  42.          if (ucKeyCode != KEY_NONE)
    * i1 h9 E: ?0 H
  43.          {9 V# m. c" _8 M, v! W7 N$ _
  44.               switch (ucKeyCode)
    / V' c8 \$ G1 ^% {! x( r& n" O- g! N: n
  45.               {
    ( y4 L1 ~  R+ n, l! h, K- P
  46.                    /* K2键按下,申请一个内存块用于8位整形变量,然后向消息邮箱发送数据 */6 s2 d# g% j/ ~8 x4 S% s) `* y& ~7 |* B
  47.                    case KEY_DOWN_K2:) @( O+ f7 s0 \
  48.                        /* 申请一个内存块用于8位整形变量 */
    ; D1 {* V! x  [. f
  49.                        pucMsg  = _alloc_box (mpool);
      |; \: `7 i: M( y* ^9 X9 L' @
  50.                        *pucMsg = ucCount++;
    ; |3 V  A. {* d2 r2 x/ r& S* u
  51.                   
    6 n; F, S8 X7 Y; o( H! l# T+ y! V( v
  52.                        /* 向消息邮箱发数据,如果消息邮箱满了,等待100个时钟节拍 */
    " T( n/ p& @6 |" s% q7 z
  53.                        if(os_mbx_send (&mailbox, pucMsg, 100) != OS_R_OK)
    ! h* C7 `/ I! z
  54.                        {
    # K' \1 f/ ~+ [8 k
  55.                             /* 发送失败,即使等待了100个时钟节拍 */
    ! S, ]- ~4 P& }; t" s
  56.                             printf("K2键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\r\n");
    9 E" [% `+ p6 _! t: N, N% Q& }
  57.                             _free_box (mpool, pucMsg);
    ; M, \. \0 T7 ^. w5 B
  58.                        }' ~/ i! r/ B7 `  o% |
  59.                        else
    - t! ~) K  P3 f4 H# P+ D$ ?2 n8 I
  60.                        {
    ; d- p5 P$ p$ }3 }7 r$ T4 i6 W
  61.                             /* 发送成功 */7 j% ^8 J4 m7 q4 m
  62.                             printf("K2键按下,向消息邮箱发送数据成功\r\n");   
    ! K( h) f; a) m9 u3 E
  63.                             _free_box (mpool, pucMsg);
    9 S: e& `- H/ L3 o0 g' {5 Q
  64.                        }
    & J# w2 j' e0 I# b' I
  65.                        break;  
    7 \1 y. F% m# N

  66. + T( `2 o/ Q; ~1 t
  67.                    /* 其他的键值不处理 */
    0 p$ t1 e# H5 W7 Q4 q; t
  68.                    default:                    
    + O% k7 r: q( k  g5 h
  69.                        break;+ L- r" U" ?+ k% |' k
  70.               }. p$ Q4 o9 E% E% {4 e& X* I! u/ E
  71.          }
    : w9 x/ C0 W7 Z% m
  72.         
    % h/ x/ J& h' \- _
  73.          os_dly_wait(20);
    # w. v: J2 |$ f
  74.      }2 c2 I9 Z, |1 ~+ f
  75. }
复制代码
* f, m6 x3 P2 ?) V. X

$ Z: \) U2 e1 B, r$ u4 X
18.2.6 函数_free_box
函数原型:
  1. int _free_box (
    1 E4 h5 ^1 Y5 ^/ u, ]
  2.     void* box_mem,    /* 内存池首地址 */# ^$ ~/ B9 m6 D, x3 }
  3.     void* box );      /* 要释放的内存块首地址 */
复制代码
; r  M8 z+ v2 A2 D
函数描述:
函数_free_box用于释放使用函数_alloc_box申请的内存块。
(1)第1个参数填写内存池的首地址。
(2)第2个参数填写要释放的内存块首地址。
" _# G1 F; A7 _8 A" @  ~5 E  u) [
使用这个函数要注意以下问题:
1.     此函数的第二个参数必须要填写正确,也就是用户使用的时候最好配套_alloc_box一起使用。
2.     函数_alloc_box支持重入,而且是线程安全的,也即是说用户可以没有限制的在主函数和中断中调用此函数。
使用举例:
  1. #include <rtl.h>" m  @5 F3 D' x* n9 u9 B( m/ W1 Y
  2. ! I& S  }0 d7 [( j8 e- D/ [
  3. #define PoolBlocks           10' x2 R. c% Y; t6 e) N: p& q
  4. #define PoolPerBlockSize     8
    1 c% u( Z/ Z; C$ _  v! v! m! D

  5. + ~# i( _! b2 r9 G* U3 Y- H1 k' y
  6. /* 声明一个内存池,10块,每块大小8字节 */0 _9 m8 B: m4 Q) y0 U- u, W  _' {9 m
  7. _declare_box(mpool, PoolPerBlockSize, PoolBlocks);
    " {) N& y1 M- F; G
  8. 6 Z$ `4 W  h! {4 `2 ~: h# k6 `
  9. /*
      I3 Z, _) ]( M( R8 ]
  10. *********************************************************************************************************' i1 ^. W8 z9 U* X2 f
  11. *         函 数 名: AppObjCreate
    0 o" J2 p: ^. Y( c. ^
  12. *         功能说明: 创建任务通信机制
    * F  d4 n" E3 M% |
  13. *         形    参: 无
    + R% L' K# O: m% b1 h8 u
  14. *         返 回 值: 无
    6 D8 t7 \0 P4 @) |+ {
  15. *********************************************************************************************************
    ( k% R# y7 ]8 [1 o$ o
  16. */! X; I, g, w: k2 Z+ N* F
  17. static void AppObjCreate (void)3 b  @& B5 z% Z
  18. {        
    1 ~7 Q! w  o) I% y; w! y. A' @
  19. /* 初始化内存池,4字节对齐,*/; Z$ W) F) z% n
  20. _init_box (mpool, sizeof (mpool), PoolPerBlockSize);
    - d* j# P2 I* A0 R  q
  21. }  T5 K6 n; j8 ]/ p7 m
  22. 7 z, i5 b  N' L7 x5 l/ \
  23.   ^1 X- q6 {7 H
  24. /*
    * j. C3 _* C0 v% r7 Z
  25. *********************************************************************************************************
    8 L- G0 y/ ?! W; q
  26. *    函 数 名: AppTaskUserIF
    8 e& p( Q' S1 Z
  27. *    功能说明: 按键消息处理     
    # Q" C( s0 V& p8 |
  28. *    形    参: 无
    1 y! E" @( `: r' r" \
  29. *    返 回 值: 无
    0 \% ]2 E6 P2 R8 _0 p$ Y
  30. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
    6 s( k! L, y: G  i0 @
  31. *********************************************************************************************************1 }' b2 }+ }* b/ @' s1 Z
  32. */% R, o# v- M! j
  33. __task void AppTaskUserIF(void)% V  V3 ^. ^8 g; P# T
  34. {
    ; e0 b9 M" L9 l! z
  35.      uint8_t  *pucMsg;
    ( a. `7 l, r2 A6 p4 L/ J& T7 H! `
  36.      uint8_t ucKeyCode, ucCount = 0;
    % r; A6 I' G( J

  37. * k. r& V8 l7 u$ H* d
  38.     while(1)' k/ g  h7 Z: p" g5 |
  39.     {
    6 E& R! y# V; g5 I5 v8 l6 B7 F
  40.          ucKeyCode = bsp_GetKey();
    % V* e  U, Y/ q- v3 K+ q& B
  41.         " p5 f% k/ \  y
  42.          if (ucKeyCode != KEY_NONE)
      A7 T0 p( j; i# L
  43.          {
    5 n* o7 h; P+ r
  44.               switch (ucKeyCode)0 V% y8 F1 X: ~
  45.               {" s+ g2 Y/ I8 K+ Y$ q% O3 `
  46.                    /* K2键按下,申请一个内存块用于8位整形变量,然后向消息邮箱发送数据 */. ]# X; \$ O3 O9 B# v6 i  \* n1 u
  47.                    case KEY_DOWN_K2:- W( S. C8 j# K; N0 ]+ N/ Z6 k
  48.                        /* 申请一个内存块用于8位整形变量 */
    % y- ~1 n) ^1 Z! j
  49.                        pucMsg  = _alloc_box (mpool);
    ) H3 z6 A- M  W# \- D/ P& n
  50.                        *pucMsg = ucCount++;
    9 ]3 e/ ^3 W0 G0 t
  51.                   " Y" I! l# u. g5 t; P; M
  52.                        /* 向消息邮箱发数据,如果消息邮箱满了,等待100个时钟节拍 */
    3 L; r% B/ i/ z" `, f( r! L
  53.                        if(os_mbx_send (&mailbox, pucMsg, 100) != OS_R_OK)  T) u0 y" t& V" x" B3 D8 I
  54.                        {
    ) |! V1 A8 N5 _. y2 ], f
  55.                             /* 发送失败,即使等待了100个时钟节拍 */
    ) l' i: P, o' t: Y- o7 ?
  56.                             printf("K2键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\r\n");
    & L6 l& O1 V/ R% H
  57.                             _free_box (mpool, pucMsg);4 U' G. T" x9 Y) A
  58.                        }- i7 T7 T8 D; B- Z+ y# q' G
  59.                        else/ I, q" i+ M3 h: p4 O1 r. N" _, }
  60.                        {7 h1 i; U$ \1 A
  61.                             /* 发送成功 */
    # z2 S' t' [- f- V
  62.                             printf("K2键按下,向消息邮箱发送数据成功\r\n");   4 i  O% f( Z. ?% N( q6 u7 r
  63.                             _free_box (mpool, pucMsg);0 m' {2 U& D* v4 h4 C4 Q9 B6 V
  64.                        }
    * v& }. c: r3 v4 ]. w4 X+ |
  65.                        break;  . J8 ^2 \& m  d
  66. * [# g% J; V4 \5 l; j/ n
  67.                    /* 其他的键值不处理 */
    : V( ~" J' m7 G. K* y
  68.                    default:                    1 F9 }, A$ Z4 `/ X( N0 S
  69.                        break;. |! d! u! r5 x2 Q/ |8 `
  70.               }
    3 Z% a0 c. c' n, _- \- H/ {
  71.          }
    : d# m( y. t) {+ j
  72.         7 p+ X' K" S) `. D9 {: x
  73.          os_dly_wait(20);- ^% K2 B, L+ V8 e$ P& }- S
  74.      }( J: }2 q/ s) x8 V" d+ ~$ u
  75. }
复制代码

" g1 O3 p/ v: g! b/ i1 ~4 Z2 Y- Y6 s9 a6 T
baiyongbin2009 回答时间:2016-2-3 15:38:39
18.3 实验例程说明(4字节对齐)
' H# E3 F. f& @9 L; }* O
18.3.1 STM32F103开发板实验
配套例子:
    V4-417_RTX实验_内存管理(4字节对齐)
实验目的:
    1.     学习RTX的内存管理(4字节对齐)。
    2.     函数_declare_box和_init_box用于4字节对齐的内存池初始化。这里4字节对齐的含义
  a.内存池的首地址是4字节对齐(4字节对齐就是地址对4求余等于0)。
  b.每个内存块大小也得是4字节的倍数,这样才能保证每申请到的一个内存块的首地址也是4字节对齐。
  c.4字节对齐是由RTX系统完成的。
实验内容:
    1. K1按键按下,串口打印。
    2. K2键按下,申请一个内存块用于8位整形变量,然后向消息邮箱发送数据。
    3. K3键按下,申请一个内存块用于16位整形变量,然后向消息邮箱发送数据。
    4. 摇杆OK键按下,申请一个内存块用于32位整形变量,然后向消息邮箱发送数据。
    5. 各个任务实现的功能如下:
  AppTaskUserIF任务   :按键消息处理。
  AppTaskLED任务     :LED闪烁。
  AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的消息邮箱数据。
  AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
RTX配置:
   RTX配置向导详情如下:
                              
18.4.png
Task Configuration
Number of concurrent running tasks
  允许创建4个任务,实际创建了如下四个任务:
                AppTaskUserIF任务   :按键消息处理。
                AppTaskLED任务     :LED闪烁。
                AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的消息邮箱数据。
                AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
    Number of tasks with user-provided stack
  创建的4个任务都是采用自定义堆栈方式。
RTX任务调试信息:
18.5.png
程序设计:
任务栈大小分配:
    staticuint64_t AppTaskUserIFStk[512/8];   /* 任务栈 */
    staticuint64_t AppTaskLEDStk[256/8];      /* 任务栈 */
    staticuint64_t AppTaskMsgProStk[512/8];  /* 任务栈 */
    staticuint64_t AppTaskStartStk[512/8];     /* 任务栈 */
    将任务栈定义成uint64_t类型可以保证任务栈是8字节对齐的,8字节对齐的含义就是数组的首地址对8求余等于0。如果不做8字节对齐的话,部分C语言库函数,浮点运算和uint64_t类型数据运算会出问题。
系统栈大小分配:
18.6.png
RTX初始化:
  1. /*
    7 @( U7 d7 C7 j
  2. *********************************************************************************************************4 e7 V2 l4 e1 Z6 b  q7 U
  3. *    函 数 名: main
      W/ ]  }( J0 e9 V  w! `0 m
  4. *    功能说明: 标准c程序入口。, t9 R8 G5 U/ y# i) x, X% K2 W) v
  5. *    形    参: 无
    7 i- K5 T7 g1 c
  6. *    返 回 值: 无
    1 P7 O; X. w8 F6 p$ ~
  7. *********************************************************************************************************4 O3 H1 W. p$ @4 _% J. H; B$ N$ U
  8. */- n7 i8 ]) B" ]9 k* o8 P; o
  9. int main (void)
    # ~1 U) D) O/ g
  10. {   
    4 P+ b& }3 n4 x
  11.      /* 初始化外设 */. S7 F, f% k% K% B' ^; I
  12.      bsp_Init();
    . c. y/ s) p) X2 y( _% ~) a+ V
  13.     , i, e" A4 h# m# o
  14.      /* 创建启动任务 */
    0 `: M! I9 E; F' b* x: `& e
  15.      os_sys_init_user (AppTaskStart,             /* 任务函数 */) ~: k1 S. L8 h# ^
  16.                        4,                        /* 任务优先级 */2 L& o3 b* b8 R. X* C
  17.                        &AppTaskStartStk,         /* 任务栈 */5 N, v8 B: z, O
  18.                        sizeof(AppTaskStartStk)); /* 任务栈大小,单位字节数 */
    & \$ x: V( H4 G: J5 c2 b- W' {
  19.      while(1);# \& L, g% p4 ~+ V- ]* A" o, F
  20. }
复制代码
6 ?1 \. Q, W% E/ b$ t) j- h/ r/ x
RTX任务创建:
  1. /*
    ( {3 ^% e3 A) r+ Y9 X5 a
  2. *********************************************************************************************************9 [- U. a/ a- T7 [! P' G
  3. *    函 数 名: AppTaskCreate
    / Y2 M; p& ^$ i$ `5 |- Y
  4. *    功能说明: 创建应用任务
    # M8 f: ]! U: ?: C+ B0 G
  5. *    形    参: 无
    - \* E7 i$ @5 _; f0 F
  6. *    返 回 值: 无
    + H9 ^7 L$ R/ L- G$ E
  7. *********************************************************************************************************
    : Q" u/ g! a6 F7 \5 U& _' @- \
  8. */! T0 I" W' N! }4 ~/ o- {" {* o, o
  9. static void AppTaskCreate (void): e  ^. X2 _6 W1 @  L
  10. {
    ' z" {2 |' F) J4 ^7 u
  11.      HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             /* 任务函数 */
    3 `! S/ n8 M; P3 k/ \! n- a
  12.                                            1,                         /* 任务优先级 */
    2 y4 V; h+ m: U# d4 L1 @5 ~4 x6 f+ q
  13.                                            &AppTaskUserIFStk,         /* 任务栈 */
    * V, y- o7 G$ d2 S: }# H
  14.                                            sizeof(AppTaskUserIFStk)); /* 任务栈大小,单位字节数 */
    % O  y* h4 J6 d  A6 X. ~
  15.     / `2 a4 V" c# N: a- S( |5 ~1 Y$ ^
  16.      HandleTaskLED = os_tsk_create_user(AppTaskLED,              /* 任务函数 */0 Y6 |; e  Y- r' T3 M4 R
  17.                                         2,                       /* 任务优先级 */
    ( `2 }* x: O) V6 v/ `1 x
  18.                                         &AppTaskLEDStk,          /* 任务栈 */
    + u; d, e5 H0 P9 q6 @* G
  19.                                         sizeof(AppTaskLEDStk));  /* 任务栈大小,单位字节数 */
    8 E- g8 a& v" p% `
  20.     1 ~1 g, P! l2 Q7 S3 t
  21.      HandleTaskMsgPro = os_tsk_create_user(AppTaskMsgPro,             /* 任务函数 */0 E- O8 Q, z7 R3 i9 I
  22.                                            3,                         /* 任务优先级 */% N. y1 @' k4 A. [1 m
  23.                                            &AppTaskMsgProStk,         /* 任务栈 */+ G0 ~, L6 `7 y  ]2 W/ u" \
  24.                                            sizeof(AppTaskMsgProStk)); /* 任务栈大小,单位字节数 */: {9 ~, `  h8 Q# J
  25. }
复制代码
/ m. u. P+ Y* M5 s( A+ A
内存管理的初始化和消息邮箱的创建:
  1. #define PoolBlocks           10
    ! d; q3 W7 i. k2 F  O+ D$ m9 [
  2. #define PoolPerBlockSize     88 d4 u( }  R7 f8 n4 ~" H
  3. ( _: h- f- ^! m, z8 Q
  4. /* 声明一个支持10个消息的消息邮箱 */; ~# {. G2 b( \  V) H, X! G- x
  5. os_mbx_declare (mailbox, 10);$ l- n2 L  O; L/ f

  6. * S0 J( K. c8 x1 M
  7. /* 声明一个内存池,10块,每块大小8字节 */
    8 M6 x+ j2 e' W* p- ]
  8. _declare_box(mpool, PoolPerBlockSize, PoolBlocks);' m4 `0 v7 e; j3 m' [: b

  9. ) y5 [2 u- [( k# @0 {, z
  10. /*$ p# O6 ~* k4 C% j- S3 J. f5 X- g
  11. *********************************************************************************************************
    # v; O4 N* F) k. c) O- k
  12. *    函 数 名: AppObjCreate5 c2 B3 K, N# b6 g
  13. *    功能说明: 创建任务通信机制
    % G3 J9 p1 d" `0 }! ]6 P5 K3 s9 d
  14. *    形    参: 无
    - J8 U1 G8 i/ s  m5 U% X& P
  15. *    返 回 值: 无
    % _" s3 B. e( s( e
  16. *********************************************************************************************************
    ! Q  u1 H* u1 N0 c1 c6 a
  17. */
    / J+ K4 }) I$ r. Q( C2 s
  18. static void AppObjCreate (void)
    3 o; X3 S( `. V* l: `6 n& K0 O4 _& ]
  19. {
    7 j. q# s* y7 }$ ~5 A' W
  20.      /* 创建消息邮箱 */
    " X9 C& Z9 r  w  V& B# e: e( S
  21.       os_mbx_init (&mailbox, sizeof(mailbox));* n! @7 g- n' Z# i2 r& f
  22.    
    8 p" t6 j* w2 E4 T9 o" _+ }
  23.      /* 初始化内存池,4字节对齐,*/! D! W: [- |$ ^5 U: b8 |' O
  24.      _init_box (mpool, sizeof (mpool), PoolPerBlockSize);' w3 Y3 `) I1 [) h
  25. }
复制代码
: U- }' [$ p3 @4 C% |! M7 o2 z
四个RTX任务的实现:
  1. /*  |6 p) J' O% j
  2. *********************************************************************************************************; S) V$ m: D! f
  3. *    函 数 名: AppTaskUserIF: Q2 o: f6 b$ d* V
  4. *    功能说明: 按键消息处理     
    & O* l1 g% W- W/ x
  5. *    形    参: 无
    % Y: e" Y' e9 A; Y5 b
  6. *    返 回 值: 无
    6 Z' ^- ?6 t' H4 }7 P
  7. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
    + X, x: d+ p4 M' R
  8. *********************************************************************************************************+ o# N% v& s+ S8 L, _1 }8 a4 B, b
  9. */5 P5 P) O+ J4 C* M# |  B4 c2 i0 ?2 y
  10. __task void AppTaskUserIF(void)  W6 ~% a2 y" b" Y
  11. {
    1 l5 X) Q5 d3 _- R8 ]; M- J; H8 D
  12.      uint8_t  *pucMsg;- ~/ c0 m% p. K+ b
  13.      uint16_t *pusMsg;  c' a2 N! L' }' L% m
  14.      uint32_t *pulMsg;% w. C+ k! c8 I+ W% x. E2 U! L/ e0 u% A
  15.      uint8_t ucKeyCode, ucCount = 0;
      d& l  x8 s" _: m$ c2 F. z! K

  16. ! ], n" B: r4 {6 a3 H
  17.     while(1)
    ; S0 q% a0 _+ g) W3 u
  18.     {0 K8 P5 z' H8 S
  19.          ucKeyCode = bsp_GetKey();
    ; x9 O) W8 M+ J2 B( J* R
  20.         
    # g; l9 u! C+ D4 z# D7 P& g% f
  21.          if (ucKeyCode != KEY_NONE)) j% p! ^8 O4 ]6 }) C4 F. n( q
  22.          {
    3 n3 f$ O5 u9 K1 S
  23.               switch (ucKeyCode)' P5 k3 v5 G4 D6 k7 c& j
  24.               {
    : @/ [, N0 ^: L5 }' J" `% t
  25.                    /* K1键按下,打印调试说明 */6 ~0 Y2 A9 Z' ~: s
  26.                    case KEY_DOWN_K1:* J% @7 m( G* q
  27.                        printf("K1键按下,使用MDK中自带的RTX调试组件,请务必使用MDK4.74版本进行调试\r\n");, F- C& f6 m; B. `& d
  28.                        break;  
    . v5 c' i, ?7 ]
  29. 0 V( `1 X* i  ?4 B6 S6 i& v+ Q
  30.                    /* K2键按下,申请一个内存块用于8位整形变量,然后向消息邮箱发送数据 */; x% E' A* U4 C2 E/ U% C
  31.                    case KEY_DOWN_K2:
    / H7 o, D: O3 P- V# Q4 _
  32.                        /* 申请一个内存块用于8位整形变量 */
    7 Q% T% W! O; K
  33.                        pucMsg  = _alloc_box (mpool);/ t8 _9 n; i+ D0 G
  34.                        *pucMsg = ucCount++;& X/ F6 Y! |/ F
  35.                   6 J7 ~7 \% E: V, h% ?+ A* H
  36.                        /* 向消息邮箱发数据,如果消息邮箱满了,等待100个时钟节拍 */
    - R5 l, Z' x0 w( J% U
  37.                        if(os_mbx_send (&mailbox, pucMsg, 100) != OS_R_OK). u2 t6 `; n( x7 G
  38.                        {, ]( S) f' _$ P6 T
  39.                             /* 发送失败,即使等待了100个时钟节拍 */
    " O- i; X5 [; b8 A% R9 `2 G$ T
  40.                             printf("K2键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\r\n");
    9 I# ]& L& w" r6 f2 a" u
  41.                             _free_box (mpool, pucMsg);% \# B# }$ O) G. \2 E/ A# Q: Y& K" L  I
  42.                        }
    * w+ `- k! \% a/ ]# c$ P
  43.                        else
    0 _* ~& _5 U0 c9 l  U4 Y* Y
  44.                        {
    0 E; f+ R+ l! K, t
  45.                             /* 发送成功 */
    # r: n2 M, Y2 x; O5 `& ~8 s& t
  46.                             printf("K2键按下,向消息邮箱发送数据成功\r\n");   
    , j' ~2 ?' Z' p) |
  47.                             _free_box (mpool, pucMsg);
    . u  \- \/ v7 r0 M; X" D
  48.                        }' C. l: I7 w, P) M# |& T
  49.                        break;  5 n2 i; z- K' g9 U  F1 l/ x( I

  50. + n3 t5 a9 p: D* Y+ d& `! F$ C
  51.                    /* K3键按下,申请一个内存块用于16位整形变量,然后向消息邮箱发送数据 */* \9 W' g0 J$ Q- W+ \$ _
  52.                    case KEY_DOWN_K3:- N' r4 ]/ Q: ^
  53.                        /* 申请一个内存块用于16位整形变量 */% Y. ^9 o. e  s, g! e
  54.                        pusMsg  = _alloc_box (mpool);
    8 \4 s$ Y: e  R% i& Y/ ]; \' g
  55.                        *pusMsg = ucCount++;8 s/ Y9 V* o3 z- B+ C0 y3 a
  56.                   
    ( m0 _: n6 V3 F7 Z; p0 r
  57.                        /* 向消息邮箱发数据,如果消息邮箱满了,等待100个时钟节拍 */
    / E( w/ O7 V% a# P$ |! P: N4 K; k0 z
  58.                        if(os_mbx_send (&mailbox, pusMsg, 100) != OS_R_OK)" j2 ~) q* Y# W& b5 T3 C& ~. H1 r8 F
  59.                        {
    7 I) C2 ^8 p5 P7 X8 ?  x2 P2 e- k
  60.                             /* 发送失败,即使等待了100个时钟节拍 */7 N- E" K- v  m  `8 y! M% C  a1 [5 w
  61.                             printf("K3键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\r\n");
    4 h2 D; g# b4 M0 O  ]
  62.                             _free_box (mpool, pusMsg);% O" Q' T& T6 G3 V0 F" h  x8 i
  63.                        }
    5 Q6 r1 c3 i: t$ M. K4 s
  64.                        else1 w" [$ S/ J+ q6 u' E! m
  65.                        {8 H9 q+ u# x8 b2 ?2 c
  66.                             /* 发送成功 */4 e6 D- j! G; I. s4 U
  67.                             printf("K3键按下,向消息邮箱发送数据成功\r\n");   9 [' c( b( {9 `. g  k; k
  68.                             _free_box (mpool, pusMsg);1 D  @: w  ~9 f& H8 v
  69.                        }
    # C& O# e" N+ G$ C9 t% ?( g3 o
  70.                        break;  
    ; p3 z# ~) w/ x) C# O- [
  71.                   / g/ }/ R, ?0 U
  72.                    /* 摇杆OK键按下,申请一个内存块用于32位整形变量,然后向消息邮箱发送数据 */, ^) ^4 R1 W0 v
  73.                    case JOY_DOWN_OK:
    ) B* }, c$ s  l  p+ Z3 W. H
  74.                        /* 申请一个内存块用于32位整形变量 */
    % ~3 \: V2 v$ D
  75.                        pulMsg  = _alloc_box (mpool);
    & O$ d" N6 n2 L& A! p
  76.                        *pulMsg = ucCount++;
    ' Y' l) N0 l" @! g. ]4 H
  77.                   
    3 H. J, m8 S$ k2 E
  78.                        /* 向消息邮箱发数据,如果消息邮箱满了,等待100个时钟节拍 */# w* g. y5 N# T( e) Q" q/ M
  79.                        if(os_mbx_send (&mailbox, pulMsg, 100) != OS_R_OK)
      C! }( F9 v/ ?/ x
  80.                        {
    $ v" f2 g& g& L$ G% A5 N; L4 Z- w
  81.                             /* 发送失败,即使等待了100个时钟节拍 */
    & _0 N* t* a+ P, e$ a; y
  82.                             printf("摇杆OK键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\r\n");8 |( q3 x& c* }5 K
  83.                             _free_box (mpool, pulMsg);# T+ t0 G/ ~/ A4 G6 \
  84.                        }- c: j0 U3 M( h& y& G8 q( K
  85.                        else2 _, A# Q: {! U, n
  86.                        {4 D* q# x- _) s7 O. f2 g' k
  87.                             /* 发送成功 */7 `, A" i  e5 \- ~
  88.                             printf("摇杆OK键按下,向消息邮箱发送数据成功\r\n");   
    7 J/ q, x7 a" k( C- |
  89.                             _free_box (mpool, pulMsg);
    6 P8 {# w# K, |' {
  90.                        }
    . ]* T3 a! q. x/ n9 @  P& m
  91.                        break;
    # f- ]. V) x4 D# {( b

  92. 5 n& K0 Q# g6 z5 ?  E
  93.                    /* 其他的键值不处理 */2 `4 j) \  T+ v. g7 ~. v
  94.                    default:                    * }% M0 v+ u+ |' f% |0 e" d
  95.                        break;# e' n1 r) g( i5 w( v3 D2 _
  96.               }
    ) N! L0 `! p" {0 d  c/ Z& V& `
  97.          }
    5 v6 W- `3 N+ K2 v  s: u8 t( n; T, w
  98.         0 z. @6 F! ?8 G$ e: s$ g5 ~
  99.          os_dly_wait(20);" a0 B# g0 _" r& v: n& t9 ]4 u
  100.      }
    1 C' ^8 {% |; e
  101. }( J8 T% G0 q, s6 N+ ~9 B

  102. 4 ~  @+ }  e. _( l8 ~* S
  103. /*( l. L- }( Z! D
  104. *********************************************************************************************************" d1 I( H  e) y- [
  105. *    函 数 名: AppTaskLED
    ( U1 V5 ]/ B* c
  106. *    功能说明: LED闪烁。& z+ S. K- m) r# V
  107. *    形    参: 无7 L( z! d0 c- ^# I) Q3 g
  108. *    返 回 值: 无$ |" g8 |9 C3 p5 I
  109. *   优 先 级: 2
    ! f7 Z$ x7 h# P8 [) ^
  110. *********************************************************************************************************
    / ~0 Q8 q9 H, Z; a1 y- ?+ p
  111. */
    5 U( C3 X8 E+ N) @5 g- o3 }! x
  112. __task void AppTaskLED(void)
    * \+ {- P4 i) m% F" G
  113. {$ V+ Z! t- U1 u' P0 Y* E2 I! w
  114.      const uint16_t usFrequency = 200; /* 延迟周期 */
    9 v3 H3 V6 G, u# @! g
  115.    
    ( ?; U! y6 _- P9 m; T
  116.      /* 设置延迟周期 */: x* p0 p1 Q* \) g; o7 C
  117.      os_itv_set(usFrequency);
    ; R% u$ F/ y3 p6 K' a
  118.    
    * x5 `; Z7 K' \2 F- p$ h9 e5 S
  119.     while(1)
    . B$ c& J, d% Z
  120.     {
    $ E7 p) K8 V9 [
  121.          bsp_LedToggle(2);6 H9 E9 E0 A1 {
  122.          bsp_LedToggle(3);% X( z6 Z+ x( a% G5 Z

  123. 1 C, S, `. p7 V+ Y+ i. {8 T
  124.          /* os_itv_wait是绝对延迟,os_dly_wait是相对延迟。*/
    : ^4 X& P7 E7 `: R, W
  125.          os_itv_wait();
      z6 a5 M0 E; C9 {4 g$ s% n
  126.     }: A: A9 |1 t: j7 o) u" j) K) J" U
  127. }
    4 `: t/ W. v* u6 f6 {
  128. " x2 z; _1 B0 Q6 [* v7 H0 `
  129. /*- W; Z) Q2 q/ t2 T* a: Q% h
  130. *********************************************************************************************************
    * ?3 s! B. y& y
  131. *    函 数 名: AppTaskMsgPro
    & b( r2 l: q& a& c1 h
  132. *    功能说明: 消息处理,等待任务AppTaskUserIF发来的消息邮箱数据
    9 B. ^" ]) ~! F% T. e+ D; V! j0 \
  133. *    形    参: 无
    " W  L4 p. Z9 S. \- v
  134. *    返 回 值: 无
    4 h* w, N6 L" D0 D& F' o( T: Q
  135. *   优 先 级: 3 9 K& D1 S: M2 d$ _5 N! W
  136. *********************************************************************************************************
    ( t8 o" ]) \* r/ P% X0 ^9 C1 _) E
  137. */( |. p+ [( r) X1 p& n/ ]$ i
  138. __task void AppTaskMsgPro(void)* E; X: e3 X! k, M5 f% ?: r
  139. {' ^/ J7 c2 r. s% h% @5 O& E
  140.      uint8_t *pMsg;) x" S0 ~& A, H8 k9 e- u1 {
  141.      OS_RESULT xResult;/ H' |! }$ c# R2 v# Y1 J0 L
  142.      const uint16_t usMaxBlockTime = 200; /* 延迟周期 */
      D- X1 {$ K1 j; F+ D8 w" H+ H' S; l
  143.    
    3 E+ x/ u2 G7 q9 z& _. a" h
  144.     while(1)
    ! J' z% z4 l) n; D) K5 J& d, c: v
  145.     {
    % J8 d! c# K( C. h* P% X; d6 X
  146.          xResult = os_mbx_wait(&mailbox, (void *)&pMsg, usMaxBlockTime);
    ! ~# y  V8 m# l2 v! J
  147.         3 K% y# X- v  ~$ v+ V
  148.          switch (xResult)" L" u$ C1 g& l  u. m7 Y* D! H- Z+ C
  149.          {3 u8 V$ r: l9 |$ h( {8 f
  150.               /* 无需等待接受到消息邮箱数据 */' U1 g1 e8 z# ~" T. W1 H: L
  151.               case OS_R_OK:
    4 G; C$ Y% e8 o0 J# P& p
  152.                    printf("无需等待接受到消息邮箱数据,pMsg = %d\r\n", *pMsg);
    $ C! _; M* D" b( g( ^
  153.                    break;  , [, @' T) G8 H. ~) F6 d
  154. 1 e# B2 z) P* w  c* v' ?# J. c
  155.               /* 消息邮箱空,usMaxBlockTime等待时间从消息邮箱内获得数据 */. _4 Y) F) K' |/ n3 o: g0 Z
  156.               case OS_R_MBX:; H' U6 A8 R: n" |3 D$ s+ n
  157.                    printf("因为消息邮箱空,usMaxBlockTime等待时间从消息邮箱内获得数据,pMsg = %d\r\n", *pMsg);
    $ C# G* O' S% b0 V, B! t
  158.                    break;
    ( U+ C: _1 v8 j. G

  159. * _/ G0 p4 e& b% J5 D( \% N3 s
  160.               /* 超时 */
    ! K5 J' E5 d* w% T. m
  161.               case OS_R_TMO:
    3 g4 b+ r+ b7 u+ G( J( A0 e
  162.                    bsp_LedToggle(1);
    ( h, h* N9 R5 b% {
  163.                    bsp_LedToggle(4);( S9 e  W; \4 S- H; l, b; V
  164.                    break;
    + C! A5 `. u' Y0 {
  165.             
    ( O7 l2 ]5 X8 y. R3 S* P! O
  166.               /* 其他值不处理 */
    . S. w% O4 ]! V3 z
  167.               default:                      \' U, u& B0 B2 o) i) ]6 O+ \1 w7 \* z
  168.                    break;
    * X4 t, j5 i) f$ r; T% D0 o
  169.          }   
    , B" R& f- G1 Z; _" v
  170.     }( O/ q9 J5 J( F% A' c
  171. }! H3 P" w$ h7 u; t- x7 @/ o

  172. 3 |& @& c: R) K, m5 s0 n+ \5 G
  173. /*, s3 g+ e0 [# @# z: o) ]& U
  174. *********************************************************************************************************
    , ]/ r4 u/ z" ^6 i) A8 a% k
  175. *    函 数 名: AppTaskStart
    ' n' _' m% t7 J
  176. *    功能说明: 启动任务,也就是最高优先级任务。这里实现按键扫描。
    & H5 x/ ]$ ?+ b! o9 G2 E! r* \
  177. *    形    参: 无$ m! ]# b' o0 W4 H% ^- V
  178. *    返 回 值: 无( i5 Q9 I: s# p) v5 [6 F! ]' M
  179. *   优 先 级: 4
    % D& s/ K7 Q- S+ X- R% G
  180. *********************************************************************************************************( E; J8 [  Z7 D% d3 y
  181. */
    - F# \: G/ Z* d5 d) g. E3 j$ K
  182. __task void AppTaskStart(void)
    + l1 h* Z- R5 j
  183. {
    ; i2 ^, b( g5 _! |: p* |4 l) M- x
  184.      /* 创建任务 */
    : t3 K& z& x( r, [$ E, M5 R) q; C7 b
  185.      AppTaskCreate();" z' ?- J' [0 c5 \3 r
  186.       W" U1 s: T# Q; a6 g/ v  [
  187.      /* 创建任务通信机制 */
    2 T' r/ f, t9 @; w5 r* ?4 I
  188.      AppObjCreate();
    ( f" K1 c( J6 _
  189.     . y; o2 f3 Q4 \: }( R5 @9 n
  190.     while(1)
    . D$ v' B1 M" F( |- R! y  S# L$ S5 b- e1 M
  191.     {
    3 k" C% }5 s1 T3 X' B1 ^
  192.          /* 按键扫描 */4 u% C) @5 b) Z
  193.          bsp_KeyScan();6 D, G+ n5 y$ X: R5 W. R
  194.         os_dly_wait(10);0 A; T6 ~* j- ]: T4 I( ^* x" ^. Y
  195.     }& N9 ]% M6 k8 ~+ ^9 P4 k  F
  196. }
复制代码
+ ^' ?" x; C; d
# d! z- V7 c: e, q! s# V! h  u3 a& |

5 R5 C- B0 p$ _/ _' D% C4 k& |
baiyongbin2009 回答时间:2016-2-3 15:43:10
18.3.2   STM32F407开发板实验
配套例子:
    V5-417_RTX实验_内存管理(4字节对齐)
实验目的:
    1.     学习RTX的内存管理(4字节对齐)。
    2.     函数_declare_box和_init_box用于4字节对齐的内存池初始化。这里4字节对齐的含义
  a.内存池的首地址是4字节对齐(4字节对齐就是地址对4求余等于0)。
  b.每个内存块大小也得是4字节的倍数,这样才能保证每申请到的一个内存块的首地址也是4字节对齐。
  c.4字节对齐是由RTX系统完成的。
实验内容:
    1. K1按键按下,串口打印。
    2. K2键按下,申请一个内存块用于8位整形变量,然后向消息邮箱发送数据。
    3. K3键按下,申请一个内存块用于16位整形变量,然后向消息邮箱发送数据。
    4. 摇杆OK键按下,申请一个内存块用于32位整形变量,然后向消息邮箱发送数据。
    5. 各个任务实现的功能如下:
  AppTaskUserIF任务   :按键消息处理。
  AppTaskLED任务     :LED闪烁。
  AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的消息邮箱数据。
  AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
RTX配置:
    RTX配置向导详情如下:
18.7.png
                              
Task Configuration
Number of concurrent running tasks
  允许创建4个任务,实际创建了如下四个任务:
                AppTaskUserIF任务   :按键消息处理。
                AppTaskLED任务     :LED闪烁。
                AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的消息邮箱数据。
                AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
    Number of tasks with user-provided stack
  创建的4个任务都是采用自定义堆栈方式。
RTX任务调试信息:
18.8.png
程序设计:
任务栈大小分配:
    staticuint64_t AppTaskUserIFStk[512/8];   /* 任务栈 */
    staticuint64_t AppTaskLEDStk[256/8];      /* 任务栈 */
    staticuint64_t AppTaskMsgProStk[512/8];  /* 任务栈 */
    staticuint64_t AppTaskStartStk[512/8];     /* 任务栈 */
    将任务栈定义成uint64_t类型可以保证任务栈是8字节对齐的,8字节对齐的含义就是数组的首地址对8求余等于0。如果不做8字节对齐的话,部分C语言库函数,浮点运算和uint64_t类型数据运算会出问题。
系统栈大小分配:
18.9.png
RTX初始化:
  1. /*2 [. L' i) p8 [* V0 i# a
  2. *********************************************************************************************************5 i3 _: L* r; I, v9 J7 k
  3. *    函 数 名: main! x- U- ~7 m4 d
  4. *    功能说明: 标准c程序入口。  I6 N3 @% N: r; t
  5. *    形    参: 无- s  r! T9 b) z$ @
  6. *    返 回 值: 无
    , s9 R3 r; w$ E; D5 Q. }$ m7 n
  7. *********************************************************************************************************
    4 U) d1 {- @1 b5 P* n
  8. */
    - n% v6 t6 V" V
  9. int main (void)
    + i9 v2 c$ R! A+ L, E
  10. {   ; o8 B0 _6 t8 \8 x8 M; |* v% z
  11.      /* 初始化外设 */
    ' g2 h: W8 E& u4 q
  12.      bsp_Init();
    5 R3 l! P# h, Q9 S. D/ O
  13.       x& |& i4 x% V% Z) S
  14.      /* 创建启动任务 */1 {% S8 p: ^/ k  D& N$ K
  15.      os_sys_init_user (AppTaskStart,             /* 任务函数 */
    0 g: G" f4 y% ]3 u7 ?6 @
  16.                        4,                        /* 任务优先级 */$ e( M; }* Q: X- p6 A" P, X/ j
  17.                        &AppTaskStartStk,         /* 任务栈 */
    - Y& D* ]' Q! L) r9 ]
  18.                        sizeof(AppTaskStartStk)); /* 任务栈大小,单位字节数 */9 B$ @  Y  n# ~! u3 f
  19.      while(1);
    9 \' \8 Z. m# a- t9 l
  20. }
复制代码

. C$ @/ b. l! U  f% X  g
RTX任务创建:
  1. /*/ W  Y/ Y  k- r
  2. *********************************************************************************************************
    7 j# Z2 j/ J$ J+ b$ |! P
  3. *    函 数 名: AppTaskCreate
    ' C$ J4 b: R. q& H3 q+ c) [$ H; x
  4. *    功能说明: 创建应用任务
    + Y8 |8 O3 A7 ~* `/ T
  5. *    形    参: 无. M+ y( d# p& F, U6 @! r/ n# {. j, }
  6. *    返 回 值: 无% w: f& T7 y- N: h) k
  7. *********************************************************************************************************
    ; l) Z' {( o; d+ N
  8. */
    ; [  |% Y/ j/ r
  9. static void AppTaskCreate (void)
    - c& J1 |7 A. z) ~; p
  10. {
    3 J' z& H( Q: P5 O) T7 Q
  11.      HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             /* 任务函数 */
    5 a6 O/ A( E$ A+ p8 Z! d& U% K) F( F8 v
  12.                                            1,                         /* 任务优先级 */! |$ P3 O) }# e" y& p, b) `
  13.                                            &AppTaskUserIFStk,         /* 任务栈 */0 t$ j* Z- q# R1 m7 ]; q) I# j! \9 \
  14.                                            sizeof(AppTaskUserIFStk)); /* 任务栈大小,单位字节数 */
    2 v3 V) O; c+ Z0 S1 O' z
  15.     ! A& Q- m) @/ }: p8 N
  16.      HandleTaskLED = os_tsk_create_user(AppTaskLED,              /* 任务函数 */; }8 ^- G3 {6 r3 ~) P# Y% T
  17.                                         2,                       /* 任务优先级 */
    # ~$ U9 ^% S  Y) {( @6 U
  18.                                         &AppTaskLEDStk,          /* 任务栈 */& ]( Z7 D/ Z8 ~# l+ M1 ?
  19.                                         sizeof(AppTaskLEDStk));  /* 任务栈大小,单位字节数 */1 [# K5 ?9 d# _/ z3 n' d2 l
  20.     9 u9 s+ P* b* T( g# L1 ]6 {* w* s
  21.      HandleTaskMsgPro = os_tsk_create_user(AppTaskMsgPro,             /* 任务函数 */
    0 W# d/ d7 s2 ?5 e: f
  22.                                            3,                         /* 任务优先级 */  ^5 |7 y/ N$ v2 @: L# b, q, B
  23.                                            &AppTaskMsgProStk,         /* 任务栈 */
    ! |$ b+ ~2 S' M+ c' C9 ?
  24.                                            sizeof(AppTaskMsgProStk)); /* 任务栈大小,单位字节数 */( ]4 e& `1 `! f2 l! E+ J6 q
  25. }
复制代码

0 K) S4 _5 p( W
内存管理的初始化和消息邮箱的创建:
  1. #define PoolBlocks           10& t. ]+ o. Y4 W# d
  2. #define PoolPerBlockSize     8
      {* `( S" [6 A7 X: `! d
  3. 5 y/ `8 E6 [4 `# O' [; R4 c: e. c
  4. /* 声明一个支持10个消息的消息邮箱 */
    + j7 b5 c  ~, I& U8 }& J. p
  5. os_mbx_declare (mailbox, 10);
    ' ^, c, b$ z( D" r4 a- z

  6. 7 P- n: n' o( P( X
  7. /* 声明一个内存池,10块,每块大小8字节 */# S7 @8 V( Q: S+ K2 Z8 Z% v" n
  8. _declare_box(mpool, PoolPerBlockSize, PoolBlocks);6 Q  o6 I7 {) L. q- I9 c( Q& s
  9. 9 \+ x* O* ?/ @2 ?0 j& v. M7 G# b
  10. /*
    6 v, o6 L) N% w0 w5 J
  11. *********************************************************************************************************9 U' B- t8 [, K  N" I* F
  12. *    函 数 名: AppObjCreate% A/ L" j1 ^6 N/ h+ W, j
  13. *    功能说明: 创建任务通信机制
    . ]7 J) @( l- u8 g- Z! H0 E: |. v
  14. *    形    参: 无
    % u; n# Y  \( ]2 `1 f) y. X  Y
  15. *    返 回 值: 无
    / v' ]  b! w- i# [: ^
  16. *********************************************************************************************************( K' t0 C+ a* U( I5 I+ ]" y3 Z
  17. */: j' Z8 T7 Y! Q
  18. static void AppObjCreate (void)  ^) A9 Q( t  R. K0 D* p6 G
  19. {& g- n2 k& u* z& r7 V
  20.      /* 创建消息邮箱 */9 ?9 e& Z+ `$ L# U% a% g5 q' s  N
  21.       os_mbx_init (&mailbox, sizeof(mailbox));9 J2 t# a% |6 U" r: q
  22.     0 d1 F/ B  {6 J
  23.      /* 初始化内存池,4字节对齐,*/
    3 }1 u2 p4 ]* l, |" C0 v8 n
  24.      _init_box (mpool, sizeof (mpool), PoolPerBlockSize);+ j3 `9 b7 Z6 g2 B
  25. }
复制代码
: B1 e( e- M! ]$ d0 M- O- q
四个RTX任务的实现:
  1. /*
    0 E6 @9 f4 V5 X+ ?% p
  2. *********************************************************************************************************$ q7 i, s8 \; {* W2 z/ j% T3 z
  3. *    函 数 名: AppTaskUserIF, ^' I# ]5 q* e8 F
  4. *    功能说明: 按键消息处理     
    ' D* `4 o. l% p2 e
  5. *    形    参: 无
    ' Z# U0 S, Z+ F6 ]7 ^( m3 x1 y) x
  6. *    返 回 值: 无3 h6 n5 B' F* J, [4 W# u
  7. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反), a, X) C$ F% j+ b% b
  8. *********************************************************************************************************
    - R% W' H0 n/ p- N* u
  9. */+ d( b' \- x/ E# X
  10. __task void AppTaskUserIF(void)
    + p5 m; `9 f. [) U* p* N3 m* r
  11. {
    8 f# j- H0 c9 X# u3 P
  12.      uint8_t  *pucMsg;6 o$ y7 u8 ?9 d, |4 A0 {
  13.      uint16_t *pusMsg;
    2 s( n+ w( Q. v- b; `. i7 S" H
  14.      uint32_t *pulMsg;
    * o) M5 t9 p7 W
  15.      uint8_t ucKeyCode, ucCount = 0;
    # v7 K5 A8 ~7 q2 a

  16. 7 @+ G$ E% ]1 v4 y' v( D
  17.     while(1)
    - g; z6 Z8 o6 q& A$ b) X$ c) h
  18.     {
    9 d0 e1 h# K8 y+ A- O
  19.          ucKeyCode = bsp_GetKey();
    4 j1 T  q9 V$ e! F
  20.         
    : a/ G5 U& S. X
  21.          if (ucKeyCode != KEY_NONE)
    6 E3 a4 y7 E, q# o2 b! @  W  S
  22.          {
    % F8 @3 Z; a7 t; B4 }/ z: w
  23.               switch (ucKeyCode)! T% x' w5 ?& }7 O. {
  24.               {$ G- v8 m1 ~- C% ^
  25.                    /* K1键按下,打印调试说明 */
    * l) f6 z# A# W1 R7 E
  26.                    case KEY_DOWN_K1:( _+ I0 o8 K- ]0 ]" I
  27.                        printf("K1键按下,使用MDK中自带的RTX调试组件,请务必使用MDK4.74版本进行调试\r\n");
    ! `4 C3 ~9 e; u9 x! U: M
  28.                        break;  
    1 ~: I$ H6 z+ W5 c1 L$ `
  29. ' l! X' w+ h+ P# ~% t7 e
  30.                    /* K2键按下,申请一个内存块用于8位整形变量,然后向消息邮箱发送数据 */
    ' Z, q) l5 u. Q) W0 q
  31.                   case KEY_DOWN_K2:
    % M# T; I  N$ C( p5 K
  32.                        /* 申请一个内存块用于8位整形变量 */
    % O' T$ y1 |- |$ }  N& J# T: P
  33.                        pucMsg  = _alloc_box (mpool);9 w8 |9 [) k5 p& r: ]) P6 P
  34.                        *pucMsg = ucCount++;) Z+ |5 m9 c9 j( O
  35.                   , d' w* v' H6 j/ n$ C1 F# a
  36.                        /* 向消息邮箱发数据,如果消息邮箱满了,等待100个时钟节拍 */& f6 b6 r) ^( D3 o
  37.                        if(os_mbx_send (&mailbox, pucMsg, 100) != OS_R_OK)
      |5 x0 I1 U9 g# B0 f  ]; Y
  38.                        {5 w+ k* U+ J$ {* ?: q! B
  39.                             /* 发送失败,即使等待了100个时钟节拍 */
    % b$ {6 a1 A; {2 H, Q9 q  @7 |
  40.                             printf("K2键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\r\n");. e% ?# s. U! b
  41.                             _free_box (mpool, pucMsg);* l- V9 R2 ~, X7 g4 ?/ b2 Y+ o
  42.                        }) R% M+ Y# F1 s
  43.                        else, ?1 B* a* N8 V+ D6 n, z2 J" T, z
  44.                        {
      S4 g; _( P/ ?' y
  45.                             /* 发送成功 */: A: Z" O6 d2 B+ ]
  46.                             printf("K2键按下,向消息邮箱发送数据成功\r\n");   ! d) D4 V) Y' ?) v
  47.                             _free_box (mpool, pucMsg);+ f$ g: e( ]$ i7 y- ]
  48.                        }5 I" Q3 ^( L  w
  49.                        break;  $ i. B* E* G* ^+ t' T+ H( R
  50. . E" t5 i! X/ o5 ?3 m/ }
  51.                    /* K3键按下,申请一个内存块用于16位整形变量,然后向消息邮箱发送数据 */
    & G9 Z: i' u8 W& h
  52.                    case KEY_DOWN_K3:
    / {' a3 v  I5 D. @
  53.                        /* 申请一个内存块用于16位整形变量 */) C. i4 j1 {- i
  54.                        pusMsg  = _alloc_box (mpool);
    1 C0 O  y# Z: N' D# _8 u1 K. d
  55.                        *pusMsg = ucCount++;5 _$ S& Q  p  C( \" J
  56.                   
    . [) E) |# V" u$ W" {* [
  57.                        /* 向消息邮箱发数据,如果消息邮箱满了,等待100个时钟节拍 */
    8 o. q0 c5 ^. K4 H# m9 l
  58.                        if(os_mbx_send (&mailbox, pusMsg, 100) != OS_R_OK)5 f0 @2 K3 C1 z2 T+ b
  59.                        {+ h6 y2 P- i. |
  60.                             /* 发送失败,即使等待了100个时钟节拍 */
    * ?* l) ]5 H( a: R+ D$ j6 e7 q( w
  61.                             printf("K3键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\r\n");
    / J$ B; f: h3 A$ M/ `7 [
  62.                             _free_box (mpool, pusMsg);
    : t( t) C$ B+ _0 @5 }) I- O
  63.                        }& B2 Q: Z3 f9 m( ~3 T" q6 s
  64.                        else
    + B! Z  x, Y  Z
  65.                        {4 A# ?. w3 J4 D' t( M
  66.                             /* 发送成功 */$ K0 F$ W( v3 o) ^  y0 n. ?- z5 I
  67.                             printf("K3键按下,向消息邮箱发送数据成功\r\n");   
    * z5 I# V' g  q9 @4 Y
  68.                             _free_box (mpool, pusMsg);
    $ x) x& @  n% M  d7 `( b% t# x9 G
  69.                        }
    9 s1 Q/ f, R6 s; G, A9 \
  70.                        break;  
    4 e4 K- j, L$ `5 Q
  71.                   
    1 r3 a! y( I3 [3 y. @/ {
  72.                    /* 摇杆OK键按下,申请一个内存块用于32位整形变量,然后向消息邮箱发送数据 */
    & J* u' p$ A5 S# y7 S
  73.                    case JOY_DOWN_OK:3 }8 |3 c$ r+ G
  74.                        /* 申请一个内存块用于32位整形变量 */
    0 W" T, l* b7 ^: ?" m3 h  K
  75.                        pulMsg  = _alloc_box (mpool);
    4 V( W1 v) x! o8 r' R1 r. J7 d
  76.                        *pulMsg = ucCount++;
    9 B6 L, O) t8 V4 _+ _
  77.                   
    ! q) F& A  V/ J  ]% e4 E% b
  78.                        /* 向消息邮箱发数据,如果消息邮箱满了,等待100个时钟节拍 */6 T$ g( L" b- B( M6 x, o( c$ j& `
  79.                        if(os_mbx_send (&mailbox, pulMsg, 100) != OS_R_OK)
    3 I. j* U1 {& i, M& x( c, N
  80.                         {
    0 G* m% T) K6 R# v. a
  81.                             /* 发送失败,即使等待了100个时钟节拍 */
    ! L* m; H7 d8 \
  82.                             printf("摇杆OK键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\r\n");
    3 L- S5 d$ p; V8 F+ Q8 e
  83.                             _free_box (mpool, pulMsg);
    - @: Z% {7 H5 N, l
  84.                        }, _, t" \( k* y7 [* Z
  85.                        else
    ! I3 H/ e6 G2 I
  86.                        {# V" Z/ C0 n) A- b* z; y
  87.                             /* 发送成功 */
    1 [; f1 J2 [. U) |% z
  88.                             printf("摇杆OK键按下,向消息邮箱发送数据成功\r\n");   & q' p8 N. G% g' s4 a
  89.                             _free_box (mpool, pulMsg);" I' r; d( M0 q4 F7 T
  90.                        }% |6 Y3 w- Y) m8 J) A
  91.                        break;! J% M2 b) j- [1 }
  92. 1 {' w; d7 l$ p6 c: a9 ?
  93.                    /* 其他的键值不处理 */" ~: V/ q$ _9 }
  94.                    default:                    7 W  U+ c- Z: [' Y' y* W. Z
  95.                        break;! b3 J2 b$ c! B  _# e+ B6 I
  96.               }
    ; w  @6 l: [$ k' n
  97.          }' F7 U" Q" y7 I" [
  98.         % O% _$ H* ]9 ^$ N2 v
  99.          os_dly_wait(20);
    6 W8 p% D2 k: U5 V4 M" E
  100.      }
    & ^, k! N5 a% r4 e  D0 B
  101. }6 V8 q4 @  M4 `; ~2 t) ^0 ~
  102. 7 y4 [) V) F# l: G- f
  103. /*
    3 ^* _5 G% H6 c) D8 O
  104. *********************************************************************************************************$ j: k  g3 C0 ^+ p
  105. *    函 数 名: AppTaskLED$ c/ x: A3 V) F+ J1 q$ M) M" f1 \
  106. *    功能说明: LED闪烁。
      H; h! _9 ^  I+ j. {
  107. *    形    参: 无& p0 P1 B; Z" Z* C8 v
  108. *    返 回 值: 无
    2 c# j, n' ]- H3 |' S( ?' Q; n+ w9 I& v
  109. *   优 先 级: 2 + `* p4 |; a4 B( s! i6 a
  110. *********************************************************************************************************
    , C# h6 Z! i7 ]4 b1 y( V
  111. */
    : ~' |) V( Q6 Z  R+ D
  112. __task void AppTaskLED(void)  s$ z9 n9 z% |; e5 a1 [
  113. {- O1 G4 C* C8 N% V7 T! `4 B
  114.      const uint16_t usFrequency = 200; /* 延迟周期 */5 m% L. Q: t, I; [1 d
  115.     ) S2 ^) |+ [: P& O9 {( _0 t
  116.      /* 设置延迟周期 */
    ' M# q% H- g& y" g# ]% L
  117.      os_itv_set(usFrequency);
    $ ~7 q* q9 R$ ?  w
  118.    
    " q2 w$ M8 N5 r+ ]' F; T  e
  119.     while(1)4 Y0 Q8 Z# [* M+ x  o- k/ x
  120.     {
    % [, }" \6 ]) z$ B* |
  121.          bsp_LedToggle(2);9 L) O, R" ?8 |8 c
  122.          bsp_LedToggle(3);0 `6 L" H1 W+ u% ?& r5 j5 S

  123. ( I! ?! ], f, }3 W
  124.          /* os_itv_wait是绝对延迟,os_dly_wait是相对延迟。*/
    : F. H7 D3 @4 l' |
  125.          os_itv_wait();/ c$ w  s; v, m; N! D6 Y- Y9 \; v
  126.     }4 ^/ T1 L2 m' ?5 M9 p
  127. }2 L4 J3 N  a; J  K) a

  128. 6 K& b7 S5 `* n0 M5 L
  129. /*! u5 _7 }0 G3 @
  130. *********************************************************************************************************
    , f& W* |% C- _* {$ h
  131. *    函 数 名: AppTaskMsgPro$ I6 L  B! ~0 w! p- w
  132. *    功能说明: 消息处理,等待任务AppTaskUserIF发来的消息邮箱数据2 ^3 x( |9 P3 J5 R) B% l$ \
  133. *    形    参: 无* ]$ {  k: [4 D: V4 s7 _
  134. *    返 回 值: 无) Z& S6 b9 p9 x3 p
  135. *   优 先 级: 3 ; i- _' Y1 g+ I, V1 _2 P! R" v
  136. *********************************************************************************************************
    ! R6 }$ f5 y, @& ]
  137. */8 }4 ^' h* q# Z. G! p
  138. __task void AppTaskMsgPro(void)
    % ?/ n. Q6 l5 x: q  _* L
  139. {
    7 C8 D  D% v0 H# }1 s( |6 L
  140.      uint8_t *pMsg;5 V- Y7 g, N& g, \# V) x
  141.      OS_RESULT xResult;
      ^, n% {: b/ P9 L
  142.      const uint16_t usMaxBlockTime = 200; /* 延迟周期 */
    5 c. Q: ]0 [% k& a( R) X8 R+ `
  143.    
    / j6 p/ }- r" D0 ~
  144.     while(1)
    + V4 j+ Q  Z* q7 ]1 y) T
  145.     {  j3 R) k) I/ T- x( e8 l2 w- D
  146.          xResult = os_mbx_wait(&mailbox, (void *)&pMsg, usMaxBlockTime);
    3 i' g9 N; i; E& k' h+ ]9 h# j3 S
  147.         
    3 c* m; N) e! ], v2 g
  148.          switch (xResult)  m% O  H0 S6 ]% g! U  E% v& F$ C
  149.          {
    2 b8 g) J" a3 E6 ~
  150.               /* 无需等待接受到消息邮箱数据 */0 Y- Z- N) R5 ^0 c7 o
  151.               case OS_R_OK:
    / Q" D/ V( B9 o5 B4 @
  152.                    printf("无需等待接受到消息邮箱数据,pMsg = %d\r\n", *pMsg);
    1 Y, o6 o  b/ ?& {* Q! R
  153.                    break;  8 {4 C8 G4 A1 l8 d5 c: {

  154.   J  l9 r1 k* O6 z; [! h; S4 J
  155.               /* 消息邮箱空,usMaxBlockTime等待时间从消息邮箱内获得数据 */
    ; Z4 X2 }0 D6 C9 I
  156.               case OS_R_MBX:
    ( i9 c' ]9 z: i5 \
  157.                    printf("因为消息邮箱空,usMaxBlockTime等待时间从消息邮箱内获得数据,pMsg = %d\r\n", *pMsg);
    7 g. J$ }, u4 @( t0 r/ r' J1 b3 G- _
  158.                    break;
    : t; K0 K! U9 h' ~- l% D7 `
  159. 1 s3 r+ K. D0 k3 }3 q
  160.               /* 超时 */5 T7 R2 u/ g  j; g* m
  161.               case OS_R_TMO:) N, Q5 c4 j2 U# L$ Z' u7 a, j
  162.                    bsp_LedToggle(1);3 O* Z4 V) d. s& a
  163.                    bsp_LedToggle(4);3 W1 f! ?7 y4 T) a* w: c8 L
  164.                    break;9 V. P1 E. Z3 T, N9 G0 u
  165.             
    9 a# Y; s4 @5 W+ R
  166.               /* 其他值不处理 */
      U3 s4 `. T7 ?) o+ S
  167.               default:                    1 F+ T+ ~+ f( X# ?( K/ _& ]
  168.                    break;; W5 W# g  j2 j
  169.          }   
    . @0 [; |. k& Z- `! Z4 l+ v2 ]
  170.     }' W# g9 R5 ]7 c/ m: x, m) b/ {
  171. }1 ~3 B3 v6 f9 L

  172. ) S2 s* l! n: n: o: p
  173. /*
    8 K: K, L; y6 ^- Z/ U
  174. *********************************************************************************************************7 f- h# P5 I0 q' O: ?
  175. *    函 数 名: AppTaskStart* ~) X$ E/ d8 T% v+ G
  176. *    功能说明: 启动任务,也就是最高优先级任务。这里实现按键扫描。% Q& b8 ^( O# V2 |! r' Y% R' q
  177. *    形    参: 无, g& j& j  S3 ?/ Z  A+ |
  178. *    返 回 值: 无
    ! w4 E# ]. ?& b
  179. *   优 先 级: 4 1 O* |. u1 P4 m; F- z
  180. *********************************************************************************************************
    ; G9 C, N, }; v4 @
  181. */, X) J3 Z# F; @; O1 L) u
  182. __task void AppTaskStart(void)7 @0 K# x& P4 d+ @% w7 R
  183. {* {' ~! o" Y+ c8 c# L% \
  184.      /* 创建任务 */
    4 U9 }/ W9 \0 [2 m- F9 u8 |( _
  185.      AppTaskCreate();3 ]$ {' ^- l. o) R9 ^6 x; W: c
  186.     - e8 j3 A: l0 Q1 m4 a- \" K# l( h
  187.      /* 创建任务通信机制 */
    9 Z9 v' A( J$ m! ~' Y; d# _
  188.      AppObjCreate();
    : |: P, f  C6 @8 F
  189.     ) p# a: x, U; i; H
  190.     while(1)
    1 J# d, g9 f* t* S& l- r" {
  191.     {
    - C$ P' Q4 E- o8 s* o
  192.          /* 按键扫描 */
    2 f6 z- b1 C- }7 r% q' \, P! b1 _
  193.          bsp_KeyScan();
    2 p  i- ]: `4 z
  194.         os_dly_wait(10);' I5 U. J' E4 r. C, [
  195.     }
复制代码
9 I3 x+ Y) k( Y6 D, o) A
( Q; p. R& T! K' M
baiyongbin2009 回答时间:2016-2-3 15:59:57
18.4 实验例程说明(8字节对齐)
  A( x% r) ^$ M$ J: l, |# ?" @
18.4.1 STM32F103开发板实验
配套例子:
    V4-418_RTX实验_内存管理(8字节对齐)
实验目的:
    1.     学习RTX的内存管理(8字节对齐)。
    2.     函数_declare_box8和_init_box8用于8字节对齐的内存池初始化。这里8字节对齐的含义:
   a.     内存池的首地址是8字节对齐(8字节对齐就是地址对8求余等于0)。
   b.    每个内存块大小也得是8字节的倍数,这样才能保证每申请到的一个内存块的首地址也是8字节对齐。
   c.     8字节对齐是由RTX系统完成的。
实验内容:
    1.K1按键按下,串口打印。
    2.K2键按下,申请一个内存块用于8位整形变量,然后向消息邮箱发送数据。
    3.K3键按下,申请一个内存块用于16位整形变量,然后向消息邮箱发送数据。
    4.摇杆OK键按下,申请一个内存块用于32位整形变量,然后向消息邮箱发送数据。
    5.摇杆UP键按下,申请一个内存块用于64位整形变量,然后向消息邮箱发送数据。
    6.各个任务实现的功能如下:
  AppTaskUserIF任务   :按键消息处理。
  AppTaskLED任务     :LED闪烁。
  AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的消息邮箱数据。
  AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
RTX配置:
    RTX配置向导详情如下:
                              
18.10.png
Task Configuration
Number of concurrent running tasks
  允许创建4个任务,实际创建了如下四个任务:
                AppTaskUserIF任务   :按键消息处理。
                AppTaskLED任务     :LED闪烁。
                AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的消息邮箱数据。
                AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
    Number of tasks with user-provided stack
  创建的4个任务都是采用自定义堆栈方式。
RTX任务调试信息:
18.11.png
程序设计:
任务栈大小分配:
    staticuint64_t AppTaskUserIFStk[512/8];   /* 任务栈 */
    staticuint64_t AppTaskLEDStk[256/8];      /* 任务栈 */
    staticuint64_t AppTaskMsgProStk[512/8];  /* 任务栈 */
    staticuint64_t AppTaskStartStk[512/8];     /* 任务栈 */
    将任务栈定义成uint64_t类型可以保证任务栈是8字节对齐的,8字节对齐的含义就是数组的首地址对8求余等于0。如果不做8字节对齐的话,部分C语言库函数,浮点运算和uint64_t类型数据运算会出问题。
系统栈大小分配:
18.12.png
RTX初始化:
  1. /*
    - Q! K, U2 D0 Y, v& J, t- S; ?
  2. *********************************************************************************************************
    1 Y  j8 K' u5 c, V# l5 e# Q
  3. *    函 数 名: main
    1 z7 p3 `6 e9 n$ g$ k( w
  4. *    功能说明: 标准c程序入口。
    ! l' C/ P, l/ w0 y; g5 a2 t
  5. *    形    参: 无
    ; d* q) f# ^, c0 F1 }
  6. *    返 回 值: 无
    - s  y" g) q$ e+ P: b0 |  p
  7. *********************************************************************************************************
    " D8 \% t, u- S1 y4 s1 _
  8. *// ?8 g' p5 M& k9 \# W
  9. int main (void)3 n2 f& T6 r, q1 o
  10. {   
    8 t& w8 _2 L5 m6 ^6 n
  11.      /* 初始化外设 */
    : L6 ?, n9 H- E+ T, x, x' t* T
  12.      bsp_Init();
    * @3 `9 M/ @4 N4 X
  13.    
    - N- {9 t2 z& r! b  Q
  14.      /* 创建启动任务 */
    8 q4 Q' {: e# ^* u8 e  n
  15.      os_sys_init_user (AppTaskStart,             /* 任务函数 */4 |1 W: ~0 n- @' P+ t' |+ b
  16.                        4,                        /* 任务优先级 */3 G2 ]8 m9 l, ~0 {9 X! c
  17.                        &AppTaskStartStk,         /* 任务栈 */# m% W1 n0 g) f
  18.                        sizeof(AppTaskStartStk)); /* 任务栈大小,单位字节数 */+ E$ c* m- ~- m) E0 b( ^
  19.      while(1);# V  G, C% U# Z3 e: [, U/ ]9 T5 L
  20. }
复制代码

7 L* a9 h, F; Q/ J, F. P% i& j8 C
RTX任务创建:
  1. /*
    # B# S) h. b6 S1 A- R# U
  2. *********************************************************************************************************
    & m& I  v: U# f( @
  3. *    函 数 名: AppTaskCreate; M- E/ o$ L! r. ?4 ^, I
  4. *    功能说明: 创建应用任务# B* O$ n1 P: r! f9 |
  5. *    形    参: 无
    5 G# }( {9 }$ o( J5 }) ~' V/ X
  6. *    返 回 值: 无
    ( \1 N( r/ z( k2 N! x+ [
  7. *********************************************************************************************************7 n4 ]% i4 i9 \4 K, T9 N
  8. */
    1 u' q. J+ M, O5 x
  9. static void AppTaskCreate (void)2 ]) w, D: F' |, X7 X* W
  10. {
    . v, m! K7 `! M# D% t6 \
  11.      HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             /* 任务函数 */7 u2 |4 y* s' m1 N3 W
  12.                                            1,                         /* 任务优先级 */
    6 H! j) c! E8 u# _
  13.                                            &AppTaskUserIFStk,         /* 任务栈 */2 m7 j+ n5 E4 T7 }
  14.                                            sizeof(AppTaskUserIFStk)); /* 任务栈大小,单位字节数 */4 N( t9 B3 Y$ o9 _
  15.    
    " _; `4 J$ i/ n% R0 p, b
  16.      HandleTaskLED = os_tsk_create_user(AppTaskLED,              /* 任务函数 */
    5 j, S8 V, n; V! G  L
  17.                                         2,                       /* 任务优先级 */, h2 D; C) s. R3 X  C- |
  18.                                         &AppTaskLEDStk,          /* 任务栈 */" B: B5 ]$ C. m% `- v, \  J2 h: I% \
  19.                                         sizeof(AppTaskLEDStk));  /* 任务栈大小,单位字节数 */( N1 D( L% r$ d8 V! [0 ~0 {
  20.     ( k% v' X. \% d* J* j1 K
  21.      HandleTaskMsgPro = os_tsk_create_user(AppTaskMsgPro,             /* 任务函数 */8 w  |8 `+ b+ h3 T, A% Q
  22.                                            3,                         /* 任务优先级 */9 }5 @& X" a; G; z5 s* p
  23.                                            &AppTaskMsgProStk,         /* 任务栈 */, {! l6 D5 R# r# U
  24.                                            sizeof(AppTaskMsgProStk)); /* 任务栈大小,单位字节数 */2 ]0 F9 K0 ?9 E0 t3 y* S/ R: i' A! ?
  25. }
复制代码
# l4 R2 G, t( D9 Z$ Y
内存管理的初始化和消息邮箱的创建:
  1. #define PoolBlocks           10
    ; o1 \5 b% g1 o
  2. #define PoolPerBlockSize     8, _1 ~( |# a* _. h+ X2 u

  3. 4 m' _$ I; {1 _
  4. /* 声明一个支持10个消息的消息邮箱 */8 H' P$ h, a4 O: ^% Z$ j6 I+ ]" ^
  5. os_mbx_declare (mailbox, 10);3 U- `# N( L/ e1 X! H1 {- N
  6. & S6 P3 S) ^' _+ P5 _" m- e
  7. /* 声明一个内存池,10个块,每块大小8字节 */
    $ F0 ~4 O9 S# `7 k4 v& R
  8. _declare_box8(mpool, PoolPerBlockSize, PoolBlocks);
    & \/ H; q4 G' s" v
  9. 2 r  D! m$ A, P
  10. /*+ j5 Q7 [" _. i
  11. *********************************************************************************************************8 P5 M" E" ?) L& U* {
  12. *    函 数 名: AppObjCreate
    , ~; C. _) t5 U) R0 `
  13. *    功能说明: 创建任务通信机制
    / m# ^* b8 }0 w& f2 @+ ^+ W1 x6 @
  14. *    形    参: 无
      d1 G% M; b7 |
  15. *    返 回 值: 无
    " E1 P( |; z6 C8 x2 H
  16. *********************************************************************************************************$ k! x3 r. S+ i' z
  17. */
    ; P; r" C' p. T' `( A0 b
  18. static void AppObjCreate (void); @0 Z( M4 `' h( o
  19. {4 j/ J  Y4 K% u5 B& y' U
  20.      /* 创建消息邮箱 */
    ' \4 _. b# o( n2 v  @; C. K7 X+ |
  21.       os_mbx_init (&mailbox, sizeof(mailbox));! f" x7 f7 t& @
  22.     6 e. K! G5 x2 n0 }# t
  23.      /* 初始化内存池,8字节对齐,*/. @, ?. @$ z0 m5 i- v- F# R
  24.      _init_box8 (mpool, sizeof (mpool), PoolPerBlockSize);& r/ D% a* x* K6 m8 q( L, }5 n
  25. }
复制代码
! v1 N' J9 f0 T4 B. u
四个RTX任务的实现:
  1. /*2 N  r* s! T3 V/ ^# R2 y6 a
  2. *********************************************************************************************************
    % B* J7 S5 l7 p
  3. *    函 数 名: AppTaskUserIF7 b+ J# j( S- h2 N8 R; W
  4. *    功能说明: 按键消息处理     1 U# S2 V4 f; k, j
  5. *    形    参: 无
    0 M8 p% I6 P4 H
  6. *    返 回 值: 无* C0 [" y% J! L0 |& I1 g5 C
  7. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)1 K8 v1 ]1 J9 O2 r) }. x& e
  8. *********************************************************************************************************
    ! w8 e/ Y2 ?9 Z3 H  T8 h
  9. */2 x  ?9 t4 }) ?2 v/ V
  10. __task void AppTaskUserIF(void)
    - s4 v. B- {" C" B3 s, w  W" s: s
  11. {
    & v. |( X0 Z% S) |$ r8 |3 b
  12.      uint8_t  *pucMsg;
    . C( G/ K1 ^* j# u8 R6 T# W9 l
  13.      uint16_t *pusMsg;8 i6 c( S! U  [3 E, a% i% ]
  14.      uint32_t *pulMsg;8 K7 z' f# S) Q) i/ y, g
  15.      uint64_t *pullMsg;! n, _) t$ T! ^! `
  16.     2 K% p. k; W" m# }' f/ H: W
  17.      uint8_t ucKeyCode, ucCount = 0;
    # y' @+ d  w1 ~* U* R1 E  Y. u

  18. . Q1 \; |" }, Z/ r% V
  19.     while(1)* S+ L/ }" |' |  r. @% @
  20.     {
    : H3 z8 s& _& E# L+ w$ p; v/ w# P$ x
  21.          ucKeyCode = bsp_GetKey();
    ) M+ [9 l1 L9 O- M0 M6 u5 q* V
  22.         ( `  d8 F3 {: r. t
  23.          if (ucKeyCode != KEY_NONE)
    " F( s- n! B4 D; X: g
  24.          {
    % ?# F8 z! L7 H+ J4 w1 y
  25.               switch (ucKeyCode)
      _) d; R; |& ~% ?. L5 y
  26.               {
    - _" `2 J7 f' W. z4 R5 y, F. [
  27.                    /* K1键按下,打印调试说明 */8 |( r1 u4 M! Y# X$ N: m
  28.                    case KEY_DOWN_K1:3 o4 b7 G- b" G( r( o) j
  29.                        printf("K1键按下,使用MDK中自带的RTX调试组件,请务必使用MDK4.74版本进行调试\r\n");6 O5 b+ q/ ?# F+ O. p) Y
  30.                        break;  
    - M2 h+ B9 n6 H; c4 c0 H4 z
  31. % Q; I1 H0 u0 I
  32.                    /* K2键按下,申请一个内存块用于8位整形变量,然后向消息邮箱发送数据 */  L' T& b' L7 p
  33.                    case KEY_DOWN_K2:
    % \6 s* H" `/ {4 f* b1 z
  34.                        /* 申请一个内存块用于8位整形变量 */6 ?* C& ^5 L! G. e8 r
  35.                        pucMsg  = _alloc_box (mpool);
    ( m1 B7 }+ a6 v! x! l- u
  36.                        *pucMsg = ucCount++;
    ; R0 A" d8 }5 o' ~
  37.                   
    4 B# V/ E, F7 F+ r* t  P# ?
  38.                        /* 向消息邮箱发数据,如果消息邮箱满了,等待100个时钟节拍 */* _: H$ d5 Q2 [. F
  39.                        if(os_mbx_send (&mailbox, pucMsg, 100) != OS_R_OK)! {+ h8 R) n& b* C2 f& r
  40.                        {
    * X( ^, g* x0 j9 }& x& T7 {0 U7 V
  41.                             /* 发送失败,即使等待了100个时钟节拍 */) V+ N' `" a% u* @
  42.                             printf("K2键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\r\n");% N* f  o& E+ H5 U
  43.                             _free_box (mpool, pucMsg);
    ) x1 l/ }5 j+ C4 o  a6 S! j
  44.                        }
    , l1 e+ L2 D8 h6 X% i; S5 R5 ^- h
  45.                        else: q9 M) ]2 j% }7 C
  46.                        {3 V$ I- I- L4 X- D2 {7 B3 H
  47.                             /* 发送成功 */
    $ `' ]. W3 e" u4 I' b
  48.                             printf("K2键按下,向消息邮箱发送数据成功\r\n");   
    ) W9 D3 J1 z% P4 H  N" f8 m  ]
  49.                             _free_box (mpool, pucMsg);, u& j- t! M# o2 a& g  @
  50.                        }
    ' m' P- L1 m. c/ K+ r) ~+ {. ~4 c
  51.                        break;  
    3 [9 @$ w4 V) f

  52. 8 P6 R1 y1 [3 o$ }+ T# S
  53.                    /* K3键按下,申请一个内存块用于16位整形变量,然后向消息邮箱发送数据 */8 ]/ I, n' k9 V0 y' t1 @9 ]
  54.                    case KEY_DOWN_K3:, b0 [+ H! G0 s, w2 C- k) x
  55.                        /* 申请一个内存块用于16位整形变量 */
    9 Y5 c* b& D8 R
  56.                        pusMsg  = _alloc_box (mpool);
    ( {1 w: ]4 A$ k* J+ [+ Z& u( f, f# z
  57.                        *pusMsg = ucCount++;/ p2 o! v- D9 S
  58.                   
    / }" d; n9 X) ?$ z, y" {9 P
  59.                        /* 向消息邮箱发数据,如果消息邮箱满了,等待100个时钟节拍 */
    / c2 A+ \. q5 y6 F( M) F
  60.                        if(os_mbx_send (&mailbox, pusMsg, 100) != OS_R_OK)
    $ z: N! }* V5 e7 r
  61.                        {2 K3 t/ n2 ?+ ^+ l
  62.                             /* 发送失败,即使等待了100个时钟节拍 */2 b% X9 o) w7 t/ u
  63.                             printf("K3键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\r\n");
    . R# f. o, t' {8 ^0 P
  64.                             _free_box (mpool, pusMsg);
    $ }, ~% U. w. G! e
  65.                        }' M, G8 f1 J, Q  b( e* f
  66.                        else
    $ i$ |& \6 A! I) Z$ v/ S0 s
  67.                        {3 \2 T) K7 c. d( ?* {
  68.                             /* 发送成功 */( a' j. N, t/ Y8 p0 X9 |
  69.                             printf("K3键按下,向消息邮箱发送数据成功\r\n");   6 X0 m; U( e7 F7 z- k0 U7 _1 q
  70.                             _free_box (mpool, pusMsg);
    4 X" J. j9 i0 F+ M$ j$ t
  71.                        }, ^8 o9 q! u% B8 j0 B
  72.                        break;  
    . Y2 c, c, z2 S& X  U% n' ^8 [# V
  73.                   ' r' V0 z' s+ `: J! Z2 R0 N
  74.                   /* 摇杆OK键按下,申请一个内存块用于32位整形变量,然后向消息邮箱发送数据 */7 v9 k( J0 K( I& |* U, P; z; O
  75.                    case JOY_DOWN_OK:
    - _2 k. M3 ~2 S( R/ ^- f% Y9 s
  76.                        /* 申请一个内存块用于32位整形变量 */
    $ o2 I8 b/ i6 Y+ A7 t
  77.                        pulMsg  = _alloc_box (mpool);
    8 {% H" f: G5 j! @5 ~: f0 M
  78.                        *pulMsg = ucCount++;
    6 ]& ?1 I3 h( O$ e
  79.                   $ ?  |. d1 k1 ?, Q/ M" P
  80.                        /* 向消息邮箱发数据,如果消息邮箱满了,等待100个时钟节拍 */
    - {. m, [1 a# e5 |
  81.                        if(os_mbx_send (&mailbox, pulMsg, 100) != OS_R_OK)
    8 k6 T+ }" B) n0 S& R. b
  82.                        {
    2 ~4 g$ \: G9 S( `1 E) ?1 ]
  83.                             /* 发送失败,即使等待了100个时钟节拍 */5 s0 N7 a# e  A% {& ^" N4 y
  84.                             printf("摇杆OK键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\r\n");
    . a% J8 u2 u3 q6 `6 r$ J
  85.                             _free_box (mpool, pulMsg);. A3 v5 |' z; T; A$ P7 u7 p# d
  86.                        }
    " j5 R# y3 }: Q' C' D/ {
  87.                        else3 b5 c, s0 _  r# }% C' M* M
  88.                        {
    6 \9 W( F, M+ R3 ~- Y+ @
  89.                             /* 发送成功 */1 c* h: D& n: U: o" V$ k9 p
  90.                             printf("摇杆OK键按下,向消息邮箱发送数据成功\r\n");   
    : M/ P, A) z. B. ^
  91.                             _free_box (mpool, pulMsg);* E" P; [- F) P) y
  92.                        }) \# _7 L2 ?- K8 |1 l
  93.                        break;! F5 p9 r+ e% T5 ^
  94. + \) y' o* q5 S: Z% [
  95.                    /* 摇杆UP键按下,申请一个内存块用于64位整形变量,然后向消息邮箱发送数据 */
    8 z! T! s* V; m1 Q" C+ \* \
  96.                    case JOY_DOWN_U:  V& }' M# ?/ T3 y8 ^
  97.                        /* 申请一个内存块用于32位整形变量 */
    3 R- w: V4 z8 z: z# }: r5 J
  98.                        pullMsg  = _alloc_box (mpool);
    : @* A5 B* Z/ d+ c
  99.                        *pullMsg = ucCount++;5 q! e) @. o1 E5 Y! X$ v8 B
  100.                   
    ' m. e, z8 |/ w
  101.                        /* 向消息邮箱发数据,如果消息邮箱满了,等待100个时钟节拍 */9 E$ s6 S5 f9 b4 a1 |8 u$ G$ n
  102.                        if(os_mbx_send (&mailbox, pulMsg, 100) != OS_R_OK)
    : i7 t# d) ?, E2 A2 a
  103.                        {
    ' ~: z$ t7 U5 B& H* E7 m
  104.                             /* 发送失败,即使等待了100个时钟节拍 */( C: ~1 t' R% w; s
  105.                             printf("摇杆OK键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\r\n");
    9 }9 ]& O# R* K
  106.                             _free_box (mpool, pullMsg);! X/ ~9 i0 b$ t% ~( p3 q3 U
  107.                        }# S! P) @* j% r2 S9 E4 t/ F
  108.                        else
    " x8 ?( M/ X: w( k9 R1 i  b
  109.                        {
    : `& [0 F2 g+ a# \  a" \: K
  110.                             /* 发送成功 */6 B2 ~, R! ]: _
  111.                             printf("摇杆OK键按下,向消息邮箱发送数据成功\r\n");   ! j" u/ |2 h& ~( b0 f
  112.                             _free_box (mpool, pullMsg);0 o; ]- R% _. _/ o+ e
  113.                        }$ F  j- ^% o- |( h7 a" C
  114.                        break;
    7 S( s% ?  a5 \1 e) O2 R, T

  115. 2 c& R4 q! D0 R6 }- x3 O' z
  116.                    /* 其他的键值不处理 */! G  G  n% Z7 K
  117.                    default:                    8 g/ p- [' Y: D7 {/ b
  118.                        break;. w/ m% u/ W3 c: t+ i4 L
  119.               }
    0 D2 l5 N" M# I6 T1 C1 H  x' H3 C
  120.          }
    ' n0 u' e6 A- ~3 M& Q. D' d
  121.         . k& s6 S7 G6 o- w
  122.          os_dly_wait(20);( \, S% d- q0 ~4 E) V0 }
  123.      }3 l, ?# T( a3 n5 c
  124. }8 T3 R+ ^" Q6 {, A9 m

  125. 4 T2 N2 c. Z% k& D; Z" P+ b) m& E
  126. /*
    4 R( E1 i* G1 P; [3 Q' J
  127. *********************************************************************************************************2 I2 M5 W6 P6 V' R6 t2 @
  128. *    函 数 名: AppTaskLED
    ( X. u+ ~; u7 ]6 L- s9 G
  129. *    功能说明: LED闪烁。
    ! i" A$ q! u% O1 g, F7 k' Y/ d
  130. *    形    参: 无- H! D, g. ^7 \) \
  131. *    返 回 值: 无
    ( f% l& R. ]- Q5 `/ a8 {+ k/ `
  132. *   优 先 级: 2
    , X  j4 w' P( c" g. Q
  133. *********************************************************************************************************# f+ o! ~" S( E2 o( n( s; L
  134. */
    ' `  z7 T5 Y7 A) F2 V
  135. __task void AppTaskLED(void)0 ~, O! Y" M* C# J
  136. {
    1 v& H/ X4 r1 ?0 h# p7 ~% |
  137.      const uint16_t usFrequency = 200; /* 延迟周期 */4 C+ C6 L) _$ c& |9 o/ z
  138.    
    4 y% V; t! D/ B- S
  139.      /* 设置延迟周期 */( m4 ]) c3 N9 _; S  P. U
  140.      os_itv_set(usFrequency);# p  N& D: t' a( N& W! f& r0 f
  141.     8 R% C: {" G5 R3 q& \0 @) q5 p  L
  142.     while(1)! t. ~5 n+ n* M2 ]" S
  143.     {& `. ]9 J6 i1 N; M
  144.          bsp_LedToggle(2);7 }' H  Y3 T7 x3 h! S. O) G
  145.          bsp_LedToggle(3);
    3 B4 y0 L" ]6 \- j

  146. $ h; {: H. X9 f; j) s
  147.          /* os_itv_wait是绝对延迟,os_dly_wait是相对延迟。*/; \, f7 a6 C+ ^% @6 X2 X( f4 N
  148.          os_itv_wait();- i2 O) v& O  l# n
  149.     }$ S7 P& O, E' G" }0 H4 D$ y: c& ?
  150. }$ I. E, z8 t8 L1 W9 s, n

  151. ) k# h& T$ o3 R/ ~) m% r6 ^) l5 m) y
  152. /*
    ( {% h( ?6 _; ?2 `( B4 s9 L
  153. *********************************************************************************************************( v5 D1 [' `& w
  154. *    函 数 名: AppTaskMsgPro
    6 j4 T+ Z& f$ ~
  155. *    功能说明: 消息处理,等待任务AppTaskUserIF发来的消息邮箱数据
    & H# N5 x% {) a* ~- E- @! }
  156. *    形    参: 无; ?  X) T2 z1 g+ m) d3 I+ R
  157. *    返 回 值: 无6 M/ p8 ]# X( g
  158. *   优 先 级: 3
    4 m8 g" _. C$ t
  159. *********************************************************************************************************
    8 \/ [7 M, Z0 G
  160. */
      N; b% f7 E2 K2 U& b/ D
  161. __task void AppTaskMsgPro(void)- k2 m4 L% H1 \3 u) D; Z
  162. {" J1 E) B4 i3 T( t) ]" R" h
  163.      uint8_t *pMsg;8 M3 F8 p) k7 x% `$ \
  164.      OS_RESULT xResult;; q  j* T0 T! p! B& }. A
  165.      const uint16_t usMaxBlockTime = 200; /* 延迟周期 */
    ) j3 z* j* t- @4 b
  166.    
    # |! [; W  q, L. ^( j+ O
  167.     while(1)7 I% x( `5 u% E3 G  _* E# {
  168.     {
    $ C- Q9 i( X9 i2 T; g
  169.          xResult = os_mbx_wait(&mailbox, (void *)&pMsg, usMaxBlockTime);
    " F6 ?6 }8 r2 T  p7 x. ~* ]
  170.         + J* {* P5 [, s) Z: h
  171.          switch (xResult)
    1 L" r3 r+ b" d# C$ F( n
  172.          {% _7 E: p* |4 b% p: x3 s
  173.               /* 无需等待接受到消息邮箱数据 */
    9 u( [: t4 H7 h
  174.               case OS_R_OK:
    ) H1 X# P2 v! ?8 @% y5 d4 K) E2 O6 S
  175.                    printf("无需等待接受到消息邮箱数据,pMsg = %d\r\n", *pMsg);9 H% e6 u5 h, G% r# K+ e
  176.                    break;  4 A7 i4 ~" \. u8 g, D6 ~

  177. ) S, I+ |# K) G* J" ~& h! k/ S
  178.               /* 消息邮箱空,usMaxBlockTime等待时间从消息邮箱内获得数据 */3 H: F. j7 T& m$ N2 @( m
  179.               case OS_R_MBX:; c3 P7 e5 b& N7 R$ E' c8 G' _
  180.                    printf("因为消息邮箱空,usMaxBlockTime等待时间从消息邮箱内获得数据,pMsg = %d\r\n", *pMsg);4 ^5 b2 n1 \# w( @$ |; {, a3 m1 Q" K
  181.                    break;
    - s! C9 H/ N* O& x" _

  182. ' X5 X0 M/ X& U+ I
  183.               /* 超时 */
    ) L( Q) f' [  p( t
  184.               case OS_R_TMO:, D" V" @. ]6 x0 N1 p8 O4 t! N
  185.                    bsp_LedToggle(1);0 A& m' ^" ?; x& ~( j+ r# s. D
  186.                    bsp_LedToggle(4);
    7 K$ [$ R1 y' c. d- i
  187.                    break;3 u7 L5 N7 k* {
  188.             
    ( L4 n& m/ P9 x9 W+ L+ n
  189.               /* 其他值不处理 */
    & U) N+ W9 o" \
  190.               default:                    
    ; R6 m+ b6 j# P6 n! H
  191.                    break;
    0 ~+ ~7 C# P4 L  q$ x8 X
  192.          }     y! `5 \. a' ]. F; T; s
  193.     }5 A) K$ o1 n4 E, p3 C
  194. }
复制代码
9 z! D- s/ g( g6 ~' Y! `) i! h4 a
, F- [  O) A. g

6 A9 ?! [7 r) c8 a: P
baiyongbin2009 回答时间:2016-2-3 16:03:50
18.4.2   STM32F407开发板实验
配套例子:
    V5-418_RTX实验_内存管理(8字节对齐)
实验目的:
    1.     学习RTX的内存管理(8字节对齐)。
    2.     函数_declare_box8和_init_box8用于8字节对齐的内存池初始化。这里8字节对齐的含义:
  a.     内存池的首地址是8字节对齐(8字节对齐就是地址对8求余等于0)。
  b.    每个内存块大小也得是8字节的倍数,这样才能保证每申请到的一个内存块的首地址也是8字节对齐。
  c.     8字节对齐是由RTX系统完成的。
实验内容:
    1.K1按键按下,串口打印。
    2.K2键按下,申请一个内存块用于8位整形变量,然后向消息邮箱发送数据。
    3.K3键按下,申请一个内存块用于16位整形变量,然后向消息邮箱发送数据。
    4.摇杆OK键按下,申请一个内存块用于32位整形变量,然后向消息邮箱发送数据。
    5.摇杆UP键按下,申请一个内存块用于64位整形变量,然后向消息邮箱发送数据。
    6.各个任务实现的功能如下:
  AppTaskUserIF任务   :按键消息处理。
  AppTaskLED任务     :LED闪烁。
  AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的消息邮箱数据。
  AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
RTX配置:
    RTX配置向导详情如下:
18.13.png
                              
Task Configuration
Number of concurrent running tasks
  允许创建4个任务,实际创建了如下四个任务:
                AppTaskUserIF任务   :按键消息处理。
                AppTaskLED任务     :LED闪烁。
                AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的消息邮箱数据。
                AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
    Number of tasks with user-provided stack
  创建的4个任务都是采用自定义堆栈方式。
RTX任务调试信息:
18.14.png
程序设计:
任务栈大小分配:
    staticuint64_t AppTaskUserIFStk[512/8];   /* 任务栈 */
    staticuint64_t AppTaskLEDStk[256/8];      /* 任务栈 */
    staticuint64_t AppTaskMsgProStk[512/8];  /* 任务栈 */
    staticuint64_t AppTaskStartStk[512/8];     /* 任务栈 */
    将任务栈定义成uint64_t类型可以保证任务栈是8字节对齐的,8字节对齐的含义就是数组的首地址对8求余等于0。如果不做8字节对齐的话,部分C语言库函数,浮点运算和uint64_t类型数据运算会出问题。
系统栈大小分配:
18.15.png
RTX初始化:
  1. /*
    3 J# e0 n, I6 {* L. ?1 J
  2. *********************************************************************************************************" C8 g( N% p, a. Y+ H0 g! Z
  3. *    函 数 名: main
    ' W$ c% o  t* p7 \( Q; H+ |: D
  4. *    功能说明: 标准c程序入口。
    & l7 k5 E! [8 t" b
  5. *    形    参: 无! ~  `7 z/ J$ d! J0 T
  6. *    返 回 值: 无! y/ a. s3 W# h# Y' }
  7. *********************************************************************************************************
    9 R& K, s  h$ f% n* Q0 o: s6 ^( T
  8. */
    7 z& V" K: @6 J: |
  9. int main (void)
    8 G. k' ]% B1 j3 M
  10. {   ! C1 Q0 f6 s; [% w  f7 s" O
  11.      /* 初始化外设 */8 ]. d; E5 ?7 y# I
  12.      bsp_Init();
    0 e# l( V' _; v8 L
  13.    
    ! {* S7 j& G( B0 [7 A0 I
  14.      /* 创建启动任务 */
    + ~7 q- s6 \* a5 N. S! i
  15.      os_sys_init_user (AppTaskStart,             /* 任务函数 */
    * ]9 m6 K+ Z2 D2 o' v5 J
  16.                        4,                        /* 任务优先级 */
    $ N5 S* |8 P" a% }
  17.                        &AppTaskStartStk,         /* 任务栈 */) v& m2 D7 d* l6 B
  18.                        sizeof(AppTaskStartStk)); /* 任务栈大小,单位字节数 */5 Y6 i' m8 l9 @$ K
  19.      while(1);/ ^  u& N9 M, ~/ {, {3 K0 h
  20. }
复制代码

4 M0 V  Z( z0 I6 C0 L
RTX任务创建:
  1. /*
    * h1 Z7 O* f- n/ O
  2. *********************************************************************************************************! [$ S! G5 N" g- T2 g
  3. *    函 数 名: AppTaskCreate
    & A  B! T2 n7 k0 E: k' [
  4. *    功能说明: 创建应用任务
    8 j# j9 T" v9 O6 w- F8 X  c0 N
  5. *    形    参: 无
    2 x5 i5 X" T9 i" Q+ z) ]- z' @
  6. *    返 回 值: 无
    $ f4 z% i1 M6 i% T! k- r6 o, O$ t0 ~
  7. *********************************************************************************************************) r( I3 `1 v: G6 I' c8 P
  8. */
    9 O6 R* u3 F" ]% W3 O) }7 U
  9. static void AppTaskCreate (void)
    7 U0 R; b+ _6 G) d/ t
  10. {
    0 _8 E$ q: p0 p
  11.      HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             /* 任务函数 */
    & o; s& P7 }1 Y1 P% `6 g* l
  12.                                            1,                         /* 任务优先级 */4 n$ I/ H0 Y# |$ h( x2 r( x: P
  13.                                            &AppTaskUserIFStk,         /* 任务栈 */
    - K& p9 m% G( {9 e8 E0 F( e
  14.                                            sizeof(AppTaskUserIFStk)); /* 任务栈大小,单位字节数 */# N8 {/ O, V! ~6 H. v' q/ ?' S9 z5 T
  15.     0 f" q* H+ c, l& s% q* W
  16.      HandleTaskLED = os_tsk_create_user(AppTaskLED,              /* 任务函数 */
    $ @9 p8 S' y/ W- L9 e) S; W. x7 {
  17.                                         2,                       /* 任务优先级 */
    1 ?2 ^! P+ w# d
  18.                                         &AppTaskLEDStk,          /* 任务栈 */
    3 Q* \& g4 c( D  V1 l- U, G; o
  19.                                         sizeof(AppTaskLEDStk));  /* 任务栈大小,单位字节数 */% ~5 t& U/ F' M: V
  20.    
    + Z1 g  N6 n- t, t
  21.      HandleTaskMsgPro = os_tsk_create_user(AppTaskMsgPro,             /* 任务函数 */! g/ b1 x4 j* [. c+ }
  22.                                            3,                         /* 任务优先级 */+ Z- B0 `  m/ V
  23.                                            &AppTaskMsgProStk,         /* 任务栈 */
    / ~* H# G# {5 R2 i/ Z0 x4 Z$ _
  24.                                            sizeof(AppTaskMsgProStk)); /* 任务栈大小,单位字节数 */
    : @0 Y6 p) S  l
  25. }
复制代码

- T/ R; t* B; [) o0 _
内存管理的初始化和消息邮箱的创建:
  1. #define PoolBlocks           10) j) p; s/ x) R# D% H
  2. #define PoolPerBlockSize     8
    0 p" `6 o) c* Q" ?6 B

  3. 8 f+ ^# Z  p( Y( z) _/ a
  4. /* 声明一个支持10个消息的消息邮箱 */
    : N) J' Y* w2 B5 V: n* w& X3 Z
  5. os_mbx_declare (mailbox, 10);% I2 {' X: {6 f* z; O* _
  6. & o2 n# B6 k) A2 U/ H
  7. /* 声明一个内存池,10个块,每块大小8字节 */
    , l  w6 v1 k, I, U
  8. _declare_box8(mpool, PoolPerBlockSize, PoolBlocks);
    ; {  r. ]& Y( P8 Y5 {: }
  9. + r9 B4 ^/ n) P6 B6 O! o
  10. /*
    & ?4 S6 c/ P" s& j- j/ ~
  11. *********************************************************************************************************$ L! w. j8 _: m
  12. *    函 数 名: AppObjCreate
    5 v4 Q6 [+ X5 }3 d3 l
  13. *    功能说明: 创建任务通信机制' t/ I8 n( B' ~" ]5 K3 d
  14. *    形    参: 无
    & K" o% F* }0 G2 E5 D0 W! {2 @
  15. *    返 回 值: 无- J' ~) Z+ s: `/ f. h
  16. ********************************************************************************************************** |% B0 O' \9 G$ m
  17. */7 K1 U' q! T8 H8 \7 {, R2 e. {8 \
  18. static void AppObjCreate (void). I( C2 S, h. T1 q
  19. {
    ; P5 j. m9 K* ~* R: X' m- P( g
  20.      /* 创建消息邮箱 */* I- m6 v1 N9 Z( y& w- V4 X
  21.       os_mbx_init (&mailbox, sizeof(mailbox));
    1 c" L4 X  B& S. e1 Q
  22.     ) E% |' X1 P* ^  Q  b
  23.      /* 初始化内存池,8字节对齐,*/; h& f, b0 A4 {. D+ |" k" t
  24.      _init_box8 (mpool, sizeof (mpool), PoolPerBlockSize);0 U7 ?9 o% ]& |* {0 X5 {/ X
  25. }
复制代码

- \& j, U* L8 |: [+ \+ g
四个RTX任务的实现:
  1. /*
    " A0 e+ t# s% L& u, m
  2. *********************************************************************************************************
    - u, V" }3 z; f& Z2 x" L
  3. *    函 数 名: AppTaskUserIF3 q2 K4 \2 {" P$ u
  4. *    功能说明: 按键消息处理     
      M# M- a" ~' W9 d# u. J
  5. *    形    参: 无0 l5 {7 V- ]% T- g
  6. *    返 回 值: 无
    / N) k6 A" V  v
  7. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)( F! P1 m" e7 P, `1 w
  8. *********************************************************************************************************& y, L" v0 Q! ^$ L- |: `0 V
  9. */3 B. C* i1 v6 P8 T" N- Z
  10. __task void AppTaskUserIF(void)6 l% B2 a* V* }9 B+ T$ i
  11. {2 {; }* P' u$ p* U6 O
  12.      uint8_t  *pucMsg;
    & s# w# k! \- {0 G
  13.      uint16_t *pusMsg;
    # y5 s  ~$ W4 v! B) g1 @
  14.      uint32_t *pulMsg;
    ! U9 z, b& _: o$ s# \& W
  15.      uint64_t *pullMsg;- m& v: O. {8 m' l6 X/ q3 T$ d
  16.    
    : g" \* n* O# E/ D+ ~  i( q
  17.      uint8_t ucKeyCode, ucCount = 0;
    4 C" ?' B! {: s" y1 T2 X

  18. 5 u5 B0 [* ]) P
  19.     while(1)8 |& H3 e) Z# L) t
  20.     {  z# N4 L8 W& \( O2 O$ G
  21.          ucKeyCode = bsp_GetKey();2 q% `: }6 b9 M
  22.         
    % C! `! f8 ]& {" g- j4 l
  23.          if (ucKeyCode != KEY_NONE)2 C1 Q% w& u; o0 I% E
  24.          {6 R% o: Z. a4 z. X9 F
  25.               switch (ucKeyCode)6 a9 U, W. M/ [* J' a
  26.               {6 ?9 T0 y- H' g/ b4 T! f& l
  27.                    /* K1键按下,打印调试说明 */: }1 r! K7 r( F, Q# m6 z  E
  28.                    case KEY_DOWN_K1:& D( o$ m" L9 p9 |5 A6 s- Y) q# N
  29.                        printf("K1键按下,使用MDK中自带的RTX调试组件,请务必使用MDK4.74版本进行调试\r\n");6 d  k9 z1 L9 j& W8 Q
  30.                        break;  . X; e. h$ W8 C4 ^

  31. / R9 X4 X( R4 h" P& f8 _
  32.                    /* K2键按下,申请一个内存块用于8位整形变量,然后向消息邮箱发送数据 */6 q, v" H: _! e6 r* ?
  33.                    case KEY_DOWN_K2:
    2 ]9 f6 _0 b: Q/ [1 L+ E
  34.                        /* 申请一个内存块用于8位整形变量 */
    0 [* ~2 c$ ]/ N& I  d1 H
  35.                        pucMsg  = _alloc_box (mpool);+ p$ V7 w' z9 o# q) d" S
  36.                        *pucMsg = ucCount++;% d+ ]; m  L) {: b; H! `' r
  37.                   
    7 H6 j( o& ?6 p' t- k7 S
  38.                        /* 向消息邮箱发数据,如果消息邮箱满了,等待100个时钟节拍 */& e- ~$ r; T8 g2 ~
  39.                        if(os_mbx_send (&mailbox, pucMsg, 100) != OS_R_OK)
    ( G/ D# P4 n) ?( x( X
  40.                        {
    ; p, A: D# H; g7 e, P
  41.                             /* 发送失败,即使等待了100个时钟节拍 */6 P$ ]/ J; ?$ Q* q
  42.                             printf("K2键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\r\n");( C& i4 ~8 B4 S# S1 v- Q- x# Y+ F: {
  43.                             _free_box (mpool, pucMsg);
    . |+ R! W) f9 r) }) [. L
  44.                        }9 B5 q: u; j7 N& g+ Q- m& P% _
  45.                        else9 A: m3 R: w& s3 T  p5 S8 W( @
  46.                        {
    - {) ~/ T! h6 z0 t: E2 h
  47.                             /* 发送成功 */
    ( c; k/ B# ?% M- l( A6 J) {
  48.                             printf("K2键按下,向消息邮箱发送数据成功\r\n");   
    " k0 `6 a+ u( l4 t
  49.                             _free_box (mpool, pucMsg);
    : n% b& l7 i0 G* q5 t- C; ~
  50.                        }$ |% `3 z1 }, Q0 T. M
  51.                        break;  
    ( H7 E$ v3 ?; W# C
  52. & S8 B" s" D4 T8 U) H
  53.                    /* K3键按下,申请一个内存块用于16位整形变量,然后向消息邮箱发送数据 */3 q4 z$ i: F% q% R6 Z
  54.                    case KEY_DOWN_K3:
      q/ `8 p8 e3 t0 M- \2 |3 v2 h
  55.                        /* 申请一个内存块用于16位整形变量 */
    ) Q  T3 z- p* z
  56.                        pusMsg  = _alloc_box (mpool);
    4 k$ I' q- x+ W7 o$ c9 e# A, r4 w, |5 K
  57.                        *pusMsg = ucCount++;
      t! v" d3 f+ P# E+ |, \
  58.                   
    - L0 ]0 w- ~6 Q
  59.                        /* 向消息邮箱发数据,如果消息邮箱满了,等待100个时钟节拍 */
    2 D( x9 K! X1 m. x( J, \" x" Q3 R- W
  60.                        if(os_mbx_send (&mailbox, pusMsg, 100) != OS_R_OK)
    " p6 [1 A$ l' v* n
  61.                        {( X9 _* S; Z3 w) B  M
  62.                             /* 发送失败,即使等待了100个时钟节拍 */1 w; f2 J3 Z4 ]5 D" @( Q3 j3 P8 M
  63.                             printf("K3键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\r\n");! V1 Z+ S/ F  G% \" L( [
  64.                             _free_box (mpool, pusMsg);( M% f! M- w) ]* a, e
  65.                        }
    0 e) q) x- T: l$ J4 k
  66.                        else+ ~1 R7 N# }1 g
  67.                        {9 x3 B1 }3 t4 i+ h
  68.                             /* 发送成功 */
    ) |5 ^8 ^* H% F$ G5 b1 J, k
  69.                             printf("K3键按下,向消息邮箱发送数据成功\r\n");   
    / s* [- L; I, v( d  L7 J; l
  70.                             _free_box (mpool, pusMsg);2 t: B! ^$ ]. m! \, b
  71.                        }
    ! w0 P9 C& @5 a5 o
  72.                        break;  
    1 X# ~9 M$ J- }2 Y) Z' @( z, N9 p
  73.                   
    9 A2 x3 }1 y' ]4 n( c) }
  74.                    /* 摇杆OK键按下,申请一个内存块用于32位整形变量,然后向消息邮箱发送数据 */: Z$ J" `$ A! ]+ w$ d9 |! d
  75.                    case JOY_DOWN_OK:
    9 ]' q/ ~3 x! x# Q
  76.                        /* 申请一个内存块用于32位整形变量 */& T3 n. B" [% m/ i
  77.                        pulMsg  = _alloc_box (mpool);
    8 {" M6 r' o! z, Z, @
  78.                        *pulMsg = ucCount++;; s) e7 x, W) L7 |
  79.                   
    ! ^- d% I5 G9 {  s
  80.                        /* 向消息邮箱发数据,如果消息邮箱满了,等待100个时钟节拍 */
    ) y  V% {5 T: d* g/ b; `
  81.                        if(os_mbx_send (&mailbox, pulMsg, 100) != OS_R_OK)
    ) g$ P* a; ^9 q: W
  82.                        {! A7 m2 _" c7 o" l) @
  83.                             /* 发送失败,即使等待了100个时钟节拍 */" [( b/ A/ G( i2 j3 |8 Z
  84.                             printf("摇杆OK键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\r\n");
    8 I5 f3 n8 C5 A; T. G, J
  85.                             _free_box (mpool, pulMsg);7 Y' z% l1 V; d8 o: B/ F: ^. j
  86.                        }0 I$ Z/ T; e( n4 n
  87.                        else
    - ]6 ]  O2 i" q7 o. H
  88.                        {' V5 ]7 M& R( x! {. B
  89.                             /* 发送成功 *// |6 {& c- H0 K4 [( Y
  90.                             printf("摇杆OK键按下,向消息邮箱发送数据成功\r\n");     ], @2 N7 d  p9 i+ d7 @' r* v) q
  91.                             _free_box (mpool, pulMsg);
    3 r: u3 ~  n1 I+ r% G& z9 H7 x2 [
  92.                        }6 {7 U. E7 I# P, Z0 W# E
  93.                        break;! z: Y0 g) _9 |. S
  94. 8 T5 B! q& h: Q$ n4 h9 I& C
  95.                    /* 摇杆UP键按下,申请一个内存块用于64位整形变量,然后向消息邮箱发送数据 */
    - N0 A$ d( W+ H5 B/ u9 c+ [2 C
  96.                    case JOY_DOWN_U:) {7 S* h2 j8 J! x' E
  97.                        /* 申请一个内存块用于32位整形变量 */
    ' z+ ~  P* R+ b& y9 E" [  C
  98.                        pullMsg  = _alloc_box (mpool);5 }$ Y  T1 Z6 h: @/ D2 ]0 `
  99.                        *pullMsg = ucCount++;
    ) U+ O  {! F9 w% F* K
  100.                   
    0 X9 Z! w# ]7 \3 j& u0 y' e( ?$ }; K
  101.                        /* 向消息邮箱发数据,如果消息邮箱满了,等待100个时钟节拍 */- L+ z8 s+ R- }2 ]$ k
  102.                        if(os_mbx_send (&mailbox, pulMsg, 100) != OS_R_OK)) c( ]+ u. Q  i- Q: x% V- b" I
  103.                        {/ V4 s. {' L* z0 A6 y- N$ D0 _; A
  104.                             /* 发送失败,即使等待了100个时钟节拍 */
    6 \4 x# {8 l9 U: d, ^/ n9 X: L
  105.                             printf("摇杆OK键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\r\n");
    % p) I; X1 a0 t9 |2 ^- x
  106.                             _free_box (mpool, pullMsg);
    " n- F/ B: r4 j' o2 e' `5 f
  107.                        }* S7 H4 v& F9 ]
  108.                        else
    ; d0 h1 b# O- K
  109.                        {5 W+ |- p' u9 D; T' r0 j3 P
  110.                             /* 发送成功 */$ D* I: Y4 ?2 i) u
  111.                             printf("摇杆OK键按下,向消息邮箱发送数据成功\r\n");   
    ( a$ M3 V. @  n  ^
  112.                             _free_box (mpool, pullMsg);8 H, `! B+ O) W# `+ H9 K* b
  113.                        }; L, s* h% [6 F& u( }# D( u
  114.                        break;8 T3 Q& T/ H) N% n2 [/ Q
  115. ! T. |! Q. G% S" [# _
  116.                    /* 其他的键值不处理 */
    ' v3 i3 Y) r" m4 c
  117.                    default:                    ( k4 T" q# Z# X1 f3 c, C
  118.                        break;& C: X/ ]* i  O4 p
  119.               }
    ) h) T3 B- k# r+ E3 \
  120.          }
    5 o* w0 t, T0 N# L0 }/ O  q, {4 r
  121.         1 D  ?- s* X8 f0 J/ y
  122.          os_dly_wait(20);% Z% e" ]$ U1 ^5 i+ x+ M
  123.      }
    * O6 ^. H  r' l. N1 ]2 K& ?
  124. }
    5 A- Z% G8 M+ ?" r$ g6 D8 f4 O

  125. # j' S& z0 B* s6 r# K& x
  126. /*
    ; r6 t0 R% O' y( _3 {
  127. *********************************************************************************************************
    7 x) o8 _8 L  ?+ @5 z
  128. *    函 数 名: AppTaskLED
    * s- D. B3 Z; o: J% }1 g% T) m( s; R
  129. *    功能说明: LED闪烁。. C  d$ o: L- y8 [* t/ q# o( f
  130. *    形    参: 无* h/ L& {3 r) n- {! e
  131. *    返 回 值: 无
    * v8 w" r: I! A+ ?0 s
  132. *   优 先 级: 2 7 {  I) i- [" E; w0 F3 Q
  133. *********************************************************************************************************
    7 L9 k2 T3 N- i6 I* f
  134. */3 z! X: `- k6 c
  135. __task void AppTaskLED(void)* _! }5 U( G( Q3 L% m  s* A( {
  136. {+ G* P7 e1 c+ g5 G0 g
  137.      const uint16_t usFrequency = 200; /* 延迟周期 */- u9 ?& X" F& i0 f% Y
  138.    
    # L) A9 C7 o5 f! R9 w# {: r
  139.      /* 设置延迟周期 */
    1 p% }; x; W% \; [
  140.      os_itv_set(usFrequency);4 ~# I& N) F, f# n' w9 Q6 g
  141.     / M$ a0 j8 [3 O/ v
  142.     while(1)
    / a8 P6 H' K3 p1 C
  143.     {
    " Q' ]. ^) R) I, p: Z. S+ N3 ^
  144.          bsp_LedToggle(2);7 L& n. h- b7 ~* d; a
  145.          bsp_LedToggle(3);
    $ S/ u$ v% _- J" }" a

  146. ! W) s1 X2 k2 f1 e
  147.          /* os_itv_wait是绝对延迟,os_dly_wait是相对延迟。*/
    $ w9 V4 {% ^7 [# q
  148.          os_itv_wait();( M. g  u" k  K: _0 Z3 @
  149.     }
    & w2 ?9 \: H6 ~# s7 T
  150. }; s1 j6 F5 e  C# o2 _$ ~; Q
  151. . P6 I+ H% g; f5 ~2 I/ Q
  152. /*
    * B; e9 z7 W  r+ J
  153. *********************************************************************************************************
    6 B" \" U) i$ L$ N. \  _$ m
  154. *    函 数 名: AppTaskMsgPro
    % }; O5 Q5 K; C, W4 v
  155. *    功能说明: 消息处理,等待任务AppTaskUserIF发来的消息邮箱数据5 v% `) v0 b7 U) v0 _+ a4 w: q
  156. *    形    参: 无- T1 {% @' W& h$ F% U
  157. *    返 回 值: 无: s* R& L9 J: Y7 g! q3 Q- `2 S
  158. *   优 先 级: 3 3 I8 J- \; `! C( S4 J
  159. *********************************************************************************************************9 U: s# s; @* u% O& t* T5 \
  160. */- g+ `2 b, ]5 |, E& @% G; J3 ]
  161. __task void AppTaskMsgPro(void)9 u, ?. ?: W+ @2 }( g' F# i
  162. {2 v5 h) k2 S) A" g  a& V5 ~
  163.      uint8_t *pMsg;
    # J' ]& G( p* P8 j+ b# k
  164.      OS_RESULT xResult;5 X  u  K9 Z! W. c/ ^9 E( B, W
  165.      const uint16_t usMaxBlockTime = 200; /* 延迟周期 */+ l& V: h( ~3 q( n, N& G
  166.       J5 W( o* r$ y% F
  167.     while(1)4 S4 n- @1 C" G0 `+ _. d) s$ E0 D
  168.     {
    , ]0 {8 w" \+ W. `3 E/ s0 B( I
  169.          xResult = os_mbx_wait(&mailbox, (void *)&pMsg, usMaxBlockTime);0 P+ p. ^2 @' s+ J8 e9 L& w
  170.         
    $ [; ?* }6 |8 f  s
  171.          switch (xResult)4 P& t0 f6 L6 {) @- m! Z: K$ Q0 T
  172.          {
    % p. b3 p, d+ s) J8 Y1 }  R7 A; s. L$ c- R
  173.               /* 无需等待接受到消息邮箱数据 */& e3 R: J) g- ?& Q; d! t
  174.               case OS_R_OK:& e% A; v! Z6 c% q! x
  175.                    printf("无需等待接受到消息邮箱数据,pMsg = %d\r\n", *pMsg);
      t" B" t9 T- C( r2 _; ?
  176.                    break;  + ~* d% |0 @( R" y
  177. 0 H. ?0 R- Y$ v) C2 P8 K
  178.               /* 消息邮箱空,usMaxBlockTime等待时间从消息邮箱内获得数据 */: x) _& O+ c0 R4 a# P& }
  179.               case OS_R_MBX:
    / R# I9 y* n  P
  180.                    printf("因为消息邮箱空,usMaxBlockTime等待时间从消息邮箱内获得数据,pMsg = %d\r\n", *pMsg);
    ; |, v# b: q  q# W
  181.                    break;3 }6 Q1 m. v4 ~) Y; j' T; H

  182. % i) `7 d  _9 X9 ^( K
  183.               /* 超时 */
    2 z% H; x( j' n- _9 S9 i( |
  184.               case OS_R_TMO:
    1 Z. A- |' z' v. h4 ?2 a2 t
  185.                    bsp_LedToggle(1);
    ( N, D8 [; s' K
  186.                    bsp_LedToggle(4);/ ?$ |5 z+ @: U0 R- f/ [
  187.                    break;- L* }( t3 C. y
  188.             
    $ ^: g  n9 u6 ], o2 t3 N
  189.               /* 其他值不处理 */  ?0 `5 P) |* y0 y0 m& i
  190.               default:                    
    : ^' V. r3 r/ w4 Y( c
  191.                    break;9 w! V4 ~( ]* }: w: H
  192.          }   + W5 I% S: n1 z3 c6 ?1 c; d
  193.     }% A  y5 Z9 U. {2 i7 d9 M
  194. }
复制代码

6 j; `6 ]/ i6 c) p( I2 R% M  S* y2 P1 U, }' k  E7 z
baiyongbin2009 回答时间:2016-2-3 16:04:25
18.5 总结
    本章节主要为大家讲解了RTX内存管理的实现方法,关于嵌入式内存管理的方案还有很多,有兴趣的同学可以查阅相关资料了解一下。

" C& x3 _1 Q, {( f
stary666 回答时间:2016-2-3 16:09:47
看看,,,,,,,,,,,,
看不透说不穿 回答时间:2019-3-24 12:58:13
有个问题请教下,RTX 邮箱传递的是数据地址,上面的例子动态生成一个内存,数据邮箱发送完后释放了内存,邮箱的接收端收到地址,但是如果数据没有来得及处理会不会用的不是真实数据,因为地址已经被释放,可能其他地方的风险。
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版