FreeRTOS学习——任务通知

一、什么是任务通知

        FreeRTOS 从版本 V8.2.0 开始提供任务通知这个功能,每个任务都有一个 32 位的通知值。按照 FreeRTOS 官方的说法,使用消息通知比通过二进制信号量方式解除阻塞任务快 45%, 并且更加省内存(无需创建队 列)。

在大多数情况下,任务通知可以替代二值信号量、计数信号量、事件标志组,可以替代长度为 1 的队列(可 以保存一个 32 位整数或指针值),并且任务通知速度更快、使用的RAM更少!

二、任务通知的更新方式

FreeRTOS 提供以下几种方式发送通知给任务 :

        发送消息给任务,如果有通知未读, 不覆盖通知值

        发送消息给任务,直接覆盖通知值

        发送消息给任务,设置通知值的一个或者多个位

        发送消息给任务,递增通知值

通过对以上方式的合理使用,可以在一定场合下替代原本的队列、信号量、事件标志组等

三、任务通知的优势和劣势

3.1、任务通知的优势

1. 使用任务通知向任务发送事件或数据,比使用队列、事件标志组或信号量快得多。

2. 使用其他方法时都要先创建对应的结构体,使用任务通知时无需额外创建结构体。

3.2、任务通知的劣势 

1. 只有任务可以等待通知中断服务函数中不可以,因为中断没有 TCB 。

2. 通知只能一对一,因为通知必须指定任务。

3. 等待通知的任务可以被阻塞, 但是发送消息的任务,任何情况下都不会被阻塞等待

4. 任务通知是通过更新任务通知值来发送数据的,任务结构体中只有一个任务通知值,只能保持一个数据。

四、相关函数

4.1、发送通知

BaseType_t xTaskNotify( TaskHandle_t     xTaskToNotify,uint32_t         ulValue,eNotifyAction    eAction 
);

参数:

xTaskToNotify:需要接收通知的任务句柄;

ulValue:用于更新接收任务通知值, 具体如何更新由形参 eAction 决定;

eAction:一个枚举,代表如何使用任务通知的值;

返回值:

如果被通知任务还没取走上一个通知,又接收了一个通知,则这次通知值未能更新并返回 pdFALSE, 而其他情况均返回pdPASS。

BaseType_t xTaskNotifyAndQuery( TaskHandle_t     xTaskToNotify,uint32_t         ulValue,eNotifyAction    eAction,uint32_t *       pulPreviousNotifyValue 
);

参数:

xTaskToNotify:需要接收通知的任务句柄;

ulValue:用于更新接收任务通知值, 具体如何更新由形参 eAction 决定;

eAction:一个枚举,代表如何使用任务通知的值;

pulPreviousNotifyValue:对象任务的上一个任务通知值,如果为 NULL, 则不需要回传, 这个时候就等价于函数 xTaskNotify()。

返回值:

如果被通知任务还没取走上一个通知,又接收了一个通知,则这次通知值未能更新并返回 pdFALSE, 而其他 情况均返回pdPASS。

BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify );

参数:

xTaskToNotify:接收通知的任务句柄, 并让其自身的任务通知值加 1。

返回值:

总是返回 pdPASS。

4.2、等待通知

        注意:等待通知API函数只能用在任务,不可应用于中断中!

uint32_t ulTaskNotifyTake( BaseType_t     xClearCountOnExit,TickType_t     xTicksToWait 
);

 参数:

xClearCountOnExit:指定在成功接收通知后,将通知值清零或减 1,pdTRUE:把通知值清零(二值信号量);pdFALSE:把通知值减一(计数型信号量);

xTicksToWait:阻塞等待任务通知值的最大时间;

返回值:

0:接收失败

非0:接收成功,返回任务通知的通知值

BaseType_t xTaskNotifyWait( uint32_t      ulBitsToClearOnEntry,uint32_t      ulBitsToClearOnExit,uint32_t *    pulNotificationValue,TickType_t    xTicksToWait 
);

