接上篇:RTOS超低功耗平台应用---FreeRTOS启动&任务创建: n l8 d: Q; v9 z9 d" D
/ n7 |; W4 a+ n1 r1 }# D1 p
/ u" E$ \( D: W1 N6 l u7 k( N& a
( k8 g ~7 [1 W/ g
首先了解一下信号量,一般信号量主要实现两个功能:
4 a& S- _; d+ _( K/ w" j6 ^ 1,两个任务之间或者中断函数跟任务之间的同步功能
8 F+ n' p9 X8 i$ M1 ?7 v 2,多个共享资源的管理
7 s8 }! C# J) C2 c- u) q$ v) g, f FreeRTOS针对这两种功能分别提供了二值信号量和计数信号量,其中二值信号量可以理解成计数,即初始化为仅有一个资源可以使用。
3 z! _$ V7 D6 p* t" ` 实验是创建一个线程,该线程通过ISR发出的信号量打印按钮按下计数,包含一个LED闪烁任务。
2 { D5 R' w2 a1 r9 t6 x7 `- /**
. C, D& O8 N$ } Z1 m1 Q; q - * @brief Start a Task.
/ _; V1 s- J7 X/ ^5 [' E$ T - * @param argument: Not used
w: {& J: c2 U4 R - * @retval None0 M" ?1 K6 b* V% E/ B. R
- */1 V/ f4 z6 f0 p( Z% S: y8 Y
- static void vAppStartTask( void *pvParameters )5 Z! _% j4 g3 D \: @' k
- {
/ T6 Y/ J+ G8 C9 l' m - (void) pvParameters;! y7 G' {4 ~- g3 t2 B' P
-
- [9 K1 g+ s# I ?% l9 n- c - for(;;)
0 d" M# ?' u4 `9 i - { y6 Z1 l1 T! ]7 N2 D
- BSP_LED_Toggle(LED2);
8 e5 w) k: b$ f5 y -
2 \+ N6 R5 |5 C9 G7 P - vTaskDelay(200);- D4 V6 r& U; L3 u9 d, L
- }
6 h4 [: R: [! V N+ h4 ?% l - }" u2 `% S+ q. h9 ?
- ?# y1 ]4 p7 \1 c8 k
- /**3 i8 W* G8 k, m
- * @brief Button Task.* |8 y0 V" ~! f0 m5 D
- * @param argument: Not used
3 Y: E. @9 n* r! m3 |1 S - * @retval None
" C2 j9 x) |8 C/ l" z; H) T - */" b! ?1 {+ x" O. P9 P1 N
- static void prvAppButtonTask( void *pvParameters )
& M! r( U& q" l - {6 V( w% K6 `* z% b7 ?! ~: V0 W
- configASSERT( xTestSemaphore ); /* The assert function determines whether the semaphore is valid. */
L4 P' Y7 q" }) }+ g5 y4 ] - 8 K$ R& k# f; E
- /* This is the task used as an example of how to synchronise a task with1 j5 ^/ V, [7 D ^; O
- an interrupt. Each time the button interrupt gives the semaphore, this task* O) H- }1 Y6 T3 J1 k4 e
- will unblock, increment its execution counter, then return to block
* Y7 I4 e/ z* u - again. */
M9 V; ?2 P; }/ ~: n+ m+ [" [ - # @1 |/ I' X5 ], o3 w/ C* {8 Q* R
- /* Take the semaphore before started to ensure it is in the correct
" C5 Z+ b7 ^3 U7 i - state. */5 w& P- J4 V9 F- d6 o0 I! V
- xSemaphoreTake( xTestSemaphore, mainDONT_BLOCK );& R$ W, K; ]% y' p+ ~
-
( J# |" o3 @6 H - for( ;; )
! h8 R2 O& F3 U+ {% _$ q6 [. m - {0 m# G' [, y* f6 J/ E" f8 i- T$ z
- xSemaphoreTake( xTestSemaphore, portMAX_DELAY );0 F7 W' V0 u7 s
- ulButtonPressCounts++;; U) f- e3 @4 _% Y$ R2 t
- printf("Button Press Counts:%d\r\n",ulButtonPressCounts);
) X w! |# E2 v& d6 f - }
. z- k, g$ m. l' g - }
" x$ M- j4 T1 i- j8 V2 y# j: \
* r- E5 W X3 ^% t7 D+ d- /**
$ X: {/ V6 m- U1 r - * @brief EXTI line detection callback.) V# B# \6 q6 r& p' J# r$ P D" B
- * @param GPIO_Pin: Specifies the pins connected EXTI line
" W. S" [& [# f - * @retval None
! v# J1 r Z, P" z* J y- w - */4 U6 [7 E0 q- y( ?3 f! x
- void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)/ o( j N" Q# Y! ~/ T, _( n
- {& C, k Q. |0 S2 N- c1 d
- if(GPIO_Pin == KEY_BUTTON_PIN)) {0 x5 h& w" d0 v
- {
1 w6 g/ Q* m* z - if (uwIncrementState == 0)
: d6 ] `. G) O( G, a - {. J; c( y0 L/ d& e8 \
- /* Change the Push button state */
% h* j! `& n& T* `) L9 b1 J! R# h - uwIncrementState = 1;
1 c8 B2 k0 q& l - }
; P4 U0 p7 @4 I1 x' k8 E7 ] - else
2 c3 q0 |9 |/ T4 Z D) S+ { - {
* W% J( {' ~7 t$ t. @ - /* Change the Push button state */
. w1 p$ }7 i1 @: M) Q/ Y - uwIncrementState = 0;' O( m0 l& G! O! \
- }
7 c+ Q; l8 {. E+ Y- D( L3 t - } 3 _$ L! N; b, _# f+ k% s2 g4 U
- }; A8 f V/ Q% p
复制代码 主函数中使用xSemaphoreCreateBinary() 创建信号量,- xTestSemaphore = xSemaphoreCreateBinary();
复制代码 按键检测任务中使用xSemaphoreTake()函数来获取信号量。按键检测使用外部中断,信号量使用完毕后的释放也是在终端服务函数中,如下
& @/ H& M5 o$ T- xSemaphoreTake( xTestSemaphore, mainDONT_BLOCK ); //获取信号,传入创建的信号量句柄xTestSemaphore
复制代码- /**( ?+ o3 B0 q. H2 ?5 A" Y) T
- * @brief EXTI15_10 IRQ
* U. g) ^) }! @ - * @param None
0 Y: y6 [7 ~6 L - * @retval None9 N! V: X% e/ E+ }% ^0 j
- */
6 ?8 J0 x( G$ W/ q+ G - void EXTI15_10_IRQHandler(void)
. v+ B2 |) D4 ]* U# h# b8 }: p - {/ g5 u# J6 n; J% w
-
, s5 c* {; ?. O. N, Y - static BaseType_t xHigherPriorityTaskWoken; - O( I5 {; C* M( |0 Y7 u6 @
-
) a; f2 l. d. ?2 y' e - /* Inerrupt message handling */# g* T! v5 _# Q5 _9 S7 ~% J w
- HAL_GPIO_EXTI_IRQHandler(KEY_BUTTON_PIN);
- G& I* F; l; O; ]) r -
" j7 a6 ^1 [4 \: q* s1 Y& G$ D - /* The handler releases a semaphore.& [' G$ f9 o2 W
- xHigherPriorityTaskWoken has been initialised to zero. */( }! a& J3 N9 _$ O* w2 |# K7 `
-
" T# x/ x0 ?% ?3 ^) j& X - if (utime_tick >= 200)
8 R& y% g/ \ C - {
" d2 k0 R# C: \8 } - /* The second parameter of the send sync signal is used to save
# C; t* G, ]! l7 A; n. F, H - whether a high-priority task is ready.*/
# }! Y8 h& @; R6 W; F; \; N - xSemaphoreGiveFromISR( xTestSemaphore, &xHigherPriorityTaskWoken ); 0 X+ h, J u, T0 `
- utime_tick = 0;
{+ E! \8 Q! Y) L" l/ `8 q+ v. N: R - }
复制代码
6 g+ N) b5 S0 ?8 `% \( F$ O
: q7 M3 _( a- d 程序运行后会执行LED闪烁任务按键计数任务,当获取到信号量后计数值加1,同时释放信号量共下次资源可用。运行效果如下
: z% n+ V' L# k& o0 ^8 u! F8 M: S. r* ~, q" z
|