任務通知代替消息隊列是在 FreeRTOS 中創建了三個任務, 其中兩個任務是用於接收任務通知,另一個任務發送任務通知。三個任務獨立運行,發送消息任務是通過檢測按鍵的按下情況來發送消息通知,另兩個任務獲取消息通知,在任務通知中沒有可用的通知之前就一直等待消息,一旦獲取到消息通知就把消息打印輸出
創建工程RTOS_TaskNotify,
配置HCLK,使用內部晶振,頻率為180MHZ(根據板子設置)
將SYS中時基源(Timebase Source)改為除SysTick之外的任意定時器即可,如:
配置板載的按鍵KEY1和KEY2
配置FreeRTOS,使用CMSIS_V1,
定義三個任務,SendTask、ReceiveTask01和ReceiveTask02
Ctrl + S生成代碼
修改代碼,
1,在main.h中添加
/* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "stdio.h" /* USER CODE END Includes */
2,在mian.c中添加
/* USER CODE BEGIN PFP */ int _write(int file , char *ptr,int len) { int i = 0; for(i = 0;i<len;i++) ITM_SendChar((*ptr++)); return len; } /* USER CODE END PFP */ ... ... ... /* USER CODE BEGIN 2 */ printf("starting...\n"); /* USER CODE END 2 */
3,在main.c中修改3個任務入口函數的內容
/* USER CODE BEGIN Header_StartSendTask */ /** * @brief Function implementing the SendTask thread. * @param argument: Not used * @retval None */ /* USER CODE END Header_StartSendTask */ void StartSendTask(void const * argument) { /* USER CODE BEGIN 5 */ BaseType_t xReturn = pdPASS;/* 定義一個創建信息返回值,默認為 pdPASS */ char test_str1[] = "this is a mail test 1";/* 消息 test1 */ char test_str2[] = "this is a mail test 2";/* 消息 test2 */ /* Infinite loop */ for(;;) { if(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == 1) { osDelay(5); if(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == 1) { while(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == 1); xReturn = xTaskNotify(ReceiveTask01Handle, (uint32_t)test_str1, eSetValueWithOverwrite); if(xReturn == pdPASS) printf("ReceiveTask01_Handle Mission notification release successful!!!\n"); } } if(HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin) == 1) { osDelay(5); if(HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin) == 1) { while(HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin) == 1); xReturn = xTaskNotify(ReceiveTask02Handle, (uint32_t)test_str2, eSetValueWithOverwrite); if(xReturn == pdPASS) printf("ReceiveTask02_Handle Mission notification release successful!!!\n"); } } osDelay(10); } /* USER CODE END 5 */ }
/* USER CODE BEGIN Header_StartReceiveTask01 */ /** * @brief Function implementing the ReceiveTask01 thread. * @param argument: Not used * @retval None */ /* USER CODE END Header_StartReceiveTask01 */ void StartReceiveTask01(void const * argument) { /* USER CODE BEGIN StartReceiveTask01 */ BaseType_t xReturn = pdTRUE;/* 定義一個創建信息返回值,默認為 pdPASS */ char *r_char; /* Infinite loop */ for(;;) { //獲取任務通知 ,沒獲取到則一直等待 xReturn=xTaskNotifyWait(0x0, UINT8_MAX, (uint32_t *)&r_char, osWaitForever); if(xReturn == pdTRUE) printf("ReceiveTask01 received %s\n",r_char); } /* USER CODE END StartReceiveTask01 */ }
/* USER CODE BEGIN Header_StartReceiveTask02 */ /** * @brief Function implementing the ReceiveTask02 thread. * @param argument: Not used * @retval None */ /* USER CODE END Header_StartReceiveTask02 */ void StartReceiveTask02(void const * argument) { /* USER CODE BEGIN StartReceiveTask02 */ BaseType_t xReturn = pdTRUE;/* 定義一個創建信息返回值,默認為 pdPASS */ char *r_char; /* Infinite loop */ for(;;) { //獲取任務通知 ,沒獲取到則一直等待 xReturn=xTaskNotifyWait(0x0, UINT8_MAX, (uint32_t *)&r_char, osWaitForever); if(xReturn == pdTRUE) printf("ReceiveTask02 received %s\n",r_char); } /* USER CODE END StartReceiveTask02 */ }
修改完畢后點擊 小錘子 構建工程,然后點擊Debug,按如下步驟配置ITM調試
全速運行之前一定要先點擊SWV ITM data Console 頁面中的紅色圓圈
現象:
分析:SendTask檢測按鍵,KEY1按下,向ReceiveTask01Handle發送任務通知;KEY2按下,向ReceiveTask02Handle發送任務通知。
ReceiveTask01獲取任務通知 ,沒獲取到則一直等待,獲取到之后打印提示信息和消息內容。
ReceiveTask02獲取任務通知 ,沒獲取到則一直等待,獲取到之后打印提示信息和消息內容。