ulBitsToClearOnEntry:函数执行前清零任务通知值那些位 。

ulBitsToClearOnExit:表示在函数退出前,清零任务通知值那些位(最大值:0xFFFFFFFF),在清 0 前,接收到的任务通知值会先被 保存到形参*pulNotificationValue 中。

pulNotificationValue:用于保存接收到的任务通知值。 如果不需要使用,则设置为 NULL 即可 。 xTicksToWait:等待消息通知的最大等待时间。

五、实操

5.1、模拟二值信号量

        按下 KEY1 则释放信号量,按下 KEY2 获取信号量。

/* USER CODE BEGIN Header */
/********************************************************************************* File Name          : freertos.c* Description        : Code for freertos applications******************************************************************************* @attention** Copyright (c) 2024 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header *//* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD *//* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables *//* USER CODE END Variables */
osThreadId TaskKEY1Handle;
osThreadId TaskKEY2Handle;/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes *//* USER CODE END FunctionPrototypes */void StartTaskKEY1(void const * argument);
void StartTaskKEY2(void const * argument);void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) *//* GetIdleTaskMemory prototype (linked to static allocation support) */
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );/* USER CODE BEGIN GET_IDLE_TASK_MEMORY */
static StaticTask_t xIdleTaskTCBBuffer;
static StackType_t xIdleStack[configMINIMAL_STACK_SIZE];void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )
{*ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer;*ppxIdleTaskStackBuffer = &xIdleStack[0];*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;/* place for user code */
}
/* USER CODE END GET_IDLE_TASK_MEMORY *//*** @brief  FreeRTOS initialization* @param  None* @retval None*/
void MX_FREERTOS_Init(void) {/* USER CODE BEGIN Init *//* USER CODE END Init *//* USER CODE BEGIN RTOS_MUTEX *//* add mutexes, ... *//* USER CODE END RTOS_MUTEX *//* USER CODE BEGIN RTOS_SEMAPHORES *//* add semaphores, ... *//* USER CODE END RTOS_SEMAPHORES *//* USER CODE BEGIN RTOS_TIMERS *//* start timers, add new ones, ... *//* USER CODE END RTOS_TIMERS *//* USER CODE BEGIN RTOS_QUEUES *//* add queues, ... *//* USER CODE END RTOS_QUEUES *//* Create the thread(s) *//* definition and creation of TaskKEY1 */osThreadDef(TaskKEY1, StartTaskKEY1, osPriorityNormal, 0, 128);TaskKEY1Handle = osThreadCreate(osThread(TaskKEY1), NULL);/* definition and creation of TaskKEY2 */osThreadDef(TaskKEY2, StartTaskKEY2, osPriorityNormal, 0, 128);TaskKEY2Handle = osThreadCreate(osThread(TaskKEY2), NULL);/* USER CODE BEGIN RTOS_THREADS *//* add threads, ... *//* USER CODE END RTOS_THREADS */}/* USER CODE BEGIN Header_StartTaskKEY1 */
/*** @brief  Function implementing the TaskKEY1 thread.* @param  argument: Not used* @retval None*/
/* USER CODE END Header_StartTaskKEY1 */
void StartTaskKEY1(void const * argument)
{/* USER CODE BEGIN StartTaskKEY1 */BaseType_t mark = 0;/* Infinite loop */for(;;){if(HAL_GPIO_ReadPin(GPIOA ,GPIO_PIN_0) == GPIO_PIN_RESET){osDelay(20);if(HAL_GPIO_ReadPin(GPIOA ,GPIO_PIN_0) == GPIO_PIN_RESET){mark = xTaskNotifyGive( TaskKEY2Handle );if(mark == pdPASS)printf("任务通知模拟二值信号量发送成功!\r\n");elseprintf("任务通知模拟二值信号量发送失败!\r\n");}while(HAL_GPIO_ReadPin(GPIOA ,GPIO_PIN_0) == GPIO_PIN_RESET);}osDelay(10);}/* USER CODE END StartTaskKEY1 */
}/* USER CODE BEGIN Header_StartTaskKEY2 */
/**
* @brief Function implementing the TaskKEY2 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTaskKEY2 */
void StartTaskKEY2(void const * argument)
{/* USER CODE BEGIN StartTaskKEY2 */uint32_t flag = 0;/* Infinite loop */for(;;){if(HAL_GPIO_ReadPin(GPIOA ,GPIO_PIN_1) == GPIO_PIN_RESET){osDelay(20);if(HAL_GPIO_ReadPin(GPIOA ,GPIO_PIN_1) == GPIO_PIN_RESET){flag = ulTaskNotifyTake(pdTRUE ,0);if(flag != 0)printf("接收成功!任务的通知值为:%d\r\n",flag);elseprintf("接收失败!\r\n");}while(HAL_GPIO_ReadPin(GPIOA ,GPIO_PIN_1) == GPIO_PIN_RESET);}osDelay(10);}/* USER CODE END StartTaskKEY2 */
}/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application *//* USER CODE END Application */

 5.2、模拟计数型信号量

        按下 KEY1 则释放信号量,按下 KEY2 获取信号量。

