Source: Technology makes dreams greater
Author: Li Xiaoyao
FreeRTOS is a customizable, preemptive multitasking kernel that is very useful and has no limit on the number of tasks. It has been analyzed many times before, simply put, FreeRTOS real-time systems can create multiple independent tasks that do not interfere with each other. For this to be achieved, each task should have its own stack space. When a task switches, the execution environment is saved to that task’s stack, so when we switch back to that task after some time, it can accurately restore the state from when it last worked.
Some tutorials have been summarized before, refer to Selected Summary | FreeRTOS from Basics to Advanced Series
FreeRTOS provides all the features required for real-time operating systems, including resource management, synchronization, and task communication. This article mainly discusses task communication, as tasks do not run together after creation, but are called in order of priority.
Wheels have also been made, many of which we can directly use. The ARM Cortex microcontroller software interface standard is CMSIS, which is a vendor-independent hardware abstraction layer. CMSIS-RTOS is a generic API for real-time operating systems, simply put, it wraps operating systems like FreeRTOS and Rtthread again to form a generic API function, aimed at making porting easier. Here we choose the interface CMSIS_V2, and the differences between CMSIS_V1 and CMSIS_V2 options in STM32CubeIDE have been discussed before.

First, create two tasks myTask01 and myTask02, as shown in the figure below:
Create two events myEvent01, myEvent02, as shown in the figure below::
Pull down to configure the following information; here we default to configuring counting semaphores, allocation methods, control block names, and other configuration information.
After generating the code, the tasks and events are as follows:
/* Definitions for myTask01 */
osThreadId_t myTask01Handle;
const osThreadAttr_t myTask01_attributes = {
.name = "myTask01",
.stack_size = 128 * 4,
.priority = (osPriority_t) osPriorityLow,
};
...
/* Definitions for myEvent02 */
osEventFlagsId_t myEvent02Handle;
const osEventFlagsAttr_t myEvent02_attributes = {
.name = "myEvent02"
};
This is the handle for creating tasks, as shown in the code below:
/* creation of myTask01 */
myTask01Handle = osThreadNew(StartTask01, NULL, &myTask01_attributes);
/* creation of myTask02 */
myTask02Handle = osThreadNew(StartTask02, NULL, &myTask02_attributes);
We rewrite the code to implement task2 sending signals to task, achieving simple task communication, as shown in the code below.
/* USER CODE END Header_StartTask01 */
void StartTask01(void *argument)
{
/* USER CODE BEGIN StartTask01 */
/* Infinite loop */
osStatus_t os_Status;
while(1)
{
os_Status = osEventFlagsWait(myTask02Handle, /* Event flag group ID */
COMM2_EVENT, /* Wait for event flag 0 and event flag 1 */
osFlagsWaitAny, /* Logical OR */
osWaitForever /* Wait indefinitely */
);
if(os_Status == COMM1_EVENT)
{
printf("startTask02 is running.\r\n");
}
}
/* USER CODE END StartTask01 */
}
/* USER CODE BEGIN Header_StartTask02 */
The specific implementation and definition of the osEventFlagsWait function are shown in the figure below:

osEventFlagsSet is used to send a signal to a task’s handle, implemented as follows:
/* USER CODE END Header_StartTask02 */
void StartTask02(void *argument)
{
/* USER CODE BEGIN StartTask02 */
/* Infinite loop */
for(;;)
{
osEventFlagsSet(myEvent01Handle, COMM1_EVENT);
osDelay(1);
}
/* USER CODE END StartTask02 */
}
Finally, multiple tasks can communicate with each other.
‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧ END ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧
Follow my public account, reply "join group" to join the technical exchange group according to the rules.
Click "Read the original text" to see more shares. Welcome to share, collect, like, and see.