接上篇:RTOS超低功耗平台应用---FreeRTOS启动&任务创建
|: ?' Q/ Q$ W" u1 [ X+ M/ ?# S3 K) |7 N
' ^5 l0 h6 F1 t4 H$ Q
) Q4 q# i9 Y1 m4 r! ?, x% n) U( R 首先了解一下信号量,一般信号量主要实现两个功能:
- Q! g- P3 z; w 1,两个任务之间或者中断函数跟任务之间的同步功能
6 @( }8 u" G8 y" y; ? K9 V 2,多个共享资源的管理( Q+ f# s( o( O
FreeRTOS针对这两种功能分别提供了二值信号量和计数信号量,其中二值信号量可以理解成计数,即初始化为仅有一个资源可以使用。6 a! p3 ~/ o; u( k4 U0 l; L
实验是创建一个线程,该线程通过ISR发出的信号量打印按钮按下计数,包含一个LED闪烁任务。( _5 l- u+ z6 F1 ^; ^0 t
- /**+ D4 _8 L1 b5 p+ T+ C( p
- * @brief Start a Task.* D3 f- Q- @/ H6 p( \5 j, O7 _
- * @param argument: Not used5 N2 G3 i$ ^2 i( z0 } W
- * @retval None9 b; n9 K0 [9 {0 e' M5 }; A5 b
- */$ x: @ e8 X/ Z9 q& k+ c' C2 L
- static void vAppStartTask( void *pvParameters )
2 y, i- E1 I' s2 A$ ^; B - {
# {% R0 k" P/ h - (void) pvParameters;
; X# l7 F7 r, g- B. v" G' u -
& X; R* V$ L: o8 v) \4 E( s) M3 B n - for(;;)9 b# y# D) b. y4 [* A m4 ?
- {5 {' }" a3 c, H( V* O
- BSP_LED_Toggle(LED2);/ j+ T- Z0 H" f
-
! [& N) D6 {) J! q( u4 a - vTaskDelay(200);
7 V/ Z- G( o- @1 b. s1 L - }# {0 t" l8 B! A8 B5 f& a! M, f$ o
- }
; Q4 V0 C! W {6 H6 \ - 7 r7 {# H2 P9 v4 b( d
- /**
; O" j* X5 I( Z3 E, c% b8 Q - * @brief Button Task.
" |9 h W8 h9 l& Z+ d0 G% q - * @param argument: Not used4 d, ]4 m ~* Q: \
- * @retval None: N7 U& F* x5 s7 [- {
- */9 \! P" s# w" @# p
- static void prvAppButtonTask( void *pvParameters )
9 V" m6 `) S1 V, f - {
3 I: s0 K0 C: F r { - configASSERT( xTestSemaphore ); /* The assert function determines whether the semaphore is valid. */2 ~1 u7 o( j# m- H
- / I* W/ _- L# ?1 `- @8 a
- /* This is the task used as an example of how to synchronise a task with: d& \1 |5 g. n
- an interrupt. Each time the button interrupt gives the semaphore, this task# f' J2 b+ U2 A2 J: M! e) ]
- will unblock, increment its execution counter, then return to block
# f- [4 A* Y2 F' g( q - again. */
8 ~6 ]: H/ v7 O# |- c. t -
! a8 b1 v6 q3 O8 o - /* Take the semaphore before started to ensure it is in the correct
: ^2 I; C$ N3 T5 q( P - state. */
/ d6 o; g; u) s1 v - xSemaphoreTake( xTestSemaphore, mainDONT_BLOCK );
) B8 a; a2 H/ R5 S( c; ] -
$ ]) d# l2 C! {* N5 t/ J" _! r - for( ;; ). Q% w$ ^1 Q7 F, `/ a$ o" W
- {8 k1 T0 Z. ~! q6 a/ f' b
- xSemaphoreTake( xTestSemaphore, portMAX_DELAY );
, y# v9 X! A. ?- Y+ p- J - ulButtonPressCounts++;
& d9 x8 r4 j! ?8 V' L! r/ n; G9 N - printf("Button Press Counts:%d\r\n",ulButtonPressCounts);
- r$ c8 _* @2 @2 Q - }3 ?% W) b5 }$ S
- }
! M$ Q; V& L: @/ V- K2 Y* r# N$ [
+ V) z" f9 f* E4 [- _- /**8 M9 j1 x0 Z& s$ v
- * @brief EXTI line detection callback.3 H+ C) E) c, s' L0 U* M. h
- * @param GPIO_Pin: Specifies the pins connected EXTI line
( h# e6 ^$ t0 ] j0 ] - * @retval None
# _ r3 J E" ^7 ~" ?# G5 F - */6 |7 M( N M" o2 {/ |3 A$ \8 O
- void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin), K$ e }( C5 C
- {
+ Z# q1 i: [+ M& O( V+ R - if(GPIO_Pin == KEY_BUTTON_PIN)
& I T$ n1 }( u# k* Q5 @- {" ` - {
5 x8 @/ \+ }2 k - if (uwIncrementState == 0)
: q- M0 `3 i/ t. r( a0 O% [ - {
' [+ f. M% R* ]- b( f- \- Z - /* Change the Push button state */& S E8 K* f& Y$ c6 n# M4 D/ v
- uwIncrementState = 1;
, `% a! Z$ f4 ?7 k- ?! ]- | - }. g) ]/ C# @8 J$ {4 f
- else
8 e8 d. \7 Y" C$ H; m - {
4 G+ Y; L0 f3 M9 i - /* Change the Push button state */
& t _/ I9 q2 H1 @+ G# S& F1 { - uwIncrementState = 0;
8 n1 D1 f/ B" h, Q8 \+ I - }
% _4 @3 ^5 U( o& H% Z - } 5 h9 z% u" `: U2 O
- }' r: c4 m* o, C/ p( t$ G: W
复制代码 主函数中使用xSemaphoreCreateBinary() 创建信号量,- xTestSemaphore = xSemaphoreCreateBinary();
复制代码 按键检测任务中使用xSemaphoreTake()函数来获取信号量。按键检测使用外部中断,信号量使用完毕后的释放也是在终端服务函数中,如下
3 Z) v3 X7 x* C% ^, ~1 [) c- xSemaphoreTake( xTestSemaphore, mainDONT_BLOCK ); //获取信号,传入创建的信号量句柄xTestSemaphore
复制代码- /**
" e U& P1 E, I" r - * @brief EXTI15_10 IRQ
5 N: a" C( u( r( |# E& |7 i7 Y. d2 f - * @param None
+ M1 ^3 U( o* d1 a% _7 L - * @retval None
) s6 X4 G$ Y( y) q8 } - */4 k4 Q) ^/ j4 J5 O: D" h' _7 v
- void EXTI15_10_IRQHandler(void)
% `8 O9 x- `- M( O - {
& P8 g! b% _8 ^+ k3 w) F" l1 N - , C# n Q* P: b* z/ n! T4 e8 N
- static BaseType_t xHigherPriorityTaskWoken; * B3 a+ ~3 T& k p6 q
- 5 q. E* w8 u+ g
- /* Inerrupt message handling */- Q9 M! P: w8 j5 c# `/ B( q
- HAL_GPIO_EXTI_IRQHandler(KEY_BUTTON_PIN); 1 q& n4 |; I7 z6 n5 Z0 H. [: G
- ( P1 u$ N _$ l6 D
- /* The handler releases a semaphore.1 ?& U& b- ~) Y% S
- xHigherPriorityTaskWoken has been initialised to zero. */
% F( e/ Y' L$ P! g3 B- F -
3 Y l, A5 y9 _0 o) g z - if (utime_tick >= 200)
) q" Y: w6 X1 M: I# t - {1 t7 ~% `5 u. J9 c
- /* The second parameter of the send sync signal is used to save
! V2 L, `+ {+ B! g' A) S - whether a high-priority task is ready.*/) \+ q: X9 Y: L; k# X9 Z! h& w5 H2 |
- xSemaphoreGiveFromISR( xTestSemaphore, &xHigherPriorityTaskWoken );
" ] a: P& D5 m/ F5 l* S1 L - utime_tick = 0;
" y! N- t& e) F1 `7 g( ? - }
复制代码 / ~ m5 m+ d* T" Q
7 b- Z' P) ^0 O5 B1 S& }
程序运行后会执行LED闪烁任务按键计数任务,当获取到信号量后计数值加1,同时释放信号量共下次资源可用。运行效果如下
" t+ o/ O* D ]/ q9 s5 y
! u2 V5 y. v6 x |