FreeRTOS task creation and deletion | FreeRTOS three

Table of contents

1. Functions related to FreeRTOS task creation and deletion

1.1. API functions to create/delete tasks

1.1.1. Dynamically create tasks

1.1.2. Static creation of tasks

1.1.3. Delete tasks

2. FreeRTOS task creation and deletion (dynamic method)

2.1. Example

3. FreeRTOS task creation and deletion (static method)

4. Critical Section and Task Scheduler

4.1. What is the critical section?

4.2. Use of critical sections

4.3. Task scheduler


1. Functions related to FreeRTOS task creation and deletion

1.1. API functions to create/delete tasks

1.1.1. Dynamically create tasks

The creation and deletion of tasks is essentially calling FreeRTOS API functions.

Function name: xTaskCreate (xxx parameter), function: dynamically create tasks;

Dynamically created task analysis:

1) The memory required for the task control block of the task and the stack space of the task are allocated by FreeRTOS from the heap managed by FreeRTOS.

2) The function has a return value. When paPASS is returned, it means that the task is created successfully. When it returns

errCOULD_ NOT_ ALLOCATE REQUIRED_ MEMORY indicates that the task creation failed

3) There are only three steps to achieve dynamic creation of task processes:

        1. Configure the macro configSUPPORT_DYNAMIC_ALLOCATION to 1;

        2. Define function entry parameters;

        3. Write the task function.

The task created by this function will immediately enter the ready state and be scheduled to run by the task scheduler. It implements three steps internally:

        1. Apply for stack memory and task control block memory;

        2. Assign values ​​to members of the TCB structure;

        3. Add new tasks to the ready list.

Dynamic task creation function prototype:

    BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
                            const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
                            const configSTACK_DEPTH_TYPE usStackDepth,
                            void * const pvParameters,
                            UBaseType_t uxPriority,
                            TaskHandle_t * const pxCreatedTask )

Parameter explanation:

pxTaskCode, meaning: pointer to task function

pcName, meaning: task name

usStackDepth, meaning: stack size

pvParameters, meaning: parameters passed to the task

uxPriority, meaning: task priority

pxCreatedTask, meaning: task handle

1.1.2. Static creation of tasks

Function name: xTaskCreateStatic (xxx parameter), function: statically create tasks

Static creation task analysis:

1) The memory required for the task control block of the task and the stack space of the task needs to be allocated and provided by the user.

2) The function has a return value. If the return value is NULL, it means that the user did not provide the corresponding memory and the task creation failed. If it is any other value, it means the task handle and the task was created successfully.

3) Five steps to statically create a task process:

        1. The macro configSUPPORT_ STATIC_ ALLOCATION needs to be configured as 1
        2. Define the task stack and TCB of the idle task & timer task
        3. Implement two interface functions: vApplicationGetTimerTaskMemory(), vApplicationGetldleTaskMemory()

        4. Define function entry parameters

        5. Write task function

The task created by this function will immediately enter the ready state and be scheduled to run by the task scheduler. The internal implementation is:

        1. Assign values ​​to members of the TCB structure (because the memory has been set in advance, there is no need to apply for memory)

        2. Add new tasks to the ready list

Static task creation prototype:

