接上篇:RTOS超低功耗平台应用---FreeRTOS启动&任务创建, a; x0 N. }. [" ~+ W: R& E
6 H2 p: d. b) d& r$ L
' b2 |1 [7 g6 ?5 V# b- `6 X
1 R/ B3 f9 q# V; \) E* f 首先了解一下信号量,一般信号量主要实现两个功能:
; q2 w. {+ {$ T 1,两个任务之间或者中断函数跟任务之间的同步功能& c/ Q1 m6 B) V9 Z- H3 N! k
2,多个共享资源的管理1 M2 V* `" F7 M/ o' L' u
FreeRTOS针对这两种功能分别提供了二值信号量和计数信号量,其中二值信号量可以理解成计数,即初始化为仅有一个资源可以使用。
; T) _4 k$ @6 N& [ 实验是创建一个线程,该线程通过ISR发出的信号量打印按钮按下计数,包含一个LED闪烁任务。4 I: t4 Z# W; M- j8 W
- /**
2 x8 b! `5 h( y, T8 F" _$ n# m - * @brief Start a Task.
! s/ q' Y% Z9 v E- } - * @param argument: Not used" e/ ?6 e3 q* z# X2 S
- * @retval None
( D; m0 n! C0 B7 w; O - */
+ k/ `# ^" Z/ F3 D: B& U( D- s - static void vAppStartTask( void *pvParameters )8 r' @/ Q7 g( s: i
- {
g/ ^+ Z# w0 g - (void) pvParameters;
# n! m" B; o* Q -
2 |% W/ N4 a9 ]! T% @ - for(;;)0 A; }* j: B) {9 }1 ?
- {
9 W( I" [: ^! h# t0 i" _4 V. [ - BSP_LED_Toggle(LED2);
7 {, v h D' b: Q4 v! m) m - 9 a. B' s9 l+ u( ^3 l1 ~
- vTaskDelay(200);
7 H$ a6 n' W! j' O, H3 ~ - }" D, c8 t/ m8 i _2 B# w
- }
# b8 Z3 t2 X$ h
. D* o* n3 a; t- /**& _1 {" Y% u* {* w2 i" c
- * @brief Button Task.' i; K: X) y" {9 k( P+ u0 }
- * @param argument: Not used7 h. i- G0 v4 @$ D& ~
- * @retval None
$ n9 E/ r2 O3 E8 V - */
4 n( R* D6 Q8 |3 d. {! a - static void prvAppButtonTask( void *pvParameters )
0 W* t" I1 V5 ]0 q0 N2 S! \0 E - {
; f7 v v' n7 z+ w" d; f - configASSERT( xTestSemaphore ); /* The assert function determines whether the semaphore is valid. */
$ j" @. M5 x9 _! R9 t - 4 d/ h6 z8 ]4 C' t/ z$ I. R
- /* This is the task used as an example of how to synchronise a task with
1 q/ z' g# f# b - an interrupt. Each time the button interrupt gives the semaphore, this task
; Q. l, F% i. O8 @: Q; O6 T1 p - will unblock, increment its execution counter, then return to block
; d/ L4 A/ t/ Q4 C' L6 {( c9 F' h - again. */3 x3 h3 Y+ R* i% h
- & e! Z3 e' x/ I/ k
- /* Take the semaphore before started to ensure it is in the correct
. Z% A4 j6 [( g, p4 z9 ] - state. */
, P4 x* ?) q5 X) X7 Q - xSemaphoreTake( xTestSemaphore, mainDONT_BLOCK );
$ O J( U9 |# Q4 `* T: F0 \ - 5 Q6 T; k* Y! J S% v7 g3 v! s! J
- for( ;; )
) S T0 i, a; l5 r - {0 d }9 k" N* I) V7 ~
- xSemaphoreTake( xTestSemaphore, portMAX_DELAY );
& m) l& z8 X- ~& v( s# q - ulButtonPressCounts++;
) z! z+ n0 ]. O% ` - printf("Button Press Counts:%d\r\n",ulButtonPressCounts);3 v* _/ Z" N: }- d& T5 U
- }" [0 n4 d7 L" w( e
- }
& S: p9 {" f, G' B4 g. ^
M9 p7 z9 w: p- /**
( t C' ?% U( ]4 H" i - * @brief EXTI line detection callback.+ u$ x* j2 E$ J' S* d9 V* G
- * @param GPIO_Pin: Specifies the pins connected EXTI line
* M) e. r e6 a- _# r - * @retval None& B& a8 U- r7 _5 T
- */
! l+ {) K. p% [ - void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)/ v. ^( f8 a* B9 C- K
- {
: _/ a: ^* d4 s$ h3 a8 ~ - if(GPIO_Pin == KEY_BUTTON_PIN)
; o' s/ U0 e' V. m8 Y4 z/ \ - {
' v8 B1 D1 b% \$ {3 |3 S. G% Y - if (uwIncrementState == 0) \; @& d# l0 k& R; x1 b1 l6 x( {0 N+ Y @
- {1 z* x2 R8 K$ q3 E# d
- /* Change the Push button state */
& y. ?7 k1 l; P U" x+ s - uwIncrementState = 1;2 O8 X) Q) |4 O- z: ?
- }
8 Q0 Z1 E; k2 A3 V - else
4 b. Z! y5 ^2 k4 [. v* `( F - {
) j% v) v! x# p/ S/ O% h& h) `, ^ - /* Change the Push button state */
" y% Y0 v+ Q) t: R - uwIncrementState = 0;# e2 _6 y/ ^) H6 m. E0 G
- }' J9 h% D4 @/ H9 E2 @$ |* @* r( Q
- }
6 g$ C, t5 v8 [6 \" U# y( v - }
: R+ P" f7 e8 V. q# |' E# R$ D {4 q
复制代码 主函数中使用xSemaphoreCreateBinary() 创建信号量,- xTestSemaphore = xSemaphoreCreateBinary();
复制代码 按键检测任务中使用xSemaphoreTake()函数来获取信号量。按键检测使用外部中断,信号量使用完毕后的释放也是在终端服务函数中,如下9 h9 F) G* ^% E* K4 o6 P8 c
- xSemaphoreTake( xTestSemaphore, mainDONT_BLOCK ); //获取信号,传入创建的信号量句柄xTestSemaphore
复制代码- /**9 M/ h$ j0 C `1 n5 k
- * @brief EXTI15_10 IRQ) E# y0 C( @2 A! [3 I+ \
- * @param None
6 Z7 b9 ]; p# a6 h6 \ - * @retval None$ i0 x5 p& y2 q) d2 `% J4 z) p
- */
/ R, J; {' Z1 s) [; I* ]( {2 C+ o - void EXTI15_10_IRQHandler(void)
1 u: \3 G" e7 b' e& J" { - {
' v$ K% X7 o, P5 V7 ]$ r8 [4 n - / ? H" s8 V& @3 P* A2 X5 B
- static BaseType_t xHigherPriorityTaskWoken; - S8 g+ V5 n+ j" c
-
: }1 Y5 [, @3 U1 w7 J$ r1 U - /* Inerrupt message handling */
7 L8 p5 P+ u* {5 r - HAL_GPIO_EXTI_IRQHandler(KEY_BUTTON_PIN); ' W& Y) }3 \% ~6 P" d
-
' V. ~8 ~' b+ i - /* The handler releases a semaphore.
* E0 G" V% `7 L. \3 `5 E1 x - xHigherPriorityTaskWoken has been initialised to zero. *// f- S& k0 S& @4 k
-
+ ^' R s: S- J, { - if (utime_tick >= 200)* b) V7 t6 I, q% u: w5 j0 j
- {7 g7 Z. H7 e0 y' _) u
- /* The second parameter of the send sync signal is used to save $ y# }4 r( r( v$ H
- whether a high-priority task is ready.*/
- C W+ V6 L' y3 Y/ _; F - xSemaphoreGiveFromISR( xTestSemaphore, &xHigherPriorityTaskWoken ); 6 S' S6 Y* D3 n4 E0 u
- utime_tick = 0;
2 i. R$ T: \, a6 V1 A: T6 d+ U - }
复制代码 + ~' R7 H* ?8 r2 C7 n* P' w
2 B- Z' \; ?! v! U 程序运行后会执行LED闪烁任务按键计数任务,当获取到信号量后计数值加1,同时释放信号量共下次资源可用。运行效果如下
0 b Z. A/ H+ }6 N% |4 ~
6 M$ s g1 d/ r9 P9 S8 W2 q; y |