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

【安富莱】【RTX操作系统教程】第19章 SVC中断方式调用...

[复制链接]
baiyongbin2009 发布时间:2016-2-3 17:08
【安富莱】【RTX操作系统教程】第19章     SVC中断方式调用用户函数 【RTX操作系统教程】第19ç«  SVC中断方式调用用户函数.pdf (710.21 KB, 下载次数: 75)
收藏 评论8 发布时间:2016-2-3 17:08

举报

8个回答
baiyongbin2009 回答时间:2016-2-3 17:19:40
19.2 RTX中SVC中断方式调用函数方法
    用户实现SVC中断方式调用函数方法如下(下面以添加两个SVC中断为例):
第1步:添加SVC_Table.s文件。
    我们在前面讲解RTX的源码移植方式时这个文件已经加上。
! C8 E- h: I8 s
第2步:使用属性__svc(x)声明函数,x从1开始,范围1-255。函数名随便命名,但是x的数值一定要保证是连续递增的。
void __svc(1) SVC_1_FunCall(uint8_t _arg1, uint16_t _arg2, uint32_t _arg3, uint64_t*_arg4);
void __svc(2) SVC_2_FunCall(void);
( V" _5 h& [& x
第3步:写上面两个函数的实际代码,并将函数名更改成__SVC_x格式(统一改成这种命名方式是为了跟RTX系统的调用方式__SVC_0统一),x是从1开始,范围1-255。上面声明的两个函数不要动,这里修改的是实际函数名。另外用户可以根据需要加上中断开关操作,因为SVC中断可以被其它高优先级的中断抢占。
/*
******************************************************************************************************
*    函 数 名: __SVC_1和__SVC_2系统服务号
*    功能说明: 被SVC中断所调用的__SVC_1和__SVC_2
*    形    参:无
*    返 回 值: 无
******************************************************************************************************
*/
//这里的__SVC_1就是函数SVC_1_FunCall
void __SVC_1(uint8_t _arg1, uint16_t _arg2,uint32_t _arg3, uint64_t *_arg4)
{
     __disable_irq();
     printf("_arg1= %d\r\n", _arg1);
     printf("_arg2= %d\r\n", _arg2);
     printf("_arg3= %d\r\n", _arg3);
     printf("_arg4= %lld\r\n", *_arg4);
     __enable_irq();
}
//这里的__SVC_2就是函数SVC_2_FunCall             
void __SVC_2(void)
{
     __disable_irq();
     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
     __enable_irq();
}

- D+ ]" s  m" J$ H* a: g
第4步将定义的两个函数添加到SVC_Table.s文件里面
   首先使用IMPORT命令声明下,类似C语言中的extern。然后添加到SVC_Table列表下,整体添加后的效果如下(红色字体是用户添加的):
               AREA    SVC_TABLE, CODE, READONLY
               EXPORT  SVC_Count
SVC_Cnt        EQU    (SVC_End-SVC_Table)/4
SVC_Count      DCD     SVC_Cnt
; Import user SVC functions here.
               IMPORT __SVC_1
                IMPORT __SVC_2
               EXPORT  SVC_Table
SVC_Table
; Insert user SVC functions here. SVC 0 used byRTL Kernel.
             DCD     __SVC_1                 ; user SVC function
               DCD    __SVC_2                 ;user SVC function
SVC_End
               END

: e: Z3 |: o# l, R6 M
+ ?6 |9 ^; P, H4 D% _/ L
至此,RTX中SVC中断的调用就实现了。实际应用的时候,用户只需调用函数SVC_1_FunCall和SVC_1_FunCall即可,这两个函数就是在SVC中断里面实现的。
7 O" |* d, I# I) G" f; J
baiyongbin2009 回答时间:2016-2-3 17:38:43
19.3 实验例程说明8 s1 `- i+ N8 u
19.3.1  STM32F103开发板实验
配套例子:
    V4-419_RTX实验_SVC中断方式调用用户函数
实验目的:
    1.     学习SVC中断方式调用用户函数
实验说明:
    1.     RTX支持配置所有任务工作特权级模式或者用户模式,宏配置在文件RTX_Conf_CM.c文件里面
       #defineOS_RUNPRIV     0
     配置为0的话,任务工作在用户级,配置为1的话,任务工作在特权级。本实验配置为0,所有任务都工作在用户级模式。
    2.     本实验演示SVC中断号调用方法。
      SVC指令带一个8位的立即数(范围0-255),可以视为是它的参数,被封装在指令本身中,如:
      SVC   3  ;   呼叫3号系统服务
      SVC0被RTX系统所使用了,用户只能使用从1开始的服务号。用户使用的时候一定要保证从1开始,而且需要连续的使用。实验中使用了SVC 1和SVC 2。
实验内容:
    1.K1按键按下,串口打印。
    2.K2键按下,向消息邮箱发送数据。任务AppTaskMsgPro接收到消息后进行消息处理。
    3.K3键按下,调用SVC的1号系统服务。
    4.摇杆OK键按下,任务运行在非特权级,调用SVC的2号系统服务,可以在中断中设置NVIC。
    5.各个任务实现的功能如下:
  AppTaskUserIF任务   :按键消息处理。
  AppTaskLED任务     :LED闪烁。
  AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的消息邮箱数据。
  AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
RTX配置:
    RTX配置向导详情如下:
19.2.png
                              
Task Configuration
Number of concurrent running tasks
  允许创建4个任务,实际创建了如下四个任务:
                AppTaskUserIF任务   :按键消息处理。
                AppTaskLED任务     :LED闪烁。
                AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的消息邮箱数据。
                AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
    Number of tasks with user-provided stack
  创建的4个任务都是采用自定义堆栈方式。
    Run in privileged mode
  设置任务运行在非特权级模式
RTX任务调试信息:
19.3.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类型数据运算会出问题。
系统栈大小分配:
19.4.png
RTX初始化:
  1. /*
    " q; n4 W. G  z, A9 [# P$ S
  2. *********************************************************************************************************
    ( D5 K  d/ W. C- k
  3. *    函 数 名: main
    , z$ D0 Z* A& A: _7 _
  4. *    功能说明: 标准c程序入口。
    , t! L) f  K2 C9 L
  5. *    形    参: 无# R' f: |) A+ O. N0 ^2 n& x
  6. *    返 回 值: 无
    , L& H8 ]9 k' N$ {
  7. *********************************************************************************************************
    3 V& p4 |. j4 Q$ h
  8. */
    * `* d1 t7 K2 g+ Y7 Q5 J
  9. int main (void)- _) e( c# ^5 ?" E
  10. {   8 ^' z1 A  [0 Q( j9 x
  11.      /* 初始化外设 */
    , v! b; ]1 S; m* R7 W
  12.      bsp_Init();6 t% V5 A8 A# Z; }* I- v* n7 s
  13.    
    ! \2 t% Y6 `" t6 n
  14.      /* 创建启动任务 */) W$ N9 \" \+ _1 j7 N; W
  15.      os_sys_init_user (AppTaskStart,             /* 任务函数 */
    % g: g* v6 O* _. H6 ^6 [
  16.                        4,                        /* 任务优先级 */* A# t5 `; K) d2 u  ~6 z1 B: \
  17.                        &AppTaskStartStk,         /* 任务栈 */
    % r3 H7 n6 Y) w4 l* D% t
  18.                        sizeof(AppTaskStartStk)); /* 任务栈大小,单位字节数 */8 V% M. v' U7 E0 ?) A9 C$ I
  19.      while(1);
    0 C9 w# x  U* w. L
  20. }