/* USER CODE BEGIN Header */
/********************************************************************************* File Name          : freertos.c* Description        : Code for freertos applications******************************************************************************* @attention** Copyright (c) 2024 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header *//* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD *//* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables *//* USER CODE END Variables */
osThreadId TaskKEY1Handle;
osThreadId TaskKEY2Handle;/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes *//* USER CODE END FunctionPrototypes */void StartTaskKEY1(void const * argument);
void StartTaskKEY2(void const * argument);void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) *//* GetIdleTaskMemory prototype (linked to static allocation support) */
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );/* USER CODE BEGIN GET_IDLE_TASK_MEMORY */
static StaticTask_t xIdleTaskTCBBuffer;
static StackType_t xIdleStack[configMINIMAL_STACK_SIZE];void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )
{*ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer;*ppxIdleTaskStackBuffer = &xIdleStack[0];*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;/* place for user code */
}
/* USER CODE END GET_IDLE_TASK_MEMORY *//*** @brief  FreeRTOS initialization* @param  None* @retval None*/
void MX_FREERTOS_Init(void) {/* USER CODE BEGIN Init *//* USER CODE END Init *//* USER CODE BEGIN RTOS_MUTEX *//* add mutexes, ... *//* USER CODE END RTOS_MUTEX *//* USER CODE BEGIN RTOS_SEMAPHORES *//* add semaphores, ... *//* USER CODE END RTOS_SEMAPHORES *//* USER CODE BEGIN RTOS_TIMERS *//* start timers, add new ones, ... *//* USER CODE END RTOS_TIMERS *//* USER CODE BEGIN RTOS_QUEUES *//* add queues, ... *//* USER CODE END RTOS_QUEUES *//* Create the thread(s) *//* definition and creation of TaskKEY1 */osThreadDef(TaskKEY1, StartTaskKEY1, osPriorityNormal, 0, 128);TaskKEY1Handle = osThreadCreate(osThread(TaskKEY1), NULL);/* definition and creation of TaskKEY2 */osThreadDef(TaskKEY2, StartTaskKEY2, osPriorityNormal, 0, 128);TaskKEY2Handle = osThreadCreate(osThread(TaskKEY2), NULL);/* USER CODE BEGIN RTOS_THREADS *//* add threads, ... *//* USER CODE END RTOS_THREADS */}/* USER CODE BEGIN Header_StartTaskKEY1 */
/*** @brief  Function implementing the TaskKEY1 thread.* @param  argument: Not used* @retval None*/
/* USER CODE END Header_StartTaskKEY1 */
void StartTaskKEY1(void const * argument)
{/* USER CODE BEGIN StartTaskKEY1 */BaseType_t mark = 0;/* Infinite loop */for(;;){if(HAL_GPIO_ReadPin(GPIOA ,GPIO_PIN_0) == GPIO_PIN_RESET){osDelay(20);if(HAL_GPIO_ReadPin(GPIOA ,GPIO_PIN_0) == GPIO_PIN_RESET){mark = xTaskNotifyGive( TaskKEY2Handle );if(mark == pdPASS)printf("任务通知模拟计数型信号量发送成功!\r\n");elseprintf("任务通知模拟计数型信号量发送失败!\r\n");}while(HAL_GPIO_ReadPin(GPIOA ,GPIO_PIN_0) == GPIO_PIN_RESET);}osDelay(10);}/* USER CODE END StartTaskKEY1 */
}/* USER CODE BEGIN Header_StartTaskKEY2 */
/**
* @brief Function implementing the TaskKEY2 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTaskKEY2 */
void StartTaskKEY2(void const * argument)
{/* USER CODE BEGIN StartTaskKEY2 */uint32_t flag = 0;/* Infinite loop */for(;;){if(HAL_GPIO_ReadPin(GPIOA ,GPIO_PIN_1) == GPIO_PIN_RESET){osDelay(20);if(HAL_GPIO_ReadPin(GPIOA ,GPIO_PIN_1) == GPIO_PIN_RESET){flag = ulTaskNotifyTake(pdFALSE ,0);if(flag != 0)printf("接收成功!任务的通知值为:%d\r\n",flag);elseprintf("接收失败!\r\n");}while(HAL_GPIO_ReadPin(GPIOA ,GPIO_PIN_1) == GPIO_PIN_RESET);}osDelay(10);}/* USER CODE END StartTaskKEY2 */
}/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application *//* USER CODE END Application */

