接上篇:STM32超低功耗平台上的RTOS培训 -- 实验1 任务创建) o' W) T9 n" j6 y9 M! x / |7 t" `1 l4 {; w! k FreeRTOS中断方式的二值信号量是实现中断函数与任务之间的同步。 - F4 t& G% O9 k9 V$ B% M0 P 1 _$ P1 }) {! G+ D2 Z4 |3 A 程序任务框图:( U3 Q, P/ _# r! X4 { 下面是本程序实现中断函数与任务之间同步的框图: 1 C, K4 u( F$ W9 U) r 程序执行的条件: > 创建两个任务:一个任务vAppStartTask()用于LED2指示灯闪烁; 一个任务prvAppButtonTask()用与等待中断后,通过串口发送按键次数;) C( a" U/ M! n7 u > 二值信号量的初始值为0,按键中断调用xSemaphoreGiveFromISR();函数释放信号量。任务prvAppButtonTask()调用xSemaphoreTake()函数获取信号量资源。/ u! C2 ]! q6 P+ z9 ? 执行过程描述:) `/ X& M9 F/ e0 a" a, l6 E! x > 任务vAppStartTask()用于LED2指示灯闪烁,和信号量之前没有关联; > 任务prvAppButtonTask()运行过程中调用xSemaphoreTake()函数,由于信号量的初始值为0,没有信号量资源可用,任务prvAppButtonTask()由运行态进入到阻塞态,串口无数据输出。- g% H t1 J1 i# I% i > 按键后,发生外部中断,中断发生,中断程序中调用xSemaphoreGiveFromISR()函数,释放信号量资源,信号量数值加1,此时信号量计数值为1,任务prvAppButtonTask()由阻塞态进入就绪态,在调度器的作用下由就绪态进入到运行态。任务prvAppButtonTask()获得信号量后,信号量数值减1,此时信号量值又变成0。 > 再次循环执,任务prvAppButtonTask()由于没有信号量资源可用,再次进入阻塞态重复执行。 ; j& x B: e8 Q6 W* s 程序执行:4 I* p% R7 x, B2 {; E8 e > 板子上LD2闪烁# y( ~4 x# ]% g' N$ k > 串口输出数据: 按一下板子上B1 USER按键,串口输出一帧数据。! B, F. L" l+ _8 g; E, ~ 程序相关的代码:为了便于查看有关信号量相关的函数位置,只截取程序中相关函数。' @: f4 D, L1 b3 U1 K 2 X1 o- B! ]; d# C4 N int main(void) { HAL_Init();1 Z! n, x0 R; [5 C- P! b6 N( S( @+ M SystemClock_Config();) m4 G& N/ l: C* A8 R0 k __HAL_RCC_PWR_CLK_ENABLE(); //Modified by ST MCU China Team, Added by JWR 2018.01.29 /* Initialize LED */ BSP_LED_Init(LED1);7 u. [% z4 N! z! }1 X BSP_LED_Init(LED2);( V5 C+ S/ z9 _' A /* Initialize buttons */( z- Q1 Q+ U: r4 Z* ? BSP_PB_Init(BUTTON_USER, BUTTON_MODE_EXTI); /* Configure Uart */# M8 }- J! i- [/ H/ m% s t BSP_Uart_Init(); //vSemaphoreCreateBinary( xTestSemaphore ); xTestSemaphore = xSemaphoreCreateBinary(); //创建二值信号量,首次创建信号量计数值为0 xTaskCreate( vAppStartTask, , t" o M6 _% } "Start", & F5 o+ A4 `% a+ w0 G' q) L configMINIMAL_STACK_SIZE, $ s0 \. W' S6 O, T! u4 i6 t! y NULL, 0 b' |, m+ S; S! X: F0 M0 ~ Start_TASK_PRIORITY, / b8 ~1 j4 p" G- n8 Z ( TaskHandle_t * ) NULL ); 3 G' { v5 ?* P xTaskCreate( 3 y6 L! j$ E* I% K: Q. [ prvAppButtonTask, & ^ M1 T* V5 @! ] "ButTest", configMINIMAL_STACK_SIZE, ( void * ) NULL, But_TEST_PRIORITY, - w1 @4 j6 M: e9 W NULL % P- K+ v' I. w2 E- H: U, [ ); * `' m9 U7 b* k6 @' T2 V8 |1 p8 Y% G vTaskStartScheduler(); for (;;);, q) Y& s& k$ N9 p# h } 2 F' t% w0 z( t# g& C% t /** * @brief Start a Task. * @param argument: Not used$ d+ j Z2 A, u K * @retval None */ static void vAppStartTask( void *pvParameters ) { (void) pvParameters;: I$ i" U. @6 x4 `8 n2 z3 j0 [- X for(;;)9 t0 q d% f% o2 |1 t/ A/ p {. D, @/ S5 X: ]% C: d1 D" h) o BSP_LED_Toggle(LED2); vTaskDelay(200); }. f" K8 ]$ T/ N1 m) M0 x) [6 y }7 A& A9 a" x" @ 8 [/ P O( @( c% A5 x9 S9 Q: D8 S /** * @brief Button Task.5 O9 X+ A J9 q5 H5 ` s8 p/ t _5 \) G * @param argument: Not used * @retval None" N, d- O9 Y" }8 o; r */ static void prvAppButtonTask( void *pvParameters )' @! {) e, S0 H/ l) H& w9 T' o {% ~ K( n8 ]- p$ s, D- h7 C" V configASSERT( xTestSemaphore ); // The assert 函数确定信号量是否有效 //获取信号量,等待时间为0,则xSemaphoreTake()在信号量无效时会立刻返回2 L0 z }* ^2 { xSemaphoreTake( xTestSemaphore, mainDONT_BLOCK );# q a; s5 K8 V( J2 A! \( W 5 F3 ^6 }$ |% d+ ?8 x+ A for( ;; )+ A2 W- z7 B0 x# S3 |% w; k* | { xSemaphoreTake( xTestSemaphore, portMAX_DELAY ); //获取信号量,超时时间为portMAX_DELAY值$ u. P! [% t- L) Q% f4 H ulButtonPressCounts++;- k- [2 d8 b* p printf("Button Press Counts:%d\r\n",ulButtonPressCounts); }% z* f/ z* W4 i2 A3 P } /**' _ s* ~. K, t8 Z; X7 @8 z * @brief EXTI line detection callback.8 f1 o' e1 Y& W * @param GPIO_Pin: Specifies the pins connected EXTI line * @retval None */& a( K" Y) g+ }8 v) D void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin), C) W6 s' V% Q {7 J; w& `: @' T" Q- g4 o" L. e" ^ if(GPIO_Pin == KEY_BUTTON_PIN); P0 r+ K6 e) p+ Q- b# r# k {- H, b2 I& x+ r3 M; | if (uwIncrementState == 0)3 W, |/ K* |, w: p# W/ W: o { /* Change the Push button state */: s, ~! c3 M% b- v uwIncrementState = 1;2 l1 L' M, Q: M h1 {. U$ K }0 G- g# N* r5 m! o else {$ c" c) E, A! X. o /* Change the Push button state */! r7 D" s Q# J4 Q uwIncrementState = 0; }+ T: w2 s8 R1 I, C5 ] } 8 H/ w) O( X7 ^" R8 l) q& D8 g } /**$ L$ o3 b' [8 K8 x. ] * @brief EXTI15_10 IRQ5 _0 i5 P+ x0 G% a6 I: V- h * @param None- V" Z; G; n$ F* z% u/ P * @retval None7 T9 x5 g/ J' j8 @/ J6 V. C */ void EXTI15_10_IRQHandler(void); N/ f0 H5 x4 }" V! E& D/ t+ ` { ' R/ w/ C# A9 t( ]5 l static BaseType_t xHigherPriorityTaskWoken; //高优先级任务是否被唤醒的状态保存 9 X# T4 X) A j ( D: M# \& s6 w- F) _5 k HAL_GPIO_EXTI_IRQHandler(KEY_BUTTON_PIN); //中断消息处理 if (utime_tick >= 200) { /* The second parameter of the send sync signal is used to save , p$ L Z5 [8 o0 \ whether a high-priority task is ready.*/5 `) u# \, y7 [. k4 N8 n: W5 V xSemaphoreGiveFromISR( xTestSemaphore, &xHigherPriorityTaskWoken ); ( [5 K2 G9 x: @4 T utime_tick = 0; } //如果 xHigherPriorityTaskWoken = pdTRUE,则切换到当前最高任务执行,然后退出中断 ; J6 ~: g7 g7 e7 y2 e portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );" Y) I. C! F) S8 ~- c! w } /** * @brief FreeRTOS Tick Hook FUNC * @param None6 x* O% d; N& K$ i7 k# F * @retval None# v9 i( w- B8 X8 z4 _& R */" |5 x0 N- S g0 G void vApplicationTickHook() { utime_tick++; /*Use for button glitch filter,It's not for the freertos kernel*/ if (utime_tick >= 65535)1 X8 \4 ? z0 B { utime_tick = 200; }! `7 `; r3 N4 D) r3 @7 h }4 E7 B. L; @+ s: d2 i /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 5 g' W: u5 [% ~4 [+ w 2 ]/ a1 @4 |, v: {- z" j, c! C # N9 ?; Z* \" \: ^ $ P2 d" a9 \* w5 J 3 m7 D# e' U7 Y |
支持下 |
写的很好,突出了重点 |