复制代码

) r4 ?/ O3 ]5 S: s" D
RTX任务创建:
  1. /*2 M8 @" C2 S! B, l: h6 R
  2. *********************************************************************************************************
    - ~  k8 I; y. D' B2 }) C. m+ X
  3. *    函 数 名: AppTaskCreate
    . u/ i* t. i6 M# r
  4. *    功能说明: 创建应用任务( V' s  w, Z& b# N7 C; ~
  5. *    形    参: 无
    / q! R% @6 m( R! k1 J7 j0 S* ~
  6. *    返 回 值: 无
    8 q  d: n0 k4 F2 f! B. o
  7. *********************************************************************************************************
    ' u' g8 ]2 |4 S7 `* I
  8. */
    ) y! c! A4 t/ u& H- }
  9. static void AppTaskCreate (void)
      i5 H& q) I. L, m* `* Y6 a/ H
  10. {1 H! n; ]! q5 y% C/ R! N9 ?
  11.      HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             /* 任务函数 */
    ! h% u' T5 i! p1 F3 H5 p, C
  12.                                            1,                         /* 任务优先级 */
    : |0 x+ y% }. C3 A7 s) r
  13.                                            &AppTaskUserIFStk,         /* 任务栈 *// t" d* ]# z" ^3 Z6 q* h% {6 x9 {' Y
  14.                                            sizeof(AppTaskUserIFStk)); /* 任务栈大小,单位字节数 */
    . \3 P5 h" @* E! B5 y. x
  15.     $ j/ s. p' f. Y( {5 Q
  16.      HandleTaskLED = os_tsk_create_user(AppTaskLED,              /* 任务函数 */
    : {- b- l; ?3 v! ~
  17.                                         2,                       /* 任务优先级 */; U5 G" C" p( l4 J% r- P
  18.                                         &AppTaskLEDStk,          /* 任务栈 */
    ! s) n" f$ ~2 A4 ?
  19.                                         sizeof(AppTaskLEDStk));  /* 任务栈大小,单位字节数 */# d+ _7 [9 y* X' t# M
  20.    
    9 r, R" O0 G, F' ?. Z6 c, |
  21.      HandleTaskMsgPro = os_tsk_create_user(AppTaskMsgPro,             /* 任务函数 */
    $ g; y) ]5 a: X
  22.                                            3,                         /* 任务优先级 */& c* j+ H" Y) i  a3 S2 ?# h+ A
  23.                                            &AppTaskMsgProStk,         /* 任务栈 */. n) n: W0 @5 x( d
  24.                                            sizeof(AppTaskMsgProStk)); /* 任务栈大小,单位字节数 */5 Q4 r1 Q  M! Q0 Y, z/ k
  25. }
复制代码
1 \; o& A0 S) ~5 J
消息邮箱的创建:
  1. #define PoolBlocks           10
    5 z, m- J9 w2 t1 ?9 r  X
  2. #define PoolPerBlockSize     8) ]: S( l" i& P! I

  3. ( e! Z2 {+ E% m* K
  4. /* 声明一个支持10个消息的消息邮箱 */
    0 d5 F" {/ _, v" R* J$ C
  5. os_mbx_declare (mailbox, 10);; O5 y: W/ b3 z# g" F8 K

  6. 3 |! ]- A$ k" ]6 J3 v6 y# }
  7. /*
    - Q2 `- I4 o* L$ R1 {* a' E$ v
  8. *********************************************************************************************************
    ) `( R3 ^, _: Z& M
  9. *    函 数 名: AppObjCreate
    " G. G' P! F5 z
  10. *    功能说明: 创建任务通信机制* ~$ E$ M3 Y" F5 W, e
  11. *    形    参: 无! N' q" q  z& }6 m( A- t2 _3 }
  12. *    返 回 值: 无
    # ?6 s; u7 q! X" `- P
  13. *********************************************************************************************************3 j" G6 o8 v1 B. `+ F
  14. */
    9 R2 \1 h) }2 \! F$ A
  15. static void AppObjCreate (void)9 }4 S* U) X% h: N
  16. {. e- l. Z4 T! Q+ [$ A
  17.      /* 创建消息邮箱 */
    " a9 ^% O0 h1 ~  B( a- L/ h! f4 }
  18.       os_mbx_init (&mailbox, sizeof(mailbox));
    8 K8 K  h$ x7 @% \$ v' d
  19.    
      I4 l' S$ N% Q* }/ D5 q/ I
  20. }
复制代码

" x' t5 `, e2 M7 h
SVC中断函数的创建:
  1. void __svc(1) SVC_1_FunCall(uint8_t _arg1, uint16_t _arg2, uint32_t _arg3, uint64_t *_arg4);/ L! K  y$ o) Y2 H% N5 G
  2. void __svc(2) SVC_2_FunCall(void);3 L# R* U6 _$ v% z$ h

  3. , {7 m/ N  M% w% E( y! x8 U) |! z* f
  4. /*
    . c5 F5 n. {0 L
  5. *********************************************************************************************************
    " n( C$ c! l/ b$ J' y7 J' a6 O
  6. *    函 数 名: __SVC_1和__SVC_2系统服务号
    % e3 Z( u$ y5 [% T
  7. *    功能说明: 被SVC中断所调用的__SVC_1和__SVC_2" N) ]( v$ e' I; R, P- V1 f4 G
  8. *    形    参: 无. A; z. l+ ?5 o5 n8 `* Q+ B4 T
  9. *    返 回 值: 无
      W" U: T' b1 o9 e5 `. {
  10. *********************************************************************************************************
    # A; k8 |# N' X, K* g( u$ N* R/ _
  11. */
    - x' T9 c) Z0 R, c3 e4 i
  12. void __SVC_1(uint8_t _arg1, uint16_t _arg2, uint32_t _arg3, uint64_t *_arg4)$ F) B7 D2 i; ^  \4 W6 ~
  13. {
    ' W0 S$ W( s! }0 N) Y8 v: ~
  14.      /*+ o6 b4 Y, p6 f, d
  15.          1. 实际应用不要在SVC中断中调用串口打印,太影响实时性,这里仅仅是为了演示. U/ N, B7 O( d5 S, L: J3 @
  16.          2. 根据需要做开关中断操作。9 z5 ^2 ]- r; |7 i3 B' z+ O
  17.      */3 d4 m6 g# o3 Z9 J
  18.      __disable_irq();
    , m8 D$ W) F: V$ O% X' X5 \  [
  19.      printf("_arg1 = %d\r\n", _arg1);% [5 ?! {4 R% i1 P% @+ x
  20.      printf("_arg2 = %d\r\n", _arg2);8 p8 L- `1 X6 p7 C; w1 [
  21.      printf("_arg3 = %d\r\n", _arg3);8 b, c( T( S& v4 q
  22.      printf("_arg4 = %lld\r\n", *_arg4);
    ) a% I/ P4 X; F& ~9 [. ]0 I6 @5 U* m
  23.      __enable_irq();
    ! t5 p- m$ W6 b) W! }. g! u
  24. }- K- n! v7 p+ B6 y+ G; s
  25.                   ; u7 Z7 B% v# M
  26. void __SVC_2(void)
    0 z5 s4 ]8 l4 Q: n6 K8 g
  27. {
    * n1 g$ E6 M* T5 w
  28.      /** M7 c0 P* z2 [5 K  I
  29.          1. 根据需要做开关中断操作。
    ) v5 k! [. W; ~/ R, x
  30.          2. 本实验所有任务都是工作在非特权级,中断函数都是运行在特权级的,此函数是在SVC中断里面运行。3 P* c5 X1 _0 u1 k4 \
  31.             所以可以在此中断中设置NVIC分组。
    2 G* `) I! @7 i& k
  32.      */
    2 O! v9 N3 b6 _; k: z  J
  33.      __disable_irq();& f8 S; k2 a3 ~( ]5 H5 R
  34.      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
    ( ]$ V) Y; E  Z# y6 |  ]6 h8 d
  35.      __enable_irq();. M: q( U5 U# _' ^3 g7 K
  36. }
复制代码

