[FreeRTOS][STM32]06 Use of FreeRTOS-Dynamic creation of multi-tasking FreeRTOS startup process

For the main process, please refer to [FreeRTOS] [STM32] 06 Use of FreeRTOS-Dynamic Creation of Single Tasks

1. Define task handle

static TaskHandle_t AppTaskCreate_Handle = NULL;

2. Hardware initialization

slightly

3. Create specific functional task functions

See Defining Task Functions

4. Use xTaskCreate to create tasks

 xReturn = xTaskCreate((TaskFunction_t)AppTaskCreate, /* task entry function */
 (const char* )"AppTaskCreate",/* task name */
(uint16_t )512, /* task stack size */
 (void* )NULL,/* Task entry function parameters */
(UBaseType_t )1, /* Task priority */
(TaskHandle_t* ) & amp;AppTaskCreate_Handle);/* Task control block pointer */

5. Use vTaskStartScheduler(); /* Start the task and enable scheduling */

Main code list

Header file
 /*
  ************************************************* *************************
 * Included header files
 ************************************************* *************************
 */
 /* FreeRTOS header files */
 #include "FreeRTOS.h"
 #include "task.h"
 /* Hardware bsp header file */
 #include "bsp_usart.h"
 ...
Declarations and Definitions
 /****************************** Task handle************************ *************/
 /*
 * The task handle is a pointer used to point to a task. When the task is created, it has a task handle.
 * In the future, if we want to operate this task, we need to use this task handle. If it is its own task operating itself, then
 * This handle can be NULL.
 */
 /* Create task handle */
 static TaskHandle_t AppTaskCreate_Handle = NULL;
 /* LED1 task handle */
 static TaskHandle_t LED1_Task_Handle = NULL;
 /* LED2 task handle */
 static TaskHandle_t LED2_Task_Handle = NULL;
 /****************************** Kernel object handle************************ *************/
 /*
 * Semaphores, message queues, event flag groups, and software timers are all kernel objects. If you want to use these kernel
 * The object must be created first. After successful creation, a corresponding handle will be returned. In fact, it is a pointer. I will follow up
 * We can operate these kernel objects through this handle.
 *
 *
 To put it bluntly, the kernel object is a global data structure. Through these data structures, we can achieve communication between tasks.
 * Various functions such as event synchronization between tasks. As for the implementation of these functions, we call the functions of these kernel objects
 * to complete
 *
 */
 
 
 /**************************** Global variable declaration************************ *************/
 /*
 * When we write an application, we may need to use some global variables.
 */
 
 
 /*
 *************************************************** *************************
 * Function declaration
 *************************************************** *************************
 */
 static void AppTaskCreate(void);/* used to create tasks */
 
 static void LED1_Task(void* pvParameters);/* LED1_Task task implementation */
 static void LED2_Task(void* pvParameters);/* LED2_Task task implementation */
 
 static void BSP_Init(void);/* Used to initialize onboard related resources */
main function
 /************************************************ *********************
 * @brief main function
 * @param none
 * @retval None
 * @note Step 1: Development board hardware initialization
 Step 2: Create APP application task
 Step 3: Start FreeRTOS and start multi-task scheduling
 *************************************************** ******************/
 int main(void)
 {<!-- -->
BaseType_t xReturn = pdPASS;/* Define a creation information return value to indicate whether the creation is successful. The default is pdPASS */
 
 /* Hardware initialization */
 BSP_Init();

/* Create AppTaskCreate task */
xReturn = xTaskCreate((TaskFunction_t)AppTaskCreate, /* task entry function */
(const char* )"AppTaskCreate",/* task name */
(uint16_t )512, /* task stack size */
(void* )NULL,/* Task entry function parameters */
(UBaseType_t )1, /* Task priority */
(TaskHandle_t* ) & amp;AppTaskCreate_Handle);/* Task control block pointer, task handle */

/* Start task scheduling */
if (pdPASS == xReturn)
vTaskStartScheduler(); /* Start the task and enable scheduling */
else
return -1;
 
while (1); /* Normally it will not be executed here */
 }
