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

【经验分享】STM32 FreeRTOS临界区

[复制链接]
STMCU小助手 发布时间:2022-6-17 14:44
01. 概述
; P8 b# N1 ]3 s3 X# J) ~1 z临界段代码也叫做临界区,是指那些必须完整运行,不能被打断的代码段,比如有的外设的初始化需要严格的时序,初始化过程中不能被打断。FreeRTOS在进入临界端代码的时候需要关闭中断,当处理完临界段代码以后再打开中断。FreeRTOS系统本身就有很多的临界段代码。这些代码都加了临界段代码保护,我们在写自己的用户程序的时候有些地方也需要添加临界段代码保护。1 q4 H7 g- g1 W6 J# g( G

: b$ V8 Q0 }' l0 B( u& }FreeRTOS与临界段代码保护有关的函数有4个:
% D( M. M5 P7 N6 E
6 X# r' H0 c9 `% H# R( v* c# D
  1. /**( ?$ _9 t  e8 w, N% }% l) I+ c2 z, P. J
  2. * task. h& T+ [5 C" L/ J9 ?2 j5 @
  3. *
    , H% O& T- r9 ^# K
  4. * Macro to mark the start of a critical code region.  Preemptive context
    7 W* \& b. A) z, L. F
  5. * switches cannot occur when in a critical region.: G" J8 K9 p7 T- W
  6. */ x  I- d) o; `) O! {" P& |
  7. * NOTE: This may alter the stack (depending on the portable implementation)0 d- T6 d9 y( `) D  ?! F
  8. * so must be used with care!
    ! K7 V' h" c$ e* {3 N* r7 N5 k/ R
  9. *  m- d* G$ b' q5 ?
  10. * \defgroup taskENTER_CRITICAL taskENTER_CRITICAL
    8 k' G5 N# e$ _
  11. * \ingroup SchedulerControl
    ! `/ J! E( z6 }6 y: h3 Y' y
  12. */
    # U2 S/ T9 u6 L$ g) @
  13. #define taskENTER_CRITICAL()               portENTER_CRITICAL() //任务级
    8 t( _7 S4 P3 [4 x- X& c9 V! F" Z
  14. #define taskENTER_CRITICAL_FROM_ISR()      portSET_INTERRUPT_MASK_FROM_ISR() //中断级
    . Z2 U# w1 a$ A0 P/ ~4 m8 j
  15. $ m4 P$ N! h& ]$ j; r9 `
  16. /**" V+ [# K$ \% F- _9 S, m6 Z
  17. * task. h
    & T7 V& f, p' \" P5 v0 }$ c
  18. *' w0 ^% O, C- ^7 v6 ?: f* t
  19. * Macro to mark the end of a critical code region.  Preemptive context
    2 o0 x( C7 b; R. B5 {
  20. * switches cannot occur when in a critical region.. `) [1 N4 Z2 t# r) F6 E
  21. *
    1 Q2 w" z' Z0 s4 o  h' F; J
  22. * NOTE: This may alter the stack (depending on the portable implementation)  ]1 x2 x/ P3 u8 L
  23. * so must be used with care!
    3 K7 X, d1 d; Y6 M3 f; }
  24. *
    0 q7 Y1 T/ U* s
  25. * \defgroup taskEXIT_CRITICAL taskEXIT_CRITICAL
    8 z6 _5 o  J7 u, }
  26. * \ingroup SchedulerControl
    7 k. k4 t& j( Y( M: L5 I! S: _
  27. */
      m' z1 I8 Y) B  M9 ^" F  G* b0 K
  28. #define taskEXIT_CRITICAL()                portEXIT_CRITICAL() //任务级
    $ n' a  J; M! [: O; N
  29. #define taskEXIT_CRITICAL_FROM_ISR( x )    portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) //中断级
复制代码

