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

【经验分享】STM32FreeRTOS二值信号量的基本介绍和操作

[复制链接]
STMCU小助手 发布时间:2022-5-20 18:57
前言
7 I6 {5 [% f' V) w2 Y8 b本文主要介绍什么是二值信号量和二值信号量的基本操作。
& r6 E' X% g+ o+ \5 J! B5 W' n" e1 G2 U  U8 c$ b
一、什么是二值信号量8 Y  I1 C$ b" X% |
信号量名副其实就是一个信号可以进行任务之前信息的交互,二值信号量通常用于互斥访问或同步。二值信号量就是一个只能保存一个数据的队列,这个队列要么是空要么是有他就只有两种状态。
, b+ I/ {- Y9 s% k+ Z) L8 K5 \1 Y
! `* G1 j: e+ }0 b二、cubeMX配置
6 L! l! J# {6 W$ |3 v1.选择添加一个二值信号量
& b. X/ ]5 ?3 J& B& ^+ D CQ(67IOWE9146%C~)Z2Q$YF.png
. e4 i4 @8 q9 ~/ n; L/ J" c9 l, c+ y0 l9 s
2.设置二值信号量
& J0 ?- K' B3 r5 W这里比较简单我们只需要设置一下二值信号量的名字即可。
' g& m: C7 A8 x2 ]4 K: E- M2 j+ S% u9 |3 Y, F
SWRDE$R(7UKEESIG4O15})1.png 8 e( W( E# Q, p  O# t9 q0 G

7 p; d6 z: o% g: D0 \三、代码编写+ \; r9 y0 a$ [8 ?2 ]
1.创建二值信号量
1 L! k& f1 U3 E; S9 g; G这部分代码cubeMX会帮我们书写好
/ P) a, [5 L$ [  V/ m1 }9 L3 D: I" a: P- m2 X8 ^" I! q. I# j
  1. /* definition and creation of myBinarySem01 */3 \+ K5 l1 O1 N, z
  2.   osSemaphoreDef(myBinarySem01);
    , C* a) z1 e( C; R+ }1 e+ ~
  3.   myBinarySem01Handle = osSemaphoreCreate(osSemaphore(myBinarySem01), 1);
    ' l9 a* D- m9 Z9 V& m0 m

  4. 2 ]- d& Z) h& a* \: y; D- g
  5.   /* USER CODE BEGIN RTOS_SEMAPHORES */
复制代码
8 S( l: p( H+ N/ H7 g4 b$ w. ^+ P
2.产生二值信号量函数
  k6 d3 o- R: F$ h本函数cubeMX对其进行了封装,其本质还是调用了xSemaphoreGiveFromISR和xSemaphoreGive两个函数。( {) q1 P/ I* H( h# J6 h! v: a

: ^, f3 Y% W/ t/ K
  1. /**
    % f2 A) v: T4 |1 g
  2. * @brief Release a Semaphore token
    * D1 j8 ?9 u6 z" Q; z# V( U
  3. * @param  semaphore_id  semaphore object referenced with \ref osSemaphore.
    & b, R( @8 Y1 t% R1 {' Q
  4. * @retval  status code that indicates the execution status of the function.
    & E8 @) i3 R5 s, Q4 t- E9 b
  5. * @note   MUST REMAIN UNCHANGED: \b osSemaphoreRelease shall be consistent in every CMSIS-RTOS./ g" L% Y) X8 q5 R, |, ~
  6. */
    + q$ p! i1 Y, ?
  7. osStatus osSemaphoreRelease (osSemaphoreId semaphore_id)
    , D! Z( P' }% H& D; _" \9 v
  8. {# b/ N( k9 j2 }  d3 B6 U
  9.   osStatus result = osOK;
    ) V7 z4 V. t% e1 E! e0 H
  10.   portBASE_TYPE taskWoken = pdFALSE;2 Z: y1 G$ @) \0 V% K
  11. . [* n2 Y( D/ b) B

  12. / D1 Z: F1 c9 \
  13.   if (inHandlerMode()) {( x& i9 h3 |5 J4 @
  14.     if (xSemaphoreGiveFromISR(semaphore_id, &taskWoken) != pdTRUE) {6 W9 k9 }* V/ e& x! k
  15.       return osErrorOS;1 M8 m& b9 S/ u9 \- I% e+ I
  16.     }) q2 ~  `3 L3 S; Y4 d
  17.     portEND_SWITCHING_ISR(taskWoken);
    2 M. `$ y( Y" y
  18.   }1 g7 Z9 {* u* Q! m6 R! k! @
  19.   else {
    & B9 ~& [3 u6 d- \# D. n
  20.     if (xSemaphoreGive(semaphore_id) != pdTRUE) {
    . K+ T% y9 i8 P5 T$ D- ?
  21.       result = osErrorOS;
    4 |$ h1 x. C0 k( x
  22.     }
    ' p7 i) T5 k* s0 ]* a; H9 o" [
  23.   }
    % x* F4 S% d' H: F0 X' d

  24. ) o3 T, J0 j+ C, r
  25.   return result;- g+ }" v, o, k# x" \/ @
  26. }3 z$ u- b  ~6 t
复制代码

9 r" W" x2 _7 T, w+ l: L! E3 z3.接收二值信号量函数  ~) @$ r+ A2 ~
本函数cubeMX也对其进行了封装,其本质还是调用了xSemaphoreTakeFromISR和xSemaphoreTake两个函数。5 o6 n, p" Q( [: Q( ?* ?$ I

' r' `  ^) ~9 w# k( i- S, V* E7 K当二值信号量接收成功的时候会返回osOK。7 o: K. ^9 S2 b4 `- |

2 x+ L+ h+ M$ d. r$ |4 O
  1. /**
    ) v% N: C$ N$ g; ]0 x
  2. * @brief Wait until a Semaphore token becomes available% v, i; X% W( m9 |* |
  3. * @param  semaphore_id  semaphore object referenced with \ref osSemaphore.
    / y9 w# \1 Q! h7 V! R
  4. * @param  millisec      timeout value or 0 in case of no time-out.. B6 V1 m2 L. ^0 g
  5. * @retval  number of available tokens, or -1 in case of incorrect parameters.
    # E2 k7 w% |! \# j0 s( \
  6. * @note   MUST REMAIN UNCHANGED: \b osSemaphoreWait shall be consistent in every CMSIS-RTOS.
    6 X3 y. ]- n1 {" o! G$ }8 R" k
  7. */- z& a8 w; A4 f7 o$ G0 E
  8. int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec)* B" p  _4 j/ Z7 ~4 b6 D( I3 Y
  9. {! W( |4 d9 ]+ @
  10.   TickType_t ticks;6 q; o. g) `5 t' [5 p
  11.   portBASE_TYPE taskWoken = pdFALSE;  
    $ ~0 C+ E, k$ G

  12. ) Y0 c% R; j% R4 d) \, J2 G' e
  13. 3 I& i  t6 K0 S+ W" H/ ]
  14.   if (semaphore_id == NULL) {+ L1 Y2 y$ E7 S) C( A: o- j
  15.     return osErrorParameter;
    " C$ \" I7 J$ y7 o" o
  16.   }
    5 ?0 S3 ^/ e7 ^

  17. ' E: p: M; _6 v/ L
  18.   ticks = 0;
    2 \2 l8 j! F. t( _- ?9 Z3 i
  19.   if (millisec == osWaitForever) {
    * S/ l+ Y* S. G! P/ m3 |" S4 b; t
  20.     ticks = portMAX_DELAY;
    / u- K4 `1 c+ M; ?
  21.   }, P2 V" S6 O$ F; M
  22.   else if (millisec != 0) {
    0 e: o$ L9 _7 N: Q, ?
  23.     ticks = millisec / portTICK_PERIOD_MS;
    - i& P; L7 |& x' c3 i1 R
  24.     if (ticks == 0) {6 [# u# E4 d; L3 V) s
  25.       ticks = 1;- P3 J# G) r& A  ]; S, u1 i( z- b0 k2 F
  26.     }
    # ]$ Y' k& |# ?; D+ N
  27.   }3 N9 A) m4 r7 J! j% m# Z6 ~/ U
  28. 6 W' B4 `6 c' F, g4 F1 ~
  29.   if (inHandlerMode()) {, ~, [: ~: u; |) S0 S7 x
  30.     if (xSemaphoreTakeFromISR(semaphore_id, &taskWoken) != pdTRUE) {
    ! w: ]' F0 J0 K/ _
  31.       return osErrorOS;: X6 y: B1 k1 d& ~
  32.     }/ p" t1 e3 y! d2 j! y
  33.         portEND_SWITCHING_ISR(taskWoken);
    ) I3 @; F0 V# B$ m, }
  34.   }  
    : [, V; G  o/ _. T  [, @
  35.   else if (xSemaphoreTake(semaphore_id, ticks) != pdTRUE) {
    % ^, B. N/ P; r% m7 F
  36.     return osErrorOS;
    7 b. V. `! L$ g: {1 L3 ?8 M$ _
  37.   }, c& F) r* ~) n

  38. % `. o. g8 e; b2 D7 R
  39.   return osOK;' D  A' X3 \6 x9 |( X# h
  40. }
复制代码
9 T% [8 h. z! U7 |+ v
四、二值信号量具体操作
$ |+ @' H# z! Y% ~3 G& c; T- F
  1. osThreadId Task1TaskHandle;
    & ]* e, k: P/ t) r+ L" m5 h
  2. osThreadId Task2TaskHandle;
    ' M- g& V! t$ D4 b  w
  3. & [; L- m, |. m4 g, r0 m0 J, l/ k$ w
  4. void Task1Task(void const * argument);9 \/ v8 c  V2 G( K! j" O3 Z7 Z
  5. void Task2Task(void const * argument);- x* i) l- `& H. F$ k+ u; I% E
  6. 4 z. P2 T) {! B
  7. osThreadDef(Task1TaskName, Task1Task, osPriorityNormal, 0, 128);" V. o# t$ K! d
  8. Task1TaskHandle = osThreadCreate(osThread(Task1TaskName), NULL);
    4 s; t. r3 q8 F

  9. 5 t- y3 v% d" O7 j, F
  10. osThreadDef(Task2TaskName, Task2Task, osPriorityNormal, 0, 128);
    2 {  e. ]$ F0 v6 W# _4 U7 Q
  11. Task2TaskHandle = osThreadCreate(osThread(Task2TaskName), NULL);, s; Y% `3 H, Q5 G' M
  12. 4 d- d! k" E# U5 H7 x
  13. //产生二值信号量任务
    - t  s  |, |* @7 H9 e
  14. void Task1Task(void const * argument)9 G. T) @# D* v
  15. {
    ' ~. c' J! b5 X3 t  J* V
  16.         static u8 i=0;3 I& s1 K$ F# e
  17.         for(;;)
    ' n& H  B' K: f# R$ ?/ ]
  18.         {/ j1 K- j; t, N+ X4 m/ O: Q
  19.                 //调用10次再产生二值信号量
    $ U3 B& F; m5 O. n
  20.                 if(++i==10)/ o. R; d5 K) J  Z$ D
  21.                 {
    " J& d0 J7 I) b4 }: `1 X
  22.                         osSemaphoreRelease(myBinarySem01Handle);//产生二值信号量                0 D4 M* L' M  E2 m
  23.                 }
    % c# \: Y! @7 a$ o, |: h
  24.                 osDelay(5);//调用延时才会释放资源
    " Y; v8 Q% s6 M4 ~# o
  25.         }: L* N7 Y0 Q4 r' _4 ]. t2 S" r
  26. }
    3 L9 u2 y+ d2 K' ~+ B6 E
  27. 2 c7 i# x# e+ Z% p9 }1 H: P
  28. ( b- J& a% n0 I( S% y
  29. //接收二值信号量任务% V2 j/ i" v* ]. V6 o2 |
  30. void Task2Task(void const * argument)
    1 y6 ?) ^  d& n: H! _: ^
  31. {
      W; h, f5 c5 |$ }0 j: \8 K
  32.         for(;;)
    2 Y, j# l2 l" e
  33.         {
    $ c( |. P* a8 W, j
  34.                 if(osOK==osSemaphoreWait(myBinarySem01Handle,portMAX_DELAY))//等待二值信号量采用死等的方式% `  p7 J: n5 H4 k! t7 |! o+ X; H
  35.             {- q. e# l7 R0 C$ \: H6 ^7 {
  36.                       //等待二值信号量成功5 V& P: p/ y+ g
  37.                    }4 s; s# Y5 G, q' g
  38.                 osDelay(5);//调用延时才会释放资源
    ! E0 N5 i) x8 s- _( Q4 Q
  39.         }" V2 S- G- U7 y1 [6 b* G# T' E! h
  40. }
    9 H. B. _5 l$ n- e/ @3 z% Y
复制代码
总结! v/ H0 Y: C/ }3 ], u- N
二值信号量的大致操作和介绍就是这样了。1 @7 C* P5 s- L/ W; i

: K/ x4 m7 e1 o; M/ R/ X& \# j) Y4 k: k; P% C+ L. p" i, _) }- q
! t3 @5 T0 x  b# g2 R8 u
收藏 评论0 发布时间:2022-5-20 18:57

举报

0个回答

所属标签

相似分享

官网相关资源

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