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

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

[复制链接]
STMCU小助手 发布时间:2022-5-20 18:57
前言
" E* k2 B9 J! s0 W# Y本文主要介绍什么是二值信号量和二值信号量的基本操作。. i( L* A8 M' p7 F8 Q
  K# [& g/ c* `5 k* z. f, g. {/ G
一、什么是二值信号量! i: K1 G6 h4 ~; d
信号量名副其实就是一个信号可以进行任务之前信息的交互,二值信号量通常用于互斥访问或同步。二值信号量就是一个只能保存一个数据的队列,这个队列要么是空要么是有他就只有两种状态。
8 p4 h  |0 {, }$ Q
8 s$ S3 R0 u7 L8 X, P% P  r: N+ A二、cubeMX配置4 s  g, w5 Y+ ?- }3 g
1.选择添加一个二值信号量& O% \( z( l# g  j" i0 j
CQ(67IOWE9146%C~)Z2Q$YF.png 0 y+ j' J1 t. E1 M

% `, {# ^' W) q7 Q1 g. F2.设置二值信号量% |; W* ~3 f- q8 M1 \6 B* ~8 t
这里比较简单我们只需要设置一下二值信号量的名字即可。6 Z) p0 K" V' O" q" ?: Y( @

/ ]- B+ a7 x( J% n7 N) D SWRDE$R(7UKEESIG4O15})1.png ' \1 I( }0 _; z
8 s3 C4 f( m% }. j8 ~! `' I
三、代码编写
8 _- v9 z1 ]3 l4 Y8 f' f7 A3 W& o1.创建二值信号量
8 L+ T, k8 r4 C$ E这部分代码cubeMX会帮我们书写好: Z! w* V% F, J  E
& v0 I/ I5 V7 o+ D0 o$ ]3 J% X
  1. /* definition and creation of myBinarySem01 */0 i' |3 G+ z& d) n0 M# o5 e
  2.   osSemaphoreDef(myBinarySem01);0 {4 b2 I7 `/ P
  3.   myBinarySem01Handle = osSemaphoreCreate(osSemaphore(myBinarySem01), 1);
    4 W0 g) ^5 ]3 A0 H) c/ F
  4. / v7 I/ v, b% \: F8 g
  5.   /* USER CODE BEGIN RTOS_SEMAPHORES */
复制代码

! @4 A" g: n7 l9 Q2.产生二值信号量函数# H2 ?- I& H7 c% L, K+ W
本函数cubeMX对其进行了封装,其本质还是调用了xSemaphoreGiveFromISR和xSemaphoreGive两个函数。
) V7 i8 d" v1 P
: |# P/ w# a* p- n
  1. /**
    % E" r5 E% z, Z' S5 y5 {' t
  2. * @brief Release a Semaphore token. N' r. a+ [3 [2 o: @
  3. * @param  semaphore_id  semaphore object referenced with \ref osSemaphore.; h/ r- u& I2 o) V
  4. * @retval  status code that indicates the execution status of the function./ b* k, [3 U% I. ?8 ?, F6 c/ ?
  5. * @note   MUST REMAIN UNCHANGED: \b osSemaphoreRelease shall be consistent in every CMSIS-RTOS.
    ) ^2 u$ C( ^/ A, E8 q+ T
  6. */
    / Q1 r8 ]4 ^' y! j0 q3 G, `9 v
  7. osStatus osSemaphoreRelease (osSemaphoreId semaphore_id)6 Y' a/ \4 \9 l3 _& a8 n" u/ e, t
  8. {2 D% M0 u$ v2 H1 a6 t
  9.   osStatus result = osOK;5 N1 q2 [1 [1 @
  10.   portBASE_TYPE taskWoken = pdFALSE;) {9 L! B8 A& v( s; M  i

  11. ' Z) U4 U# M# d

  12. " W4 S. T: r7 }$ L6 d% E6 Y
  13.   if (inHandlerMode()) {" r/ Q+ `* ~2 \4 h- A3 J0 l. V! f
  14.     if (xSemaphoreGiveFromISR(semaphore_id, &taskWoken) != pdTRUE) {6 d9 _; y$ @% ^5 R$ j
  15.       return osErrorOS;
    3 Y2 D% b- L# B* m' m8 C+ ]9 T) {" e
  16.     }( c, q/ T) [& z/ r
  17.     portEND_SWITCHING_ISR(taskWoken);
    / y% ]/ f0 _; }  P" E9 J
  18.   }" F: C+ o& |) I" ~( A
  19.   else {
    3 a0 }: r1 l. S/ m
  20.     if (xSemaphoreGive(semaphore_id) != pdTRUE) {8 i& r  l+ b2 U0 R7 f& J" E
  21.       result = osErrorOS;
    9 j' P4 a* q( G' h: Y  ]( J
  22.     }( D! Z, |7 y: b" g- M; p7 P
  23.   }' K% X7 b$ `+ f3 v8 t
  24. 3 Z& [( A- e$ N
  25.   return result;
    . d+ f# F9 u) d/ V# F  d- ~1 ^( I
  26. }
    / }! ^1 J. `  a0 \
复制代码
! n  O* }- n* \" r9 O1 H5 B
3.接收二值信号量函数  z5 B) I# b; Z* n0 n1 D9 }( W
本函数cubeMX也对其进行了封装,其本质还是调用了xSemaphoreTakeFromISR和xSemaphoreTake两个函数。7 t+ A# d  z* V( ]1 t

( ?& f/ o0 W$ ]/ [6 q6 u( I% i当二值信号量接收成功的时候会返回osOK。$ L& l% t2 h4 e* {+ C8 e

  v' _% N* g+ Z: @  b# w. B" v
  1. /**6 C: N  ?7 ?( i! m$ w+ Z' P
  2. * @brief Wait until a Semaphore token becomes available
      D7 ?9 d" U, i" L
  3. * @param  semaphore_id  semaphore object referenced with \ref osSemaphore.
    ' o6 s0 w4 b  K% V$ M5 p' b
  4. * @param  millisec      timeout value or 0 in case of no time-out., L8 K: N  g5 A
  5. * @retval  number of available tokens, or -1 in case of incorrect parameters.
    : [; S- z( @8 i  I; r) Z* ?
  6. * @note   MUST REMAIN UNCHANGED: \b osSemaphoreWait shall be consistent in every CMSIS-RTOS.
    $ |8 H4 t  X9 r7 b
  7. */
    $ P+ n. {/ n( s
  8. int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec)% B9 }9 o0 ~8 ^
  9. {' J4 H+ j1 `& l* A7 P
  10.   TickType_t ticks;4 J$ I% d* z/ L" Q/ [, s: N
  11.   portBASE_TYPE taskWoken = pdFALSE;  
    8 {! `1 |8 H) g; J; v* p) D; s7 I: T( K
  12. ( ~4 t" j$ y! ~5 g; }

  13. . }# @6 d+ W0 U( F' C# S# j5 I
  14.   if (semaphore_id == NULL) {' i( y8 @* U+ |5 }, K- N/ }
  15.     return osErrorParameter;* l, b( ?/ M' }6 ^; |
  16.   }$ h7 E2 P$ w/ K2 z' P0 I

  17. ) p- Z9 b1 w$ T3 X* v/ a
  18.   ticks = 0;# w& O+ c: g+ R  ~7 E! \: ?, x" O
  19.   if (millisec == osWaitForever) {+ j/ w# U" _( m' h( K; R/ q6 \
  20.     ticks = portMAX_DELAY;6 [) x# v" H6 b/ h; p) z
  21.   }
    " ~% m0 z2 o  L+ O! |* D
  22.   else if (millisec != 0) {# D2 q" A7 e. n! r$ S
  23.     ticks = millisec / portTICK_PERIOD_MS;  W; Q( P/ M) I  O
  24.     if (ticks == 0) {
    0 F! y0 R$ n, t  X+ R9 n; n. D
  25.       ticks = 1;
    ( D; q' P. P6 M8 h
  26.     }/ R/ z6 _1 V$ M7 Q
  27.   }
    0 i3 i. H9 h- {/ h' d9 |. c  ~

  28. ! @0 e1 Y% m( b; d
  29.   if (inHandlerMode()) {7 t4 Y7 r" Q& ~4 G
  30.     if (xSemaphoreTakeFromISR(semaphore_id, &taskWoken) != pdTRUE) {) [6 a$ M& P" h* M) G% u- I. r
  31.       return osErrorOS;
    8 h; g0 O" {4 [7 a: E: Q. B
  32.     }! {4 L8 X7 Z: b
  33.         portEND_SWITCHING_ISR(taskWoken);
    & N5 X, r: `5 [5 N" J) C
  34.   }  % E- i  H* \& ^6 H0 C+ G
  35.   else if (xSemaphoreTake(semaphore_id, ticks) != pdTRUE) {6 f5 r, U$ R7 _+ u
  36.     return osErrorOS;6 z" V& H& R; k4 U/ ~4 M
  37.   }/ S' ?$ H7 u9 T. a
  38. 5 k# t; f# ?" B& T6 Y
  39.   return osOK;9 E, R# J$ V4 j% `% {* n' P
  40. }
复制代码
- j$ V& H! a) D% {- v4 s
四、二值信号量具体操作2 ?, @& y) n) ~
  1. osThreadId Task1TaskHandle;% @' A+ A. _/ z9 z3 z
  2. osThreadId Task2TaskHandle;
    + F; V: z1 \" j% S, U& x5 P

  3. 6 u4 |  ~" w( \8 B' L
  4. void Task1Task(void const * argument);
    1 s2 J% M, T, H  D
  5. void Task2Task(void const * argument);
    . f. z% W1 F/ B9 `# ?1 ?  l
  6. : ]2 r  Y3 F$ d2 t/ _" u9 W
  7. osThreadDef(Task1TaskName, Task1Task, osPriorityNormal, 0, 128);
    8 q* S9 u/ H: d4 c+ y7 I# ]
  8. Task1TaskHandle = osThreadCreate(osThread(Task1TaskName), NULL);
    2 g, u/ ~3 |- q( a2 e9 {
  9. 6 m5 j( j+ v4 I/ a1 F
  10. osThreadDef(Task2TaskName, Task2Task, osPriorityNormal, 0, 128);! I- p8 v' Q' w  j
  11. Task2TaskHandle = osThreadCreate(osThread(Task2TaskName), NULL);" d* w% C& A, \' X
  12. $ b3 O- K+ V2 t- D
  13. //产生二值信号量任务
    ' a' E5 i) S: {9 Z% X: @; T
  14. void Task1Task(void const * argument)" G# s' l$ w1 v0 }- y1 w
  15. {
    9 `. E' t, a" y8 }6 [5 n
  16.         static u8 i=0;
    8 [' x, i' O2 F- n7 M+ }9 I  o
  17.         for(;;)) _4 ]% w4 q$ L4 z5 w6 V: X% Y+ f: b
  18.         {
    " N0 L( \3 z# _( s/ x
  19.                 //调用10次再产生二值信号量6 W, I9 Z+ N6 P8 @7 c  P
  20.                 if(++i==10)
    % L9 s  `  o: ?6 ]
  21.                 {
    $ w) K; Q2 Z4 M- W4 |
  22.                         osSemaphoreRelease(myBinarySem01Handle);//产生二值信号量               
    7 @# M, b' r8 e
  23.                 }
    . H7 F1 W4 _! I# f& V
  24.                 osDelay(5);//调用延时才会释放资源2 }5 D$ @4 J8 p. R( K* n; f
  25.         }7 o! b0 X- R1 Y( H) S5 M
  26. }
    ( h( P/ n% {' _* t% F

  27. * C( i2 j* ^4 L4 f7 M% C
  28. % s$ O# J: M# O4 d# ~
  29. //接收二值信号量任务
    0 R' f) H5 [" f5 p7 L
  30. void Task2Task(void const * argument)6 f9 J1 A) x- _& ^4 @* `
  31. {
    1 V8 d+ g6 i7 c; B* a5 n- @5 y
  32.         for(;;)* B; P* }- s! d+ O, F% @/ e! l
  33.         {, v5 _7 h& @" U" q' c5 a" _
  34.                 if(osOK==osSemaphoreWait(myBinarySem01Handle,portMAX_DELAY))//等待二值信号量采用死等的方式
    1 m) [! ^7 Z9 ^+ \+ m* O# }& o! c
  35.             {
    , Y  _6 n$ T1 f. L# Y
  36.                       //等待二值信号量成功
    ( Z5 N8 H  R, a; @. }& Z: [6 O! M; q
  37.                    }1 ^2 K% J) \1 m4 p
  38.                 osDelay(5);//调用延时才会释放资源7 b0 Y% y; i, m/ z4 d0 Z
  39.         }2 \+ q) j9 E- P: O% V- X
  40. }
    & i2 }6 J6 f* r0 j0 x0 U& u9 a/ _
复制代码
总结- I) E' V) R4 E/ d9 J  A- N
二值信号量的大致操作和介绍就是这样了。: R0 ^6 l7 I% f- b

" t( v% N8 p' {7 i6 x/ ~$ I+ m# B6 w
4 Y! ]9 e7 ?& m0 C  o$ i
收藏 评论0 发布时间:2022-5-20 18:57

举报

0个回答

所属标签

相似分享

官网相关资源

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