% f; N6 w: E7 H- }' Y( m
SVC_Table.s文件中SVC中断的设置(红色字体是需要用户添加的):
  1. void __svc(1) SVC_1_FunCall(uint8_t _arg1, uint16_t _arg2, uint32_t _arg3, uint64_t *_arg4);" `- m# c0 b2 @$ G: Q5 j7 \
  2.                 AREA    SVC_TABLE, CODE, READONLY
    ; q- ?( T& ]- A  t

  3. 6 f* U6 d) b% N- w0 W4 y- v
  4.                 EXPORT  SVC_Count
      Z! h* M+ b$ B. B7 Q) @' L

  5. + \) @; n2 f3 c4 q: z( _6 L
  6. SVC_Cnt         EQU    (SVC_End-SVC_Table)/4
    # D( S* n) Q+ v7 a" c7 u% F. s
  7. SVC_Count       DCD     SVC_Cnt6 C, V$ o( L+ h$ z

  8. * D6 r. ]% z0 n* N
  9. ; Import user SVC functions here./ `  |) d6 p1 I
  10.                 IMPORT  __SVC_1
    4 T( z# u* G$ e* r. S9 |0 T) J/ z* R
  11.                 IMPORT  __SVC_2
    % z; k/ M; E! h- z
  12. " A* V& d5 a0 S2 X8 Y" n: T3 |
  13.                 EXPORT  SVC_Table8 v4 y3 t, y% c
  14. SVC_Table2 }- @' W0 [$ Y2 j9 g. T
  15. ; Insert user SVC functions here. SVC 0 used by RTL Kernel.
    % n' N; Q& s5 a2 J
  16.                DCD     __SVC_1                 ; user SVC function
    # @9 Y* O) J& Y; o
  17.                DCD     __SVC_2                 ; user SVC function/ H9 `& ]: V3 E0 G: n! ~( T; f
  18. ! `! Z- w, L7 B- i9 L1 S% P1 U
  19. SVC_End
    4 |% J) X# u+ k& [! G7 r1 u
  20. , z1 o" D6 E( A# L
  21.                 END
复制代码
, T6 ~  o: U! {# T
四个RTX任务的实现:
  1. /*7 `: ]5 J2 _5 Y0 Z4 ^8 p% r3 |2 l
  2. *********************************************************************************************************" i- H) ~& u' r) X
  3. *    函 数 名: AppTaskUserIF
    6 A4 }; ]6 Y9 l! C
  4. *    功能说明: 按键消息处理     
    ; T1 ]8 Y0 {% ]
  5. *    形    参: 无. T" @! [, i8 N# y$ H5 l5 `; I
  6. *    返 回 值: 无, E3 U: g2 d. @# w
  7. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)) `' q3 S+ L  d  _9 W+ }
  8. *********************************************************************************************************4 k" D& N# t8 D; _& P) O( F2 H
  9. */
    , R% E" Y4 f9 H" q
  10. __task void AppTaskUserIF(void)
    - v5 o  c. O) {/ N2 `
  11. {9 ]* K/ n" S7 {  u& G9 }0 s
  12.      uint8_t ucMsgTra = 0;
    9 v( a9 {0 g6 ]% E& m" ]
  13.      uint8_t ucMsg = 0;
    * E, h+ j* z" Q2 D7 n' |% C6 W
  14.      uint16_t usMsg = 0;
    8 \6 E; r5 }* X- i; T- M; _& c* w/ `
  15.      uint32_t ulMsg = 0;# T& d9 k: H# @- P
  16.      uint64_t ullMsg = 0;
    . }9 i. ^8 Y) e% k' d
  17.      uint8_t ucKeyCode;  P+ s( \8 `' O; w7 B3 Z

  18. 6 u1 P2 Y4 @' O5 ]& o
  19.     while(1)
    1 U5 `2 u& X- W0 P
  20.     {5 J! C/ m; K$ r$ |3 ]* h' p
  21.          ucKeyCode = bsp_GetKey();% x: ]  G8 U: [7 t8 P7 a
  22.         
    ! L* C$ c# v  o, D: Z1 `) Y9 `
  23.          if (ucKeyCode != KEY_NONE)
    7 n8 Q$ H& C, Q: O# r
  24.          {
    * J& q$ w: G! i8 z7 e# \
  25.               switch (ucKeyCode)" u8 Q5 K% y+ {7 t
  26.               {# Z. [% i3 e5 V8 M
  27.                    /* K1键按下,打印调试说明 */
    ! u7 |( V1 C" Q+ C/ {$ G
  28.                    case KEY_DOWN_K1:  O: p, Q! B+ |4 N
  29.                        printf("K1键按下,使用MDK中自带的RTX调试组件,请务必使用MDK4.74版本进行调试\r\n");7 K) b% Z: u8 \7 G0 X; B
  30.                        break;  " i9 e# z) T; |3 ^2 w- M) [. L

  31. ) F2 B8 l# p9 w5 @2 X
  32.                    /* K2键按下,向消息邮箱发送数据 */
    6 W9 n! z  s0 R, |! o8 I
  33.                    case KEY_DOWN_K2:
    - H8 Z" j5 V9 H% i9 P3 ]
  34.                        ucMsgTra++;
    # T. |. p: O) l/ E
  35.     5 d6 ?  r, S# \! k! }+ l
  36.                        /* 向消息邮箱发数据,如果消息邮箱满了,等待100个时钟节拍 */" y, b( Y4 D. B! @- u% ^0 Q" C
  37.                        if(os_mbx_send (&mailbox, &ucMsgTra, 100) != OS_R_OK)" L" r* k" u' H4 s" J* b1 T2 t
  38.                        {
    0 G1 v6 v6 v$ ^1 d8 U: J* r
  39.                             /* 发送失败,即使等待了100个时钟节拍 */" R( b) n' O! T% M6 Q  s
  40.                             printf("K2键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\r\n");
    + R# f! e! [$ J$ W  {' g' t* l
  41.                        }8 G4 O( v/ Q( @
  42.                        else- x0 n/ X. ^# \' N, h5 o
  43.                        {
    " O( P4 q! ]! |
  44.                             /* 发送成功 */# j3 E2 }- j: y5 L
  45.                             printf("K2键按下,向消息邮箱发送数据成功\r\n");                          
    5 t$ h6 i2 h, Q' Y& W- f8 J1 r% ?3 U
  46.                        }' Y& Z. v, O" Q# z. S8 j
  47.                        break;
    ! ?: n/ g! X0 z" \* k, i
  48.                      
      H# z8 }) b4 I& r* T) y
  49.                    /* K3键按下,调用SVC的1号系统服务 */
    * q/ K# Z! U- w! @! J  F1 b- t
  50.                    case KEY_DOWN_K3:
    ! j( |, n4 S. o9 Z! `" h
  51.                        printf(" K3键按下,调用SVC的1号系统服务\r\n");
    ; ^4 [+ B% Q) r# Y$ X
  52.                        ullMsg++;
      M1 @0 _# F+ ~8 [% d; t- @5 a7 _
  53.                        SVC_1_FunCall(++ucMsg, ++usMsg, ++ulMsg, &ullMsg);7 m, L9 U8 M8 E  G
  54.                        break;/ o- y; y2 w, X! p
  55.                   5 Z  |0 ~, z6 O' _
  56.                    /* 摇杆OK键按下,任务运行在非特权级,调用SVC的2号系统服务,可中断中设置NVIC */) _8 B0 j' O* H/ x* t+ G! L
  57.                    case JOY_DOWN_OK:
    , V! P0 d1 W' f0 R% f5 J
  58.                        printf("摇杆OK键按下,任务运行在非特权级,调用SVC的2号系统服务,可中断中设置NVIC( {9 O8 I; P; _! ?! ]$ s
  59. \r\n");
    + J. ^8 A! i3 y
  60.                        SVC_2_FunCall();% T5 T& b  B" Y, W8 r
  61.                        break;- z! \, m% a8 ?7 l/ u

  62. ' t+ d% |; w  v/ g
  63.                    /* 其他的键值不处理 */
    3 x! |( b( ^3 V# D7 P3 Z
  64.                    default:                    
    ' m' o) v, @# Z8 Y5 y4 v
  65.                        break;
    4 \  `3 x# a' }! p( t
  66.               }
    / a( ]1 ]( a- H$ A
  67.          }: E; }# ?+ M. @
  68.         4 j. j( T! `+ Z% j  }: I
  69.          os_dly_wait(20);( W9 Y# u0 z0 Q; W; O! \
  70.      }
    ( B  H. q/ ?% d
  71. }1 G5 @5 T  ]" Z/ ?2 O# l  v; \) q

  72. ! \; T1 \  R! Q. T
  73. /*
    0 P. b/ T! \( G# a8 g
  74. *********************************************************************************************************
    $ r% y3 m! O0 G6 T
  75. *    函 数 名: AppTaskLED
    ( p* J5 i' G* [1 I2 p1 ]2 o; C
  76. *    功能说明: LED闪烁。
    # J; R9 O; U1 p) G8 k' }& C' m+ F
  77. *    形    参: 无
    5 r1 }+ E# u! J/ }. k9 l
  78. *    返 回 值: 无/ h/ F* Z9 u: b2 d
  79. *   优 先 级: 2 $ Z; H- m, q: i2 s# @7 f5 w; J
  80. *********************************************************************************************************
    $ P+ C3 a: z2 E2 x( Q" J2 ~6 [
  81. */
    # f. C. k2 s* V6 @$ y3 U
  82. __task void AppTaskLED(void)' k0 S0 R1 ]3 S; e
  83. {
    0 P5 n+ V9 |8 Q! z
  84.      const uint16_t usFrequency = 200; /* 延迟周期 */
    $ C8 t8 ^' G# ^" Z( t! y& \
  85.    
    1 I7 s, M0 N# G/ E: d( Q
  86.      /* 设置延迟周期 */
    * x0 q' G& S* C$ N% {# S1 i
  87.      os_itv_set(usFrequency);+ ?/ e( W- M  i+ x1 ]* ^
  88.     7 Z6 L! K' G' }  ~* u. s  C
  89.     while(1)3 J- r; g1 G' v* E' Q
  90.     {- U' z% t, M; y7 v$ k- ^* P) d
  91.          bsp_LedToggle(2);) i; O: o6 j, t" ^' o% i
  92.          bsp_LedToggle(3);
    * d! `6 ]2 B0 Z8 C; [0 r5 J
  93. ) t1 I4 g+ Q5 N) X4 E  h2 x
  94.          /* os_itv_wait是绝对延迟,os_dly_wait是相对延迟。*/
    - C0 l0 k. u2 ^( R
  95.          os_itv_wait();! e4 _" d3 p, j6 A/ O) \& E4 K
  96.     }
    7 `$ d* f. o1 ~
  97. }
    * ]2 ^7 X% T" e) L- Z% ]

  98. , y8 _& k& j4 g9 x% p" @& d3 ?3 [
  99. /*& n4 M" D% ~; A" f, z) u; N! j
  100. *********************************************************************************************************
    3 Q( f# _& V) S" p3 D7 z
  101. *    函 数 名: AppTaskMsgPro
    . v) J1 T: w. W0 x& |6 Q, v
  102. *    功能说明: 消息处理,等待任务AppTaskUserIF发来的消息邮箱数据) }: I6 @: z. g$ R
  103. *    形    参: 无/ C8 g6 q% ?0 k9 K/ o
  104. *    返 回 值: 无
    7 o$ u! b9 Z. K9 h4 R
  105. *   优 先 级: 3 ! j0 t% t* s: k6 L) Y- R
  106. *********************************************************************************************************& ], w6 l$ m$ ~- y& s
  107. */
    . J& |' }2 D$ e( J( D4 ]
  108. __task void AppTaskMsgPro(void)! \, D3 ~& ]& l* j1 k) s+ U
  109. {& V2 B. |# F8 [; X
  110.      uint8_t *pMsg;
    , x* _0 d% P% W$ H& U0 b$ U6 B
  111.      OS_RESULT xResult;1 d8 X+ {6 y, `& E- @
  112.      const uint16_t usMaxBlockTime = 200; /* 延迟周期 */- T3 b+ Q- h" U8 s' I! P
  113.    
    4 O$ g, S/ U8 }6 R4 n( y% U: }
  114.     while(1)
    ! V; b5 K$ J, g! X0 t
  115.     {
    . ]! Q3 E5 l) R1 |. F, m
  116.          xResult = os_mbx_wait(&mailbox, (void *)&pMsg, usMaxBlockTime);
    + j/ P% `+ u# d& ?' c
  117.         + W3 ^; t$ [& ]/ C2 }; ^6 |
  118.          switch (xResult)
    " w. y2 R& l! _! W. F* c0 c* \, D7 B
  119.          {
    + G% t. g/ y: x. h" t7 U; D9 {0 b
  120.               /* 无需等待接受到消息邮箱数据 */. C3 M  ^9 ?" K) ^+ A  G# p
  121.               case OS_R_OK:  j2 E/ n9 k4 M7 J, b1 Q  I8 j
  122.                    printf("无需等待接受到消息邮箱数据,pMsg = %d\r\n", *pMsg);
    8 _: Z) L& v7 ]  w! t+ X* W3 F
  123.                    break;  2 h+ t. @' {3 ]* ~( F0 r) {7 c' }

  124. 5 J1 }5 n; L# d" Z  F
  125.               /* 消息邮箱空,usMaxBlockTime等待时间从消息邮箱内获得数据 */
    9 l* t" u* x# I4 V0 Y
  126.               case OS_R_MBX:* ]$ _2 H7 M. Q
  127.                    printf("消息邮箱空,usMaxBlockTime等待时间从消息邮箱内获得数据,pMsg = %d\r\n", *pMsg);
    . p, w% S+ ~- F
  128.                    break;
    ; K8 o, A4 z2 Y  G: Y5 Z
  129. , I  H6 _2 [1 [
  130.               /* 超时 */
    / ~, \1 b# r0 J1 @4 S
  131.               case OS_R_TMO:( N/ i3 W0 n) h* Q' y1 r
  132.                    bsp_LedToggle(1);3 ~$ j( m+ O8 W7 f
  133.                    bsp_LedToggle(4);
    1 T! L1 Y$ f& M. W+ i7 Q# Y
  134.                    break;$ h- [  Q0 h3 o2 E5 s0 L' u
  135.              & B; B) M$ Z# T. {6 z
  136.               /* 其他值不处理 */. ~2 x# v& u- V1 e. o! c7 c* |4 L
  137.               default:                    
    4 d  @2 _5 m# ]* b
  138.                    break;& w  y( d5 a! Z8 _
  139.          }   / k& }1 S% |- H* `0 U
  140.     }' U# t- N5 F. ~. I
  141. }0 F3 y# C  H7 d4 w# a
  142. * ~  ]% O: u  g2 W7 U7 c. X# \
  143. /*
    1 p( I4 M9 O1 [, V! x
  144. *********************************************************************************************************
    ) ^! g( m1 f# \
  145. *    函 数 名: AppTaskStart. P: r3 z4 p; u4 N/ @
  146. *    功能说明: 启动任务,也就是最高优先级任务。这里实现按键扫描。
    4 R+ c* `& p" ~# Y; I' u, r2 M( K& o
  147. *    形    参: 无
    . h/ d1 a  z; i; }# T1 k9 L
  148. *    返 回 值: 无- y' e3 d2 S  ?- |  Q0 n0 t- @
  149. *   优 先 级: 4
    9 Z/ N5 L& _/ f7 S9 i
  150. *********************************************************************************************************' {4 y; ~% R3 D! l( y
  151. */
    # i( k% v+ J+ s+ ?; b2 O
  152. __task void AppTaskStart(void)5 Z' k' ?: B6 ?0 A# M8 i
  153. {7 @+ X9 L% m% L) D
  154.      /* 创建任务 */
    . O: A6 J! E/ g7 |& U
  155.      AppTaskCreate();, `4 K3 S! N+ \! i
  156.    
    6 _- L4 @! N# b
  157.      /* 创建任务通信机制 */9 \$ z) B( Q3 S" s2 z5 h
  158.      AppObjCreate();1 M$ G8 B* E1 R
  159.    
    2 h( L! Y$ C5 a) r- Q
  160.     while(1)( Y) D0 O# W4 j7 f- `
  161.     {6 P" D5 U9 u( L; l
  162.          /* 按键扫描 */
    8 G. W+ d* _1 h$ O) G
  163.          bsp_KeyScan();
    3 i- q# z) b0 t! Z0 y5 f  x
  164.         os_dly_wait(10);) z. X8 _  R8 x+ X- l+ Y
  165.     }2 G+ h' S( t3 l# U: c" X
  166. }