( c- _& k9 z1 R4 x9 v02. 任务级临界区代码保护# r) v  o, c/ ~" a2 k0 Q
taskENTER_CRITICAL()和taskEXIT_CRITICAL()是任务级的临界区代码保护,一个是进入临界区,一个是退出临界区,这两个函数一定要成对的使用。
9 Q8 n- f* d2 }4 D& A- D6 G6 ]8 k0 O- I" u! x7 u5 O
  1. /**0 l* _- P% F8 C$ H! `, @
  2. * task. h0 x' N4 ~: V& i" P9 |0 Z( c
  3. *
    4 l: B& y# b: ?7 s, p
  4. * Macro to mark the start of a critical code region.  Preemptive context/ L! T. w. }/ I4 z+ O( R
  5. * switches cannot occur when in a critical region.# U0 y# r0 g' X% e: _4 m7 I6 I9 L
  6. *
    . j& W4 p7 g  w! T8 V' g+ ?$ T
  7. * NOTE: This may alter the stack (depending on the portable implementation)
    ! S; B9 p# L% o- W& c" p( D
  8. * so must be used with care!6 x( M- T$ x" o2 x  j* a/ A
  9. *) T0 j1 q2 ]' {4 ~1 h
  10. * \defgroup taskENTER_CRITICAL taskENTER_CRITICAL
    ' N; ]; N9 i& X7 A
  11. * \ingroup SchedulerControl% ~' i* }+ B1 N' M2 `
  12. */
    " v2 Y* `7 e3 B1 _* [/ A
  13. #define taskENTER_CRITICAL()               portENTER_CRITICAL() //任务级( A( G  R6 I8 X% q. [) v; ^; n+ ^2 _

  14. / n; i9 i2 e+ Z; c2 a! X$ q
  15. 3 k- n/ G. w  Z: o4 b1 B  c( I
  16. /**# T  v6 t/ ~. v4 @1 N) D1 j& i
  17. * task. h
    . X: t! T; I: K1 u" W
  18. *
    % l$ u. X( K) p; D* a: Q
  19. * Macro to mark the end of a critical code region.  Preemptive context0 ~2 g$ u$ d+ H
  20. * switches cannot occur when in a critical region.) Y, O- `" W. C, x3 r" r
  21. *
    % W' b; W* }" g1 g! f6 c4 A/ Y9 O& j
  22. * NOTE: This may alter the stack (depending on the portable implementation)
    ( e# N) g9 X# d2 i
  23. * so must be used with care!
    4 n: y9 ?6 p  P
  24. ** @: i$ W. q# P* p+ E7 P* X
  25. * \defgroup taskEXIT_CRITICAL taskEXIT_CRITICAL5 s, g! l. m+ T, T: ]
  26. * \ingroup SchedulerControl9 j+ B) ]: `( D' v
  27. */& V0 ]& H$ ^! I! H' [3 l
  28. #define taskEXIT_CRITICAL()                portEXIT_CRITICAL() //任务级
