前言
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
. 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
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
- /* definition and creation of myBinarySem01 */3 \+ K5 l1 O1 N, z
- osSemaphoreDef(myBinarySem01);
, C* a) z1 e( C; R+ }1 e+ ~ - myBinarySem01Handle = osSemaphoreCreate(osSemaphore(myBinarySem01), 1);
' l9 a* D- m9 Z9 V& m0 m
2 ]- d& Z) h& a* \: y; D- g- /* 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- /**
% f2 A) v: T4 |1 g - * @brief Release a Semaphore token
* D1 j8 ?9 u6 z" Q; z# V( U - * @param semaphore_id semaphore object referenced with \ref osSemaphore.
& b, R( @8 Y1 t% R1 {' Q - * @retval status code that indicates the execution status of the function.
& E8 @) i3 R5 s, Q4 t- E9 b - * @note MUST REMAIN UNCHANGED: \b osSemaphoreRelease shall be consistent in every CMSIS-RTOS./ g" L% Y) X8 q5 R, |, ~
- */
+ q$ p! i1 Y, ? - osStatus osSemaphoreRelease (osSemaphoreId semaphore_id)
, D! Z( P' }% H& D; _" \9 v - {# b/ N( k9 j2 } d3 B6 U
- osStatus result = osOK;
) V7 z4 V. t% e1 E! e0 H - portBASE_TYPE taskWoken = pdFALSE;2 Z: y1 G$ @) \0 V% K
- . [* n2 Y( D/ b) B
/ D1 Z: F1 c9 \- if (inHandlerMode()) {( x& i9 h3 |5 J4 @
- if (xSemaphoreGiveFromISR(semaphore_id, &taskWoken) != pdTRUE) {6 W9 k9 }* V/ e& x! k
- return osErrorOS;1 M8 m& b9 S/ u9 \- I% e+ I
- }) q2 ~ `3 L3 S; Y4 d
- portEND_SWITCHING_ISR(taskWoken);
2 M. `$ y( Y" y - }1 g7 Z9 {* u* Q! m6 R! k! @
- else {
& B9 ~& [3 u6 d- \# D. n - if (xSemaphoreGive(semaphore_id) != pdTRUE) {
. K+ T% y9 i8 P5 T$ D- ? - result = osErrorOS;
4 |$ h1 x. C0 k( x - }
' p7 i) T5 k* s0 ]* a; H9 o" [ - }
% x* F4 S% d' H: F0 X' d
) o3 T, J0 j+ C, r- return result;- g+ }" v, o, k# x" \/ @
- }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- /**
) v% N: C$ N$ g; ]0 x - * @brief Wait until a Semaphore token becomes available% v, i; X% W( m9 |* |
- * @param semaphore_id semaphore object referenced with \ref osSemaphore.
/ y9 w# \1 Q! h7 V! R - * @param millisec timeout value or 0 in case of no time-out.. B6 V1 m2 L. ^0 g
- * @retval number of available tokens, or -1 in case of incorrect parameters.
# E2 k7 w% |! \# j0 s( \ - * @note MUST REMAIN UNCHANGED: \b osSemaphoreWait shall be consistent in every CMSIS-RTOS.
6 X3 y. ]- n1 {" o! G$ }8 R" k - */- z& a8 w; A4 f7 o$ G0 E
- int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec)* B" p _4 j/ Z7 ~4 b6 D( I3 Y
- {! W( |4 d9 ]+ @
- TickType_t ticks;6 q; o. g) `5 t' [5 p
- portBASE_TYPE taskWoken = pdFALSE;
$ ~0 C+ E, k$ G
) Y0 c% R; j% R4 d) \, J2 G' e- 3 I& i t6 K0 S+ W" H/ ]
- if (semaphore_id == NULL) {+ L1 Y2 y$ E7 S) C( A: o- j
- return osErrorParameter;
" C$ \" I7 J$ y7 o" o - }
5 ?0 S3 ^/ e7 ^
' E: p: M; _6 v/ L- ticks = 0;
2 \2 l8 j! F. t( _- ?9 Z3 i - if (millisec == osWaitForever) {
* S/ l+ Y* S. G! P/ m3 |" S4 b; t - ticks = portMAX_DELAY;
/ u- K4 `1 c+ M; ? - }, P2 V" S6 O$ F; M
- else if (millisec != 0) {
0 e: o$ L9 _7 N: Q, ? - ticks = millisec / portTICK_PERIOD_MS;
- i& P; L7 |& x' c3 i1 R - if (ticks == 0) {6 [# u# E4 d; L3 V) s
- ticks = 1;- P3 J# G) r& A ]; S, u1 i( z- b0 k2 F
- }
# ]$ Y' k& |# ?; D+ N - }3 N9 A) m4 r7 J! j% m# Z6 ~/ U
- 6 W' B4 `6 c' F, g4 F1 ~
- if (inHandlerMode()) {, ~, [: ~: u; |) S0 S7 x
- if (xSemaphoreTakeFromISR(semaphore_id, &taskWoken) != pdTRUE) {
! w: ]' F0 J0 K/ _ - return osErrorOS;: X6 y: B1 k1 d& ~
- }/ p" t1 e3 y! d2 j! y
- portEND_SWITCHING_ISR(taskWoken);
) I3 @; F0 V# B$ m, } - }
: [, V; G o/ _. T [, @ - else if (xSemaphoreTake(semaphore_id, ticks) != pdTRUE) {
% ^, B. N/ P; r% m7 F - return osErrorOS;
7 b. V. `! L$ g: {1 L3 ?8 M$ _ - }, c& F) r* ~) n
% `. o. g8 e; b2 D7 R- return osOK;' D A' X3 \6 x9 |( X# h
- }
复制代码 9 T% [8 h. z! U7 |+ v
四、二值信号量具体操作
$ |+ @' H# z! Y% ~3 G& c; T- F- osThreadId Task1TaskHandle;
& ]* e, k: P/ t) r+ L" m5 h - osThreadId Task2TaskHandle;
' M- g& V! t$ D4 b w - & [; L- m, |. m4 g, r0 m0 J, l/ k$ w
- void Task1Task(void const * argument);9 \/ v8 c V2 G( K! j" O3 Z7 Z
- void Task2Task(void const * argument);- x* i) l- `& H. F$ k+ u; I% E
- 4 z. P2 T) {! B
- osThreadDef(Task1TaskName, Task1Task, osPriorityNormal, 0, 128);" V. o# t$ K! d
- Task1TaskHandle = osThreadCreate(osThread(Task1TaskName), NULL);
4 s; t. r3 q8 F
5 t- y3 v% d" O7 j, F- osThreadDef(Task2TaskName, Task2Task, osPriorityNormal, 0, 128);
2 { e. ]$ F0 v6 W# _4 U7 Q - Task2TaskHandle = osThreadCreate(osThread(Task2TaskName), NULL);, s; Y% `3 H, Q5 G' M
- 4 d- d! k" E# U5 H7 x
- //产生二值信号量任务
- t s |, |* @7 H9 e - void Task1Task(void const * argument)9 G. T) @# D* v
- {
' ~. c' J! b5 X3 t J* V - static u8 i=0;3 I& s1 K$ F# e
- for(;;)
' n& H B' K: f# R$ ?/ ] - {/ j1 K- j; t, N+ X4 m/ O: Q
- //调用10次再产生二值信号量
$ U3 B& F; m5 O. n - if(++i==10)/ o. R; d5 K) J Z$ D
- {
" J& d0 J7 I) b4 }: `1 X - osSemaphoreRelease(myBinarySem01Handle);//产生二值信号量 0 D4 M* L' M E2 m
- }
% c# \: Y! @7 a$ o, |: h - osDelay(5);//调用延时才会释放资源
" Y; v8 Q% s6 M4 ~# o - }: L* N7 Y0 Q4 r' _4 ]. t2 S" r
- }
3 L9 u2 y+ d2 K' ~+ B6 E - 2 c7 i# x# e+ Z% p9 }1 H: P
- ( b- J& a% n0 I( S% y
- //接收二值信号量任务% V2 j/ i" v* ]. V6 o2 |
- void Task2Task(void const * argument)
1 y6 ?) ^ d& n: H! _: ^ - {
W; h, f5 c5 |$ }0 j: \8 K - for(;;)
2 Y, j# l2 l" e - {
$ c( |. P* a8 W, j - if(osOK==osSemaphoreWait(myBinarySem01Handle,portMAX_DELAY))//等待二值信号量采用死等的方式% ` p7 J: n5 H4 k! t7 |! o+ X; H
- {- q. e# l7 R0 C$ \: H6 ^7 {
- //等待二值信号量成功5 V& P: p/ y+ g
- }4 s; s# Y5 G, q' g
- osDelay(5);//调用延时才会释放资源
! E0 N5 i) x8 s- _( Q4 Q - }" V2 S- G- U7 y1 [6 b* G# T' E! h
- }
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
|