复制代码
* B0 k; `0 W: g
  W* i1 e' c2 P
baiyongbin2009 回答时间:2016-2-3 17:43:49
19.3.2   STM32F407开发板实验
配套例子:
    V5-419_RTX实验_SVC中断方式调用用户函数
实验目的:
    1.     学习SVC中断方式调用用户函数
实验说明:
    1.     RTX支持配置所有任务工作特权级模式或者用户模式,宏配置在文件RTX_Conf_CM.c文件里面
      #defineOS_RUNPRIV     0
      配置为0的话,任务工作在用户级,配置为1的话,任务工作在特权级。本实验配置为0,所有任务都工作在用户级模式。
    2.     本实验演示SVC中断号调用方法。
      SVC指令带一个8位的立即数(范围0-255),可以视为是它的参数,被封装在指令本身中,如:
      SVC   3  ;   呼叫3号系统服务
      SVC0被RTX系统所使用了,用户只能使用从1开始的服务号。用户使用的时候一定要保证从1开始,而且需连续的使用。实验中使用了SVC 1和SVC 2。
实验内容:
    1.K1按键按下,串口打印。
    2.K2键按下,向消息邮箱发送数据。任务AppTaskMsgPro接收到消息后进行消息处理。
    3.K3键按下,调用SVC的1号系统服务。
    4.摇杆OK键按下,任务运行在非特权级,调用SVC的2号系统服务,可以在中断中设置NVIC。
    5.各个任务实现的功能如下:
  AppTaskUserIF任务   :按键消息处理。
  AppTaskLED任务     :LED闪烁。
  AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的消息邮箱数据。
  AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
RTX配置:
    RTX配置向导详情如下:
                              
19.5.png
Task Configuration
Number of concurrent running tasks
  允许创建4个任务,实际创建了如下四个任务:
                AppTaskUserIF任务   :按键消息处理。
                AppTaskLED任务     :LED闪烁。
                AppTaskMsgPro任务 :消息处理,等待任务AppTaskUserIF发来的消息邮箱数据。
                AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
    Number of tasks with user-provided stack
  创建的4个任务都是采用自定义堆栈方式。
     Run in privileged mode
  设置任务运行在非特权级模式
RTX任务调试信息:
19.6.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类型数据运算会出问题。
系统栈大小分配:
19.7.png
RTX初始化:
  1. /*
    / {/ V$ S+ g$ Z0 D
  2. *********************************************************************************************************
    5 [5 [4 ]; u3 G% ^
  3. *    函 数 名: main" w% d2 H) ~5 `, B, F$ L
  4. *    功能说明: 标准c程序入口。/ t0 d9 L# l' u. w- r: Q
  5. *    形    参: 无3 S& |- N/ o+ B* q* j
  6. *    返 回 值: 无
    7 C) c9 L/ e6 x+ T% b
  7. *********************************************************************************************************8 Y' s! @6 b+ a# w
  8. */. m; q/ ?* `# A, z
  9. int main (void)6 I. G7 R* F* x6 l
  10. {   * B1 y( F' c* K1 g' _* c
  11.      /* 初始化外设 */
    9 }% J; G/ R7 S+ ~5 [0 T8 N; Q; p  V$ Y
  12.      bsp_Init();
    - K: q- l7 f! K! F  k
  13.    
    ' M  H. ^9 b- v$ T* b/ `9 L
  14.      /* 创建启动任务 */7 R; @6 {3 a$ n. B9 y3 j' f7 t9 O
  15.      os_sys_init_user (AppTaskStart,             /* 任务函数 */
    " t$ m+ ^) y) \: ?+ i& @7 v4 y4 e
  16.                        4,                        /* 任务优先级 */
    6 ^1 X. y% U; O$ g6 ?, J
  17.                        &AppTaskStartStk,         /* 任务栈 */3 G* G- C3 ?% ~2 L0 H* A; \
  18.                        sizeof(AppTaskStartStk)); /* 任务栈大小,单位字节数 */8 R3 T/ i" ?$ W) u; S6 Y0 `5 X+ F
  19.      while(1);
    3 m( R' I2 I* b) X' |% e. a" K
  20. }
复制代码
, z, i' _  v1 R4 K  s) q9 ~
RTX任务创建:
  1. /*7 N: j' i- k7 R; M$ r" Y
  2. *********************************************************************************************************8 t' V) Y) a! E7 }2 I3 }! q$ \2 |" P% b
  3. *    函 数 名: AppTaskCreate  V/ C3 `+ f! E- R# D% m& [
  4. *    功能说明: 创建应用任务6 a1 h) y& i" t# L- g# Q
  5. *    形    参: 无
    2 j# H- D3 ]- S7 y+ G. K' C/ {
  6. *    返 回 值: 无
    1 Y" S  k$ Z  p- j% F, O
  7. *********************************************************************************************************
    , t/ ?% W, \, j6 v1 D) d
  8. */$ P7 [( K% j( p, J1 Q" n
  9. static void AppTaskCreate (void)
    ; d9 H" h, ^5 O& h
  10. {  M; \+ B% n" E; ?8 z" E& P* k
  11.      HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             /* 任务函数 */, V% g+ `2 X# C$ p) A1 u% A. T
  12.                                            1,                         /* 任务优先级 */# a% Z9 ?: l. h6 M
  13.                                            &AppTaskUserIFStk,         /* 任务栈 */+ P* e% c+ f8 \# [/ x
  14.                                            sizeof(AppTaskUserIFStk)); /* 任务栈大小,单位字节数 */
    ! m0 L. [5 ]7 x% d0 Q0 q5 A; p+ d
  15.    
    - m2 F/ P4 Q. s9 f
  16.      HandleTaskLED = os_tsk_create_user(AppTaskLED,              /* 任务函数 */
    ' |/ Z8 {3 J# a" }& X  j6 u7 D
  17.                                         2,                       /* 任务优先级 */
    1 x6 C/ z% s9 e8 z
  18.                                         &AppTaskLEDStk,          /* 任务栈 */
    2 r1 E. r$ s4 H; W+ }; y4 z. [6 E
  19.                                         sizeof(AppTaskLEDStk));  /* 任务栈大小,单位字节数 */, G$ M' V4 u" b' x( {5 q( E6 u  M
  20.    
    8 I1 p. E$ M" B& Y' o7 @8 j0 i
  21.      HandleTaskMsgPro = os_tsk_create_user(AppTaskMsgPro,             /* 任务函数 */
    0 z  d- f# z  @* q; n; P% c
  22.                                            3,                         /* 任务优先级 */
    " c* x8 O( u9 J2 v4 n  A. X- }6 v
  23.                                            &AppTaskMsgProStk,         /* 任务栈 */6 L7 ^, @& g5 ~8 R
  24.                                            sizeof(AppTaskMsgProStk)); /* 任务栈大小,单位字节数 */
    ( E4 w- n  |6 P7 Q6 \
  25. }
复制代码

1 e$ m$ |5 B  I) [# l8 x5 C4 I( c5 K
消息邮箱的创建:
  1. #define PoolBlocks           10
    " P! S9 R, p7 u/ h- S: P, c
  2. #define PoolPerBlockSize     8
    $ H" Q+ n3 i9 E' G# E5 S, r
  3. 6 S9 O  o  T! R" ?2 x: R0 U
  4. /* 声明一个支持10个消息的消息邮箱 */: S% l7 ]- {: o; i2 j2 {) W& o" t. W  |
  5. os_mbx_declare (mailbox, 10);
    5 q' k: b& f$ |1 t
  6. 5 _8 q9 V8 }2 \& W, \) v9 e
  7. /*
    7 S- [  a4 e9 q& [% l
  8. *********************************************************************************************************
    6 P" h7 v7 Q$ Z8 T. C* p
  9. *    函 数 名: AppObjCreate1 }3 i$ x% T" p2 B
  10. *    功能说明: 创建任务通信机制
    ; J5 i8 Z# V: d# |. Q
  11. *    形    参: 无% Y1 |4 p: e0 |" u
  12. *    返 回 值: 无  X) k( `5 i. ^3 [4 H
  13. *********************************************************************************************************
    4 a9 ?  G* Q0 M# J! x% O* W6 G: `- ~- ], b
  14. */
    2 o/ I% D0 ^8 ~6 y  V+ e7 H
  15. static void AppObjCreate (void)
    7 T9 A+ p- y2 t
  16. {
    ) [2 N5 f( R% F8 i
  17.      /* 创建消息邮箱 */  g! Z2 Z9 w# u% S% `$ P
  18.       os_mbx_init (&mailbox, sizeof(mailbox));* g4 `1 h3 d7 a: U6 A! p5 ?' {
  19.    
    2 \7 H$ h& Q( V# [  Z% `$ ~& c
  20. }
复制代码
- h" N" x; {9 F# g/ Y
SVC中断函数的创建:
  1. void __svc(1) SVC_1_FunCall(uint8_t _arg1, uint16_t _arg2, uint32_t _arg3, uint64_t *_arg4);4 h' q# O* e2 j+ _
  2. void __svc(2) SVC_2_FunCall(void);
    , u) ?3 `" G3 H; D' O% ^3 K8 I# [
  3. ( i/ R" n" Z+ e. i! Z1 G
  4. /*+ W. ^; x2 s* o/ t( k& E' X
  5. *********************************************************************************************************
    " {6 B/ w5 s5 D3 s2 E( W2 j+ D
  6. *    函 数 名: __SVC_1和__SVC_2系统服务号
    6 y* }0 U  Y1 X3 k3 p
  7. *    功能说明: 被SVC中断所调用的__SVC_1和__SVC_2% V; w: O$ T# R
  8. *    形    参: 无
    ' F$ Z7 z1 y' F8 Q5 j! Q
  9. *    返 回 值: 无1 ^2 t' _. z) Q  W. c. C$ f4 L
  10. *********************************************************************************************************/ @; t7 G' ~1 j0 o9 Z! U
  11. */+ t; a6 V" u' y" t8 {# q- i! g
  12. void __SVC_1(uint8_t _arg1, uint16_t _arg2, uint32_t _arg3, uint64_t *_arg4)1 ]  ?$ C- Z1 Q4 L0 `
  13. {
    3 x5 b8 }6 ?' d2 }$ m7 ^: X/ g
  14.      /*' ?9 n+ O; e% O7 j  G+ ]. S0 J
  15.          1. 实际应用不要在SVC中断中调用串口打印,太影响实时性,这里仅仅是为了演示
    3 O- A" I& a& w" o
  16.          2. 根据需要做开关中断操作。: v  `' v, H  E8 q& C; R
  17.      */$ Y' T4 U8 ]  @6 Y$ H3 q  Y5 _
  18.      __disable_irq();  n* q- L; O6 F
  19.      printf("_arg1 = %d\r\n", _arg1);# B5 F" v2 P/ Z4 L% @: z( M
  20.      printf("_arg2 = %d\r\n", _arg2);
    # `) Y# D, |  N' @& ~% }. `
  21.      printf("_arg3 = %d\r\n", _arg3);/ U7 J4 I/ @& I3 e9 b3 t# J
  22.      printf("_arg4 = %lld\r\n", *_arg4);/ t& j+ q5 W+ N! H4 ^7 y) B
  23.      __enable_irq();" h  q1 Q- R0 s4 p, b& j
  24. }. c3 L* B$ Q2 B- x  I9 k
  25.                   
    ) P; @2 l  ?2 h& Y# f
  26. void __SVC_2(void)
    4 P% T2 N' K. g' p1 q1 N
  27. {* b, V+ K* @) `' I" r" a7 A
  28.      /*- Z& I4 R4 e2 H: t, ]
  29.          1. 根据需要做开关中断操作。
    $ t. `0 W* F* X
  30.          2. 本实验所有任务都是工作在非特权级,中断函数都是运行在特权级的,此函数是在SVC中断里面运行。( n! w1 k: G: I- Q; f
  31.             所以可以在此中断中设置NVIC分组。! ?& B' |2 B' N& k
  32.      */
    * l4 g! S! T/ {: U8 V2 p  s
  33.      __disable_irq();
    1 N! _# k- Y% ~7 |. r
  34.      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
    1 ]" @- C, p( o' B4 h) s2 q
  35.      __enable_irq();
    ) m* h4 L! K+ o5 S  r( m9 I3 u
  36. }
复制代码
* ?+ e* _: R7 v1 x$ v
SVC_Table.s文件中SVC中断的设置(红色字体是需要用户添加的):
  1. void __svc(1) SVC_1_FunCall(uint8_t _arg1, uint16_t _arg2, uint32_t _arg3, uint64_t *_arg4);- Q9 c+ R! r2 O* n8 ]% O
  2.                 AREA    SVC_TABLE, CODE, READONLY7 T  l4 F4 V0 y, F  Y

  3. . o9 |0 n. N+ h% V
  4.                 EXPORT  SVC_Count
    , K0 v/ `: W  F

  5. - l. J" q7 [' r9 o
  6. SVC_Cnt         EQU    (SVC_End-SVC_Table)/49 a: T* q* J+ P6 e3 v
  7. SVC_Count       DCD     SVC_Cnt
    " \: E; X$ n! G2 Z, A3 z
  8. 6 ^  p# ^! X5 C$ r5 }4 S6 v
  9. ; Import user SVC functions here.
    3 \' o; z2 c  n( j* E5 q
  10.                 IMPORT  __SVC_1
    3 Y" v2 \9 `" b# V1 `9 g  `( X% r
  11.                 IMPORT  __SVC_2
    0 V% W- A9 k% a
  12. : M$ N$ C6 r* k4 X3 g
  13.                 EXPORT  SVC_Table
    * Y, `+ s/ }; R. j
  14. SVC_Table
      w- ^: A* h  ]- k9 k, {
  15. ; Insert user SVC functions here. SVC 0 used by RTL Kernel.
    % r8 R) L" F$ `
  16.                DCD     __SVC_1                 ; user SVC function: k5 R% X+ u% s
  17.                DCD     __SVC_2                 ; user SVC function
    / a% c4 j4 F" K4 j* o  J- Z: i

  18. 4 u& F1 |, i1 k* E0 d4 E; \8 y! o
  19. SVC_End
    + A  O/ g$ L. l5 }4 R( z0 N( S: _7 c
  20. 3 @; A' T3 k+ c
  21.                 END
复制代码
8 s, r/ y7 @- E9 Y5 y
四个RTX任务的实现:
  1. /*; B- V  l2 L% {4 R
  2. *********************************************************************************************************
    $ A( S) P& u- T* H* Y
  3. *    函 数 名: AppTaskUserIF- X1 E6 E6 n" S4 }- W, I
  4. *    功能说明: 按键消息处理     ! u# J) a  \) w4 L* h# |6 Z% S
  5. *    形    参: 无
    ! m2 d5 L* K4 J" i  e+ b
  6. *    返 回 值: 无1 e/ M+ W! ~; \7 N3 j4 e
  7. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
    6 H. @" w: x- y% X$ i$ J9 N" Z# @
  8. *********************************************************************************************************, L0 w9 ^  R9 J' Y$ S( D8 N
  9. */: N0 J4 [: [: c0 y$ ~, P
  10. __task void AppTaskUserIF(void)
    , ]! V% Q" j5 A9 L  y
  11. {
      f* D" D  k9 f9 `3 i: M
  12.      uint8_t ucMsgTra = 0;, d4 p" p1 Y' [9 W7 s
  13.      uint8_t ucMsg = 0;
    ; ^% Y* B( z, J1 K5 L" L
  14.      uint16_t usMsg = 0;6 B5 y* b; |5 ~: D1 P
  15.      uint32_t ulMsg = 0;
    0 ^' ~1 O0 V, c) m" l. \% [0 v
  16.      uint64_t ullMsg = 0;
    7 d1 S4 |( l9 y  H/ a
  17.      uint8_t ucKeyCode;1 B$ H5 F, J6 P  q# g" U! _, N
  18. 0 _% G5 C: `( P$ P2 O/ S# N! ?
  19.     while(1)
    # u7 j) |' A, c. y
  20.     {
    ' ~$ i, w* ]) k4 d8 F0 V1 b% _
  21.          ucKeyCode = bsp_GetKey();( K" F; I1 \* k
  22.         ( n8 G0 k* j# P! s# C
  23.          if (ucKeyCode != KEY_NONE)- o; E" U. i/ _% B/ I
  24.          {- X1 t( s! Z6 P$ G2 |8 _- o: q
  25.               switch (ucKeyCode)
    " v) C" E3 J. T( C5 u5 _: ^# b% d
  26.               {
      n' W+ v  t2 f* j
  27.                    /* K1键按下,打印调试说明 */# `% @0 \  {4 @9 [/ p6 h- @7 y" V
  28.                    case KEY_DOWN_K1:8 ?5 R2 Z4 z- V0 k+ U2 j
  29.                        printf("K1键按下,使用MDK中自带的RTX调试组件,请务必使用MDK4.74版本进行调试\r\n");
    1 `% _5 n, ^  |
  30.                        break;  
    $ F3 N5 c- A, u; z! ]
  31. # }, F! k; A0 e) L8 ~1 C, i" ^" ^
  32.                    /* K2键按下,向消息邮箱发送数据 */* o) B5 d# Q# S4 o4 [1 G2 h
  33.                    case KEY_DOWN_K2:. J9 t$ L- j6 M) q( [6 A
  34.                        ucMsgTra++;
    ! a1 Q) D& t" m- h4 I- J: Q. A
  35.    
    - |. d2 t( T& P& `( L
  36.                        /* 向消息邮箱发数据,如果消息邮箱满了,等待100个时钟节拍 */
    ' o$ z9 S7 W3 B2 u7 p5 e# N
  37.                        if(os_mbx_send (&mailbox, &ucMsgTra, 100) != OS_R_OK)
      |$ R6 |' E; S8 `4 z1 j4 }
  38.                        {! H  \! P+ f% X7 y
  39.                             /* 发送失败,即使等待了100个时钟节拍 */, }1 }5 P% q7 ^6 e
  40.                             printf("K2键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\r\n");
    7 C5 m0 A* }3 U( _% M9 S
  41.                        }
    : X" Q7 f5 o$ E
  42.                        else
    # R4 n9 z* y3 y
  43.                        {8 v5 o7 T0 E6 A7 w, o8 D
  44.                             /* 发送成功 */
    . j& S0 c" p6 z( ~
  45.                             printf("K2键按下,向消息邮箱发送数据成功\r\n");                          
    , U9 Q6 b  c! p& F
  46.                        }
    1 ?. W+ a& R5 j3 A
  47.                        break;
    " h7 l3 u' X! h4 L  |( e2 |
  48.                       % o6 B) L% ?7 u. D  H; V$ w" H
  49.                    /* K3键按下,调用SVC的1号系统服务 */
    9 k9 w1 E& B7 G# c4 ?' J9 A8 P
  50.                    case KEY_DOWN_K3:! f) A5 V/ z- n1 l, c, M( T' l
  51.                        printf(" K3键按下,调用SVC的1号系统服务\r\n");
    ; i' Z, H  v+ w5 ]
  52.                        ullMsg++;
    0 e' N4 n0 H+ I, d
  53.                        SVC_1_FunCall(++ucMsg, ++usMsg, ++ulMsg, &ullMsg);
    " d3 `2 w' o& t  k! A
  54.                        break;
    ) r) b$ b' `- T5 G4 p0 x! u6 ?
  55.                   
    4 o/ E7 n' q: J0 T' O
  56.                    /* 摇杆OK键按下,任务运行在非特权级,调用SVC的2号系统服务,可中断中设置NVIC */
    & s, @& U. x5 O% c
  57.                    case JOY_DOWN_OK:- L/ {0 m! P$ X" m
  58.                        printf("摇杆OK键按下,任务运行在非特权级,调用SVC的2号系统服务,可中断中设置NVIC: F2 `6 f0 b1 w/ z1 o, }: l" W
  59. \r\n");0 v* q, h5 B. z
  60.                         SVC_2_FunCall();
    ( w, S5 X+ F; a+ _; j2 ]# Y
  61.                        break;
    " O) X  s2 }  \$ Q/ B* G  M+ v7 i

  62. ; f" X% U" i# s0 {: _0 [6 y
  63.                    /* 其他的键值不处理 */6 i7 c! J  B* ^+ E
  64.                    default:                    $ f  b& b5 P# J4 w
  65.                        break;
    2 J! }& T& ~0 s: [. [9 |
  66.               }
    ( W& f5 N- d4 v1 a
  67.          }
    9 u, e0 m: s  c: `/ X
  68.         
      W( ?' q0 F  h$ H+ Y; E
  69.          os_dly_wait(20);
    6 G) X. U; V* A1 e- v& Q9 q
  70.      }
    ' f# a/ u# E5 C1 d  a
  71. }
    & _* ~( B( S2 H* d. K
  72. 5 W7 D+ m9 M0 T* E. A
  73. /*; m2 H- `1 J0 I$ e
  74. *********************************************************************************************************
      S7 [, I4 d1 U8 l; }, w
  75. *    函 数 名: AppTaskLED
    " I6 _+ f5 `) D8 u
  76. *    功能说明: LED闪烁。
    9 S% E. Q( f2 i, r- [9 E
  77. *    形    参: 无; ]: w  p0 f" e; o& |
  78. *    返 回 值: 无
    3 z8 q$ F4 E, d6 y% K
  79. *   优 先 级: 2 ( E( l7 ]  o$ C0 z
  80. *********************************************************************************************************, m4 n+ P( z$ E
  81. */
    ; R; j. D: x2 Q0 H9 x% L
  82. __task void AppTaskLED(void)
    : ?$ n* E: B2 q% b+ B0 k( C
  83. {7 d! a+ z: z1 b1 F5 @, g
  84.      const uint16_t usFrequency = 200; /* 延迟周期 */+ t; ~3 S0 L4 n, V
  85.    
    4 _/ z( ^8 _' U  {
  86.      /* 设置延迟周期 */! Y1 G4 }. l7 q# x# H$ I, ~
  87.      os_itv_set(usFrequency);
      \" h( V0 R: q& k% \! f& [
  88.    
    9 e7 o2 W6 V" D
  89.     while(1)
    & k* x( z$ P% y- [9 z
  90.     {* K9 d' E+ m7 X( D5 v( O0 x/ `/ ?
  91.          bsp_LedToggle(2);, O& F( j! T3 B! _
  92.          bsp_LedToggle(3);
    # X6 \2 z( M+ V( Z( q2 r

  93. # ~/ j3 a! Q" H& o. [1 y; K
  94.          /* os_itv_wait是绝对延迟,os_dly_wait是相对延迟。*/$ W1 u, w7 j  @5 q2 h8 c/ V, l8 o
  95.          os_itv_wait();% S/ d! _8 @' ~4 ~0 ^6 R
  96.     }
    ; g5 I1 Y! u7 P  S) Q" ]
  97. }
    9 _6 ]( K" w, H8 G/ Q6 }# G) w( J

  98. 4 J5 _9 \- F/ L, S
  99. /*1 S+ u, r' D0 s: n' ^
  100. *********************************************************************************************************
    3 e9 K2 g# a0 Q4 K2 @
  101. *    函 数 名: AppTaskMsgPro' P" V) g6 N& z
  102. *    功能说明: 消息处理,等待任务AppTaskUserIF发来的消息邮箱数据0 I- E1 m3 O+ S- A
  103. *    形    参: 无; y" V  }2 ?, D  @$ p) a0 g
  104. *    返 回 值: 无
    ' ^  k/ C3 z! f1 M/ F& c
  105. *   优 先 级: 3
    4 P5 O4 X' S: L
  106. *********************************************************************************************************7 H; `8 J( F1 M- y8 I# y. R
  107. */& W0 h0 M' b6 K* m
  108. __task void AppTaskMsgPro(void)
    / x& _8 \( @& e% D  o6 r
  109. {
    & {; L; t4 e' X' M8 d
  110.      uint8_t *pMsg;1 a8 S! {3 R1 V* l! F- D9 }) i
  111.      OS_RESULT xResult;
    # C' h5 T! ?' K  ]7 V# i
  112.      const uint16_t usMaxBlockTime = 200; /* 延迟周期 */& }- k8 G9 z# Z
  113.     / }& p# Z! V* r
  114.     while(1); n: p( |! @  a7 ^
  115.     {3 T) N$ ]) x. E6 l
  116.          xResult = os_mbx_wait(&mailbox, (void *)&pMsg, usMaxBlockTime);
    / d2 b* K! v5 t% ~
  117.         # N9 i6 X! |$ k0 h  Q; J, Q
  118.          switch (xResult)
    / F- |2 A! p5 E+ l& e4 j9 ]
  119.          {
    - {$ Z3 [4 g* G6 G6 b, B- y* K
  120.               /* 无需等待接受到消息邮箱数据 */; ~+ f0 F: N* U  Q5 j3 I% x
  121.               case OS_R_OK:
    7 U& Y8 ]) n' A2 d, W1 d0 s
  122.                    printf("无需等待接受到消息邮箱数据,pMsg = %d\r\n", *pMsg);" B, A: f: @# [; V
  123.                    break;  * K) ~! s8 P/ v( W
  124. - H  [" ]; Q+ p/ P1 S
  125.               /* 消息邮箱空,usMaxBlockTime等待时间从消息邮箱内获得数据 */
    ( X5 \3 `# V  N, ^$ u2 r+ U7 G
  126.               case OS_R_MBX:% h" q/ J5 B/ c' C( x
  127.                    printf("消息邮箱空,usMaxBlockTime等待时间从消息邮箱内获得数据,pMsg = %d\r\n", *pMsg);1 W- S- l7 Y4 A' ]  F) |+ ^" Z
  128.                    break;4 v0 D9 b2 C  Q* }  L! s

  129. " q, R2 X& K/ z$ ]. N3 o
  130.               /* 超时 */
      w$ L( V  n. v4 `2 ~" q
  131.               case OS_R_TMO:
    / ]: p& z- a' B( V4 ?
  132.                    bsp_LedToggle(1);3 {0 |3 v0 N, I" x' ?3 i
  133.                    bsp_LedToggle(4);
    6 K/ c$ E; U4 X
  134.                    break;; d, L  g  D+ m9 S" t
  135.              / t# O1 K3 M9 O& ]
  136.               /* 其他值不处理 */
    + m- d/ V/ l" W* ^$ w5 ]: L* a% I
  137.               default:                    / g! n) A" e- O' ]
  138.                    break;) Y4 H& H* t$ Y2 L6 K
  139.          }   
    / g+ J. h& _% E
  140.     }
    4 ~" K; O0 z1 h! ^. P1 v
  141. }
    4 i) b# e; ^; D* ?
  142. 5 k- W+ u/ E$ ~3 b% ?3 _. T3 q6 N
  143. /*
    5 @4 F* N% y3 N2 Z
  144. *********************************************************************************************************, D6 _- b* D  i( p  I' m
  145. *    函 数 名: AppTaskStart
    3 a7 ?! o, ^* H. P$ ^; x
  146. *    功能说明: 启动任务,也就是最高优先级任务。这里实现按键扫描。+ c% l1 K/ Z$ h  }- c3 F7 c- x
  147. *    形    参: 无
    9 I$ d0 C( v# v/ m; N
  148. *    返 回 值: 无
    . H, o) L6 }- l5 b( G
  149. *   优 先 级: 4
    9 y, U: y* ?% |0 N
  150. *********************************************************************************************************9 @+ v3 ]4 j( j  Y( y
  151. */( |$ s- r9 z  T4 c9 x) F
  152. __task void AppTaskStart(void)
    3 U- B+ x3 ?/ _6 M" ?
  153. {
      @, Y5 i, C6 z3 ?
  154.      /* 创建任务 */
    $ p( t( N, s, X* S2 Z  i* B
  155.      AppTaskCreate();
    # z3 n, X- ]0 S  K! t6 q- E3 m
  156.     & J' w% r, G8 w6 n  H
  157.      /* 创建任务通信机制 */) o2 b( l3 [7 b" E- F4 j  ~; r: X5 [
  158.      AppObjCreate();) r( C1 H6 A/ |: _- A2 N$ I
  159.     * ]2 M0 I# z6 p. j
  160.     while(1)
    , t6 O" M" q9 d8 x# [
  161.     {
    - J8 ]- x( a# J, y) W: {" R( Y
  162.          /* 按键扫描 */
    8 h! s9 g0 q/ y& q+ i
  163.          bsp_KeyScan();/ G* O' Q) F# b
  164.         os_dly_wait(10);
    2 t* M9 f! G* v+ F2 [
  165.     }! e- K5 f1 _5 ]. N2 Z
  166. }
复制代码

6 W1 h, F  O- R( ^- T+ Q5 y# B; m6 X# k4 ^7 c$ L
baiyongbin2009 回答时间:2016-2-3 17:44:39
19.4 总结
    本章节主要大家讲解了如何采用SVC中断方式调用用户函数,更多SVC中断方面的知识可以看Cortex-M3或者M4权威指南。
/ j; e4 O  k9 i' L% b* z, |7 j$ o4 R- s
zhangdaijin 回答时间:2016-2-3 21:09:38
谢谢分享
niexiaohui 回答时间:2016-2-4 09:45:25
好样的。楼主幸苦!
党国特派员 回答时间:2016-2-6 09:08:29
楼主,有没有完整的PDF? null.png null1.png null2.png null3.png null4.png
feixiang20 回答时间:2018-1-15 20:54:26
篇幅可真长

所属标签

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