5.3、模拟事件标志组

        两个任务( task1 和 task2),task1 检测按键,如果检测到 KEY1 和 KEY2 都按过, 则执行 task2 。

/* USER CODE BEGIN Header */
/********************************************************************************* File Name          : freertos.c* Description        : Code for freertos applications******************************************************************************* @attention** Copyright (c) 2024 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header *//* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD *//* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables *//* USER CODE END Variables */
osThreadId Task1Handle;
osThreadId Task2Handle;/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes *//* USER CODE END FunctionPrototypes */void StartTask1(void const * argument);
void StartTask2(void const * argument);void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) *//* GetIdleTaskMemory prototype (linked to static allocation support) */
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );/* USER CODE BEGIN GET_IDLE_TASK_MEMORY */
static StaticTask_t xIdleTaskTCBBuffer;
static StackType_t xIdleStack[configMINIMAL_STACK_SIZE];void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )
{*ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer;*ppxIdleTaskStackBuffer = &xIdleStack[0];*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;/* place for user code */
}
/* USER CODE END GET_IDLE_TASK_MEMORY *//*** @brief  FreeRTOS initialization* @param  None* @retval None*/
void MX_FREERTOS_Init(void) {/* USER CODE BEGIN Init *//* USER CODE END Init *//* USER CODE BEGIN RTOS_MUTEX *//* add mutexes, ... *//* USER CODE END RTOS_MUTEX *//* USER CODE BEGIN RTOS_SEMAPHORES *//* add semaphores, ... *//* USER CODE END RTOS_SEMAPHORES *//* USER CODE BEGIN RTOS_TIMERS *//* start timers, add new ones, ... *//* USER CODE END RTOS_TIMERS *//* USER CODE BEGIN RTOS_QUEUES *//* add queues, ... *//* USER CODE END RTOS_QUEUES *//* Create the thread(s) *//* definition and creation of Task1 */osThreadDef(Task1, StartTask1, osPriorityNormal, 0, 128);Task1Handle = osThreadCreate(osThread(Task1), NULL);/* definition and creation of Task2 */osThreadDef(Task2, StartTask2, osPriorityNormal, 0, 128);Task2Handle = osThreadCreate(osThread(Task2), NULL);/* USER CODE BEGIN RTOS_THREADS *//* add threads, ... *//* USER CODE END RTOS_THREADS */}/* USER CODE BEGIN Header_StartTask1 */
/*** @brief  Function implementing the Task1 thread.* @param  argument: Not used* @retval None*/
/* USER CODE END Header_StartTask1 */
void StartTask1(void const * argument)
{/* USER CODE BEGIN StartTask1 *//* Infinite loop */for(;;){if(HAL_GPIO_ReadPin(GPIOA ,GPIO_PIN_0) == GPIO_PIN_RESET){osDelay(20);if(HAL_GPIO_ReadPin(GPIOA ,GPIO_PIN_0) == GPIO_PIN_RESET){printf("bit23位置1\r\n");xTaskNotifyAndQuery(Task2Handle ,0x800000 ,eSetBits ,NULL);}while(HAL_GPIO_ReadPin(GPIOA ,GPIO_PIN_0) == GPIO_PIN_RESET);}if(HAL_GPIO_ReadPin(GPIOA ,GPIO_PIN_1) == GPIO_PIN_RESET){osDelay(20);if(HAL_GPIO_ReadPin(GPIOA ,GPIO_PIN_1) == GPIO_PIN_RESET){printf("bit1与bit0位置1\r\n");xTaskNotifyAndQuery(Task2Handle ,0x3 ,eSetBits ,NULL);		/*0011*/}while(HAL_GPIO_ReadPin(GPIOA ,GPIO_PIN_1) == GPIO_PIN_RESET);}osDelay(10);}/* USER CODE END StartTask1 */
}/* USER CODE BEGIN Header_StartTask2 */
/**
* @brief Function implementing the Task2 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTask2 */
void StartTask2(void const * argument)
{/* USER CODE BEGIN StartTask2 */uint32_t events = 0,result_bit = 0;/* Infinite loop */for(;;){xTaskNotifyWait(0 ,0xFFFFFFFF ,&events ,portMAX_DELAY);if(events & 0x800000)result_bit |= 0x800000;if(events & 0x3)result_bit |= 0x3;if(result_bit == (0x800000 | 0x3)){printf("请假成功,任务通知模拟事件标志组成功!\r\n");result_bit = 0;}osDelay(10);}/* USER CODE END StartTask2 */
}/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application *//* USER CODE END Application */