复制代码
7 a6 d& [  x! G( s! I' T1 C. D# p
portENTER_CRITICAL()和portEXIT_CRITICAL()也是宏定义,在portmacro.h中有定义。
  1.     #define portENTER_CRITICAL()                      vPortEnterCritical()
    % G9 J* X/ b- A, H2 r' M
  2.     #define portEXIT_CRITICAL()                       vPortExitCritical()
复制代码
* v7 e+ N. m2 p( e4 m$ U. c
vPortEnterCritical()和vPortExitCritical()函数实现如下:: z) I( ?* Z  b7 Z# k

# W5 J9 J( g! f( s
  1. void vPortEnterCritical( void )5 C! \( X5 f4 V4 I
  2. {
    8 E) _, o) y( e4 P- ^
  3.     portDISABLE_INTERRUPTS();
    # t) [0 D: r; z
  4.     uxCriticalNesting++;
    4 C5 z1 X8 z# `8 y, x

  5. * [# I: F* p! j% c$ y- n
  6.     /* This is not the interrupt safe version of the enter critical function so
    9 Z4 e/ d5 D( s% Q
  7.      * assert() if it is being called from an interrupt context.  Only API
    ) r+ y: |4 T2 _5 j
  8.      * functions that end in "FromISR" can be used in an interrupt.  Only assert if
    # X& m# r% e$ f* U, l8 Y* M
  9.      * the critical nesting count is 1 to protect against recursive calls if the
    ) M& J! ]- I6 u
  10.      * assert function also uses a critical section. */
    3 @8 _( C! d2 s9 t. g6 r& w, a
  11.     if( uxCriticalNesting == 1 )
    6 }- F$ N5 F3 V! x% M9 I: V/ l+ s' M5 V
  12.     {2 K; a( `- i9 W) m2 H' w. N6 Q
  13.         configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );: f. @; J( w2 _
  14.     }  \+ D" h2 Y' T- e2 {/ U' D
  15. }
    0 H% K) f* `$ z0 ~1 J6 w4 D

  16. " n7 C. e% t' s: A0 y/ ~! ]8 v# B
  17. void vPortExitCritical( void ): `6 T5 q) Z% Q# @, J+ T$ E
  18. {
    / }& Z; L" K, B* t- q
  19.     configASSERT( uxCriticalNesting );% z/ x) y; n3 I
  20.     uxCriticalNesting--;
    : ~. P8 W, ]8 Q5 I7 f+ p( d

  21. * S# ~" q4 x; c8 ]; S" M$ A# X
  22.     if( uxCriticalNesting == 0 )
    & {( w( l( A" ?7 a3 Q( n5 H) B
  23.     {
    9 H. B. R$ D: [' R- H5 m
  24.         portENABLE_INTERRUPTS();
    * l/ _  A5 [* F1 q5 ]7 r, B" h
  25.     }9 R6 Z8 G8 C5 k, c
  26. }
复制代码
) g4 z$ k* a3 W8 N% E' p  A  Y
03.中断级临界区代码保护$ O# h2 j& @- ^5 G
taskENTER_CRITICAL_FROM_ISR()和taskEXIT_CRITICAL_FROM_ISR()是中断级别临界区代码保护,是用在中断服务程序中的,而且这个中断的优先级一定要低于预先设置的值。! Y% h; A0 U+ X1 S

' z" r% m! o# V6 S5 n! b: e( I( C
  1. /**" C) X3 B+ R- P! h# K2 [
  2. * task. h0 K; p% P) B5 V
  3. *
    , `9 J- H; t' @
  4. * Macro to mark the start of a critical code region.  Preemptive context8 q# B' z. t$ t/ F6 |
  5. * switches cannot occur when in a critical region.4 H8 _+ x/ A! r3 U& q* T
  6. *
    % C5 F* ~* Q/ U; p4 f6 ~# F
  7. * NOTE: This may alter the stack (depending on the portable implementation)
    , h& C' ~+ A) T0 X% j
  8. * so must be used with care!
    " v4 o( o2 v! X3 Z. \5 _" [( R- @% I
  9. *! ^  L7 b5 S+ @
  10. * \defgroup taskENTER_CRITICAL taskENTER_CRITICAL
    + \% j( i. `2 w3 n/ c3 z& }5 z
  11. * \ingroup SchedulerControl9 S- J  w  \+ ]2 c: f) m; v* y# e
  12. */. k: Q- p- R$ B- J4 i' y
  13. #define taskENTER_CRITICAL_FROM_ISR()      portSET_INTERRUPT_MASK_FROM_ISR() //中断级
    5 `3 D1 f5 [4 U1 i: W; N0 A$ `
  14. 2 O* I" v7 ]! C2 o
  15. /**: J. o' E* ^, ^
  16. * task. h. p! H# p5 T3 u$ `; j9 S
  17. *' t# c. R6 b+ \5 G+ I
  18. * Macro to mark the end of a critical code region.  Preemptive context
    8 N8 Z1 K+ K6 q7 s0 g
  19. * switches cannot occur when in a critical region.* C2 J2 Z7 u3 r4 Z9 \  F
  20. *, v5 p& p- K1 F7 b
  21. * NOTE: This may alter the stack (depending on the portable implementation). u0 x. Z1 P2 e  L! x2 A
  22. * so must be used with care!! z: m) B/ Q4 U+ X5 K, k! ]) a6 f% k( i5 U
  23. *
    # I0 {2 c% U( I+ ~7 i
  24. * \defgroup taskEXIT_CRITICAL taskEXIT_CRITICAL7 ?( t. w; |1 O: E" N9 M. n
  25. * \ingroup SchedulerControl0 i" S6 s/ T5 i  L6 T7 O( s
  26. */3 ]3 }8 S: ~3 t5 ~
  27. #define taskEXIT_CRITICAL_FROM_ISR( x )    portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) //中断级
复制代码
9 O9 B) z, h  t+ _6 h
在portmacro.h文件中有如下定义:
9 M: m7 W5 }9 L0 J# ^
- j) L4 I/ V$ u  B' v' W
  1.     #define portSET_INTERRUPT_MASK_FROM_ISR()         ulPortRaiseBASEPRI()
    $ ~( J' m1 V# B( C! U0 N' n
  2.     #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x )    vPortSetBASEPRI( x )
复制代码
( M) l% `8 U" ^" y! I
ulPortRaiseBASEPRI()和vPortSetBASEPRI()相关实现8 P$ ^% Y: x2 P8 Q9 ]

4 z. P) L# L0 ]7 N+ e+ a
  1.     static portFORCE_INLINE void vPortSetBASEPRI( uint32_t ulBASEPRI )8 \# r3 P: |5 S$ A* y
  2.     {% a2 r8 y! H" `0 o4 W
  3.         __asm
    % v. p# f  F& D" O( q! B
  4.         {) `4 D5 x* r2 t$ K  n3 @# E0 f
  5.             /* Barrier instructions are not used as this function is only used to- {$ g: s/ f  d8 J
  6.              * lower the BASEPRI value. */
    + D/ I$ S" T5 ^: {/ s, G
  7. /* *INDENT-OFF* */6 z4 Y1 _7 B# Z8 H1 J- f0 G1 b( q1 V
  8.         msr basepri, ulBASEPRI$ U- B+ X% T- d, S- @% ~" d
  9. /* *INDENT-ON* */
    . N9 J2 J, J9 H6 A6 w
  10.         }+ \3 M) i3 F" ~' v, {
  11.     }
      B, v8 X0 R$ @6 f0 V
  12. 5 |; u" d/ z  i& i! O
  13.     static portFORCE_INLINE uint32_t ulPortRaiseBASEPRI( void )
    ! x2 g- j! C2 t1 w
  14.     {
    : x1 Z+ a" m) v6 m9 X$ k
  15.         uint32_t ulReturn, ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;+ R+ b8 ^$ ?5 W- V: w! R# g
  16. 8 q" w# R1 S3 ]$ b) U1 q
  17.         __asm
    $ ~! Y" k" D: w& D* S: G" L
  18.         {7 j' F( f4 g  T' [" e6 r3 F
  19.             /* Set BASEPRI to the max syscall priority to effect a critical2 ?" G: w  p# s/ J
  20.              * section. */# X" j; g( l. W. I; v7 J3 x
  21. /* *INDENT-OFF* */
    ( B3 t- s6 t5 c" E5 b8 s
  22.             mrs ulReturn, basepri* g$ q) w9 \. \7 i6 r" A6 j
  23.             msr basepri, ulNewBASEPRI+ |( r4 e, K: G# [! c; l, u, d
  24.             dsb
    & ~( k1 k; N  G* I
  25.             isb
    2 v5 e8 s. O0 l* _' a' L- [) ?
  26. /* *INDENT-ON* */
    $ c, P3 {) ?% {8 a* J- v
  27.         }
    * f+ r# o& q4 a+ c9 u
  28. 7 f$ x. S* n* g  F& ^7 U8 s
  29.         return ulReturn;
      |* q: z2 ]1 g7 J
  30.     }
复制代码

( Q; P  X) Q1 r) }! T中断级临界区代码应用示例
: ~1 z5 z+ o# O% m3 Z* t9 M
6 E7 O/ X8 j& L/ d VZH7[`C$VHWTLU)0[DF5F{N.png + M/ K+ a- x4 v( @* r( D2 g
3 f3 E6 |; x1 p/ K+ t
赞 收藏 评论0 发布时间:2022-6-17 14:44

举报

0个回答

所属标签

相似技术帖

官网相关资源

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