Task entry function
 /********************************************** *************************
 * @ function name: AppTaskCreate
 * @ Function description: In order to facilitate management, all task creation functions are placed in this function.
 * @parameter: none
 * @Return value: None
 
*************************************************** *******************/
 static void AppTaskCreate(void)
 {<!-- -->
 BaseType_t xReturn = pdPASS;/* Define a creation information return value, the default is pdPASS */
 
 taskENTER_CRITICAL(); //Enter the critical section
 
 /* Create LED_Task task */
 xReturn = xTaskCreate((TaskFunction_t)LED1_Task, /* Task entry function */
(const char* )"LED1_Task",/* task name */
(uint16_t )512, /* Task stack size */
(void* )NULL, /* task entry function parameters */
(UBaseType_t )2, /* Task priority */
(TaskHandle_t* ) & amp;LED1_Task_Handle);/* Task control block pointer */
 if (pdPASS == xReturn)
printf("Creation of LED1_Task task successful!\r\
");
 
 /* Create LED_Task task */
 xReturn = xTaskCreate((TaskFunction_t)LED2_Task, /* Task entry function */
(const char* )"LED2_Task",/* task name */
(uint16_t )512, /* Task stack size */
(void* )NULL, /* task entry function parameters */
(UBaseType_t )3, /* Priority of task */
(TaskHandle_t* ) & amp;LED2_Task_Handle);/* Task control block pointer */
 if (pdPASS == xReturn)
printf("Creation of LED2_Task task successful!\r\
");
 
 vTaskDelete(AppTaskCreate_Handle); //Delete the AppTaskCreate task
 
 taskEXIT_CRITICAL(); //Exit the critical section
 }

XX, start!

The startup of an RTOS project follows these two processes.
The first

/* Hardware initialization */
Hardware initialization. The hardware initialization step still belongs to the category of bare metal.
/* RTOS system initialization */
RTOS system initialization
/* Create task 1, but task 1 will not be executed because the scheduler has not been started */
Create various tasks. All the tasks to be used have been created here, but they will not be scheduled yet because the RTOS scheduler has not been turned on at this time.
/* Create task 2, but task 2 will not be executed because the scheduler has not been started */
Start the RTOS scheduler and start task scheduling. At this time, the scheduler selects a task with the highest priority from the tasks just created to start running.
/* Start RTOS and start scheduling */

The second kind

/* Hardware initialization */

/* RTOS system initialization */

/* Create a task */
Create a start task. Then create various application tasks in this initial task
/* Start RTOS and start scheduling */
Start the RTOS scheduler and start task scheduling. At this time, the scheduler will execute the initial task just created, which is the task of creating the task.

Create tasks. After each task is created, it will enter the ready state, and the system will perform scheduling. If the priority of the newly created task is higher than the priority of the initial task, the newly created task will be executed. When the new task blocks Return to the point where the initial task was interrupted and continue execution. Otherwise, continue to create new tasks until all tasks are created.

After various application tasks are created, the initial task closes itself and the mission is completed.

FreeRTOS startup process

1. Power on Reset_Handler

We know that after the microcontroller is powered on, after getting the top pointer of the stack when starting from Flash, Reset_Handler is executed. At the end of the reset function, the C library function __main is called. The main job of the __main function is to initialize the heap and stack of the system, and finally call the main function in C to enter the world of C.

 Reset_Handler PROC
 EXPORT Reset_Handler[WEAK]
 IMPORT __main
 IMPORT SystemInit
 LDR R0, =SystemInit
 BLX-R0
 LDR R0, =__main
 BXR0
 ENDP

2.xTaskCreate creates a task

After reaching the main function, the xTaskCreate() function creates a task, and FreeRTOS will automatically help us with initialization tasks within the create task function, such as initializing the heap memory.

3. Turn on task scheduling

After the task is created, idle task and timer task are not implemented. These are all implemented in the opening scheduling function vTaskStartScheduler().

Why idle tasks? Because once FreeRTOS is started, it must ensure that there is a task in the running state (Runing) in the system at all times, and idle tasks cannot be suspended or deleted. The priority of idle tasks is the lowest, so that other tasks in the system can Tasks can seize the CPU usage rights of idle tasks at any time. These are all necessary things for the system and are automatically implemented by FreeRTOS.

Dynamically create idle tasks

The priority and stack size of the idle task are defined by the user in FreeRTOSConfig.h. The task handle of the idle task is stored in the static variable xIdleTaskHandle. The user can call the API function xTaskGetIdleTaskHandle() to obtain the idle task handle. FreeRTOS does this automatically.

Create timer task

If the macro definition configUSE_TIMERS is enabled in FreeRTOSConfig.h, FreeRTOS will complete it automatically.