FreeRTOS Series Part 2 - task creation and deletion

Posted by Chezshire on Mon, 17 Jan 2022 10:38:35 +0100

1. Task create and delete API functions

functiondescribe
xTaskCreateCreate a task using a dynamic method
xTaskCreateStaticCreate a task using a static method
xTaskDelete()Delete a task
  • xTaskCreate
    This function is used to create a task. The task requires RAM to save the status information related to the task (task control block)
    The task also needs some RAM as the task stack. If you use the function xTaskCreate() to create a task, then these
    The required RAM will be automatically allocated from the FreeRTOS heap, so the memory management file must be provided, which is used by default
    heap_4.c this memory management file, and the macro configSUPPORT_DYNAMIC_ALLOCATION must be 1.
/*
Entry parameters
pxTaskCode:  Task function.
pcName:  Task name is generally used for tracking and debugging. The length of task name cannot exceed. configMAX_TASK_NAME_LEN. 
usStackDepth:  The task stack size. Note that the stack actually applied is 4 times that of ussackdepth. The task stack size of idle tasks is configMINIMAL_STACK_SIZE. 
pvParameters: Parameters passed to the task function.
uxPriotiry: Task priority, range 0~ configMAX_PRIORITIES-1. 
pxCreatedTask: Task handle. After the task is created successfully, the task handle of the task will be returned. In fact, this handle is the task stack of the task. This parameter is used to save the task handle. Other API functions may use this handle.

Return value:
pdPASS: Task created successfully.
errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY:  Task creation failed because of insufficient heap memory!
*/
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
						const char * const pcName,
						const uint16_t usStackDepth,
						void * const pvParameters,
						UBaseType_t uxPriority,
						TaskHandle_t * const pxCreatedTask )
  • xTaskCreateStatic

This function has the same function as xTaskCreate(). It is also used to create tasks, but the tasks created with this function are required
The required RAM needs to be provided by the user. If you want to use this function, you need to set the macro
configSUPPORT_STATIC_ALLOCATION is defined as 1.

/*
Inlet parameters:
pxTaskCode:  Task function.
pcName:  Task name is generally used for tracking and debugging. The length of task name cannot exceed. configMAX_TASK_NAME_LEN. 
usStackDepth:  Task stack size. Since this function is a static method to create a task, the task stack is given by the user. It is generally an array. This parameter is the size of this array.
pvParameters: Parameters passed to the task function.
uxPriotiry: Task priority, range 0~ configMAX_PRIORITIES-1. 
puxStackBuffer: The task stack is generally an array, and the array type should be StackType_t type.
pxTaskBuffer: Task control block.

Return value:
NULL:  Task creation failed. This will be caused when puxStackBuffer or pxTaskBuffer is NULL
 The occurrence of the error.
Other values: if the task is created successfully, the task handle of the task is returned.
*/
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 )
  • vTaskDelete()
    Delete a task created with the function xtask create() or xtask createstatic(), and the deleted task will no longer exist
    In, that is, it will never enter the running state again. The handle of this task cannot be used after the task is deleted! If this task
    If the task is created using a dynamic method, that is, using the function xTaskCreate(), this task will be created after the task is deleted
    The stack and control block memory requested before the service will be released in the idle task, so when calling the function vtask delete(), it will be deleted
    After the task, the idle task must be given a certain running time.
    Only the memory allocated to the task by the kernel will be automatically released after the task is deleted, and the user will allocate it to the task
    Memory needs to be released by the user. For example, in a task, the user calls the function pvPortMalloc() to allocate 500 bytes of memory
    After the task is deleted, the user must also call the function vPortFree() to release the 500 bytes of memory. No
    It will cause memory leakage. The prototype of this function is as follows:
/*
Inlet parameters:
xTaskToDelete: The task handle of the task to delete.
Return value:
nothing
*/
vTaskDelete( TaskHandlet xTaskToDelete )

2. Experiment

2.1 create and delete tasks using static methods

Programming

1. When using static methods to create tasks, you need to set the macro configsupport_ STATIC_ The allocation is set to 1 in the file freertosconfig Set in H

#define configSUPPORT_STATIC_ALLOCATION 1 / / static memory

2. After the program is compiled, you will be prompted that two functions are undefined.
Undefined function:

void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );
void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t**ppxTimerTaskStackBuffer,uint32_t *pulTimerTaskStackSize );

Undefined cause analysis:
The task scheduling function void vtaskstartscheduler (void) internally creates two tasks: idle task and software timer task. If a task is created using a static method, the memory required by the task control block and task stack of these two tasks needs to be created by the user, so you need to define and implement these functions.

//Idle task stack
static StackType_t IdleTaskStack[configMINIMAL_STACK_SIZE];
//Idle task control block
static StaticTask_t IdleTaskTCB;
//Timer service task stack
static StackType_t TimerTaskStack[configTIMER_TASK_STACK_DEPTH];
//Timer service task control block
static StaticTask_t TimerTaskTCB;

// Memory required for idle tasks					
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, 
																	StackType_t **ppxIdleTaskStackBuffer,
																	uint32_t *pulIdleTaskStackSize )
{
						
	*ppxIdleTaskTCBBuffer = &IdleTaskTCB;
	*ppxIdleTaskStackBuffer = IdleTaskStack;
	*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}

// Memory required for timer tasks					
void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, 
																	StackType_t **ppxTimerTaskStackBuffer,
																	uint32_t *pulTimerTaskStackSize )
{
						
	*ppxTimerTaskTCBBuffer=&TimerTaskTCB;
	*ppxTimerTaskStackBuffer=TimerTaskStack;
	*pulTimerTaskStackSize=configTIMER_TASK_STACK_DEPTH;
}

