前言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
" 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
* 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- /* definition and creation of myBinarySem01 */
3 S9 l2 ~! ^! D; i - osSemaphoreDef(myBinarySem01);
9 W9 Q6 D1 D! w5 U4 I9 ?$ }% G - myBinarySem01Handle = osSemaphoreCreate(osSemaphore(myBinarySem01), 1);: W, [, ?4 X9 P' i# \
- # S5 }# w0 N/ f; |
- /* 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* |
- /**( z' I$ G- k) M* b: W/ X/ [$ ^
- * @brief Release a Semaphore token
; R- q8 N! s" j& G0 A& g - * @param semaphore_id semaphore object referenced with \ref osSemaphore.- s8 i4 @2 y. f* `) e
- * @retval status code that indicates the execution status of the function.
3 Y: A: t0 H; \) f - * @note MUST REMAIN UNCHANGED: \b osSemaphoreRelease shall be consistent in every CMSIS-RTOS.0 Z, x% _8 X+ F8 h {' b
- */
+ `( Z1 ~0 `$ w0 E: g% \% ?: F - osStatus osSemaphoreRelease (osSemaphoreId semaphore_id)
+ C" e S2 W, x6 O - { {5 u& Q* ^# a/ N5 Y" N7 p+ I
- osStatus result = osOK;
9 b4 [# g& ~; i- q! }0 m" q @ - portBASE_TYPE taskWoken = pdFALSE;/ M* u; t) f0 U& L
- $ f( g% S& [) k2 U% Z1 h0 q. Y
; g) X I+ p) [$ s- S& R* B- if (inHandlerMode()) {
8 D2 [7 C$ Q6 M- ^/ P - if (xSemaphoreGiveFromISR(semaphore_id, &taskWoken) != pdTRUE) {. V' g1 l+ a8 _& f& P& J
- return osErrorOS;
% J+ M/ H% a8 I - }
/ C7 b; X. r, I4 h - portEND_SWITCHING_ISR(taskWoken);1 `6 ~ E, s; P' ~; K3 r/ k
- }
( t/ {2 }$ @- V5 p/ x( V- u! [* {3 ] - else {; d" ]$ t( T3 _3 R$ [4 |. D
- if (xSemaphoreGive(semaphore_id) != pdTRUE) {
@7 L7 R; s) \* @ - result = osErrorOS;
5 X; O- ^/ n* U1 P - }) |% w3 k u5 u
- }/ X# m3 f I8 W
- ( y* T" Y' `" @& q% o( d1 G$ ]
- return result;
# A: e( ?# m: N3 G" P( Y; O - }. [' 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 `! ^- /**
+ O& R. ], E+ A) i0 i+ w - * @brief Wait until a Semaphore token becomes available
, Z6 s7 Q0 i- s - * @param semaphore_id semaphore object referenced with \ref osSemaphore.
( R/ b5 M) |) }+ d - * @param millisec timeout value or 0 in case of no time-out.- K- ?- H- c# E$ y/ L! U
- * @retval number of available tokens, or -1 in case of incorrect parameters.
( G$ \ o8 V. s' X9 |7 t - * @note MUST REMAIN UNCHANGED: \b osSemaphoreWait shall be consistent in every CMSIS-RTOS.* M% z! `6 M/ L$ T( a- D+ G
- */( `# m( s! z7 q+ ]- \! `
- int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec)
( U/ f H, D0 [ K5 X - {
; D. h' x$ l/ G3 v - TickType_t ticks;
0 ]% ]+ C) L8 j, w! x - portBASE_TYPE taskWoken = pdFALSE;
: {; K+ E, Z; X b - ! b _9 \5 n# p; ^+ M% y
7 p9 Y) m* M! E- if (semaphore_id == NULL) {
1 w, z3 ]4 \6 {& ]( p1 p - return osErrorParameter;
: B! N# ?& _, Z9 | - }2 Z! k2 s6 s0 y0 k7 V5 j1 A8 w
8 [+ ^# p# i4 } Q+ @, n- ticks = 0;1 U8 L# q, ~! z# d6 h
- if (millisec == osWaitForever) {
% v; ]$ t4 |( \" P3 H - ticks = portMAX_DELAY;
. ^6 ~) T) x2 q$ u) ` - }
5 `! q Z( P, [6 X: T - else if (millisec != 0) {9 y8 w9 z* a6 d" D) q
- ticks = millisec / portTICK_PERIOD_MS;9 W: b7 @6 p4 Y, G$ z- p
- if (ticks == 0) {7 Z0 I) A& k0 m& \5 q2 K- L
- ticks = 1;9 \2 t9 E) q& ]5 l. B
- }: N# L4 Y7 D& b/ n2 Q/ M) |
- }8 i+ l$ N; y% |0 Y
* N% [9 ?7 J0 v) J" S- if (inHandlerMode()) {
: {. _7 l: u4 u. z. S - if (xSemaphoreTakeFromISR(semaphore_id, &taskWoken) != pdTRUE) {
6 B0 t( Z# p: } - return osErrorOS;
( Z5 `$ l( X5 M* \5 x) H4 _+ @ - }
" }7 ^7 X& `: R! ]1 h7 T - portEND_SWITCHING_ISR(taskWoken);
. X7 c1 v7 M- m9 ~9 N - }
! t5 r9 k8 ?' H1 W* ? - else if (xSemaphoreTake(semaphore_id, ticks) != pdTRUE) {
I- t: V5 F1 B( y+ s - return osErrorOS;! Z( @4 W6 ?; F0 ]# b
- }1 ?! V9 D+ S8 x$ o2 i; F1 Z
- 1 B% t/ J$ `! ?2 {& K
- return osOK;* Q2 f1 c4 h: W2 ?0 g
- }
复制代码
) G/ }3 G. F# e2 X& _9 o1 M# C四、二值信号量具体操作2 O6 Z) {2 }$ F" ^7 y) O2 l
- osThreadId Task1TaskHandle;
. Y+ p! W$ b3 q - osThreadId Task2TaskHandle;" `/ Z3 Y3 ]: n( j1 V- u( R
' z9 k6 l S/ s/ v: h* z- void Task1Task(void const * argument);7 ~6 z: A; h) r" q
- void Task2Task(void const * argument);6 [& w$ I( R/ ~! t' [
- 5 c$ p* N* H! f
- osThreadDef(Task1TaskName, Task1Task, osPriorityNormal, 0, 128);
0 z) V: ~& H2 A% {7 L - Task1TaskHandle = osThreadCreate(osThread(Task1TaskName), NULL);; ^' w m% h( Z* p3 ^. J9 m
- " l! r3 Z) h% ^- K/ K: Z
- osThreadDef(Task2TaskName, Task2Task, osPriorityNormal, 0, 128);* D9 M( @& W4 Z9 Y# Y
- Task2TaskHandle = osThreadCreate(osThread(Task2TaskName), NULL); |' b# c4 |2 i9 k9 h
- ) [- U$ E) V& I6 K: j
- //产生二值信号量任务5 O. R5 p# B5 s. u1 f3 k6 a/ b5 W
- void Task1Task(void const * argument)
* [5 B X& G% s# M - {; T6 b; s- v% |5 h5 r- l
- static u8 i=0;3 D( }" v2 h/ T$ P
- for(;;)
: ?( E. t1 S3 L$ ? - {
6 B" Y& D. y2 } - //调用10次再产生二值信号量
" I; e$ h* n9 w( K% f$ O7 z6 H - if(++i==10)
( W+ I- B6 j- U" N. T# _1 s6 v8 E - {4 g1 d C2 q4 Z
- osSemaphoreRelease(myBinarySem01Handle);//产生二值信号量 - M: Q# D% {7 f; y" M- C
- }# @% Q) U& Y* X& E# ` ?% ?
- osDelay(5);//调用延时才会释放资源# B4 R& X# d k( U' G( ] z
- }9 c6 R5 X, w2 S# r- ^' i
- }1 w, L; L2 Q# C& F: V5 Y8 N. d) w; _
5 Z2 k/ K: V/ V3 F! U* T
u, j" S4 j, T- //接收二值信号量任务- h ?! ?( [) v
- void Task2Task(void const * argument): h7 ?) ~* Z- U2 S' S' ]' [( E
- {* Y4 b: g9 G* R3 S
- for(;;)
; K& N2 {/ l* Q, m3 Q6 H2 o - {& D+ G l2 |: x! }7 l
- if(osOK==osSemaphoreWait(myBinarySem01Handle,portMAX_DELAY))//等待二值信号量采用死等的方式
+ ~2 q }' \% D- s) P; Q - {
8 y1 A/ i! ?6 k - //等待二值信号量成功7 n8 _- X4 n9 O
- }" y( t) {: { Q7 |6 ?: Q
- osDelay(5);//调用延时才会释放资源
& @$ N: i3 w! v+ i+ U$ G - }6 r, B$ a$ Y" f U* { f; a
- }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 ` |