接上篇:RTOS超低功耗平台应用---FreeRTOS启动&任务创建% O: X" p r. W: D5 F* p6 `
" q) N# m3 i9 U2 c% P P
: m- i% b& q' x0 x5 H
0 p# R$ E; {$ ?# P/ a. f7 R( N 首先了解一下信号量,一般信号量主要实现两个功能:
! w- O6 c# m2 H# H7 {. ^ 1,两个任务之间或者中断函数跟任务之间的同步功能% S* @$ g0 X- Q, ~7 P; m$ v. H
2,多个共享资源的管理
& D5 w+ ~/ H" i! v; \- ^ c FreeRTOS针对这两种功能分别提供了二值信号量和计数信号量,其中二值信号量可以理解成计数,即初始化为仅有一个资源可以使用。( q+ |# f1 `" A* U+ n$ n" X
实验是创建一个线程,该线程通过ISR发出的信号量打印按钮按下计数,包含一个LED闪烁任务。2 d& ?8 s8 @! g {9 ]
- /**
4 s, m {3 b; l - * @brief Start a Task.' I; L' U* ~- i
- * @param argument: Not used+ Q/ k: }/ D8 j4 v3 v0 x e" j4 t! a
- * @retval None5 M, `: p- ~: @. F J# P* v8 C" U
- */1 o" |5 F0 f2 V B
- static void vAppStartTask( void *pvParameters )1 x2 s% O; B! r5 u0 K9 s6 V
- {3 E% V# X+ g2 ]% X
- (void) pvParameters;. N" q1 t) f( r1 ^+ c( z4 j
-
J& d' ]* d& t! ?7 L! {- \ - for(;;)6 ^& q& W& {5 ^, d A3 K q w
- {8 e ~8 w3 M. m! l* H9 R1 z
- BSP_LED_Toggle(LED2);
! ~0 @1 m% N; c9 ~ -
+ @, Q& n" i$ n" B( _, B) Q4 z; ~ - vTaskDelay(200);
7 y- Q+ q# Y. m: h& l - }% L6 P9 l4 W4 O3 E8 [5 p! |
- }5 y) R+ c1 s* B! j* J$ S% r3 Q
" o* ]2 B$ V7 `/ d% A+ v- /**
6 D0 n+ D5 F3 S/ Z: y2 Z0 A8 @* E - * @brief Button Task.) F+ H( i S1 ]+ { W/ t( _
- * @param argument: Not used
; z/ U# a$ c' m! W/ L4 b - * @retval None) r. F- h2 O- h% J; j
- */
& d, g+ ?* g3 h+ d: D0 H - static void prvAppButtonTask( void *pvParameters )# O; K3 [3 j( M8 X- D' M' }
- {
+ k3 ~8 B0 E% H2 F, T - configASSERT( xTestSemaphore ); /* The assert function determines whether the semaphore is valid. *// P+ F) Q, O1 f2 f
- / S! i6 l! R2 W* m& J
- /* This is the task used as an example of how to synchronise a task with
: y1 ^/ H- V" c9 ~, y( o - an interrupt. Each time the button interrupt gives the semaphore, this task7 p' Z& o+ ]7 E
- will unblock, increment its execution counter, then return to block$ w# t5 l* B) I: Y. ]9 L
- again. */7 K, G# L) o( D u% ^6 H
-
1 S0 _5 Y# Q6 N. Z: ` - /* Take the semaphore before started to ensure it is in the correct7 N3 ~( c" b9 r
- state. */9 H1 U3 u' D9 |5 }
- xSemaphoreTake( xTestSemaphore, mainDONT_BLOCK );
7 O% |# D) ~$ G% _7 d - 1 y6 w+ ~! [& Q. Q
- for( ;; )3 F* c+ B5 z5 s$ X/ R) B; u
- {' i7 u$ u4 D+ I* m: m. X
- xSemaphoreTake( xTestSemaphore, portMAX_DELAY );
: I5 p0 h* {. v h& B9 F - ulButtonPressCounts++;
, m" c" l) }1 z& E) D. e - printf("Button Press Counts:%d\r\n",ulButtonPressCounts);
+ ?; u& M5 A: ~8 y - }
( d5 B% V m* K7 @ - }* b8 c" J0 \) E8 j: \- t
- 7 v4 c6 t5 k* M! r) `
- /**
+ b) i4 F# ^5 i6 u" x6 N0 u r0 j - * @brief EXTI line detection callback.
5 H. h2 z% M- Y9 \2 c$ v" O5 j - * @param GPIO_Pin: Specifies the pins connected EXTI line
" ?* i0 v& \) h# k - * @retval None/ }, |8 h" O/ U1 F# g9 V
- */
. e$ p! b# w; a2 T( e+ N - void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
; Y! l- X# B3 r: \7 x% F - {# @; t, k \8 D' ^) V
- if(GPIO_Pin == KEY_BUTTON_PIN)
8 @9 d' Q" a4 M: Y' w7 p: ] - {$ b( `$ r' Z9 B) [
- if (uwIncrementState == 0)5 E6 y3 m) R' |+ S# @- i3 n* r
- {
0 ?8 u# r& U: M: h, x - /* Change the Push button state */2 c! T, e# A4 g7 \" Y
- uwIncrementState = 1;
; z4 _) ~1 a" t. ~6 ?; l8 B - }9 s; D5 L2 `4 O' w4 E; X/ R9 q
- else
6 O, I- s3 @0 @" u7 Y - {
4 p, _6 j, h/ z8 c' q3 p - /* Change the Push button state */
" A7 m8 V. V9 ]( e1 N. j - uwIncrementState = 0; G* }: P. h) j5 B6 [
- }4 M9 Z0 A( |7 g5 U, {. g. q
- } 5 q$ T o6 l2 y& z! l9 g1 Q: T
- }
, D6 K { q. [ l6 }) ], R
复制代码 主函数中使用xSemaphoreCreateBinary() 创建信号量,- xTestSemaphore = xSemaphoreCreateBinary();
复制代码 按键检测任务中使用xSemaphoreTake()函数来获取信号量。按键检测使用外部中断,信号量使用完毕后的释放也是在终端服务函数中,如下
& \* C: N0 }5 x- xSemaphoreTake( xTestSemaphore, mainDONT_BLOCK ); //获取信号,传入创建的信号量句柄xTestSemaphore
复制代码- /**. d. Q; f( G! c$ A$ ]: n
- * @brief EXTI15_10 IRQ3 |3 V8 u+ V6 m5 X
- * @param None
) s0 E( n9 e2 D$ ^+ [0 O7 m - * @retval None
& d( m" ~6 l* f1 D% l3 B - */
i% y ^7 B; }) K, c) Q - void EXTI15_10_IRQHandler(void)
, z) u" Y1 ]( s& ?) s - {% W6 ?1 M$ @9 [6 B7 J+ c
-
2 t* \: p! B/ Z - static BaseType_t xHigherPriorityTaskWoken; ! ~: b& A2 D: c, L& }
- 0 F6 k1 f, }- T/ O! V! d
- /* Inerrupt message handling */
, d4 `3 }" J4 A$ Q: Q4 P5 w+ r+ A - HAL_GPIO_EXTI_IRQHandler(KEY_BUTTON_PIN); ! }& R$ M3 e: b
-
+ O. V% H" X) F! H6 N R - /* The handler releases a semaphore.
& e. o4 h/ T3 v% J( w9 |& {0 ^9 Y - xHigherPriorityTaskWoken has been initialised to zero. */( ~5 r5 ]4 k7 ~5 n
-
1 O; y# O$ {' d$ I% }+ ]% S h - if (utime_tick >= 200): x% a2 B3 f2 F8 k4 D
- {
! V. h- P# y9 B0 S - /* The second parameter of the send sync signal is used to save
- Y- M6 _- ?. r6 O; m& k - whether a high-priority task is ready.*/- q5 X! ] s i& I, ?
- xSemaphoreGiveFromISR( xTestSemaphore, &xHigherPriorityTaskWoken );
# }# }& [4 C% s - utime_tick = 0;
9 g J1 B- J# a1 v - }
复制代码
) [+ ^8 r! \# ]9 h F
* [. v6 E& F, |$ i3 [ 程序运行后会执行LED闪烁任务按键计数任务,当获取到信号量后计数值加1,同时释放信号量共下次资源可用。运行效果如下
( W, Y2 [! n* x$ L
( w* m8 [/ o' i/ j+ p |