接上篇:STM32超低功耗平台上的RTOS培训 -- 实验1 任务创建 & J" F& c2 P2 c- i 0 I# W: o V( e" N2 S FreeRTOS中断方式的二值信号量是实现中断函数与任务之间的同步。- ]( ?* l9 k( n' `8 \6 i4 c$ R! o - T3 Q) ^+ N2 `6 W' A 5 K2 l$ l7 F- Q5 O: c. G 程序任务框图:3 p4 p# F; z+ K$ i; _! E; v0 U* ? 下面是本程序实现中断函数与任务之间同步的框图: ; m( B" \+ L! K! ] 程序执行的条件:% R! F+ E# @" K% ~' W# p > 创建两个任务:一个任务vAppStartTask()用于LED2指示灯闪烁;: g4 y3 J: L7 o5 {! G 一个任务prvAppButtonTask()用与等待中断后,通过串口发送按键次数;" {7 i( o3 D6 o. `5 n > 二值信号量的初始值为0,按键中断调用xSemaphoreGiveFromISR();函数释放信号量。任务prvAppButtonTask()调用xSemaphoreTake()函数获取信号量资源。9 `( X3 I. A. S, q& v: u 执行过程描述: > 任务vAppStartTask()用于LED2指示灯闪烁,和信号量之前没有关联;6 g6 K* D1 D3 i4 r E > 任务prvAppButtonTask()运行过程中调用xSemaphoreTake()函数,由于信号量的初始值为0,没有信号量资源可用,任务prvAppButtonTask()由运行态进入到阻塞态,串口无数据输出。 > 按键后,发生外部中断,中断发生,中断程序中调用xSemaphoreGiveFromISR()函数,释放信号量资源,信号量数值加1,此时信号量计数值为1,任务prvAppButtonTask()由阻塞态进入就绪态,在调度器的作用下由就绪态进入到运行态。任务prvAppButtonTask()获得信号量后,信号量数值减1,此时信号量值又变成0。 > 再次循环执,任务prvAppButtonTask()由于没有信号量资源可用,再次进入阻塞态重复执行。 程序执行: > 板子上LD2闪烁5 }+ c \4 h; m I > 串口输出数据: 按一下板子上B1 USER按键,串口输出一帧数据。 程序相关的代码:为了便于查看有关信号量相关的函数位置,只截取程序中相关函数。6 ]7 K9 d- q" k ) g. k- D! U6 E0 U int main(void) { HAL_Init(); SystemClock_Config();" w# [) j, Z; H; [) ~ __HAL_RCC_PWR_CLK_ENABLE(); //Modified by ST MCU China Team, Added by JWR 2018.01.29 + m( g- D! T7 z7 F& p /* Initialize LED */3 A+ Y/ D9 P# L: u3 M BSP_LED_Init(LED1); BSP_LED_Init(LED2);# F# F9 \- Q9 g, t. i /* Initialize buttons */6 Y& u9 M% f" [2 }, m BSP_PB_Init(BUTTON_USER, BUTTON_MODE_EXTI); ! a3 B0 g$ y1 R' S2 r. V7 g6 | /* Configure Uart */ BSP_Uart_Init();8 s- A: r6 x9 K' T9 P8 C- C " b: T: B* e: i% T# W/ [* S //vSemaphoreCreateBinary( xTestSemaphore );+ P1 V$ j+ Q8 S8 @1 E$ i8 f, M xTestSemaphore = xSemaphoreCreateBinary(); //创建二值信号量,首次创建信号量计数值为0 xTaskCreate( vAppStartTask, ' n, c* f8 S' u+ Q$ ]4 ?( [ "Start", configMINIMAL_STACK_SIZE, 3 n1 {1 F; E8 X9 f6 Z& j% `* u6 Q ~ NULL, Start_TASK_PRIORITY, * s* U/ |" W5 `; T- Z3 H1 y4 Z ( TaskHandle_t * ) NULL ); xTaskCreate( ) Q D3 ]0 R; \" }( H prvAppButtonTask, "ButTest", / s9 ^$ A* X! I: s9 P configMINIMAL_STACK_SIZE, ( void * ) NULL, 4 _% N, w1 M. |, J. N0 O But_TEST_PRIORITY, NULL + D4 W8 o2 L$ p );: w. v! l4 w; I vTaskStartScheduler();6 ?% }. C \0 `9 [3 Y for (;;); }- s+ V% U: D$ @0 }3 o$ N, x2 Z 8 ]' G( O; }) X3 A; i /** * @brief Start a Task.- u6 O2 T2 `. U+ B" j * @param argument: Not used * @retval None */ static void vAppStartTask( void *pvParameters ) { (void) pvParameters; * W P% j, e5 P- A4 q0 V2 } for(;;) { BSP_LED_Toggle(LED2); vTaskDelay(200);+ X5 e( n1 s" s9 N }* {5 G: p" L$ [! R ^ } /**8 R5 G- Y* h4 ^2 F. _" V' K * @brief Button Task. * @param argument: Not used * @retval None% Z: h, T8 `; g! j$ I J */ static void prvAppButtonTask( void *pvParameters ) {! V c+ W$ B5 c9 \ configASSERT( xTestSemaphore ); // The assert 函数确定信号量是否有效$ V: O p. `5 l- s: o' t //获取信号量,等待时间为0,则xSemaphoreTake()在信号量无效时会立刻返回; l( p3 i* b2 p xSemaphoreTake( xTestSemaphore, mainDONT_BLOCK );9 H0 V2 v* J4 p! R " }; G N: @9 A3 h for( ;; ) {9 h' e4 U' A& l9 B xSemaphoreTake( xTestSemaphore, portMAX_DELAY ); //获取信号量,超时时间为portMAX_DELAY值 ulButtonPressCounts++; printf("Button Press Counts:%d\r\n",ulButtonPressCounts); }) C/ R# R2 ?' w) L5 f- L% V9 t# ` }. r. `$ y. ~( { 1 y4 s( z7 U) ^8 M& ?5 T. U /**/ `$ P. J, a; N' K( @ * @brief EXTI line detection callback. * @param GPIO_Pin: Specifies the pins connected EXTI line* r* @' B8 ^! H+ A3 T( @6 ? * @retval None */ void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)* D2 ]( ]* Q! G0 N% Z { if(GPIO_Pin == KEY_BUTTON_PIN)9 r3 D" v8 Q( }0 a2 c; ~% k { if (uwIncrementState == 0) {) K3 Y/ ~1 p5 s w: N3 Y2 b& k, R /* Change the Push button state */# U5 v/ K5 u5 \5 ] uwIncrementState = 1; } else5 F1 R" g1 i' ?1 L& h0 B: e { /* Change the Push button state */ uwIncrementState = 0;5 W- b3 E4 B! W } } 3 F5 s4 m Y8 I/ ?0 w& _ }! q$ R* G `" G0 x* \# l /** * @brief EXTI15_10 IRQ( h, D6 s* _# u6 }1 V/ m8 k * @param None9 `$ `! V9 c+ \4 E; S * @retval None0 |0 m0 i4 \$ q" I _# C" w1 h */ void EXTI15_10_IRQHandler(void); q% i7 B$ X9 D I { 9 _' o4 `/ L$ f- e" l+ V static BaseType_t xHigherPriorityTaskWoken; //高优先级任务是否被唤醒的状态保存 3 _! e6 x | ^) A. E& @ HAL_GPIO_EXTI_IRQHandler(KEY_BUTTON_PIN); //中断消息处理 & F% X/ L8 w/ R* V; w' ~) k if (utime_tick >= 200) { /* The second parameter of the send sync signal is used to save whether a high-priority task is ready.*// e( x2 o& r7 N, @ ~ xSemaphoreGiveFromISR( xTestSemaphore, &xHigherPriorityTaskWoken ); utime_tick = 0;1 a- z+ ^9 W8 d& ^ }! Y; b& X, b$ r6 _ //如果 xHigherPriorityTaskWoken = pdTRUE,则切换到当前最高任务执行,然后退出中断 7 h: I9 R+ J( n C" N, W portEND_SWITCHING_ISR( xHigherPriorityTaskWoken ); }) s2 m @1 k1 S 9 u5 G0 I8 R5 z* g & {! J# i& K. l* Y( g /** * @brief FreeRTOS Tick Hook FUNC W1 p1 D5 i) U: j( s * @param None' N( P6 f6 |6 y1 f4 l6 I9 j * @retval None */ void vApplicationTickHook(); R: q; ~: {6 U+ q: B, W6 m' G* r {9 R/ G9 T8 X1 F+ h9 G utime_tick++; /*Use for button glitch filter,It's not for the freertos kernel*/ if (utime_tick >= 65535) { utime_tick = 200; }# t. Z7 Y# r$ u& B: Z5 z9 ~ }/ k8 j/ _2 {6 ?0 `+ l. O /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ $ q# D7 Q; @" n; P' G; x" o 6 S7 D p6 Z0 { y& M4 \ ! V+ N0 J. V3 C6 t* Z7 a# E4 q - m) s5 I/ `) C. t1 t+ Q; x- f/ y |
支持下 |
写的很好,突出了重点 |