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

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

[复制链接]
baiyongbin2009 发布时间:2016-2-3 17:08
【安富莱】【RTX操作系统教程】第19章     SVC中断方式调用用户函数 【RTX操作系统教程】第19ç«  SVC中断方式调用用户函数.pdf (710.21 KB, 下载次数: 76)
赞 收藏 评论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的源码移植方式时这个文件已经加上。

- s3 @7 \1 x. R6 S# [) q5 j, q% _
第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);
& F6 U- u( f. O9 b$ n
第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();
}

" {  p* v; F; w* i! w( R/ X/ j
第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
2 o$ q# ^6 S0 h+ ?7 \/ m

2 f5 M0 B+ p8 b' v
至此,RTX中SVC中断的调用就实现了。实际应用的时候,用户只需调用函数SVC_1_FunCall和SVC_1_FunCall即可,这两个函数就是在SVC中断里面实现的。

+ ~; R0 B/ u  L; c! n# h6 X
baiyongbin2009 回答时间:2016-2-3 17:38:43
19.3 实验例程说明  i  q* I- q5 L$ b
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. /*; G) v. r: d  F' K- q9 g! Y
  2. *********************************************************************************************************
    . Z4 {( d: r& ~" T- k
  3. *    函 数 名: main
    " y( T9 O6 r, E9 ^7 @8 _" U
  4. *    功能说明: 标准c程序入口。
    4 S) ~5 i: p5 ^
  5. *    形    参: 无
    ; p) z& S, a1 ?& j9 [$ n8 }
  6. *    返 回 值: 无! b$ n% R, ^4 I+ w+ e3 k- s
  7. *********************************************************************************************************5 T9 v/ U6 m1 G6 v( S" I% l0 i
  8. */8 z) C2 ?1 W# S* ~* q$ g+ Z
  9. int main (void)# f! j, |8 F0 q+ z( X, D1 @. G. P' a
  10. {   3 B- ?3 w0 F4 E) c
  11.      /* 初始化外设 */, V* w# G8 E% k5 `
  12.      bsp_Init();+ @9 f9 p% D" b$ L3 R
  13.     0 B1 {) R1 \1 q$ \9 K
  14.      /* 创建启动任务 */& ~7 Y& j8 t. d# m) a% R& I
  15.      os_sys_init_user (AppTaskStart,             /* 任务函数 */( K) I5 |" {2 G% a1 K( B
  16.                        4,                        /* 任务优先级 */
    ! @/ F* Y9 B7 E
  17.                        &AppTaskStartStk,         /* 任务栈 */% P4 k( |' \: S1 h
  18.                        sizeof(AppTaskStartStk)); /* 任务栈大小,单位字节数 */8 a; V' P4 p# K# W$ C% \
  19.      while(1);
      H2 Z0 W2 l2 e( {: d
  20. }
复制代码

# g4 @/ M9 i) _
RTX任务创建:
  1. /*) K) m* c- }# _6 ]* f1 C0 j
  2. *********************************************************************************************************
    + ]9 K9 s9 i3 O2 y  \& _, u
  3. *    函 数 名: AppTaskCreate( i! ]- K% B! b; ^4 E, Q  d
  4. *    功能说明: 创建应用任务
    / }9 {) O# k% h( }( \; Q) n. V
  5. *    形    参: 无0 i% p5 H" ~" C% j7 b1 c
  6. *    返 回 值: 无
    8 @" _3 K" z' [- S" F4 E! I( f
  7. *********************************************************************************************************
    ! E  w6 T/ P& D% w  u' S, Z+ u
  8. */6 {) h( }4 x9 ?/ Y3 B
  9. static void AppTaskCreate (void)
    . g% M* K! D# C& R9 ?4 p
  10. {
    9 A4 g3 c% Z+ V) Q9 I( s
  11.      HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             /* 任务函数 */" y+ T, w1 O+ g9 b7 h. e0 x
  12.                                            1,                         /* 任务优先级 */) C1 ?4 n0 e- _+ @7 {+ l3 n
  13.                                            &AppTaskUserIFStk,         /* 任务栈 */+ q& ?1 N7 N/ E* I, |+ i5 S4 a' j
  14.                                            sizeof(AppTaskUserIFStk)); /* 任务栈大小,单位字节数 */
    ; ^" b4 a4 v# k" Y
  15.    
    9 @8 Q. A0 N: D8 c+ O- w8 q
  16.      HandleTaskLED = os_tsk_create_user(AppTaskLED,              /* 任务函数 */: Y, W8 y5 J! ^" Q) L5 f1 P
  17.                                         2,                       /* 任务优先级 */
    ' E% ~. `% z% H( X5 U4 u! V
  18.                                         &AppTaskLEDStk,          /* 任务栈 */1 J7 [8 y* R7 F5 ]5 o  F( }1 W0 E
  19.                                         sizeof(AppTaskLEDStk));  /* 任务栈大小,单位字节数 */
    5 l! U% s1 p* V5 H& v9 L
  20.     . q, `% L4 R# ^% F4 ~0 H
  21.      HandleTaskMsgPro = os_tsk_create_user(AppTaskMsgPro,             /* 任务函数 */( s2 c8 M$ Y) V
  22.                                            3,                         /* 任务优先级 */5 q, q: L, [* T- n' P
  23.                                            &AppTaskMsgProStk,         /* 任务栈 */
    2 R4 U+ L& X! R" l3 }6 f* z
  24.                                            sizeof(AppTaskMsgProStk)); /* 任务栈大小,单位字节数 */
    # g! T* l9 D6 I( _
  25. }
复制代码

5 w$ o. C# t. [  I0 @1 G* X
消息邮箱的创建:
  1. #define PoolBlocks           10
      P4 B, `' q5 Y/ `
  2. #define PoolPerBlockSize     8
    5 `& _, \& P. J: v
  3. + k; n+ t* q8 F! x
  4. /* 声明一个支持10个消息的消息邮箱 */
    : Z1 |6 ^8 {: o$ A! W
  5. os_mbx_declare (mailbox, 10);  i3 H; {( K9 y. E# I0 e: v' s% t

  6. 1 D7 C$ |/ }% b; \3 J% k9 {
  7. /*
    2 `# g3 T9 g' s8 }
  8. *********************************************************************************************************' q. B' w0 `$ N( y4 }, h3 W
  9. *    函 数 名: AppObjCreate% f/ ]+ c! X9 l
  10. *    功能说明: 创建任务通信机制6 |7 U  V% i1 Y! P) Q
  11. *    形    参: 无
    , Q: F7 e5 N, _1 i; L0 U$ ]1 u- @
  12. *    返 回 值: 无
    ! O# D$ C3 F# e4 S* O) u. X8 q
  13. *********************************************************************************************************
    6 Y* H( }* W4 X/ q" {5 ~2 ~
  14. */
    , w4 Y: [1 {; t/ ^2 o6 |
  15. static void AppObjCreate (void)
    1 n2 E. C# a$ p
  16. {
    # U- L1 L" y( Y
  17.      /* 创建消息邮箱 */! |. j' L/ s, e- q* z2 x
  18.       os_mbx_init (&mailbox, sizeof(mailbox));8 F* u4 Z' L( {' I; n
  19.     3 z% F( C  _* D, X
  20. }
复制代码

" u# t- c- ?/ o( @. B# B
SVC中断函数的创建:
  1. void __svc(1) SVC_1_FunCall(uint8_t _arg1, uint16_t _arg2, uint32_t _arg3, uint64_t *_arg4);/ G* q$ j6 K6 z& ~
  2. void __svc(2) SVC_2_FunCall(void);
    % n: @* t+ \7 m; f! L9 Y$ @
  3. 0 g0 Y/ S& Q+ M1 {$ f
  4. /*% u3 ?) b. X! |+ W. a. Y: g
  5. *********************************************************************************************************
    / ^+ t+ {( m: B9 v) p( k0 f. k
  6. *    函 数 名: __SVC_1和__SVC_2系统服务号+ i# U) I( A$ K( \. ~$ {
  7. *    功能说明: 被SVC中断所调用的__SVC_1和__SVC_2; }; _& N7 @7 a; g( x8 {! r
  8. *    形    参: 无
    / i0 T8 k8 F0 k, B
  9. *    返 回 值: 无
    ! r# d; w# X# \+ R8 o
  10. *********************************************************************************************************- |4 v" p' I0 Z8 k" B
  11. */
    7 `6 E9 T' t. U: _3 A& P" v+ c
  12. void __SVC_1(uint8_t _arg1, uint16_t _arg2, uint32_t _arg3, uint64_t *_arg4)
    , e2 E; Q- k" P
  13. {
    ' R$ ]. s& U" E6 N4 y* ]1 t: X
  14.      /*( B; ?" q' e$ P8 J9 i" Q
  15.          1. 实际应用不要在SVC中断中调用串口打印,太影响实时性,这里仅仅是为了演示
    % L1 I7 l4 R2 Z! _+ j! p
  16.          2. 根据需要做开关中断操作。
    ) B6 _! ]7 v. @( T$ C) r/ h0 {) N/ U
  17.      */
    " F5 ?3 o% I! w  s3 v$ U) G6 \
  18.      __disable_irq();
    * a- W% c- p, F, w
  19.      printf("_arg1 = %d\r\n", _arg1);
    $ k8 S' u& L. p) K7 N+ ^; l, x
  20.      printf("_arg2 = %d\r\n", _arg2);
    2 ^2 [- ^! `8 g9 H6 I: o$ _3 Y5 d
  21.      printf("_arg3 = %d\r\n", _arg3);
      ~. x  Z7 n; I; d
  22.      printf("_arg4 = %lld\r\n", *_arg4);
    5 o1 e9 K% C$ d  B! b4 v0 s
  23.      __enable_irq();
    ; B7 J+ I' A! c
  24. }0 ~% H, q3 u: B' P2 H/ D2 ?/ |
  25.                   + [$ I+ z7 h/ e6 F. {
  26. void __SVC_2(void)
    $ i0 N( l6 {) V) s4 g
  27. {
    1 D  Q8 W/ j  B
  28.      /*- u; w! n. K8 B. r" d! }  m
  29.          1. 根据需要做开关中断操作。
    2 }# k; @5 D4 q) a: p
  30.          2. 本实验所有任务都是工作在非特权级,中断函数都是运行在特权级的,此函数是在SVC中断里面运行。/ K5 ^9 k# g/ S5 d% r
  31.             所以可以在此中断中设置NVIC分组。- l6 {6 V1 j; r! U
  32.      *// c* @7 z0 q  e) b3 \
  33.      __disable_irq();
    - c6 H; [! ?3 `0 }' j
  34.      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
    1 r1 [3 T7 z9 @/ Z# y1 H) W, R9 S
  35.      __enable_irq();% y5 K. K# D% {$ Y4 V" b% R
  36. }
复制代码
8 G6 x1 @; d# o; Z# z) P
SVC_Table.s文件中SVC中断的设置(红色字体是需要用户添加的):
  1. void __svc(1) SVC_1_FunCall(uint8_t _arg1, uint16_t _arg2, uint32_t _arg3, uint64_t *_arg4);6 A, S1 q4 f0 P$ z
  2.                 AREA    SVC_TABLE, CODE, READONLY
    ( V0 _4 t6 j7 I
  3. 3 [9 n5 q) ?6 L9 @/ `  V
  4.                 EXPORT  SVC_Count
    & D( r# u. x; ^, Y/ |

  5. 9 e6 U  i4 N: d( |! W
  6. SVC_Cnt         EQU    (SVC_End-SVC_Table)/43 g$ L7 j9 q/ d7 t/ [( m# Y
  7. SVC_Count       DCD     SVC_Cnt
    2 d: j5 |$ B- f

  8. " b: u3 h3 Q" G! ]* [! X' i; f
  9. ; Import user SVC functions here.# x( p% n( `! y/ m
  10.                 IMPORT  __SVC_1* d$ F$ `" b; `- e
  11.                 IMPORT  __SVC_2
    6 `, H  E- U1 f7 \. u2 d
  12. ( E9 L) f4 T! R" k. p- W+ c& }
  13.                 EXPORT  SVC_Table
    " N- _; p4 t9 E8 k3 s
  14. SVC_Table, W2 @* C8 [) b+ S6 z/ a+ ?
  15. ; Insert user SVC functions here. SVC 0 used by RTL Kernel.6 u) s  l( J1 M4 e. V1 r. |! W
  16.                DCD     __SVC_1                 ; user SVC function
    - @. h" ~9 C1 G% I7 m4 `! u
  17.                DCD     __SVC_2                 ; user SVC function( u$ _% L# t6 b' N( U* ~
  18. : A/ {9 o% q( M- R# E
  19. SVC_End
    5 s+ I& ~6 c  F* P: e$ Q4 G
  20. / X9 t/ g' \  ?0 o' y/ @* W; {( g
  21.                 END
复制代码
% Y& E1 Z6 j! ^* j5 U4 O
四个RTX任务的实现:
  1. /*
    " K2 u( o2 s9 o3 Y  R  h: v. B4 b
  2. *********************************************************************************************************
    . c$ F' L. @* v' R/ m# D  T
  3. *    函 数 名: AppTaskUserIF" Y6 _& ]; ?; k0 }
  4. *    功能说明: 按键消息处理     % y, j  T+ [3 T* I5 i7 Y
  5. *    形    参: 无7 g& w+ D4 N/ I$ t- \
  6. *    返 回 值: 无; ^+ ?- ?* A' Y6 Y  m
  7. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
    ) Z# y; y! I3 d, {1 {
  8. *********************************************************************************************************$ |# |0 o5 E* S# E
  9. */
    0 I5 a' i0 F0 P" j( o# K
  10. __task void AppTaskUserIF(void)
    % U, B+ `5 Q4 q
  11. {3 N9 E! [7 ]. ]/ K. a5 F
  12.      uint8_t ucMsgTra = 0;# T6 @( r: R2 \' Q! y, i" M/ h+ z  L$ u
  13.      uint8_t ucMsg = 0;
    ) O8 R! Z2 I3 }3 X! }1 V) a- L
  14.      uint16_t usMsg = 0;
    ) ?8 w3 X8 I; N: f- ?2 t8 e, l
  15.      uint32_t ulMsg = 0;
    . x* h) S# D, [8 v4 Y, G; W  E
  16.      uint64_t ullMsg = 0;7 }2 u% p& x3 Q0 N! g
  17.      uint8_t ucKeyCode;
    8 G# v" V5 v, M+ g* l
  18. 5 \- o* Z% V4 l+ H5 `  G
  19.     while(1)1 |& j  q5 f( _  y) [
  20.     {
    + F3 H' ?5 V5 E( ]
  21.          ucKeyCode = bsp_GetKey();
    / @6 k# {% i) T$ V/ R7 i
  22.         
    8 V* K, T" x  u- v1 V
  23.          if (ucKeyCode != KEY_NONE)
    4 C' H) U1 `5 x1 e2 [- Q7 C' I
  24.          {
    1 {# i5 Y- a: l# n
  25.               switch (ucKeyCode)
    4 m; F4 }; X) g, |" a
  26.               {
    ) q6 V$ F6 i' U2 S  H! W
  27.                    /* K1键按下,打印调试说明 */" ?' K2 F) r% w% \
  28.                    case KEY_DOWN_K1:
      @/ E& A5 J+ |3 |
  29.                        printf("K1键按下,使用MDK中自带的RTX调试组件,请务必使用MDK4.74版本进行调试\r\n");
    ' U! r, _: o- K/ P7 E" ~  F( ]
  30.                        break;  4 q6 y1 l$ x( t* y8 @9 F9 X
  31. 7 g! `' u' t% H6 m, R8 |
  32.                    /* K2键按下,向消息邮箱发送数据 */
    ) M. ]8 v0 k8 v. R; O# E
  33.                    case KEY_DOWN_K2:
    ( {! G1 C4 b" a8 E
  34.                        ucMsgTra++;' k6 N3 H  q) U* r# K
  35.       S+ O' O0 V8 a: P' ~
  36.                        /* 向消息邮箱发数据,如果消息邮箱满了,等待100个时钟节拍 */
    8 f2 J2 v5 J2 x: T$ H  [( ?
  37.                        if(os_mbx_send (&mailbox, &ucMsgTra, 100) != OS_R_OK)
    ) n! @2 [2 A) _8 d) I
  38.                        {- _( q* f6 q( Y9 p5 s' T  _' e3 S/ I. ^6 }
  39.                             /* 发送失败,即使等待了100个时钟节拍 */* c8 I/ ]7 Y4 q7 n2 c/ i' X2 e5 I
  40.                             printf("K2键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\r\n");
    8 Z8 b, v' }- v. o1 a7 H+ O; \
  41.                        }
    ! c* P$ X! w" M$ ?% F6 _0 ~
  42.                        else
    2 t/ \! Y4 Y8 _
  43.                        {% e" c" S' B5 p9 z% W( x1 t1 o
  44.                             /* 发送成功 */
    ( C1 l% c( N) N. d
  45.                             printf("K2键按下,向消息邮箱发送数据成功\r\n");                          7 e0 Y0 U' I1 ?  M
  46.                        }
    " H. Q9 u9 I) [6 N5 G
  47.                        break;+ B6 {7 O! k9 x. n* P
  48.                      
    6 a1 E( F3 Z9 n. H. Q
  49.                    /* K3键按下,调用SVC的1号系统服务 */3 L8 n  U0 E4 g8 A! V, V. n' W1 m( L2 R& T
  50.                    case KEY_DOWN_K3:$ s8 S6 t$ }* \! j: D
  51.                        printf(" K3键按下,调用SVC的1号系统服务\r\n");
    " b1 N6 R* C2 E
  52.                        ullMsg++;# k$ P/ n8 m8 X8 X
  53.                        SVC_1_FunCall(++ucMsg, ++usMsg, ++ulMsg, &ullMsg);
    , z( _# S' }) }" C# e" j% u+ j
  54.                        break;
    / R+ w$ B# [+ X3 p4 b* N
  55.                   + E( H+ j( ?/ C0 a/ M
  56.                    /* 摇杆OK键按下,任务运行在非特权级,调用SVC的2号系统服务,可中断中设置NVIC */& D' o; r) l5 `2 _* r
  57.                    case JOY_DOWN_OK:- }' C# }( w* K* w
  58.                        printf("摇杆OK键按下,任务运行在非特权级,调用SVC的2号系统服务,可中断中设置NVIC% {+ {$ B8 n5 e& `5 M- C- J
  59. \r\n");) E. ]9 z4 Q' C$ D8 J8 h9 V
  60.                        SVC_2_FunCall();/ H% e5 O5 f2 l
  61.                        break;+ ^3 q7 f! m1 U9 i7 Z
  62. . _5 D4 h0 F' S  T7 O
  63.                    /* 其他的键值不处理 */5 E6 T. i; F+ |4 b) w& v3 |
  64.                    default:                    
    ) A: E- E. a& _8 a
  65.                        break;
    * M# p) Z2 ~4 y0 T0 H3 Z
  66.               }
    ; E8 I$ a% n, R' e7 Z
  67.          }0 r/ C( J; `% v% a0 w
  68.         ' l8 h* R# P9 R0 P+ A8 E  x
  69.          os_dly_wait(20);
    9 {, o6 t7 s$ l2 d
  70.      }9 d: `- y" f- G
  71. }
    % `: q5 }( x! w) g8 m

  72. ' |3 H+ t0 \; ?
  73. /*
    0 u7 V6 F# w# x8 x
  74. ********************************************************************************************************** `+ t# S  F8 _* }# g5 s. A
  75. *    函 数 名: AppTaskLED
    ! j+ ~  t) B% W
  76. *    功能说明: LED闪烁。6 B- z4 o; k, Y* c0 u" S
  77. *    形    参: 无
    1 c9 Q2 q" a6 [- N+ e( Z, n
  78. *    返 回 值: 无
    % p' ^" U4 M+ |9 z8 \3 {
  79. *   优 先 级: 2 2 b3 Y$ k; X0 V7 j/ h3 {: g7 ?
  80. *********************************************************************************************************
    ; ?4 G% g6 h! k' {
  81. */
    # D; {( p7 h. t% T% ^) @$ K* M2 D/ K
  82. __task void AppTaskLED(void)
    " n( N# M) d/ x$ k, V
  83. {. x% ?9 h$ d: {6 d7 Z4 X) J6 y
  84.      const uint16_t usFrequency = 200; /* 延迟周期 */
    7 {1 o  j6 h, J" d/ P3 R
  85.     $ X6 @! |1 Z  v$ Z1 U
  86.      /* 设置延迟周期 */
    5 V& P4 ^" ]% d
  87.      os_itv_set(usFrequency);
    ( o/ |# }+ v: H
  88.    
    4 W4 w( U/ `9 s1 s7 N. E
  89.     while(1)- K" \9 A; g  ~# s6 r  b
  90.     {
    4 d8 q4 ^" Y3 }6 L! a2 u
  91.          bsp_LedToggle(2);5 J  [: h  G# h1 ]6 k5 V
  92.          bsp_LedToggle(3);
    ! p; S# b4 [$ O4 }' @+ U6 L0 [

  93. 1 L' K) C0 Q6 u$ {% N/ K) R
  94.          /* os_itv_wait是绝对延迟,os_dly_wait是相对延迟。*/
    1 G  C5 U* p( r* Z# B6 X& U
  95.          os_itv_wait();6 i& y0 U( G, w% f
  96.     }
    3 N1 y8 p  w3 f- S( k, k+ v& h
  97. }
    + H8 j, p- V$ d3 N+ T* y1 S8 {7 q

  98. / D- I- D5 K9 O3 c, g
  99. /*
    . w2 W; P" c: }( o8 n' b, x  y
  100. *********************************************************************************************************
    2 g* ^; D+ J# r- ~
  101. *    函 数 名: AppTaskMsgPro2 t. O- x& V6 U  Q1 G  d8 T/ a
  102. *    功能说明: 消息处理,等待任务AppTaskUserIF发来的消息邮箱数据% d. u6 y7 H0 I  e8 w
  103. *    形    参: 无
    8 W7 X# h  g- {" u/ U& J  q1 i4 n
  104. *    返 回 值: 无
    ) K, |0 _! p3 C9 P# V7 T. w+ d
  105. *   优 先 级: 3
    2 ^- W4 X+ K( B% V0 e
  106. *********************************************************************************************************
    9 c. P' x9 I. e/ g! O0 Z
  107. */
    9 b( t' o; R. p* {( n# F
  108. __task void AppTaskMsgPro(void)
    3 A% _2 ?' h: m9 T$ y/ U/ V
  109. {
    9 V6 V. |! j) n' m% w
  110.      uint8_t *pMsg;
    ; ~8 r% r* ]) W' e2 G! b
  111.      OS_RESULT xResult;, ~* M$ X. a: U% J5 ~+ E
  112.      const uint16_t usMaxBlockTime = 200; /* 延迟周期 */
    : l3 l7 ~% q* D* Y- N6 r& y+ w4 o
  113.     / x. x) P! L2 S0 g6 q/ p- M: @9 `
  114.     while(1)4 o! v6 g: I, T  K
  115.     {
    ; t# V0 Q' h/ b) x; c! A/ P
  116.          xResult = os_mbx_wait(&mailbox, (void *)&pMsg, usMaxBlockTime);" k+ f' A  c  t* G% c* |6 X! y
  117.         / q8 a& f- T0 Q% G, m& m
  118.          switch (xResult)) l$ H) _+ [- [/ R- l- P9 {3 m
  119.          {* s* }# w! |, y$ p) y$ G+ P
  120.               /* 无需等待接受到消息邮箱数据 */
    - B0 k5 p0 e' A$ k: }2 y( o! G
  121.               case OS_R_OK:4 x( F6 ^4 C- {1 n: @! ?. o
  122.                    printf("无需等待接受到消息邮箱数据,pMsg = %d\r\n", *pMsg);1 L, O) J8 v2 ~( ^
  123.                    break;  ) V- T# Q. g1 K- F1 V; N. P6 p

  124. / B" L$ ]4 B, ^3 R3 O
  125.               /* 消息邮箱空,usMaxBlockTime等待时间从消息邮箱内获得数据 */0 D& R% e4 M' m9 w
  126.               case OS_R_MBX:& U; `8 s& _0 X" R, _
  127.                    printf("消息邮箱空,usMaxBlockTime等待时间从消息邮箱内获得数据,pMsg = %d\r\n", *pMsg);
    6 B9 P+ V) D2 H4 x( U/ T2 ~
  128.                    break;
    ' i! C+ ^5 r' V4 w! C

  129. % \/ Y5 C0 f$ e4 P
  130.               /* 超时 */# N( ?2 l" j/ v+ Q* n4 X% l
  131.               case OS_R_TMO:5 `' p. G. _) Q3 N9 C% P
  132.                    bsp_LedToggle(1);7 g" [( S) X& T% x
  133.                    bsp_LedToggle(4);' c* \' N+ H" Y! |7 s; f
  134.                    break;  e  W7 j1 v, U
  135.             
    4 \* E, p5 H& b' |
  136.               /* 其他值不处理 */
    5 t$ H1 A: `+ N# _2 f6 p
  137.               default:                    
    5 R" ~6 y+ h  n% f& \. e. G
  138.                    break;
    + y/ X3 [" T) R
  139.          }   
    " T( `9 j8 m- d5 y( H* {5 J
  140.     }, N& D. o3 u+ \, d
  141. }
    3 q! K) D4 G+ H  l

  142. 2 W6 M$ ?* S! w2 b! |9 l* R5 \
  143. /*
    ) h8 `" d7 i3 w3 m
  144. *********************************************************************************************************" C5 h) v1 D" u4 Y0 K& ~
  145. *    函 数 名: AppTaskStart
    1 G1 e+ D! Y& G/ {4 Z+ D9 ~6 U
  146. *    功能说明: 启动任务,也就是最高优先级任务。这里实现按键扫描。! q! A) G7 F( Q
  147. *    形    参: 无
    + J0 l: D$ ~2 H2 c, G) @$ q4 E$ u0 v( k
  148. *    返 回 值: 无
    2 K3 A3 G  @5 Q) A
  149. *   优 先 级: 4
    ; }6 s# q9 E; Y
  150. *********************************************************************************************************
    / ]* M/ E1 J0 B$ V& V* s: `) D& H
  151. */% S3 o0 f! y3 L( t. _; [9 F
  152. __task void AppTaskStart(void)
    2 E6 O1 E, m/ J, x, S
  153. {8 n9 N4 b) L# I" Q3 `
  154.      /* 创建任务 */
    7 A+ U/ n5 b3 _4 A, q) n+ q
  155.      AppTaskCreate();5 G) u* G4 C5 E
  156.     0 |( V' q$ E' V1 H5 M8 S
  157.      /* 创建任务通信机制 */
    : ?& t* d; I5 ]$ c5 b8 ^
  158.      AppObjCreate();
    7 k! T5 j2 O5 I* W" O  x7 q
  159.    
    7 K/ S! @/ ]6 s# ^
  160.     while(1)7 Y: r7 F+ |+ ?$ V9 Z. o
  161.     {5 y7 [0 Q/ g4 B. c7 D
  162.          /* 按键扫描 */
    5 W5 K) Z: C" C5 I4 C
  163.          bsp_KeyScan();
    / O/ @9 |0 q  d+ c
  164.         os_dly_wait(10);  W1 r& m1 w" y' D. u
  165.     }, X  N2 \7 w8 p3 H8 m
  166. }
复制代码
( H* I4 n( J) n* H; H' C' j9 c
+ f5 E4 G/ u5 `) x7 {8 g
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. /*
    / \1 ^! ~( u( o& X2 n4 V
  2. *********************************************************************************************************  |2 p  y3 T$ v5 l6 f9 F0 T+ p6 f
  3. *    函 数 名: main3 q' c8 g8 j8 P- z. a+ y5 c. Z* [: {
  4. *    功能说明: 标准c程序入口。
    6 f! n& e  q. e
  5. *    形    参: 无
    " l# s  h" ?3 r( d8 t& P* A2 A
  6. *    返 回 值: 无6 q9 ~" ^, _+ m4 Q# i
  7. *********************************************************************************************************
    9 u  c9 ^( }4 M1 H1 z, G( j
  8. */
    $ R9 b% M" D+ w
  9. int main (void)
    4 s# [. ]/ q5 W& |( V- W- e
  10. {   
    # L- a3 q+ }. X
  11.      /* 初始化外设 */
    0 q' r$ M# \7 y7 I
  12.      bsp_Init();5 u8 Q' d; k% q2 |# J& Q* `# Q9 w8 y# L
  13.    
    + ~3 Q! E$ C: q6 N
  14.      /* 创建启动任务 */- F! T( M/ G" T
  15.      os_sys_init_user (AppTaskStart,             /* 任务函数 */! ^9 s' I! R/ ?1 C0 \/ J) k- ~
  16.                        4,                        /* 任务优先级 */
    % J4 L9 v" D: Y
  17.                        &AppTaskStartStk,         /* 任务栈 */
    ) @1 d8 i# N; P1 \+ m
  18.                        sizeof(AppTaskStartStk)); /* 任务栈大小,单位字节数 */5 R$ o9 s$ u; W% T% [- f% i; i3 n) U
  19.      while(1);
    9 S, j# l9 C& e2 j  t: t1 E; E
  20. }
复制代码
1 Y- X/ C3 N9 x3 I
RTX任务创建:
  1. /*
    & p# x- |. Z4 C0 R/ p/ O3 t
  2. *********************************************************************************************************
    $ p9 L) j' q' |3 F( @# z+ N1 ~
  3. *    函 数 名: AppTaskCreate
    3 S$ C" _8 I: \$ \
  4. *    功能说明: 创建应用任务$ B1 S% ~1 b$ |( d* p* o$ ]1 `; Z
  5. *    形    参: 无
    ) t, F1 L& l% L# R- h
  6. *    返 回 值: 无
    6 q7 Q: ]8 ]* g- {: ]
  7. *********************************************************************************************************- Z9 D! t2 Y: V
  8. */8 S6 S# a* T% y( t
  9. static void AppTaskCreate (void)
    5 r! f& S+ b# P( l/ d
  10. {
    ( P2 h5 f2 J, _7 _0 n
  11.      HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             /* 任务函数 */5 m5 Z- i4 A' i5 V' }
  12.                                            1,                         /* 任务优先级 */, t6 u7 }* {, m8 |
  13.                                            &AppTaskUserIFStk,         /* 任务栈 */2 W; @" G! Y7 y' [3 Q5 k8 {0 T- P
  14.                                            sizeof(AppTaskUserIFStk)); /* 任务栈大小,单位字节数 */) B' C/ H; ?1 ?: ~
  15.     4 Z/ X5 y, [, b( c8 M8 `3 W8 H6 ]. |
  16.      HandleTaskLED = os_tsk_create_user(AppTaskLED,              /* 任务函数 */
    8 S9 F  z* w2 D8 ?  p/ V. n/ n" c0 l! e
  17.                                         2,                       /* 任务优先级 */" q  G8 x8 f9 J  \# n( g7 R9 z
  18.                                         &AppTaskLEDStk,          /* 任务栈 */4 T% o% z! F$ J5 v/ r! Y, L
  19.                                         sizeof(AppTaskLEDStk));  /* 任务栈大小,单位字节数 */
    1 ?+ K+ U; W4 L+ a& [1 [
  20.    
    9 U0 u. x* {8 s$ p3 j! Q
  21.      HandleTaskMsgPro = os_tsk_create_user(AppTaskMsgPro,             /* 任务函数 */$ t. |( {, b4 l. ]5 |# U
  22.                                            3,                         /* 任务优先级 */9 c9 X  Y; ~- N7 {
  23.                                            &AppTaskMsgProStk,         /* 任务栈 */
    0 D; E/ T4 L5 ^) n# Z
  24.                                            sizeof(AppTaskMsgProStk)); /* 任务栈大小,单位字节数 */
    1 {) H/ B6 a# J: r5 O8 }: ]
  25. }
复制代码

4 I7 T6 l1 _/ R0 }! b9 ?
消息邮箱的创建:
  1. #define PoolBlocks           10( |2 _; F6 C7 `  l9 `
  2. #define PoolPerBlockSize     8/ ~4 {2 @% I! K9 P/ [8 J

  3. - O# ]; t5 _$ I3 B
  4. /* 声明一个支持10个消息的消息邮箱 */
    7 u# Z. t" [1 y, {. G+ r
  5. os_mbx_declare (mailbox, 10);' Z& J) ]: v8 H) u

  6. % e0 Y. b  \5 N7 J4 h5 I0 v* O
  7. /*
    # M/ o! ?7 F$ ~. c
  8. *********************************************************************************************************
    ) r! t5 A% B" O% b+ x
  9. *    函 数 名: AppObjCreate
    6 `3 s0 Y5 `  e  S
  10. *    功能说明: 创建任务通信机制
    ( u% A/ U( r* _" E; X$ ^
  11. *    形    参: 无
    ) C0 d9 ?  f7 u
  12. *    返 回 值: 无
      W' }  E! \; a9 ^: Y
  13. *********************************************************************************************************
    0 O) y7 _1 u" P( ^
  14. */
    - S8 Q4 J- h8 d) T9 l4 g2 ?* z
  15. static void AppObjCreate (void)5 }$ `" u# }0 K
  16. {% R( A3 |( J( o1 J/ w) z5 w$ R
  17.      /* 创建消息邮箱 */. Z* O6 N2 C; i: s. I0 @
  18.       os_mbx_init (&mailbox, sizeof(mailbox));
    ( |- g1 w  p7 w- w, s
  19.    
    # G+ P5 T/ Q( Z* ?. m- L. k# R! z; W+ y
  20. }
复制代码
" S/ K3 Y  _8 t! g* u8 r: ?
SVC中断函数的创建:
  1. void __svc(1) SVC_1_FunCall(uint8_t _arg1, uint16_t _arg2, uint32_t _arg3, uint64_t *_arg4);4 f: |, `9 {7 Y/ {" a/ {) z& {
  2. void __svc(2) SVC_2_FunCall(void);9 x6 E5 A. c: }- G) Z
  3. ' t) I+ r, i& N
  4. /*
    & X2 o4 B9 d/ k8 q  a3 K6 |
  5. *********************************************************************************************************
    + g2 T$ ^$ R) m( b  q' D3 T. e
  6. *    函 数 名: __SVC_1和__SVC_2系统服务号
    , A* f1 H! ?) _" ?0 v2 I6 P
  7. *    功能说明: 被SVC中断所调用的__SVC_1和__SVC_2
    7 p9 z& D& @: E+ Z
  8. *    形    参: 无7 [; ?% \# t( x  L7 x
  9. *    返 回 值: 无
    4 x! \/ \9 N$ J# z/ x4 B, ^
  10. *********************************************************************************************************' [, _, R9 _( \5 F! z4 t: t$ f
  11. */
    7 x" g% X& c! I* c% Q* @1 x/ F
  12. void __SVC_1(uint8_t _arg1, uint16_t _arg2, uint32_t _arg3, uint64_t *_arg4)
    / Z, _4 C3 ~! h9 Y
  13. {9 r$ ?8 v7 P& Q& Q" w* \
  14.      /*- Q3 [+ y. m/ x
  15.          1. 实际应用不要在SVC中断中调用串口打印,太影响实时性,这里仅仅是为了演示
    ; R+ l& c" s1 J, R% ]
  16.          2. 根据需要做开关中断操作。# f$ {' p: [" `: a4 W2 j1 m2 c
  17.      */
    % s) L- d9 C& D% C
  18.      __disable_irq();
    ) W# k9 f6 o: I7 i
  19.      printf("_arg1 = %d\r\n", _arg1);9 Z- t; i, e; U& `7 G
  20.      printf("_arg2 = %d\r\n", _arg2);* @2 `: e8 T! }! i# c/ K0 A
  21.      printf("_arg3 = %d\r\n", _arg3);1 ~1 R  @+ e3 o
  22.      printf("_arg4 = %lld\r\n", *_arg4);
    " |' q: o8 [; T$ C# R  D  ], J% D
  23.      __enable_irq();# L: L. g; ^/ M% J4 C
  24. }
    1 r/ N6 \* r0 _
  25.                   # X6 T# `# N- X# y8 x2 A
  26. void __SVC_2(void)8 _* w; w6 T1 w" H3 W8 S- A" t
  27. {
    * [' j- Q  I9 n
  28.      /*
    + A1 O. D$ E  G! Z5 I1 f
  29.          1. 根据需要做开关中断操作。
    % P% g3 H9 I! Q
  30.          2. 本实验所有任务都是工作在非特权级,中断函数都是运行在特权级的,此函数是在SVC中断里面运行。
    : j1 l/ p& S  m% `( I
  31.             所以可以在此中断中设置NVIC分组。% V; P  N8 c- D
  32.      */) f4 T  f5 }; }( j, l
  33.      __disable_irq();; R3 r$ Z2 d1 z# e) N
  34.      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
    ! j6 J  g4 v( i/ R* s0 W
  35.      __enable_irq();& ]! i  Z& ?) s5 j, j2 g( y$ b
  36. }
复制代码

6 \  Y" ~. r) g0 s5 a% G
SVC_Table.s文件中SVC中断的设置(红色字体是需要用户添加的):
  1. void __svc(1) SVC_1_FunCall(uint8_t _arg1, uint16_t _arg2, uint32_t _arg3, uint64_t *_arg4);. r) L) C/ f; _5 L' q0 R
  2.                 AREA    SVC_TABLE, CODE, READONLY- k5 Q6 v5 t, G; n3 [3 p

  3. ' N- U% U2 |0 g, b3 }9 O) ^
  4.                 EXPORT  SVC_Count' x6 w# y' H& N: [

  5. ' J. T) Z. D  L% z0 @9 I
  6. SVC_Cnt         EQU    (SVC_End-SVC_Table)/4* k& d5 ~' b8 |$ w+ M: I, n
  7. SVC_Count       DCD     SVC_Cnt* O  C" f7 y9 R, _# j
  8. 9 V* ?( `# [) k1 c) p$ s
  9. ; Import user SVC functions here.
    7 u. r9 n0 p$ t3 N; e5 k" E1 R
  10.                 IMPORT  __SVC_1
    ; z1 n' a4 v/ o7 H- W/ r8 }
  11.                 IMPORT  __SVC_2
    1 @- O. V. F' P+ @& t6 Z

  12. ; H% B, a2 |8 W  G2 d
  13.                 EXPORT  SVC_Table) u1 z. U, y/ ~
  14. SVC_Table# ^+ Z% ~2 R% f. X7 G
  15. ; Insert user SVC functions here. SVC 0 used by RTL Kernel.
    4 ^2 e1 {' W& T$ d! j4 F. C
  16.                DCD     __SVC_1                 ; user SVC function: `* }, h4 V5 }. d' M
  17.                DCD     __SVC_2                 ; user SVC function; m2 l- `. q; M6 c

  18. 0 q1 _( ~: `6 D/ m4 A
  19. SVC_End
    . s  }, c, K$ s9 J/ }; D

  20. # K. _/ Y2 s# X& _; t% }7 m
  21.                 END
复制代码
+ d# X2 ~# l- S6 G' o1 M4 A2 I
四个RTX任务的实现:
  1. /*
    " r3 o& s- r3 B! Q5 s8 Y
  2. *********************************************************************************************************
    , z; D. I. F- P( Y
  3. *    函 数 名: AppTaskUserIF3 E3 V5 P! E2 {+ G1 |5 F: q& m
  4. *    功能说明: 按键消息处理     
      N1 X8 m" G5 h& F/ |6 Y6 Q0 M
  5. *    形    参: 无# {! u! p& V, a& ]+ M, S
  6. *    返 回 值: 无. o' @3 Z8 s& s0 |2 q3 {
  7. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
    ! z- V* }* l# P: p+ n" ?
  8. *********************************************************************************************************
    4 j' J6 J. o7 t( V
  9. */
    3 w! \5 m5 S0 x8 E: M
  10. __task void AppTaskUserIF(void)
    , \$ s* P$ w* j$ m) |8 x. d
  11. {$ G7 a# c. k5 Q2 T. E, E. M! y
  12.      uint8_t ucMsgTra = 0;( T, v8 i7 c5 b% E
  13.      uint8_t ucMsg = 0;' @* Y! E0 V% y* I
  14.      uint16_t usMsg = 0;
    # Z* `5 s6 i- D: ?
  15.      uint32_t ulMsg = 0;
      k$ T: {8 j* Z
  16.      uint64_t ullMsg = 0;. H( N% \" ?; q* l# ?, ^6 |& A5 ]# G
  17.      uint8_t ucKeyCode;" {, B' A1 p7 c1 k4 _

  18. 4 K! \$ a  y& p7 M/ v8 m
  19.     while(1); l8 R  X4 w) E/ J7 u* Q& K
  20.     {1 d* Y! Z# D# A
  21.          ucKeyCode = bsp_GetKey();
    ) T1 R3 A/ f* |
  22.         
      c( j$ _5 w0 @% ]! f0 f7 F
  23.          if (ucKeyCode != KEY_NONE)1 V1 ^6 D& l3 G" K% D. {
  24.          {! o* V: b+ p9 `3 j# a, U, Z* A
  25.               switch (ucKeyCode)  W' B& ~; u$ L- e4 o  @+ C4 B- s
  26.               {
    ' j2 O& R" b) I& |
  27.                    /* K1键按下,打印调试说明 */% M1 \; \, ]. G: R
  28.                    case KEY_DOWN_K1:
    ( c7 K/ z& |; J) l% a( ^
  29.                        printf("K1键按下,使用MDK中自带的RTX调试组件,请务必使用MDK4.74版本进行调试\r\n");! s3 ]' u3 f8 R, I, y" `0 [# @3 Z" c
  30.                        break;  . @8 L/ y7 c( `+ B5 T

  31. 8 b7 s  T$ y  J
  32.                    /* K2键按下,向消息邮箱发送数据 */% v1 ?5 D  `$ X* [. R7 W
  33.                    case KEY_DOWN_K2:
    4 t0 d! @# L' S( w" Y7 i
  34.                        ucMsgTra++;
    1 [+ T, V, b7 a7 J" \4 ~: X+ C
  35.    
    7 Z6 D2 f  A% Y; D* }8 }
  36.                        /* 向消息邮箱发数据,如果消息邮箱满了,等待100个时钟节拍 */
    # D5 V, T' d. O: v& d1 S
  37.                        if(os_mbx_send (&mailbox, &ucMsgTra, 100) != OS_R_OK)( P3 m0 Y) H' B. i/ M
  38.                        {- B9 w- v3 }2 D6 f& }
  39.                             /* 发送失败,即使等待了100个时钟节拍 */; x0 |) a0 F$ j" p
  40.                             printf("K2键按下,向消息邮箱发送数据失败,即使等待了100个时钟节拍\r\n");
    ) C0 x/ D1 P: T7 v( y5 [6 M
  41.                        }- ]4 n9 s& h0 J/ \- {4 W8 T
  42.                        else
    6 v& s( Z. t6 `5 A- q3 B( M
  43.                        {
    3 W0 H6 R' ^3 S1 P- [  y
  44.                             /* 发送成功 */4 q2 V4 ?6 d& h) e2 a" A5 m( M
  45.                             printf("K2键按下,向消息邮箱发送数据成功\r\n");                          
    * S: y  m! U) ]7 o
  46.                        }6 ]' }' P: v# o: u" ^
  47.                        break;& N! \, L1 h8 o: G! d
  48.                      
    7 K8 f: A' R, c. M2 k5 E3 F
  49.                    /* K3键按下,调用SVC的1号系统服务 */
    - C) D6 i" {' n$ z
  50.                    case KEY_DOWN_K3:
    / ]/ j  p+ Q+ d: ]
  51.                        printf(" K3键按下,调用SVC的1号系统服务\r\n");
    9 k7 l! [; i, g7 l# W
  52.                        ullMsg++;. O* ]: {6 {  K4 o
  53.                        SVC_1_FunCall(++ucMsg, ++usMsg, ++ulMsg, &ullMsg);
    5 X; ]3 D2 V: ]5 T8 d
  54.                        break;: Q6 H9 z# S$ ]6 \
  55.                   - b' b( D( H0 i+ m) F8 O/ ~' a1 y
  56.                    /* 摇杆OK键按下,任务运行在非特权级,调用SVC的2号系统服务,可中断中设置NVIC */: k: t4 Y, R2 l' z1 i. T+ |' v
  57.                    case JOY_DOWN_OK:+ K3 {4 A- ~4 w6 h& T/ L
  58.                        printf("摇杆OK键按下,任务运行在非特权级,调用SVC的2号系统服务,可中断中设置NVIC
    / D# ^) T2 @) I1 o! e; v& D
  59. \r\n");4 V1 M6 }8 W* Z
  60.                         SVC_2_FunCall();
    % w" ^! U; S  l
  61.                        break;
    5 a" m" A- \& A. p# E* `
  62. ) `% P3 s& p9 j4 D4 B
  63.                    /* 其他的键值不处理 */9 R3 M$ s7 z, q. }0 C& ^2 z
  64.                    default:                    
    8 b+ @2 K1 l+ @  \
  65.                        break;1 h5 y9 g& o. _
  66.               }
    - Z8 b" X! p4 h" J/ r- m
  67.          }
    2 c$ B. G$ y* M, s' q+ n# P
  68.         
    " G3 s! @3 C' {- m2 Y1 X
  69.          os_dly_wait(20);, Q% |- z( ^. L, F
  70.      }
    ! v. O/ W, S) i1 J. m. m, b
  71. }
    9 Q: K7 g. a' N  V
  72. ! q9 F0 K3 @' l
  73. /*
    ; A& y& G$ l* n& l/ }; f! w) L: d
  74. *********************************************************************************************************
    / W( g! S$ @. C7 s! i
  75. *    函 数 名: AppTaskLED
    ) H2 b8 s5 g. B& H' r) g
  76. *    功能说明: LED闪烁。
    $ \( @" \) M) |" S" ]" o; w
  77. *    形    参: 无
    ; E3 p/ S* H% V" d! ^' E2 s
  78. *    返 回 值: 无% B3 }( w6 o, N1 \  ?6 ]! T: U' V
  79. *   优 先 级: 2
    $ a6 [+ r) P  X
  80. *********************************************************************************************************7 ?- O0 w" _4 {1 o9 h1 V
  81. */
    + I/ b9 I* [# F0 H2 m0 j! S
  82. __task void AppTaskLED(void)
    6 Y8 J' I7 {) b5 d6 Z
  83. {9 }, r, k: M* J0 w; }% _8 W5 {/ J
  84.      const uint16_t usFrequency = 200; /* 延迟周期 */
    " k; B9 y. k2 K& R) x4 i
  85.     + v- j4 c: d4 s
  86.      /* 设置延迟周期 */
    6 W/ x! u$ Q4 t$ i6 a; U
  87.      os_itv_set(usFrequency);8 \, _- c8 F; }
  88.     $ c9 G# t1 A9 P  E
  89.     while(1)
    % C' Z0 c9 k& O4 ~% y+ x# J) ^
  90.     {6 L- ^. d8 @$ n+ d, h' m
  91.          bsp_LedToggle(2);
    2 c* i3 [- I4 w1 Y5 U. z
  92.          bsp_LedToggle(3);
    * \' \1 ~, n; B" x3 W9 d

  93. " w) x$ b4 k2 V) [( x$ r
  94.          /* os_itv_wait是绝对延迟,os_dly_wait是相对延迟。*/
    4 A# `! z+ Q% T* I
  95.          os_itv_wait();
    8 V  B3 }% g0 M8 D/ y3 ^
  96.     }! S" P0 `# S$ [
  97. }
    1 K% Z) w) A. [7 M& L4 M3 q9 d

  98. 8 \: N7 T' J& _! ]9 |
  99. /*
    9 i0 u6 ?8 I- P+ J* }! n5 Z) l
  100. *********************************************************************************************************
    4 f5 c7 y8 }' H) s( ~  f  B) D
  101. *    函 数 名: AppTaskMsgPro! b- U& |* l: Q% S% b; z# H9 v
  102. *    功能说明: 消息处理,等待任务AppTaskUserIF发来的消息邮箱数据
    & q: m! s4 ^8 K& ^
  103. *    形    参: 无
    $ \3 S- O8 B7 Z7 N& U% c' G
  104. *    返 回 值: 无0 _8 I6 F, \% E
  105. *   优 先 级: 3
    . k! U  s+ E3 `2 @2 }8 C9 y; V
  106. *********************************************************************************************************9 O; c0 J/ t- ?. O. v: Y" C
  107. */
    8 m( l% H* |8 e1 Y
  108. __task void AppTaskMsgPro(void)% d4 @2 n) z! Q6 p
  109. {2 C. P! O# V* E' T- D8 s
  110.      uint8_t *pMsg;+ e. T& D+ q8 @4 ]/ P
  111.      OS_RESULT xResult;
    1 {% v, X9 ^" d! N8 K# U
  112.      const uint16_t usMaxBlockTime = 200; /* 延迟周期 */7 k7 c; W8 H. x( K  L0 X8 t
  113.     ; `8 ?" ^2 I9 U% K& A! A& U
  114.     while(1)
    ! L5 O5 K( T4 r$ P! @/ N: U
  115.     {1 e8 j3 A! S8 I3 o, M8 ?3 {) l
  116.          xResult = os_mbx_wait(&mailbox, (void *)&pMsg, usMaxBlockTime);
    ! ]$ F3 f# e: m. V# n8 U' v
  117.         
    + K' k/ _, [1 c+ l$ ^1 h8 Z, Y) M
  118.          switch (xResult)
    ' m) n) ~2 z' [3 m) U4 n
  119.          {# K! p# x9 E' ^2 T( E+ ~0 D
  120.               /* 无需等待接受到消息邮箱数据 */( M  Y5 w" F4 _
  121.               case OS_R_OK:( j/ R" b) I- M: c# m% J" l
  122.                    printf("无需等待接受到消息邮箱数据,pMsg = %d\r\n", *pMsg);: J: {7 j+ s9 v  Y" N: @$ M
  123.                    break;  
    0 G' r- r5 i. \3 _% u
  124. 5 n9 O8 p; d/ Q* K8 |' Q- N
  125.               /* 消息邮箱空,usMaxBlockTime等待时间从消息邮箱内获得数据 */
    & Z( @: i% ^) z/ i/ P  S
  126.               case OS_R_MBX:
    $ u" i" w) E! Y8 h
  127.                    printf("消息邮箱空,usMaxBlockTime等待时间从消息邮箱内获得数据,pMsg = %d\r\n", *pMsg);
    * t( R- h: W$ E1 N" V+ j3 Q5 X, [; `
  128.                    break;
    & U3 o: N: f3 e9 O4 e% l9 e
  129. 2 Z0 ]; p6 ~) P( |, \3 X; ]# H
  130.               /* 超时 *// j1 S2 b3 e8 k
  131.               case OS_R_TMO:
      a; P1 {6 G. V0 X  A9 T
  132.                    bsp_LedToggle(1);% C3 j+ v. o/ z: U9 g
  133.                    bsp_LedToggle(4);
    ) g4 A; q  ]& t, o+ u
  134.                    break;8 o, L( f3 }2 w. v: l/ O* B- ?$ B
  135.             
    # H0 ]2 o; C/ m2 Z  ]# {3 ~: E
  136.               /* 其他值不处理 */' d  p! _* L7 @; s
  137.               default:                    1 |; o  g/ T3 v0 m9 q
  138.                    break;
      W, ]0 \2 x8 g
  139.          }   
    : K1 j2 b( P) o" I
  140.     }
      d# Y$ S* C( K( J, I
  141. }$ v* g3 {9 B+ h0 w3 n

  142. % a6 n9 I& U2 ]. a# H* e' Z$ g
  143. /*
    # m. V. ]7 P* `& o. q4 n' X
  144. *********************************************************************************************************1 p( P3 H  w3 j/ p' e
  145. *    函 数 名: AppTaskStart( g8 i- F* ~/ S
  146. *    功能说明: 启动任务,也就是最高优先级任务。这里实现按键扫描。
    1 c- Q9 x  }- l: x- J/ u
  147. *    形    参: 无+ G9 d3 M6 J, z; p
  148. *    返 回 值: 无
    9 j/ X$ }% B( h' ]2 f3 F+ W$ [0 ^
  149. *   优 先 级: 4
    ' w  Q2 B8 A3 f2 `7 {. j; r3 j
  150. *********************************************************************************************************2 e5 F" ~1 A( M1 A4 J
  151. */1 w, F/ Q# s. ?' A! v! u& @! P- o
  152. __task void AppTaskStart(void)! K8 E- ^- A) G2 B( ~% k
  153. {/ E+ C: w6 J0 E' R: T3 D( @# i
  154.      /* 创建任务 */
    0 x: T; z: K0 ?7 y8 e; V
  155.      AppTaskCreate();
    ( @$ B7 a3 L3 `+ k
  156.    
    . M+ z/ k$ b3 R0 z7 @. i
  157.      /* 创建任务通信机制 */+ z# a4 y; A. W
  158.      AppObjCreate();! Q" V* y, S& o9 l1 _
  159.    
    $ ^; l0 \# ~7 ]9 O
  160.     while(1)
    # P0 T9 F& r! I9 Q
  161.     {) b( F2 k. T. g) G( a6 w, R
  162.          /* 按键扫描 */; e; n* U$ N$ N$ y# I
  163.          bsp_KeyScan();3 @6 W5 z& H- Y
  164.         os_dly_wait(10);
    : \8 c  t5 U) X2 D' ]" \
  165.     }+ g) B3 O0 _' J( C" j
  166. }
复制代码
5 O1 d, Q& l5 n/ h4 u6 M

1 a" R4 k1 T1 N' n# u/ W$ R
baiyongbin2009 回答时间:2016-2-3 17:44:39
19.4 总结
    本章节主要大家讲解了如何采用SVC中断方式调用用户函数,更多SVC中断方面的知识可以看Cortex-M3或者M4权威指南。
; D: t2 G# P9 [
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管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版