FreeRTOS task creation and suspension
1 task related concepts
Task status
-
Running state
When a task is running, it can be said that the task is running. If it is a single core processor, there is always only one task in progress at any time. -
Ready
Tasks in the ready state are those that are ready (these tasks are not blocked or suspended) and can be run, but the tasks in the ready state have not been run because there is a higher priority task running. -
Blocking state
When a task is waiting for an external event, it indicates that it is in the blocking state. For example, calling the function vtask delay() will enter the blocking state until the delay cycle is completed. There is a timeout in the blocking state. After that, it will exit the blocking state. -
Suspended state
After the task is suspended, it cannot enter the running state again, but there is no timeout. Call the functions vtask suspend() and xtask resume()
Task priority
- Preemptive scheduling: when a new task is ready and the priority is greater than or equal to the priority of the current task, the current task will be preempted; You need to configure yourself_ Preemption configuration.
- Each task can be assigned a 0 ~ configmax_ The priority of priorities-1 (defined in freertosconfig. H), and the macro definition cannot exceed 32
- The highest priority task in ready status will run.
- When configure_ TIME_ When slicing is defined as 1, multiple tasks can share a priority, which is in FreeRTOS by default H has been defined as 1
Task function
Use xtask create() to create a task
Official task function template
void vATaskFunction(void *pvParameters) { for(;;) { //Task application vTaskDeley(); } vTaskDelete(NULL); }
If you want to jump out of the loop end task, add vtask delete (null);
Task control block
In tasks Defined in C
typedef struct tskTaskControlBlock { volatile StackType_t *pxTopOfStack; //Top of task stack #if ( portUSING_MPU_WRAPPERS == 1 ) xMPU_SETTINGS xMPUSettings;//mpu related settings #endif ListItem_t xStateListItem; //Status list item ListItem_t xEventListItem; //Event list item UBaseType_t uxPriority; //Task priorities StackType_t *pxStack; //Start address of task stack char pcTaskName[ configMAX_TASK_NAME_LEN ]; //Task name #if ( portSTACK_GROWTH > 0 ) StackType_t *pxEndOfStack; //Task stack bottom #endif #if ( portCRITICAL_NESTING_IN_TCB == 1 ) UBaseType_t uxCriticalNesting; //Nesting depth of critical area #If (configure_trace_facility = = 1) / / used in trace or debug UBaseType_t uxTCBNumber; /*< Stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */ UBaseType_t uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */ #endif #if ( configUSE_MUTEXES == 1 ) UBaseType_t uxBasePriority; //The basic priority of the task is used when the priority is reversed UBaseType_t uxMutexesHeld; //The number of mutually exclusive semaphores obtained by the task #endif #if ( configUSE_APPLICATION_TASK_TAG == 1 ) TaskHookFunction_t pxTaskTag; #endif #If (confignum_thread_local_storage_points > 0) / / related to local storage void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ]; #endif #if( configGENERATE_RUN_TIME_STATS == 1 ) uint32_t ulRunTimeCounter; //It is used to record the total running time of the task #endif #if ( configUSE_NEWLIB_REENTRANT == 1 ) struct _reent xNewLib_reent; //A newlib struct variable is used to create a new struct #endif #If (configure_task_notifications = = 1) / / task notification related variables volatile uint32_t ulNotifiedValue; volatile uint8_t ucNotifyState; #endif /* See the comments above the definition of tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */ #If (tskstatic_and_dynamic_allocation_possible! = 0) / / used to mark whether it is created dynamically or statically uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */ #endif #if( INCLUDE_xTaskAbortDelay == 1 ) uint8_t ucDelayAborted; #endif } tskTCB; /* The old tskTCB name is maintained above then typedefed to the new TCB_t name below to enable the use of older kernel aware debuggers. */ typedef tskTCB TCB_t;
task stack
If you create a task with xTaskCreate(), it will be created dynamically and the stack will be allocated automatically. If you create a task with xTaskCreateStatic(), it will be created statically. The programmer needs to define the task stack and pass the first address of the stack to the function as a parameter puxsackbuffer
2 task related API s
Task creation and deletion API
API functions for task creation and deletion mainly include xTaskCreate(), xTaskCreateStatic(), xTaskCreateRestricted(), vTaskDelete()
- Dynamic task creation xTaskCreate()
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, //Task function const char * const pcName, //Task name, length limited const configSTACK_DEPTH_TYPE usStackDepth, //The task stack size actually applied for is 4 times that of ussackdepth void * const pvParameters, //Parameters passed to the task function UBaseType_t uxPriority, //Task priority TaskHandle_t * const pxCreatedTask) //task handle
Return value
pdPASS: task created successfully
errCOULD_NOT...: Task creation failed, out of memory
- Static task creation xtask createstatic()
TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode, //Task function const char * const pcName, //Task name, length limited const uint32_t ulStackDepth, //The task stack size actually applied for is 4 times that of ussackdepth void * const pvParameters, //Parameters passed to the task function UBaseType_t uxPriority, //Task priority StackType_t * const puxStackBuffer, //task stack StaticTask_t * const pxTaskBuffer ) //Task control block
Return value
NULL: task creation failed. This error will occur when puxStackBuffer or pxTaskBuffer is NULL
Other values: the task is created successfully, and the handle of the task is returned
-
Create tasks with MPU restrictions xtask createrestricted()
-
Delete task vTaskDelete()
void vTaskDelete( TaskHandle_t xTaskToDelete ) //The task handle of the task to delete
API task suspend and resume
The task suspension and recovery API mainly uses three functions: vtask suspend(), vtask resume(), vtask resumefromisr()
- Suspend task vtask suspend()
void vTaskSuspend( TaskHandle_t xTaskToSuspend ) //The task handle of the task to suspend
When creating a task, a task handle will be assigned to each task.
-
If you use the dynamic creation function xTaskCreate() to create a task, the parameter pxCreatedTask of the function is the task handle of the task.
-
If you use the static creation function xTaskCreateStatic() to create a task, the return value of the function is the task handle of the task.
-
Resume task vtask resume()
void vTaskResume( TaskHandle_t xTaskToResume ) //Task handle to recover
- Resume the operation of a task in the interrupt service function vtask resumefromisr()
The interrupted version of vTaskResume(), which is used to resume the task in the interruption
BaseType_t vTaskResumeFromISR( TaskHandle_t xTaskToResume ) //Task handle to recover
Return value
pdTRUE the task priority of the resumed task is equal to or higher than that of the currently running task (interrupted task), which means that a context switch must be performed after the interrupt service function is introduced
pdFALSE the priority of the resumed task is lower than that of the current task, and context switching is not required
3 experiment
Creating tasks using dynamic methods
Create tasks by assigning task priority, task stack size, and task handle
for example
//Task priority #define START_TASK_PRIO 1 //Task stack size #define START_STK_SIZE 128 //task handle TaskHandle_t StartTask_Handler; //Task function void start_task(void *pvParameters);
Create a start task, create two tasks respectively, and then delete the start task
//Create start task xTaskCreate((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 (TaskHandle_t* )&StartTask_Handler); //task handle vTaskStartScheduler(); //Turn on task scheduling
Start task function
//Start task function void start_task(void *pvParameters) { taskENTER_CRITICAL(); //Enter critical zone //Create TASK1 task xTaskCreate((TaskFunction_t )task1_task, (const char* )"task1_task", (uint16_t )TASK1_STK_SIZE, (void* )NULL, (UBaseType_t )TASK1_TASK_PRIO, (TaskHandle_t* )&Task1Task_Handler); //Create TASK2 task xTaskCreate((TaskFunction_t )task2_task, (const char* )"task2_task", (uint16_t )TASK2_STK_SIZE, (void* )NULL, (UBaseType_t )TASK2_TASK_PRIO, (TaskHandle_t* )&Task2Task_Handler); vTaskDelete(StartTask_Handler); //Delete start task taskEXIT_CRITICAL(); //Exit critical zone }
Two task functions
//task1 task function void task1_task(void *pvParameters) { u8 task1_num=0; POINT_COLOR = BLACK; LCD_DrawRectangle(5,110,115,314); //Draw a rectangle LCD_DrawLine(5,130,115,130); //Draw a line POINT_COLOR = BLUE; LCD_ShowString(6,111,110,16,16,"Task1 Run:000"); 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"); } LCD_Fill(6,131,114,313,lcd_discolor[task1_num%14]); //Filled area LCD_ShowxNum(86,111,task1_num,3,16,0x80); //Displays the number of task executions vTaskDelay(1000); //Delay 1s, that is, 1000 clock beats } } //task2 task function void task2_task(void *pvParameters) { u8 task2_num=0; POINT_COLOR = BLACK; LCD_DrawRectangle(125,110,234,314); //Draw a rectangle LCD_DrawLine(125,130,234,130); //Draw a line POINT_COLOR = BLUE; LCD_ShowString(126,111,110,16,16,"Task2 Run:000"); 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); LCD_ShowxNum(206,111,task2_num,3,16,0x80); //Displays the number of task executions LCD_Fill(126,131,233,313,lcd_discolor[13-task2_num%14]); //Filled area vTaskDelay(1000); //Delay 1s, that is, 1000 clock beats } }
Create task using static method
Before using the static creation method, set freertosconfig H macro definition configSUPPORT_STATIC_ALLOCATION
Define more task stacks and task control blocks than dynamic tasks, such as
//Task priority #define START_TASK_PRIO 1 //Task stack size #define START_STK_SIZE 128 //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);
Other steps are similar