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

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

[复制链接]
STMCU小助手 发布时间:2022-5-20 18:57
前言4 }0 [& z/ W3 c7 X6 m2 n  A3 v
本文主要介绍什么是二值信号量和二值信号量的基本操作。
+ J6 I: O+ z/ h1 k/ F1 p
7 f7 K; y  h0 n" g% {( }' z" `一、什么是二值信号量3 x6 S  m, Q; [' t9 v
信号量名副其实就是一个信号可以进行任务之前信息的交互,二值信号量通常用于互斥访问或同步。二值信号量就是一个只能保存一个数据的队列,这个队列要么是空要么是有他就只有两种状态。
9 R5 {4 E5 }9 ?" n9 H" c* t- t3 @# m' H, g+ E
二、cubeMX配置2 Y' P: {$ E& _4 }6 v& n: q- _# \
1.选择添加一个二值信号量" ]% y2 ?' a! s; S% T2 t# F7 m
CQ(67IOWE9146%C~)Z2Q$YF.png " t1 k) p2 X3 ]0 f* Z* N
# Y  h- l* w( }( D
2.设置二值信号量$ D/ h6 D7 e1 B7 F
这里比较简单我们只需要设置一下二值信号量的名字即可。; z7 V) S  Z2 p: j9 b* r

5 M! Q2 L. j, e9 O SWRDE$R(7UKEESIG4O15})1.png
* s4 I- ^! v# f& i8 R
0 j3 o' C6 r" T( d三、代码编写
( N& u9 p  X8 _. n4 V) J" M1.创建二值信号量
4 X1 }& t! F7 V; @- J3 Y1 L这部分代码cubeMX会帮我们书写好
. H/ l: I0 r& d
5 I' e3 N- G, q5 f& U* d0 O7 G8 A8 o
  1. /* definition and creation of myBinarySem01 */
    3 S9 l2 ~! ^! D; i
  2.   osSemaphoreDef(myBinarySem01);
    9 W9 Q6 D1 D! w5 U4 I9 ?$ }% G
  3.   myBinarySem01Handle = osSemaphoreCreate(osSemaphore(myBinarySem01), 1);: W, [, ?4 X9 P' i# \
  4. # S5 }# w0 N/ f; |
  5.   /* USER CODE BEGIN RTOS_SEMAPHORES */
复制代码
, Y2 N& p) \8 W( x, K$ ~1 _
2.产生二值信号量函数+ ]0 Q7 Q; [( Q1 Z$ Z! B6 \9 f
本函数cubeMX对其进行了封装,其本质还是调用了xSemaphoreGiveFromISR和xSemaphoreGive两个函数。
6 k1 J4 [+ _/ E3 W  b" w% h0 p% B% N/ K* |
  1. /**( z' I$ G- k) M* b: W/ X/ [$ ^
  2. * @brief Release a Semaphore token
    ; R- q8 N! s" j& G0 A& g
  3. * @param  semaphore_id  semaphore object referenced with \ref osSemaphore.- s8 i4 @2 y. f* `) e
  4. * @retval  status code that indicates the execution status of the function.
    3 Y: A: t0 H; \) f
  5. * @note   MUST REMAIN UNCHANGED: \b osSemaphoreRelease shall be consistent in every CMSIS-RTOS.0 Z, x% _8 X+ F8 h  {' b
  6. */
    + `( Z1 ~0 `$ w0 E: g% \% ?: F
  7. osStatus osSemaphoreRelease (osSemaphoreId semaphore_id)
    + C" e  S2 W, x6 O
  8. {  {5 u& Q* ^# a/ N5 Y" N7 p+ I
  9.   osStatus result = osOK;
    9 b4 [# g& ~; i- q! }0 m" q  @
  10.   portBASE_TYPE taskWoken = pdFALSE;/ M* u; t) f0 U& L
  11. $ f( g% S& [) k2 U% Z1 h0 q. Y

  12. ; g) X  I+ p) [$ s- S& R* B
  13.   if (inHandlerMode()) {
    8 D2 [7 C$ Q6 M- ^/ P
  14.     if (xSemaphoreGiveFromISR(semaphore_id, &taskWoken) != pdTRUE) {. V' g1 l+ a8 _& f& P& J
  15.       return osErrorOS;
    % J+ M/ H% a8 I
  16.     }
    / C7 b; X. r, I4 h
  17.     portEND_SWITCHING_ISR(taskWoken);1 `6 ~  E, s; P' ~; K3 r/ k
  18.   }
    ( t/ {2 }$ @- V5 p/ x( V- u! [* {3 ]
  19.   else {; d" ]$ t( T3 _3 R$ [4 |. D
  20.     if (xSemaphoreGive(semaphore_id) != pdTRUE) {
      @7 L7 R; s) \* @
  21.       result = osErrorOS;
    5 X; O- ^/ n* U1 P
  22.     }) |% w3 k  u5 u
  23.   }/ X# m3 f  I8 W
  24. ( y* T" Y' `" @& q% o( d1 G$ ]
  25.   return result;
    # A: e( ?# m: N3 G" P( Y; O
  26. }. [' e3 {" d# p) i7 g
复制代码
' R; U; K- t9 U& X
3.接收二值信号量函数: V2 f" W7 u0 U' C
本函数cubeMX也对其进行了封装,其本质还是调用了xSemaphoreTakeFromISR和xSemaphoreTake两个函数。
) y9 u( h  ?5 [) c& ]$ w/ v. X4 x7 f+ r% R
当二值信号量接收成功的时候会返回osOK。
9 l# [4 Z! F# @8 Q
. U4 L/ b/ i6 `! ^
  1. /**
    + O& R. ], E+ A) i0 i+ w
  2. * @brief Wait until a Semaphore token becomes available
    , Z6 s7 Q0 i- s
  3. * @param  semaphore_id  semaphore object referenced with \ref osSemaphore.
    ( R/ b5 M) |) }+ d
  4. * @param  millisec      timeout value or 0 in case of no time-out.- K- ?- H- c# E$ y/ L! U
  5. * @retval  number of available tokens, or -1 in case of incorrect parameters.
    ( G$ \  o8 V. s' X9 |7 t
  6. * @note   MUST REMAIN UNCHANGED: \b osSemaphoreWait shall be consistent in every CMSIS-RTOS.* M% z! `6 M/ L$ T( a- D+ G
  7. */( `# m( s! z7 q+ ]- \! `
  8. int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec)
    ( U/ f  H, D0 [  K5 X
  9. {
    ; D. h' x$ l/ G3 v
  10.   TickType_t ticks;
    0 ]% ]+ C) L8 j, w! x
  11.   portBASE_TYPE taskWoken = pdFALSE;  
    : {; K+ E, Z; X  b
  12. ! b  _9 \5 n# p; ^+ M% y

  13. 7 p9 Y) m* M! E
  14.   if (semaphore_id == NULL) {
    1 w, z3 ]4 \6 {& ]( p1 p
  15.     return osErrorParameter;
    : B! N# ?& _, Z9 |
  16.   }2 Z! k2 s6 s0 y0 k7 V5 j1 A8 w

  17. 8 [+ ^# p# i4 }  Q+ @, n
  18.   ticks = 0;1 U8 L# q, ~! z# d6 h
  19.   if (millisec == osWaitForever) {
    % v; ]$ t4 |( \" P3 H
  20.     ticks = portMAX_DELAY;
    . ^6 ~) T) x2 q$ u) `
  21.   }
    5 `! q  Z( P, [6 X: T
  22.   else if (millisec != 0) {9 y8 w9 z* a6 d" D) q
  23.     ticks = millisec / portTICK_PERIOD_MS;9 W: b7 @6 p4 Y, G$ z- p
  24.     if (ticks == 0) {7 Z0 I) A& k0 m& \5 q2 K- L
  25.       ticks = 1;9 \2 t9 E) q& ]5 l. B
  26.     }: N# L4 Y7 D& b/ n2 Q/ M) |
  27.   }8 i+ l$ N; y% |0 Y

  28. * N% [9 ?7 J0 v) J" S
  29.   if (inHandlerMode()) {
    : {. _7 l: u4 u. z. S
  30.     if (xSemaphoreTakeFromISR(semaphore_id, &taskWoken) != pdTRUE) {
    6 B0 t( Z# p: }
  31.       return osErrorOS;
    ( Z5 `$ l( X5 M* \5 x) H4 _+ @
  32.     }
    " }7 ^7 X& `: R! ]1 h7 T
  33.         portEND_SWITCHING_ISR(taskWoken);
    . X7 c1 v7 M- m9 ~9 N
  34.   }  
    ! t5 r9 k8 ?' H1 W* ?
  35.   else if (xSemaphoreTake(semaphore_id, ticks) != pdTRUE) {
      I- t: V5 F1 B( y+ s
  36.     return osErrorOS;! Z( @4 W6 ?; F0 ]# b
  37.   }1 ?! V9 D+ S8 x$ o2 i; F1 Z
  38. 1 B% t/ J$ `! ?2 {& K
  39.   return osOK;* Q2 f1 c4 h: W2 ?0 g
  40. }
复制代码

) G/ }3 G. F# e2 X& _9 o1 M# C四、二值信号量具体操作2 O6 Z) {2 }$ F" ^7 y) O2 l
  1. osThreadId Task1TaskHandle;
    . Y+ p! W$ b3 q
  2. osThreadId Task2TaskHandle;" `/ Z3 Y3 ]: n( j1 V- u( R

  3. ' z9 k6 l  S/ s/ v: h* z
  4. void Task1Task(void const * argument);7 ~6 z: A; h) r" q
  5. void Task2Task(void const * argument);6 [& w$ I( R/ ~! t' [
  6. 5 c$ p* N* H! f
  7. osThreadDef(Task1TaskName, Task1Task, osPriorityNormal, 0, 128);
    0 z) V: ~& H2 A% {7 L
  8. Task1TaskHandle = osThreadCreate(osThread(Task1TaskName), NULL);; ^' w  m% h( Z* p3 ^. J9 m
  9. " l! r3 Z) h% ^- K/ K: Z
  10. osThreadDef(Task2TaskName, Task2Task, osPriorityNormal, 0, 128);* D9 M( @& W4 Z9 Y# Y
  11. Task2TaskHandle = osThreadCreate(osThread(Task2TaskName), NULL);  |' b# c4 |2 i9 k9 h
  12. ) [- U$ E) V& I6 K: j
  13. //产生二值信号量任务5 O. R5 p# B5 s. u1 f3 k6 a/ b5 W
  14. void Task1Task(void const * argument)
    * [5 B  X& G% s# M
  15. {; T6 b; s- v% |5 h5 r- l
  16.         static u8 i=0;3 D( }" v2 h/ T$ P
  17.         for(;;)
    : ?( E. t1 S3 L$ ?
  18.         {
    6 B" Y& D. y2 }
  19.                 //调用10次再产生二值信号量
    " I; e$ h* n9 w( K% f$ O7 z6 H
  20.                 if(++i==10)
    ( W+ I- B6 j- U" N. T# _1 s6 v8 E
  21.                 {4 g1 d  C2 q4 Z
  22.                         osSemaphoreRelease(myBinarySem01Handle);//产生二值信号量                - M: Q# D% {7 f; y" M- C
  23.                 }# @% Q) U& Y* X& E# `  ?% ?
  24.                 osDelay(5);//调用延时才会释放资源# B4 R& X# d  k( U' G( ]  z
  25.         }9 c6 R5 X, w2 S# r- ^' i
  26. }1 w, L; L2 Q# C& F: V5 Y8 N. d) w; _

  27. 5 Z2 k/ K: V/ V3 F! U* T

  28.   u, j" S4 j, T
  29. //接收二值信号量任务- h  ?! ?( [) v
  30. void Task2Task(void const * argument): h7 ?) ~* Z- U2 S' S' ]' [( E
  31. {* Y4 b: g9 G* R3 S
  32.         for(;;)
    ; K& N2 {/ l* Q, m3 Q6 H2 o
  33.         {& D+ G  l2 |: x! }7 l
  34.                 if(osOK==osSemaphoreWait(myBinarySem01Handle,portMAX_DELAY))//等待二值信号量采用死等的方式
    + ~2 q  }' \% D- s) P; Q
  35.             {
    8 y1 A/ i! ?6 k
  36.                       //等待二值信号量成功7 n8 _- X4 n9 O
  37.                    }" y( t) {: {  Q7 |6 ?: Q
  38.                 osDelay(5);//调用延时才会释放资源
    & @$ N: i3 w! v+ i+ U$ G
  39.         }6 r, B$ a$ Y" f  U* {  f; a
  40. }5 o) V7 S# d3 V2 O! V* K7 p
复制代码
总结
6 C5 ]3 `2 f  c+ q: m二值信号量的大致操作和介绍就是这样了。; W; s- U0 n, g3 t: X) r. y
4 }( ~: d: J* e6 S
7 S- J4 u+ H) ]! f$ z: g1 k: v

7 }) {) A: D1 _  Q$ H* ^* Q9 `
赞 收藏 评论0 发布时间:2022-5-20 18:57

举报

0个回答

所属标签

相似技术帖

官网相关资源

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