接上篇:STM32超低功耗平台上的RTOS培训 -- 实验1 任务创建 . v$ U+ l b/ i FreeRTOS中断方式的二值信号量是实现中断函数与任务之间的同步。 N1 ?7 |- ~3 _ - C# T; J8 t' w 程序任务框图: 下面是本程序实现中断函数与任务之间同步的框图: - d1 ~3 Z% m) p. \0 H9 d g- M* b! O1 n: @ 程序执行的条件:7 L+ H( G4 t! H > 创建两个任务:一个任务vAppStartTask()用于LED2指示灯闪烁; 一个任务prvAppButtonTask()用与等待中断后,通过串口发送按键次数;8 C2 j6 x. F' F- X+ b > 二值信号量的初始值为0,按键中断调用xSemaphoreGiveFromISR();函数释放信号量。任务prvAppButtonTask()调用xSemaphoreTake()函数获取信号量资源。% P7 x$ o# O; G8 D 执行过程描述: > 任务vAppStartTask()用于LED2指示灯闪烁,和信号量之前没有关联; > 任务prvAppButtonTask()运行过程中调用xSemaphoreTake()函数,由于信号量的初始值为0,没有信号量资源可用,任务prvAppButtonTask()由运行态进入到阻塞态,串口无数据输出。! k1 c: l" z6 T6 ~. {4 n > 按键后,发生外部中断,中断发生,中断程序中调用xSemaphoreGiveFromISR()函数,释放信号量资源,信号量数值加1,此时信号量计数值为1,任务prvAppButtonTask()由阻塞态进入就绪态,在调度器的作用下由就绪态进入到运行态。任务prvAppButtonTask()获得信号量后,信号量数值减1,此时信号量值又变成0。 > 再次循环执,任务prvAppButtonTask()由于没有信号量资源可用,再次进入阻塞态重复执行。/ x2 ?) f) H1 M5 w* A/ f. v 程序执行:$ m: o% c( B7 V& G* R% @# i% d, \ > 板子上LD2闪烁: d- J8 i; {2 v8 p: |; A > 串口输出数据: 按一下板子上B1 USER按键,串口输出一帧数据。0 h; A' ]8 d) I! W1 C 3 v" l8 z) v" v' a 程序相关的代码:为了便于查看有关信号量相关的函数位置,只截取程序中相关函数。 : {2 @; x( u$ U Y int main(void) { HAL_Init(); SystemClock_Config(); __HAL_RCC_PWR_CLK_ENABLE(); //Modified by ST MCU China Team, Added by JWR 2018.01.29 /* Initialize LED */ BSP_LED_Init(LED1); BSP_LED_Init(LED2); /* Initialize buttons */! N, z3 n" c+ Z BSP_PB_Init(BUTTON_USER, BUTTON_MODE_EXTI); /* Configure Uart */7 ]7 r3 K9 a; v9 U5 j" g. }! h3 K6 C- E BSP_Uart_Init();; {" ?+ o; J" F //vSemaphoreCreateBinary( xTestSemaphore );: d# g# T8 S8 K xTestSemaphore = xSemaphoreCreateBinary(); //创建二值信号量,首次创建信号量计数值为06 w) Y# ~0 X/ q( \ xTaskCreate( . S" f5 }$ F i& P& | vAppStartTask, "Start", & J8 ?# {3 }/ E) g6 T' w6 f) @! s' i configMINIMAL_STACK_SIZE, & \7 ]0 }7 w8 Q# `( }" f9 r! T NULL, Start_TASK_PRIORITY, ! [9 [7 K9 B) p ( TaskHandle_t * ) NULL );8 b" c; }. n) D) { xTaskCreate( . K" ?/ G; o! @( }& n9 S prvAppButtonTask, "ButTest", - V/ t0 |. _9 A9 U0 L f configMINIMAL_STACK_SIZE, ( void * ) NULL, ) B7 z* Y( _9 t1 R( m But_TEST_PRIORITY, # w5 Z0 @5 r" G" b L0 Z& [ NULL );2 e) Y+ z4 p$ |$ G h2 K vTaskStartScheduler();" b7 y4 l' t: j% w0 z' |* U3 Q0 f for (;;);- b0 I/ W* }, h. v. n8 Z } " w. A4 y6 Q6 S0 O5 F /**/ r4 X! D# w. q4 d7 x: ? * @brief Start a Task. * @param argument: Not used' J# V5 J, d# B- c6 q: {! Q3 a * @retval None */- T# C( f1 c( o static void vAppStartTask( void *pvParameters ) {4 T! O' @8 I8 f3 h0 L9 m0 D# p$ I (void) pvParameters; 7 j, R& i7 N+ N! j3 x5 v" S2 `" m for(;;) {( G4 o( b. |' m- J# S. c* r BSP_LED_Toggle(LED2);7 m: A5 Z9 V. {: s/ M0 w6 {2 @! g: c vTaskDelay(200); } }' w. x* j! `$ P' t5 O p 2 t4 \0 @$ D" H* t2 Z) @ /** * @brief Button Task. * @param argument: Not used * @retval None& }5 L8 e$ P: Q% D- p# Y */( `7 c M" M8 L: G( k static void prvAppButtonTask( void *pvParameters ) {1 c1 l) `" a" v2 r configASSERT( xTestSemaphore ); // The assert 函数确定信号量是否有效 //获取信号量,等待时间为0,则xSemaphoreTake()在信号量无效时会立刻返回8 X0 g. E- r; i' K) u5 Q xSemaphoreTake( xTestSemaphore, mainDONT_BLOCK );0 K7 K; |1 C' c' j for( ;; ) y$ q9 Q# l3 r {! y* F1 ]$ @) P0 G/ Z: x xSemaphoreTake( xTestSemaphore, portMAX_DELAY ); //获取信号量,超时时间为portMAX_DELAY值" Q8 A* a9 a* M7 R( R9 @: Q5 q ulButtonPressCounts++;9 d0 ?& d6 f/ q5 k, } printf("Button Press Counts:%d\r\n",ulButtonPressCounts); }. o3 S! O) ]' V. X8 K" Z } /** * @brief EXTI line detection callback. * @param GPIO_Pin: Specifies the pins connected EXTI line * @retval None */ void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if(GPIO_Pin == KEY_BUTTON_PIN) {" A; ]% |7 m1 G/ m) _. \ if (uwIncrementState == 0)+ z. a5 p1 j+ O8 H3 ~8 { {6 o. j- N# p! C /* Change the Push button state */ uwIncrementState = 1;. z( b$ w0 a0 f }+ o4 B% i. Z& @& Y else { /* Change the Push button state */ uwIncrementState = 0;6 O2 h+ K( Y" m4 f }! W; T( C5 }7 M$ j } }/ t" b; N% K7 Q, L# q1 p / {, u; a2 {+ {& P2 k, [ /** * @brief EXTI15_10 IRQ# A( }1 v3 f. i, \, z. \0 f * @param None3 T" i, q3 `; n; B4 q6 s l+ `" ^7 A * @retval None */ c1 D H# o+ J void EXTI15_10_IRQHandler(void)8 N& K8 Y1 N% s* Z4 d2 ^ {2 f: `/ N7 e( }2 l; H" J/ K4 W& d 1 u7 s! v2 w' X n% Z. k, @ static BaseType_t xHigherPriorityTaskWoken; //高优先级任务是否被唤醒的状态保存 HAL_GPIO_EXTI_IRQHandler(KEY_BUTTON_PIN); //中断消息处理 if (utime_tick >= 200) { /* The second parameter of the send sync signal is used to save # z% T _3 {/ ~# Y+ I4 y whether a high-priority task is ready.*/ xSemaphoreGiveFromISR( xTestSemaphore, &xHigherPriorityTaskWoken ); {4 Z+ S8 l# x2 |2 y utime_tick = 0; }9 t0 T/ U, \8 Z5 F5 H //如果 xHigherPriorityTaskWoken = pdTRUE,则切换到当前最高任务执行,然后退出中断 ) d7 q( |1 | N6 Q+ I portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );9 P, e5 Y0 t* P I0 W. K3 z# i }' B7 `3 I0 v: x. D3 U /** * @brief FreeRTOS Tick Hook FUNC * @param None/ Y9 w5 ?7 f4 S7 y( F6 }6 g * @retval None; N! J3 l' U5 s P; m. M */ void vApplicationTickHook() { utime_tick++; /*Use for button glitch filter,It's not for the freertos kernel*/3 |: L) r$ ^( {9 j t if (utime_tick >= 65535) { utime_tick = 200;4 X% s9 s4 K& ^7 n5 p1 ~: f }2 G. b. k% B w% @ }6 ]1 W* _) R) w) K " |& H: y9 b5 V$ g( l1 f0 ^# x0 Z /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ ) e8 N3 ]( l0 j+ h$ s$ v; \ 7 I: W5 ?# D; ?7 g - ]9 z6 D$ l$ G7 o" J |
支持下 |
写的很好,突出了重点 |