5.4、模拟邮箱

        邮箱是长度为1的队列

5.4.1、覆盖

/* USER CODE BEGIN Header */
/********************************************************************************* File Name          : freertos.c* Description        : Code for freertos applications******************************************************************************* @attention** Copyright (c) 2024 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header *//* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD *//* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables *//* USER CODE END Variables */
osThreadId TaskSendHandle;
osThreadId TaskReceiveHandle;/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes *//* USER CODE END FunctionPrototypes */void StartTaskSend(void const * argument);
void StartTaskReceive(void const * argument);void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) *//* GetIdleTaskMemory prototype (linked to static allocation support) */
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );/* USER CODE BEGIN GET_IDLE_TASK_MEMORY */
static StaticTask_t xIdleTaskTCBBuffer;
static StackType_t xIdleStack[configMINIMAL_STACK_SIZE];void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )
{*ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer;*ppxIdleTaskStackBuffer = &xIdleStack[0];*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;/* place for user code */
}
/* USER CODE END GET_IDLE_TASK_MEMORY *//*** @brief  FreeRTOS initialization* @param  None* @retval None*/
void MX_FREERTOS_Init(void) {/* USER CODE BEGIN Init *//* USER CODE END Init *//* USER CODE BEGIN RTOS_MUTEX *//* add mutexes, ... *//* USER CODE END RTOS_MUTEX *//* USER CODE BEGIN RTOS_SEMAPHORES *//* add semaphores, ... *//* USER CODE END RTOS_SEMAPHORES *//* USER CODE BEGIN RTOS_TIMERS *//* start timers, add new ones, ... *//* USER CODE END RTOS_TIMERS *//* USER CODE BEGIN RTOS_QUEUES *//* add queues, ... *//* USER CODE END RTOS_QUEUES *//* Create the thread(s) *//* definition and creation of TaskSend */osThreadDef(TaskSend, StartTaskSend, osPriorityNormal, 0, 128);TaskSendHandle = osThreadCreate(osThread(TaskSend), NULL);/* definition and creation of TaskReceive */osThreadDef(TaskReceive, StartTaskReceive, osPriorityNormal, 0, 128);TaskReceiveHandle = osThreadCreate(osThread(TaskReceive), NULL);/* USER CODE BEGIN RTOS_THREADS *//* add threads, ... *//* USER CODE END RTOS_THREADS */}/* USER CODE BEGIN Header_StartTaskSend */
/*** @brief  Function implementing the TaskSend thread.* @param  argument: Not used* @retval None*/
/* USER CODE END Header_StartTaskSend */
void StartTaskSend(void const * argument)
{/* USER CODE BEGIN StartTaskSend */static uint32_t cnt = 0;/* Infinite loop */for(;;){if(HAL_GPIO_ReadPin(GPIOA ,GPIO_PIN_0) == GPIO_PIN_RESET){osDelay(20);if(HAL_GPIO_ReadPin(GPIOA ,GPIO_PIN_0) == GPIO_PIN_RESET){if(cnt == 0){xTaskNotify(TaskReceiveHandle ,1 ,eSetValueWithOverwrite);    /*覆盖*/cnt++;printf("任务通知模拟邮箱(长度为1的队列)写入值:1\r\n");}else{xTaskNotify(TaskReceiveHandle ,5 ,eSetValueWithOverwrite);printf("任务通知模拟邮箱(长度为1的队列)写入值:5\r\n");cnt = 0;}}while(HAL_GPIO_ReadPin(GPIOA ,GPIO_PIN_0) == GPIO_PIN_RESET);}osDelay(10);}/* USER CODE END StartTaskSend */
}/* USER CODE BEGIN Header_StartTaskReceive */
/**
* @brief Function implementing the TaskReceive thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTaskReceive */
void StartTaskReceive(void const * argument)
{/* USER CODE BEGIN StartTaskReceive */uint32_t notify_queue = 0;/* Infinite loop */for(;;){if(HAL_GPIO_ReadPin(GPIOA ,GPIO_PIN_1) == GPIO_PIN_RESET){osDelay(20);if(HAL_GPIO_ReadPin(GPIOA ,GPIO_PIN_1) == GPIO_PIN_RESET){xTaskNotifyWait(0 ,0xFFFFFF ,&notify_queue ,portMAX_DELAY);printf("任务通知模拟邮箱接收值为:%d\r\n",notify_queue);}while(HAL_GPIO_ReadPin(GPIOA ,GPIO_PIN_1) == GPIO_PIN_RESET);}osDelay(10);}/* USER CODE END StartTaskReceive */
}/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application *//* USER CODE END Application */

