前言
" 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
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
' \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
- /* definition and creation of myBinarySem01 */0 i' |3 G+ z& d) n0 M# o5 e
- osSemaphoreDef(myBinarySem01);0 {4 b2 I7 `/ P
- myBinarySem01Handle = osSemaphoreCreate(osSemaphore(myBinarySem01), 1);
4 W0 g) ^5 ]3 A0 H) c/ F - / v7 I/ v, b% \: F8 g
- /* 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- /**
% E" r5 E% z, Z' S5 y5 {' t - * @brief Release a Semaphore token. N' r. a+ [3 [2 o: @
- * @param semaphore_id semaphore object referenced with \ref osSemaphore.; h/ r- u& I2 o) V
- * @retval status code that indicates the execution status of the function./ b* k, [3 U% I. ?8 ?, F6 c/ ?
- * @note MUST REMAIN UNCHANGED: \b osSemaphoreRelease shall be consistent in every CMSIS-RTOS.
) ^2 u$ C( ^/ A, E8 q+ T - */
/ Q1 r8 ]4 ^' y! j0 q3 G, `9 v - osStatus osSemaphoreRelease (osSemaphoreId semaphore_id)6 Y' a/ \4 \9 l3 _& a8 n" u/ e, t
- {2 D% M0 u$ v2 H1 a6 t
- osStatus result = osOK;5 N1 q2 [1 [1 @
- portBASE_TYPE taskWoken = pdFALSE;) {9 L! B8 A& v( s; M i
' Z) U4 U# M# d
" W4 S. T: r7 }$ L6 d% E6 Y- if (inHandlerMode()) {" r/ Q+ `* ~2 \4 h- A3 J0 l. V! f
- if (xSemaphoreGiveFromISR(semaphore_id, &taskWoken) != pdTRUE) {6 d9 _; y$ @% ^5 R$ j
- return osErrorOS;
3 Y2 D% b- L# B* m' m8 C+ ]9 T) {" e - }( c, q/ T) [& z/ r
- portEND_SWITCHING_ISR(taskWoken);
/ y% ]/ f0 _; } P" E9 J - }" F: C+ o& |) I" ~( A
- else {
3 a0 }: r1 l. S/ m - if (xSemaphoreGive(semaphore_id) != pdTRUE) {8 i& r l+ b2 U0 R7 f& J" E
- result = osErrorOS;
9 j' P4 a* q( G' h: Y ]( J - }( D! Z, |7 y: b" g- M; p7 P
- }' K% X7 b$ `+ f3 v8 t
- 3 Z& [( A- e$ N
- return result;
. d+ f# F9 u) d/ V# F d- ~1 ^( I - }
/ }! ^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- /**6 C: N ?7 ?( i! m$ w+ Z' P
- * @brief Wait until a Semaphore token becomes available
D7 ?9 d" U, i" L - * @param semaphore_id semaphore object referenced with \ref osSemaphore.
' o6 s0 w4 b K% V$ M5 p' b - * @param millisec timeout value or 0 in case of no time-out., L8 K: N g5 A
- * @retval number of available tokens, or -1 in case of incorrect parameters.
: [; S- z( @8 i I; r) Z* ? - * @note MUST REMAIN UNCHANGED: \b osSemaphoreWait shall be consistent in every CMSIS-RTOS.
$ |8 H4 t X9 r7 b - */
$ P+ n. {/ n( s - int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec)% B9 }9 o0 ~8 ^
- {' J4 H+ j1 `& l* A7 P
- TickType_t ticks;4 J$ I% d* z/ L" Q/ [, s: N
- portBASE_TYPE taskWoken = pdFALSE;
8 {! `1 |8 H) g; J; v* p) D; s7 I: T( K - ( ~4 t" j$ y! ~5 g; }
. }# @6 d+ W0 U( F' C# S# j5 I- if (semaphore_id == NULL) {' i( y8 @* U+ |5 }, K- N/ }
- return osErrorParameter;* l, b( ?/ M' }6 ^; |
- }$ h7 E2 P$ w/ K2 z' P0 I
) p- Z9 b1 w$ T3 X* v/ a- ticks = 0;# w& O+ c: g+ R ~7 E! \: ?, x" O
- if (millisec == osWaitForever) {+ j/ w# U" _( m' h( K; R/ q6 \
- ticks = portMAX_DELAY;6 [) x# v" H6 b/ h; p) z
- }
" ~% m0 z2 o L+ O! |* D - else if (millisec != 0) {# D2 q" A7 e. n! r$ S
- ticks = millisec / portTICK_PERIOD_MS; W; Q( P/ M) I O
- if (ticks == 0) {
0 F! y0 R$ n, t X+ R9 n; n. D - ticks = 1;
( D; q' P. P6 M8 h - }/ R/ z6 _1 V$ M7 Q
- }
0 i3 i. H9 h- {/ h' d9 |. c ~
! @0 e1 Y% m( b; d- if (inHandlerMode()) {7 t4 Y7 r" Q& ~4 G
- if (xSemaphoreTakeFromISR(semaphore_id, &taskWoken) != pdTRUE) {) [6 a$ M& P" h* M) G% u- I. r
- return osErrorOS;
8 h; g0 O" {4 [7 a: E: Q. B - }! {4 L8 X7 Z: b
- portEND_SWITCHING_ISR(taskWoken);
& N5 X, r: `5 [5 N" J) C - } % E- i H* \& ^6 H0 C+ G
- else if (xSemaphoreTake(semaphore_id, ticks) != pdTRUE) {6 f5 r, U$ R7 _+ u
- return osErrorOS;6 z" V& H& R; k4 U/ ~4 M
- }/ S' ?$ H7 u9 T. a
- 5 k# t; f# ?" B& T6 Y
- return osOK;9 E, R# J$ V4 j% `% {* n' P
- }
复制代码 - j$ V& H! a) D% {- v4 s
四、二值信号量具体操作2 ?, @& y) n) ~
- osThreadId Task1TaskHandle;% @' A+ A. _/ z9 z3 z
- osThreadId Task2TaskHandle;
+ F; V: z1 \" j% S, U& x5 P
6 u4 | ~" w( \8 B' L- void Task1Task(void const * argument);
1 s2 J% M, T, H D - void Task2Task(void const * argument);
. f. z% W1 F/ B9 `# ?1 ? l - : ]2 r Y3 F$ d2 t/ _" u9 W
- osThreadDef(Task1TaskName, Task1Task, osPriorityNormal, 0, 128);
8 q* S9 u/ H: d4 c+ y7 I# ] - Task1TaskHandle = osThreadCreate(osThread(Task1TaskName), NULL);
2 g, u/ ~3 |- q( a2 e9 { - 6 m5 j( j+ v4 I/ a1 F
- osThreadDef(Task2TaskName, Task2Task, osPriorityNormal, 0, 128);! I- p8 v' Q' w j
- Task2TaskHandle = osThreadCreate(osThread(Task2TaskName), NULL);" d* w% C& A, \' X
- $ b3 O- K+ V2 t- D
- //产生二值信号量任务
' a' E5 i) S: {9 Z% X: @; T - void Task1Task(void const * argument)" G# s' l$ w1 v0 }- y1 w
- {
9 `. E' t, a" y8 }6 [5 n - static u8 i=0;
8 [' x, i' O2 F- n7 M+ }9 I o - for(;;)) _4 ]% w4 q$ L4 z5 w6 V: X% Y+ f: b
- {
" N0 L( \3 z# _( s/ x - //调用10次再产生二值信号量6 W, I9 Z+ N6 P8 @7 c P
- if(++i==10)
% L9 s ` o: ?6 ] - {
$ w) K; Q2 Z4 M- W4 | - osSemaphoreRelease(myBinarySem01Handle);//产生二值信号量
7 @# M, b' r8 e - }
. H7 F1 W4 _! I# f& V - osDelay(5);//调用延时才会释放资源2 }5 D$ @4 J8 p. R( K* n; f
- }7 o! b0 X- R1 Y( H) S5 M
- }
( h( P/ n% {' _* t% F
* C( i2 j* ^4 L4 f7 M% C- % s$ O# J: M# O4 d# ~
- //接收二值信号量任务
0 R' f) H5 [" f5 p7 L - void Task2Task(void const * argument)6 f9 J1 A) x- _& ^4 @* `
- {
1 V8 d+ g6 i7 c; B* a5 n- @5 y - for(;;)* B; P* }- s! d+ O, F% @/ e! l
- {, v5 _7 h& @" U" q' c5 a" _
- if(osOK==osSemaphoreWait(myBinarySem01Handle,portMAX_DELAY))//等待二值信号量采用死等的方式
1 m) [! ^7 Z9 ^+ \+ m* O# }& o! c - {
, Y _6 n$ T1 f. L# Y - //等待二值信号量成功
( Z5 N8 H R, a; @. }& Z: [6 O! M; q - }1 ^2 K% J) \1 m4 p
- osDelay(5);//调用延时才会释放资源7 b0 Y% y; i, m/ z4 d0 Z
- }2 \+ q) j9 E- P: O% V- X
- }
& 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
|