
接上篇:STM32超低功耗平台上的RTOS培训 -- 实验1 任务创建 FreeRTOS中断方式的二值信号量是实现中断函数与任务之间的同步。 程序任务框图: 下面是本程序实现中断函数与任务之间同步的框图: ![]() 程序执行的条件: > 创建两个任务:一个任务vAppStartTask()用于LED2指示灯闪烁; 一个任务prvAppButtonTask()用与等待中断后,通过串口发送按键次数; > 二值信号量的初始值为0,按键中断调用xSemaphoreGiveFromISR();函数释放信号量。任务prvAppButtonTask()调用xSemaphoreTake()函数获取信号量资源。 执行过程描述: > 任务vAppStartTask()用于LED2指示灯闪烁,和信号量之前没有关联; > 任务prvAppButtonTask()运行过程中调用xSemaphoreTake()函数,由于信号量的初始值为0,没有信号量资源可用,任务prvAppButtonTask()由运行态进入到阻塞态,串口无数据输出。 > 按键后,发生外部中断,中断发生,中断程序中调用xSemaphoreGiveFromISR()函数,释放信号量资源,信号量数值加1,此时信号量计数值为1,任务prvAppButtonTask()由阻塞态进入就绪态,在调度器的作用下由就绪态进入到运行态。任务prvAppButtonTask()获得信号量后,信号量数值减1,此时信号量值又变成0。 > 再次循环执,任务prvAppButtonTask()由于没有信号量资源可用,再次进入阻塞态重复执行。 程序执行: > 板子上LD2闪烁 > 串口输出数据: 按一下板子上B1 USER按键,串口输出一帧数据。 ![]() 程序相关的代码:为了便于查看有关信号量相关的函数位置,只截取程序中相关函数。 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 */ BSP_PB_Init(BUTTON_USER, BUTTON_MODE_EXTI); /* Configure Uart */ BSP_Uart_Init(); //vSemaphoreCreateBinary( xTestSemaphore ); xTestSemaphore = xSemaphoreCreateBinary(); //创建二值信号量,首次创建信号量计数值为0 xTaskCreate( vAppStartTask, "Start", configMINIMAL_STACK_SIZE, NULL, Start_TASK_PRIORITY, ( TaskHandle_t * ) NULL ); xTaskCreate( prvAppButtonTask, "ButTest", configMINIMAL_STACK_SIZE, ( void * ) NULL, But_TEST_PRIORITY, NULL ); vTaskStartScheduler(); for (;;); } /** * @brief Start a Task. * @param argument: Not used * @retval None */ static void vAppStartTask( void *pvParameters ) { (void) pvParameters; for(;;) { BSP_LED_Toggle(LED2); vTaskDelay(200); } } /** * @brief Button Task. * @param argument: Not used * @retval None */ static void prvAppButtonTask( void *pvParameters ) { configASSERT( xTestSemaphore ); // The assert 函数确定信号量是否有效 //获取信号量,等待时间为0,则xSemaphoreTake()在信号量无效时会立刻返回 xSemaphoreTake( xTestSemaphore, mainDONT_BLOCK ); for( ;; ) { xSemaphoreTake( xTestSemaphore, portMAX_DELAY ); //获取信号量,超时时间为portMAX_DELAY值 ulButtonPressCounts++; printf("Button Press Counts:%d\r\n",ulButtonPressCounts); } } /** * @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) { if (uwIncrementState == 0) { /* Change the Push button state */ uwIncrementState = 1; } else { /* Change the Push button state */ uwIncrementState = 0; } } } /** * @brief EXTI15_10 IRQ * @param None * @retval None */ void EXTI15_10_IRQHandler(void) { 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 whether a high-priority task is ready.*/ xSemaphoreGiveFromISR( xTestSemaphore, &xHigherPriorityTaskWoken ); utime_tick = 0; } //如果 xHigherPriorityTaskWoken = pdTRUE,则切换到当前最高任务执行,然后退出中断 portEND_SWITCHING_ISR( xHigherPriorityTaskWoken ); } /** * @brief FreeRTOS Tick Hook FUNC * @param None * @retval None */ void vApplicationTickHook() { utime_tick++; /*Use for button glitch filter,It's not for the freertos kernel*/ if (utime_tick >= 65535) { utime_tick = 200; } } /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |
支持下 |
写的很好,突出了重点 |