结果:

 

5.4.2、不覆盖

/* USER CODE BEGIN Header */
/********************************************************************************* File Name          : freertos.c* Description        : Code for freertos applications******************************************************************************* @attention** Copyright (c) 2024 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header *//* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD *//* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables *//* USER CODE END Variables */
osThreadId TaskSendHandle;
osThreadId TaskReceiveHandle;/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes *//* USER CODE END FunctionPrototypes */void StartTaskSend(void const * argument);
void StartTaskReceive(void const * argument);void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) *//* GetIdleTaskMemory prototype (linked to static allocation support) */
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );/* USER CODE BEGIN GET_IDLE_TASK_MEMORY */
static StaticTask_t xIdleTaskTCBBuffer;
static StackType_t xIdleStack[configMINIMAL_STACK_SIZE];void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )
{*ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer;*ppxIdleTaskStackBuffer = &xIdleStack[0];*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;/* place for user code */
}
/* USER CODE END GET_IDLE_TASK_MEMORY *//*** @brief  FreeRTOS initialization* @param  None* @retval None*/
void MX_FREERTOS_Init(void) {/* USER CODE BEGIN Init *//* USER CODE END Init *//* USER CODE BEGIN RTOS_MUTEX *//* add mutexes, ... *//* USER CODE END RTOS_MUTEX *//* USER CODE BEGIN RTOS_SEMAPHORES *//* add semaphores, ... *//* USER CODE END RTOS_SEMAPHORES *//* USER CODE BEGIN RTOS_TIMERS *//* start timers, add new ones, ... *//* USER CODE END RTOS_TIMERS *//* USER CODE BEGIN RTOS_QUEUES *//* add queues, ... *//* USER CODE END RTOS_QUEUES *//* Create the thread(s) *//* definition and creation of TaskSend */osThreadDef(TaskSend, StartTaskSend, osPriorityNormal, 0, 128);TaskSendHandle = osThreadCreate(osThread(TaskSend), NULL);/* definition and creation of TaskReceive */osThreadDef(TaskReceive, StartTaskReceive, osPriorityNormal, 0, 128);TaskReceiveHandle = osThreadCreate(osThread(TaskReceive), NULL);/* USER CODE BEGIN RTOS_THREADS *//* add threads, ... *//* USER CODE END RTOS_THREADS */}/* USER CODE BEGIN Header_StartTaskSend */
/*** @brief  Function implementing the TaskSend thread.* @param  argument: Not used* @retval None*/
/* USER CODE END Header_StartTaskSend */
void StartTaskSend(void const * argument)
{/* USER CODE BEGIN StartTaskSend */static uint32_t cnt = 0;/* Infinite loop */for(;;){if(HAL_GPIO_ReadPin(GPIOA ,GPIO_PIN_0) == GPIO_PIN_RESET){osDelay(20);if(HAL_GPIO_ReadPin(GPIOA ,GPIO_PIN_0) == GPIO_PIN_RESET){if(cnt == 0){xTaskNotify(TaskReceiveHandle ,1 ,eSetValueWithoutOverwrite);		/*不覆盖*/cnt++;printf("任务通知模拟邮箱(长度为1的队列)写入值:1\r\n");}else{xTaskNotify(TaskReceiveHandle ,5 ,eSetValueWithoutOverwrite);printf("任务通知模拟邮箱(长度为1的队列)写入值:5\r\n");cnt = 0;}}while(HAL_GPIO_ReadPin(GPIOA ,GPIO_PIN_0) == GPIO_PIN_RESET);}osDelay(10);}/* USER CODE END StartTaskSend */
}/* USER CODE BEGIN Header_StartTaskReceive */
/**
* @brief Function implementing the TaskReceive thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTaskReceive */
void StartTaskReceive(void const * argument)
{/* USER CODE BEGIN StartTaskReceive */uint32_t notify_queue = 0;/* Infinite loop */for(;;){if(HAL_GPIO_ReadPin(GPIOA ,GPIO_PIN_1) == GPIO_PIN_RESET){osDelay(20);if(HAL_GPIO_ReadPin(GPIOA ,GPIO_PIN_1) == GPIO_PIN_RESET){xTaskNotifyWait(0 ,0xFFFFFF ,&notify_queue ,portMAX_DELAY);printf("任务通知模拟邮箱接收值为:%d\r\n",notify_queue);}while(HAL_GPIO_ReadPin(GPIOA ,GPIO_PIN_1) == GPIO_PIN_RESET);}osDelay(10);}/* USER CODE END StartTaskReceive */
}/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application *//* USER CODE END Application */