The subject code is as follows:

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "timer.h"
#include "lcd.h"
#include "FreeRTOS.h"
#include "task.h"
/************************************************
 ALIENTEK Mini STM32F103 Development board FreeRTOS experiment 6-1
 FreeRTOS Task creation and deletion (dynamic method) - library function version
 Technical support: www.openedv.com com
 Taobao store: http://eboard.taobao.com 
 Pay attention to wechat public platform wechat: "punctual atom", and obtain STM32 data for free.
 Guangzhou Xingyi Electronic Technology Co., Ltd  
 Author: punctual atom @ ALIENTEK
************************************************/

//Task priority
#define START_TASK_PRIO		1
//Task stack size	
#define START_STK_SIZE 		128  
// Start task stack
StackType_t StartTaskStack[START_STK_SIZE];
//Task control block
StaticTask_t StartTaskTCB;
//task handle 
TaskHandle_t StartTask_Handler;
//Task function
void start_task(void *pvParameters);


//Idle task stack
static StackType_t IdleTaskStack[configMINIMAL_STACK_SIZE];
//Idle task control block
static StaticTask_t IdleTaskTCB;
//Timer service task stack
static StackType_t TimerTaskStack[configTIMER_TASK_STACK_DEPTH];
//Timer service task control block
static StaticTask_t TimerTaskTCB;


//Task priority
#define TASK1_TASK_PRIO		2
//Task stack size	
#define TASK1_STK_SIZE 		128  
// Start task stack
StackType_t Task1Stack[TASK1_STK_SIZE];
//Task control block
StaticTask_t Task1TCB;
//task handle 
TaskHandle_t Task1Task_Handler;
//Task function
void task1_task(void *pvParameters);

//Task priority
#define TASK2_TASK_PRIO		3
//Task stack size	
#define TASK2_STK_SIZE 		128  
// Start task stack
StackType_t Task2Stack[TASK2_STK_SIZE];
//Task control block
StaticTask_t Task2TCB;
//task handle 
TaskHandle_t Task2Task_Handler;
//Task function
void task2_task(void *pvParameters);



// Memory required for idle tasks					
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, 
																	StackType_t **ppxIdleTaskStackBuffer,
																	uint32_t *pulIdleTaskStackSize )
{
						
	*ppxIdleTaskTCBBuffer = &IdleTaskTCB;
	*ppxIdleTaskStackBuffer = IdleTaskStack;
	*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}

// Memory required for timer tasks					
void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, 
																	StackType_t **ppxTimerTaskStackBuffer,
																	uint32_t *pulTimerTaskStackSize )
{
						
	*ppxTimerTaskTCBBuffer=&TimerTaskTCB;
	*ppxTimerTaskStackBuffer=TimerTaskStack;
	*pulTimerTaskStackSize=configTIMER_TASK_STACK_DEPTH;
}
int main(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//Set system interrupt priority group 4	 
	delay_init();	    				//Delay function initialization	 
	uart_init(115200);					//Initialize serial port
	LED_Init();		  					//Initialize LED
//	LCD_Init(); 							// Initialize LCD
	
	//Create start task
	StartTask_Handler = xTaskCreateStatic((TaskFunction_t )start_task,            //Task function
                (const char*    )"start_task",          //Task name
                (uint16_t       )START_STK_SIZE,        //Task stack size
                (void*          )NULL,                  //Parameters passed to the task function
                (UBaseType_t    )START_TASK_PRIO,       //Task priority
                (StackType_t*  ) StartTaskStack,
								(StaticTask_t* ) &StartTaskTCB);   //task handle               
    vTaskStartScheduler();          //Turn on task scheduling
}

//Start task function
void start_task(void *pvParameters)
{
  taskENTER_CRITICAL();           //Enter critical zone
    //Create TASK1 task
  Task1Task_Handler = xTaskCreateStatic((TaskFunction_t )task1_task,             
                (const char*    )"task1_task",           
                (uint16_t       )TASK1_STK_SIZE,        
                (void*          )NULL,                  
                (UBaseType_t    )TASK1_TASK_PRIO,        
                (StackType_t*  ) Task1Stack,
								(StaticTask_t* ) &Task1TCB);   
    //Create TASK2 task
	Task2Task_Handler  = xTaskCreateStatic((TaskFunction_t )task2_task,     
                (const char*    )"task2_task",   
                (uint16_t       )TASK2_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )TASK2_TASK_PRIO,
                (StackType_t*  ) Task2Stack,
								(StaticTask_t* ) &Task2TCB); 
    vTaskDelete(StartTask_Handler); //Delete start task
    taskEXIT_CRITICAL();            //Exit critical zone
}

//task1 task function
void task1_task(void *pvParameters)
{
	u8 task1_num=0;
	
	while(1)
	{
		task1_num++;	//Task execution times plus 1 pay attention to Task1_ When num1 is added to 255, it will be cleared!!
		LED0=!LED0;
		printf("Task 1 has been performed:%d second\r\n",task1_num);
		if(task1_num==5) 
		{
      vTaskDelete(Task2Task_Handler);//Task 1 execute 5 times delete task 2
			printf("Task 1 deleted task 2!\r\n");
		}
     vTaskDelay(1000);                           //Delay 1s, that is, 1000 clock beats	
	}
}

//task2 task function
void task2_task(void *pvParameters)
{
	u8 task2_num=0;
	
	while(1)
	{
		task2_num++;	//Task 2 execution times plus 1 pay attention to Task1_ When num2 is added to 255, it will be cleared!!
    LED1=!LED1;
		printf("Task 2 has been performed:%d second\r\n",task2_num);
    vTaskDelay(1000);                           //Delay 1s, that is, 1000 clock beats	
	}
}


Topics: FreeRTOS