|
接上篇:STM32超低功耗平台上的RTOS培训 -- 实验1 任务创建$ R' {3 {! F7 ]9 b' a, S( v. T 3 Q+ t" e& L" x8 o, ^( y : b3 J9 b; l& Q8 u% U6 N6 Q& I FreeRTOS中断方式的二值信号量是实现中断函数与任务之间的同步。8 Z& P0 j/ x2 M: ]. D9 ~ . K1 G1 h4 \/ B! l/ \0 e$ j & U. H1 c2 u) h/ O$ w 程序任务框图:7 U- @# ^: P' g% z! U, ^8 n 下面是本程序实现中断函数与任务之间同步的框图:9 y) f s: v* M0 d, ~
; @% k* J+ ?1 o; A; N: D6 D 程序执行的条件:. i. b+ W. K4 l C > 创建两个任务:一个任务vAppStartTask()用于LED2指示灯闪烁; 一个任务prvAppButtonTask()用与等待中断后,通过串口发送按键次数;: N! Q2 Z9 a+ g, S" p; Z1 b > 二值信号量的初始值为0,按键中断调用xSemaphoreGiveFromISR();函数释放信号量。任务prvAppButtonTask()调用xSemaphoreTake()函数获取信号量资源。 执行过程描述: > 任务vAppStartTask()用于LED2指示灯闪烁,和信号量之前没有关联; > 任务prvAppButtonTask()运行过程中调用xSemaphoreTake()函数,由于信号量的初始值为0,没有信号量资源可用,任务prvAppButtonTask()由运行态进入到阻塞态,串口无数据输出。 > 按键后,发生外部中断,中断发生,中断程序中调用xSemaphoreGiveFromISR()函数,释放信号量资源,信号量数值加1,此时信号量计数值为1,任务prvAppButtonTask()由阻塞态进入就绪态,在调度器的作用下由就绪态进入到运行态。任务prvAppButtonTask()获得信号量后,信号量数值减1,此时信号量值又变成0。 > 再次循环执,任务prvAppButtonTask()由于没有信号量资源可用,再次进入阻塞态重复执行。% v4 s7 ^' v) P" Q2 j 程序执行: > 板子上LD2闪烁 > 串口输出数据: 按一下板子上B1 USER按键,串口输出一帧数据。
程序相关的代码:为了便于查看有关信号量相关的函数位置,只截取程序中相关函数。 : g2 g6 b2 f1 U, ? int main(void) { HAL_Init(); SystemClock_Config();" m6 I/ F$ V# y% K9 O __HAL_RCC_PWR_CLK_ENABLE(); //Modified by ST MCU China Team, Added by JWR 2018.01.29+ C7 F0 C/ E2 Y3 C /* Initialize LED */ BSP_LED_Init(LED1); BSP_LED_Init(LED2); /* Initialize buttons */ BSP_PB_Init(BUTTON_USER, BUTTON_MODE_EXTI);% L6 l6 r7 n$ \' Q+ I/ { /* Configure Uart */% s5 I+ d) e7 ]+ ^ BSP_Uart_Init();0 w1 l" Y- `: C( A+ F3 N; o" U% Q //vSemaphoreCreateBinary( xTestSemaphore ); xTestSemaphore = xSemaphoreCreateBinary(); //创建二值信号量,首次创建信号量计数值为0' ]/ z: a4 `: T4 x- R7 d/ F o xTaskCreate( 8 Y# ~ [: k& r; g vAppStartTask, "Start", # z* h; ~: T- f- @ @/ z configMINIMAL_STACK_SIZE, h. | B2 _; g' K, Q' l6 b NULL, : u7 v$ e& i1 A5 {& l Start_TASK_PRIORITY, : D/ ]/ X9 V# Q+ T( v; J1 S ( TaskHandle_t * ) NULL ; S- z7 ?3 [) c) A) c( b5 C3 K0 d );8 P/ y4 L% O. V- h6 d: P xTaskCreate( prvAppButtonTask, "ButTest", 7 C/ x. l( I$ X7 f: B8 } configMINIMAL_STACK_SIZE, 2 X3 S+ ^+ v. \! Q) y. X ( void * ) NULL, But_TEST_PRIORITY, ) G7 O0 b5 j9 r$ n: e5 t NULL . k, S( {) K" ?: @% n) V# A ); * N9 A7 y$ ~ n/ ^% N/ k- J vTaskStartScheduler();; g' a! n& H W for (;;); } ! E3 N( n3 E: a /**& |# {; D1 s, R0 n' o- \: \ * @brief Start a Task.3 E0 S, d% Q/ u9 n+ c * @param argument: Not used2 Y* t$ o3 c5 t1 T; q# n * @retval None. c% b9 O5 s7 g7 }* ~0 ]- z7 K, X */ static void vAppStartTask( void *pvParameters )' b6 I6 I! `- r# c, J2 z. Y1 n5 Q { (void) pvParameters;' Q! I: }+ o/ n: k8 o for(;;) {, z# e ^9 c9 }: I g BSP_LED_Toggle(LED2);) F; h% e6 T+ B7 F8 y vTaskDelay(200); } }$ S0 p5 {, x; ^2 W9 G" Y7 F% a i# M " F y& {1 e6 V /**. Q. Z0 B- \& h$ c9 z, \# | * @brief Button Task.$ Y' j) n8 o4 Q * @param argument: Not used * @retval None+ V9 g+ P1 C2 Z4 R */6 [! k+ j. ]+ p# q$ N' u static void prvAppButtonTask( void *pvParameters ) { configASSERT( xTestSemaphore ); // The assert 函数确定信号量是否有效 //获取信号量,等待时间为0,则xSemaphoreTake()在信号量无效时会立刻返回& s- j1 x- y ~) t( H xSemaphoreTake( xTestSemaphore, mainDONT_BLOCK );3 R# S) T2 d5 [6 a6 q i* s for( ;; ) { xSemaphoreTake( xTestSemaphore, portMAX_DELAY ); //获取信号量,超时时间为portMAX_DELAY值 S0 E5 c" M9 z& h8 J# ^9 K ulButtonPressCounts++; printf("Button Press Counts:%d\r\n",ulButtonPressCounts); } } /** * @brief EXTI line detection callback." j8 P9 A3 ^1 E3 n: F * @param GPIO_Pin: Specifies the pins connected EXTI line * @retval None C' m' `/ B2 S( L */* K- ]8 g( c. J# n1 D. U4 S void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)' c4 `9 T% R/ c9 s { Y" Q$ | W- d if(GPIO_Pin == KEY_BUTTON_PIN) N4 e1 d3 v% {6 F# b+ U, D2 a {6 M' g3 h+ Q! _( X; v- U8 w6 D$ Q/ \8 v if (uwIncrementState == 0) {/ L. ?, I$ J1 e a8 l4 l2 V0 q /* Change the Push button state */ uwIncrementState = 1; } A/ c) M0 b& v else% m2 k) u3 o; S0 d+ }6 L8 t {0 W: \1 ^' l9 p* h /* Change the Push button state */' Q3 R$ v- c" Q uwIncrementState = 0;& B% K# O: Z2 U) I: A } } " P7 Y y/ O3 ?! y1 y7 ?1 u4 P4 K" b }$ j( Q& U; \2 E8 P4 P+ m/ t' F r /** * @brief EXTI15_10 IRQ# @( r$ y9 N# z. a/ A * @param None+ Y. O$ i: }+ W; F; G * @retval None c3 T- p7 t/ W3 ~ */- C& ?( V# T8 n- }& t void EXTI15_10_IRQHandler(void), v! }0 N( m, z' ~3 f5 b0 |( F { static BaseType_t xHigherPriorityTaskWoken; //高优先级任务是否被唤醒的状态保存 ; X9 L F3 T: |7 g HAL_GPIO_EXTI_IRQHandler(KEY_BUTTON_PIN); //中断消息处理 - c) j$ {4 A6 T3 `1 W : r4 ^6 _& P" ?3 c: v5 ^4 ^ if (utime_tick >= 200) {, x8 L* o% \$ x$ K$ c" N! l /* The second parameter of the send sync signal is used to save whether a high-priority task is ready.*/) ~8 ?) l/ W& S; T. P$ ?. [ u; P xSemaphoreGiveFromISR( xTestSemaphore, &xHigherPriorityTaskWoken ); utime_tick = 0; }; D) z6 p6 N( h7 [ //如果 xHigherPriorityTaskWoken = pdTRUE,则切换到当前最高任务执行,然后退出中断 1 X. a/ d2 Q9 B0 E: G# S portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );# p" O' v1 Q$ l3 k; U2 i } / K, P3 S3 }% w! X P7 ^2 J ) H# [9 q% W7 d& d/ i9 {6 W2 w /**, H' x9 v' `3 x7 X3 O1 t0 W( A. R0 d# \ * @brief FreeRTOS Tick Hook FUNC" e3 Y3 w' W' w: }& F! s9 \- z * @param None * @retval None' r$ t) K& B6 R% @ */- L7 p* ^6 B6 p$ x0 z void vApplicationTickHook()0 \+ ?: ^, `0 @0 }0 Y; a) g- I' W# A { utime_tick++; /*Use for button glitch filter,It's not for the freertos kernel*/0 a! j+ M/ S5 a$ ^ if (utime_tick >= 65535) { utime_tick = 200;. S* n' q, x) v" V( j. D8 M( w3 C }, `4 D! G; k8 i6 ~ }" }& D/ H w$ T& n% k : x! D6 u3 Y' Z3 N /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ ( u. i) I6 v. n* Y 1 P5 C, `% n Y" {# ]$ ` & \* d0 h6 z* G( q! j - y( B5 l- F9 \: b4 i3 | ( H* d5 g0 s9 B8 @0 \ , D6 N! l$ f' K+ B |
| 支持下 |
| 写的很好,突出了重点 |
微信公众号
手机版