结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/335908.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

图解Kubernetes的服务(Service)

pod 准备: 不要直接使用和管理Pods: 当使用ReplicaSet水平扩展scale时,Pods可能被terminated当使用Deployment时,去更新Docker Image Version,旧Pods会被terminated,然后创建新Pods 0 啥是服务&#xf…

pyqt调用UI和开启子进程

UI制作 qrc 注意调用UI前把样式表里绑定的资源(qrc)转换成py导入进去 xxx.qrc转xxx.py 两种方法 1命令 pyrcc5 -o icons_rc.py icons.qrc 2外部工具pyrcc 实参 -o $FileNameWithoutExtension$.py $FileNameWithoutExtension$.qrcsdz.qrc→→sdaz.py 在代码里写 import…

Python 安卓开发:Kivy、BeeWare、Flet、Flutter

kivy:https://github.com/kivy python-for-android :https://python-for-android.readthedocs.io/en/latest/ BeeWare:https://docs.beeware.org/en/latest/ Flet:https://github.com/flet-dev/flet 把 PySide6 移植到安卓上去&a…

PostgreSQL ZIP版安装完全手册

前言 ZIP免安装版下载地址:社区 DL 页面 (enterprisedb.com) 选择所需的版本下载即可。 安装 将下载的zip安装包(我这里下载的是postgresql-15.5-1-windows-x64-binaries.zip)解压至D盘根路径下,解压后路径:D:/pgsq…