TaskHandle_t xTaskCreateStatic
(
    TaskFunction_t pxTaskCode,          /*指向任务函数的指针*/
    const char * const pcName,          /*任务函数名*/
    const uint32_t ulStackDepth,        /*任务堆栈大小注意字为单位*/ 
    void * const pvParameters,          /*传递的任务函数参效
    UBaseType_t uxPriority,             /*任务优先级*/
    StackType_t * const puxStackBuffer, /*任务堆栈,-般为数组,由“配*/
    StaticTask_t * const pxTaskBuffer   /*任务控制块指针,由用户分配
);

1.1.3. Delete tasks

Function name: vTaskDelete(TaskHandle_t xTaskToDelete), function: delete tasks

Formal parameter: xTaskToDelete, description: task handle of the task to be deleted

Delete task function analysis:

1) The deleted task will be removed from the ready task list, blocked task list, pending task list and event list

2) When the parameter passed in is NULL, the task deletes the task itself (the task is currently running)

3) The idle task will be responsible for releasing the memory allocated by the system in the deleted task. However, the memory requested by the user before the task is deleted needs to be released in advance before the task is deleted, otherwise it will cause memory leaks.

4) Only two steps are needed to use:

        1. To use the delete task function, the macro INCLUDE_ _vTaskDelete needs to be configured as 1.
        2. The entry parameter enters the task handle to be deleted (NULL represents the deletion itself)

5) Internal implementation process of task deletion:
        1. Obtain the control block of the task to be deleted, and determine which task needs to be deleted through the incoming task handle. NULL means deleting itself.
        2. The task to be deleted is removed from the list and the The task is removed from the list, including: ready, blocked, suspended, event and other lists.
        3. To delete the task itself, it needs to be added to the waiting list for deletion first. The memory release will be executed in the idle task. Determine the task that needs to be deleted and delete it. Other tasks, release memory, number of tasks - 1
        4. Update the blocking time of the next task, update the blocking timeout of the next task, in case the deleted task is the next blocking timeout task

2. FreeRTOS task creation and deletion (dynamic method)

2.1. Example

illustrate:

1) The following example creates a start task, creates task 1 and task 2 in the start task, and deletes itself after the two tasks are created.

2) Task 1 realizes the flashing of led0 every 100ms, and task 1 realizes the flashing of led1 every 100ms.

3) When transplanting and testing, pay attention to whether the corresponding configurations are consistent. Directly copying the code and testing will basically result in an error.

#include "stm32f10x.h"
#include "stdio.h"
#include "string.h"
 
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "queue.h"
#include "timers.h"
#include "event_groups.h"
 
#include "led.h"
#include "usart.h"
 
 
 
//初始任务 用于创建其他任务,创建后自动删除
#define INIT_TASK_PRIO 1              /* 任务优先级   */
#define INIT_STK_SIZE  256            /* 任务堆栈大小 */
TaskHandle_t INITTask_Handler;        /* 任务句柄     */
void init_task(void *pvParameters);   /* 任务函数     */
 
//LED0灯闪烁 
#define LED0_TASK_PRIO 2              /* 任务优先级   */
#define LED0_STK_SIZE  128            /* 任务堆栈大小 */
TaskHandle_t LED0Task_Handler;        /* 任务句柄     */
void led0_task(void *pvParameters);   /* 任务函数     */
 
//LED1灯闪烁
#define LED1_TASK_PRIO 3              /* 任务优先级   */
#define LED1_STK_SIZE  128            /* 任务堆栈大小 */
TaskHandle_t LED1Task_Handler;        /* 任务句柄     */
void led1_task(void *pvParameters);   /* 任务函数     */
 
 
 
int main(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
	LED_Init();                      //LED初始化
	USART1_Init(115200);             //USART1初始化
	
	LED0_H;
	LED1_H;
	//初始任务
  xTaskCreate((TaskFunction_t )init_task,             //任务函数
              (const char*    )"init_task",           //任务名称
              (uint16_t       )INIT_STK_SIZE,         //任务堆栈大小
              (void*          )NULL,                  //传递给任务函数的参数
              (UBaseType_t    )INIT_TASK_PRIO,        //任务优先级
              (TaskHandle_t*  )&INITTask_Handler);    //任务句柄              
  vTaskStartScheduler();    
}
 
//初始任务任务函数
void init_task(void *pvParameters)
{
	taskENTER_CRITICAL();            //进入临界区
							
	//创建LED0任务
	xTaskCreate((TaskFunction_t )led0_task,
							(const char*    )"led0_task",
							(uint16_t       )LED0_STK_SIZE,
							(void*          )NULL,
							(UBaseType_t    )LED0_TASK_PRIO,
							(TaskHandle_t*  )&LED0Task_Handler);
							
	//创建LED1任务
	xTaskCreate((TaskFunction_t )led1_task,
							(const char*    )"led1_task",
							(uint16_t       )LED1_STK_SIZE,
							(void*          )NULL,
							(UBaseType_t    )LED1_TASK_PRIO,
							(TaskHandle_t*  )&LED1Task_Handler);
							
	vTaskDelete(INITTask_Handler); //删除初始任务
	taskEXIT_CRITICAL();           //退出临界区
}
 
void led0_task(void *pvParameters)
{
	while(1)
	{
		LED0_L;
		vTaskDelay(100);
		LED0_H;
		vTaskDelay(100);
		printf("LED0 Test\r\n");
	}
}
 
void led1_task(void *pvParameters)
{
	while(1)
	{
		LED1_L;
		vTaskDelay(100);
		LED1_H;
		vTaskDelay(100);
		printf("LED1 Test\r\n");
	}
}

3. FreeRTOS task creation and deletion (static method)

illustrate:

1) Static creation tasks have more steps than state creation tasks, as follows:

1. Two interface functions need to be implemented-->The idle task interface must be implemented. The timer task is not necessary. If not used, the corresponding macro will be closed.

2) Other steps are consistent with creating dynamic tasks

No examples yet

4. Critical Section and Task Scheduler

4.1. What is the critical section?

1. Critical section of code

        The critical section of the code is also called the critical section, which refers to the code that is indivisible during processing. The execution of these codes is not allowed to be interrupted. Once this part of the code starts executing, no interrupts are allowed to be entered (this is not absolute, if the interrupt does not call any code that contains the critical section, and does not access any shared resources used by the critical section, this interrupt may be executed). In order to ensure the execution of the critical section code, interrupts must be turned off before entering the critical section, and interrupts must be turned on immediately after the execution of the critical section code is completed.

4.2. Use of critical sections

Example: When we create a task, each time a task is created, the task will be scheduled to the running state by the task scheduler. But we hope that all tasks will be created and run according to the specified priority. In this case, we need to use critical sections.

Usage idea: Before creating a task, use FreeRTOS's built-in function -->taskENTER_CRITICAL() to enter the critical section. After that, the tasks created will remain in the ready state. The task scheduler cannot schedule tasks. When all tasks When the creation is completed, we use FreeRTOS's built-in function -->taskEXIT_CRITICAL() to exit the critical section. At this time, all created tasks are ready, but when we use preemption, the tasks will run according to priority to achieve our goal.

4.3. Task scheduler

Function: vTaskStartScheduler(), function: start task scheduling

How to use: After creating the task, just call this function. It only needs to be called once each time the program runs (just call this function after the first created task function)

When we create tasks, the tasks will not be automatically sorted. We need to use FreeRTOS's built-in function --> vTaskStartScheduler() to help us sort the created tasks according to priority so that the program can run in order.

Guess you like

Origin blog.csdn.net/qq_57663276/article/details/128744524