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.mzph.cn/news/609817.shtml

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

相关文章

解析游戏开发中的ECS设计模式:实体、组件、系统的完美协同

ECS(Entity-Component-System)是一种设计模式,通常用于构建和管理具有大量实体和复杂交互的系统,尤其在游戏开发中得到广泛应用。这个模式的核心思想是将系统中的组件、实体和系统进行分离,以提高代码的可维护性、可扩…

鸿蒙原生应用/元服务开发-长时任务

概述 功能介绍 应用退至后台后,对于在后台需要长时间运行用户可感知的任务,例如播放音乐、导航等。为防止应用进程被挂起,导致对应功能异常,可以申请长时任务,使应用在后台长时间运行。申请长时任务后,系统…

Linux调试------gdb的使用

目录 前言 一、gdb打开可执行程序 二、查看代码与操作断点 1.l 查看代码 2.b 打断点 3.info b 查看断点信息 4.d 删除断点 5.disable 和 enable 断点的禁用与启用 三、调试 1.r 启动调试 2. n 逐过程 3. s 逐语句 4.display显示变量 5.undisplay 取消显…

e2studio开发磁力计LIS2MDL(1)----轮询获取磁力计数据

e2studio开发磁力计LIS2MDL.1--轮询获取磁力计数据 概述视频教学样品申请源码下载速率新建工程工程模板保存工程路径芯片配置工程模板选择时钟设置UART配置UART属性配置设置e2studio堆栈e2studio的重定向printf设置R_SCI_UART_Open()函数原型回调函数user_uart_callback ()prin…

根据MySql的表名,自动生成实体类,模仿ORM框架

ORM框架可以根据数据库的表自动生成实体类,以及相应CRUD操作 本文是一个自动生成实体类的工具,用于生成Mysql表对应的实体类。 新建Winform窗体应用程序AutoGenerateForm,框架(.net framework 4.5), 添加对System.Configuration的…

高效构建Java应用:Maven入门和进阶(三)

高效构建Java应用:Maven入门和进阶(三) 三. Maven的核心功能和构建管理3.1 依赖管理和配置3.2 依赖传递和冲突3.3 依赖导入失败场景和解决方案3.4 扩展构建管理和插件配置 三. Maven的核心功能和构建管理 3.1 依赖管理和配置 Maven 依赖管理…

CentOS安装Docker(超详细)

CentOS安装Docker 1 知识小课堂2 CentOS安装Docker2.1 1.1.卸载(可选)1.2.安装docker1.3.启动docker1.4.配置镜像加速 3 CentOS安装DockerCompose3.1.下载3.2.修改文件权限3.3.Base自动补全命令: 4 Docker镜像仓库4.1.简化版镜像仓库4.2.带有…

数据分析求职-知识脑图

今天和大家聊聊数据分析求职常见面试题,这是这个系列的第一篇文章,但是我不想开始就直接罗列题目,因为这样的文章实在太多了,同学们的兴趣程度肯定一般。所以,我想先和大家聊聊在准备面试题时候通常遇到的困扰&#xf…

GFP-CERTIFIED®FLUOFORTE®钙离子检测试剂盒

Enzo Life Sciences的GFP-CERTIFIED FLUOFORTE Calcium assay kit提供了一种荧光分析方法,用于检测广泛生物靶标的细胞内钙动员情况。相对于其他商业化的染料,GFP-CERTIFIED FLUOFORTE染料是最亮和最灵敏的荧光钙指示剂。该试剂盒为贴壁和非贴壁细胞系提…

生物信息学中的可重复性研究

科学就其本质而言,是累积渐进的。无论你是使用基于网络的还是基于命令行的工具,在进行研究时都应保证该研究可被其他研究人员重复。这有利于你的工作的累积与进展。在生物信息学领域,这意味着如下内容。 工作流应该有据可查。这可能包括在电脑…

linux 压力测试 AB ApacheBench

ab的简介 ab是apachebench命令的缩写。 ab是apache自带的压力测试工具。ab非常实用,它不仅可以对apache服务器进行网站访问压力测试,也可以对或其它类型的服务器进行压力测试。比如nginx、tomcat、IIS等 ab的原理 ab的原理:ab命令会创建多…

ros架构

ROS(Robot Operating System)是一个灵活的、分布式的系统架构,用于构建机器人软件。它由一系列工具、库和约定组成,提供了一套通用的功能和通信机制,以支持机器人系统的开发、部署和运行。 ROS架构主要包括以下几个核心…

C++面试宝典第17题:找规律填数

题目 仔细观察下面的数字序列,找到规律,并填写空白处的数字。 (1)1, 2, 4, 7, 11, 16, __ (2)-1, 2, 7, 28, __, 126 (3)6, 10, 18, 32, 57, __ (4)19, 6, 1, 2, 11, __ (5)2, 3, 5, 7, 11, __ (6)1, 8, 9, 4, __, 1/6 (7)1, 2, 3, 7, 16, __, 321 (8)1, 2, …

linux异常情况,排查处理中

登录客户环境后,发现一个奇怪情况如下图,之前也遇到过,直接fuser -ck /backup操作的话,主机将会重启,因数据库运行中,等待停机维护时间,同时也在想办法不重启的情况下解决该问题 [rootdb ~]# f…

git撤销提交到本地的commit

有些时候,当我们提交代码到本地后,突然发现因为某些原因需要撤销提交本地的代码。 就比如我,因为代码写错了分支,已经提交到本地了,而我需要取消,并且还要把代码搞得另外的分支上。 提交前: …

SpiderFlow爬虫平台 前台RCE漏洞复现(CVE-2024-0195)

0x01 产品简介 SpiderFlow是新一代爬虫平台,以图形化方式定义爬虫流程,以流程图的方式定义爬虫,不写代码即可完成爬虫,是一个高度灵活可配置的爬虫平台。 0x02 漏洞概述 SpiderFlow爬虫平台src/main/java/org/spiderflow/controller/FunctionController.java文件的Functi…

【elfboard linux开发板】11. 版本管理和修改设备树流程(点亮LED)

1. 版本管理 1.1 初始化git仓库 git init 生成一个.git 目录 git config --global user.name 用户名 git config --global user.email 邮箱 1.2 查看.gitignore vim .gitignore 1.3 添加删除到缓存区 git status 查看状态 git add 文件名 git rm 文件名 1.4 提交当前记录 …

【AI视野·今日Robot 机器人论文速览 第七十期】Thu, 4 Jan 2024

AI视野今日CS.Robotics 机器人学论文速览 Thu, 4 Jan 2024 Totally 17 papers 👉上期速览✈更多精彩请移步主页 Daily Robotics Papers Many-Objective-Optimized Semi-Automated Robotic Disassembly Sequences Authors Takuya Kiyokawa, Kensuke Harada, Weiwei …

canvas绘制路径之 beginPath() 和 closePath()

查看专栏目录 canvas示例教程100专栏,提供canvas的基础知识,高级动画,相关应用扩展等信息。canvas作为html的一部分,是图像图标地图可视化的一个重要的基础,学好了canvas,在其他的一些应用上将会起到非常重…

《Shader开发实战》-笔记

一、初识游戏图形 1、什么是渲染? 渲染实际上就是创建图像的过程,在渲染过程中创建的图像被称为渲染或者帧,该图像(帧)以每秒多次在计算机屏幕上进行呈现,即帧率。 负责渲染图像(帧&#xff09…