[Markdown] Markdown常用快捷键分类汇总

文章目录 Markdown1、标题2、列表3、强调4、链接和图片5、代码和公式6、表格和任务列表7、引用8、分割线9、脚注10、目录11、注释12、定义 Markdown Markdown是一种轻量级的标记语言,可以让你用简单的语法来编写格式丰富的文档。 Markdown编辑器是一种专门用于编辑…

Java IO学习和总结(超详细)

一、理解 I/O 是输入和输出的简写,指的是数据在计算机内部和外部设备之间的流动。简单来说,当你从键盘输入数据、从鼠标选择操作,或者在屏幕上看到图像,这些都是 I/O 操作。它就像是计算机与外部世界沟通的桥梁,没有 I…

springboot虹软人脸识别集成

准备工作 虹软开放平台中创建一个新的应用 虹软开发平台【点我跳转】 开始上代码 基本配置 将下载的jar包放到src同级目录下 <!-- 虹软--><dependency><groupId>com.arcsoft.face</groupId><artifactId>arcsoft-sdk-face</artifactI…

使用numpy处理图片——镜像翻转和旋转

在《使用numpy处理图片——基础操作》一文中&#xff0c;我们介绍了如何使用numpy修改图片的透明度。本文我们将介绍镜像翻转和旋转。 镜像翻转 上下翻转 from PIL import Image import numpy as np img Image.open(example.png) data np.array(img)# axis0 is vertical, a…

使用Nonebot编写QQ机器人

使用 NoneBot 这个工具&#xff0c;来编写 QQ 机器人。 安装基础软件 一、安装 NoneBot 库 直接使用 pip 安装即可 pip install nonebot二、安装酷Q 软件和 HTTP API 插件 酷Q 软件可以直接到官网下载&#xff0c;https://cqp.cc/b/news&#xff0c;或者可以到网盘下载&am…

【Databand】日期时间函数

文章目录 获取当前日期和时间日期格式化函数日期加减运算日期时间和时间戳转化日期时间各部分拆分日期时间加减运算实际应用扩展总结 获取当前日期和时间 Databend 使用 UTC 作为默认时区&#xff0c;并允许您将时区更改为当前地理位置。 -- 查看时区 select timezone(); ---…

C2-3.3.2 机器学习/深度学习——数据增强

C2-3.3.2 数据增强 参考链接 1、为什么要使用数据增强&#xff1f; ※总结最经典的一句话&#xff1a;希望模型学习的更稳健 当数据量不足时候&#xff1a; 人工智能三要素之一为数据&#xff0c;但获取大量数据成本高&#xff0c;但数据又是提高模型精度和泛化效果的重要因…

YOLOv5改进 | 2023主干篇 | EfficientViT替换Backbone(高效的视觉变换网络)

一、本文介绍 本文给大家带来的改进机制是EfficientViT(高效的视觉变换网络),EfficientViT的核心是一种轻量级的多尺度线性注意力模块,能够在只使用硬件高效操作的情况下实现全局感受野和多尺度学习。本文带来是2023年的最新版本的EfficientViT网络结构,论文题目是Effici…