这里写目录标题
- 一、任务创建和删除的API函数(熟悉)
- 二、任务创建和删除(动态方法)(掌握)
- 三、任务创建和删除(静态方法)(掌握)
一、任务创建和删除的API函数(熟悉)
任务的创建和删除本质就是调用FreeRTOS的API函数
动态创建任务:任务的任务控制块以及任务的栈空间所需的内存,均由 FreeRTOS 从 FreeRTOS 管理的堆中分配(自动)
静态创建任务:任务的任务控制块以及任务的栈空间所需的内存,需用户分配提供(手动)
动态创建任务函数
BaseType_t xTaskCreate
(TaskFunction_t pxTaskCode, /* 指向任务函数的指针 */ const char * const pcName, /* 任务名字,最大长度configMAX_TASK_NAME_LEN */const configSTACK_DEPTH_TYPE usStackDepth, /* 任务堆栈大小,注意字为单位 */void * const pvParameters, /* 传递给任务函数的参数 */UBaseType_t uxPriority, /* 任务优先级,范围:0 ~ configMAX_PRIORITIES - 1 */TaskHandle_t * const pxCreatedTask /* 任务句柄,就是任务的任务控制块 */
)
实现动态创建任务流程
此函数创建的任务会立刻进入就绪态,由任务调度器调度运行
任务控制块结构体成员介绍
typedef struct tskTaskControlBlock
{volatile StackType_t * pxTopOfStack; /* 任务栈栈顶,必须为TCB的第一个成员 */ListItem_t xStateListItem; /* 任务状态列表项 */ListItem_t xEventListItem; /* 任务事件列表项 */ UBaseType_t uxPriority; /* 任务优先级,数值越大,优先级越大 */StackType_t * pxStack; /* 任务栈起始地址 */char pcTaskName[ configMAX_TASK_NAME_LEN ]; /* 任务名字 */ …省略很多条件编译的成员
} tskTCB;
任务栈栈顶,在任务切换时的任务上下文保存、任务恢复息息相关
注意:每个任务都有属于自己的任务控制块,类似身份证
静态创建任务函数
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、当传入的参数为NULL,则代表删除任务自身(当前正在运行的任务)
2、空闲任务会负责释放被删除任务中由系统分配的内存,但是由用户在任务删除前申请的内存, 则需要由用户在任务被删除前提前释放,否则将导致内存泄露
删除任务流程:
二、任务创建和删除(动态方法)(掌握)
1、实验目的:学会 xTaskCreate( ) 和 vTaskDelete( ) 的使用
2、实验设计:将设计四个任务:start_task、task1、task2、task3
四个任务的功能如下:
#include "freertos_demo.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"/******************************************************************************************************/
/*FreeRTOS配置*/
/* START_TASK 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define START_TASK_PRIO 1 /* 任务优先级 */
#define START_STK_SIZE 128 /* 任务堆栈大小 */
TaskHandle_t StartTask_Handler; /* 任务句柄 */
void start_task(void *pvParameters); /* 任务函数 *//* TASK1 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK1_PRIO 2 /* 任务优先级 */
#define TASK1_STK_SIZE 128 /* 任务堆栈大小 */
TaskHandle_t Task1Task_Handler; /* 任务句柄 */
void task1(void *pvParameters); /* 任务函数 *//* TASK2 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK2_PRIO 3 /* 任务优先级 */
#define TASK2_STK_SIZE 128 /* 任务堆栈大小 */
TaskHandle_t Task2Task_Handler; /* 任务句柄 */
void task2(void *pvParameters); /* 任务函数 *//* TASK3 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK3_PRIO 4 /* 任务优先级 */
#define TASK3_STK_SIZE 128 /* 任务堆栈大小 */
TaskHandle_t Task3Task_Handler; /* 任务句柄 */
void task3(void *pvParameters); /* 任务函数 */
/******************************************************************************************************/
/* LCD刷屏时使用的颜色 */
uint16_t lcd_discolor[11] = {WHITE, BLACK, BLUE, RED,MAGENTA, GREEN, CYAN, YELLOW,BROWN, BRRED, GRAY};/*** @brief FreeRTOS例程入口函数* @param 无* @retval 无*/void freertos_demo(void)
{lcd_show_string(10, 10, 220, 32, 32, "STM32", RED);lcd_show_string(10, 47, 220, 24, 24, "Task Create & Del", RED);lcd_show_string(10, 76, 220, 16, 16, "ATOM@ALIENTEK", RED);lcd_draw_rectangle(5, 110, 115, 314, BLACK);lcd_draw_rectangle(125, 110, 234, 314, BLACK);lcd_draw_line(5, 130, 115, 130, BLACK);lcd_draw_line(125, 130, 234, 130, BLACK);lcd_show_string(15, 111, 110, 16, 16, "Task1: 000", BLUE);lcd_show_string(135, 111, 110, 16, 16, "Task2: 000", BLUE);xTaskCreate((TaskFunction_t )start_task, /* 任务函数 */(const char* )"start_task", /* 任务名称 */(uint16_t )START_STK_SIZE, /* 任务堆栈大小 */(void* )NULL, /* 传入给任务函数的参数 */(UBaseType_t )START_TASK_PRIO, /* 任务优先级 */(TaskHandle_t* )&StartTask_Handler); /* 任务句柄 */vTaskStartScheduler(); //开启任务调度
}
/*** @brief start_task* @param pvParameters : 传入参数(未用到)* @retval 无*/void start_task(void *pvParameters){taskENTER_CRITICAL(); /* 进入临界区 *//* 创建任务1 */xTaskCreate((TaskFunction_t )task1, /* 任务函数 */(const char* )"task1", /* 任务名称 */(uint16_t )TASK1_STK_SIZE, /* 任务堆栈大小 */(void* )NULL, /* 传入给任务函数的参数 */(UBaseType_t )TASK1_PRIO, /* 任务优先级 */(TaskHandle_t* )&Task1Task_Handler); /* 任务句柄 *//* 创建任务2 */xTaskCreate((TaskFunction_t )task2, /* 任务函数 */(const char* )"task2", /* 任务名称 */(uint16_t )TASK2_STK_SIZE, /* 任务堆栈大小 */(void* )NULL, /* 传入给任务函数的参数 */(UBaseType_t )TASK2_PRIO, /* 任务优先级 */(TaskHandle_t* )&Task2Task_Handler); /* 任务句柄 *//* 创建任务3 */xTaskCreate((TaskFunction_t )task3, /* 任务函数 */(const char* )"task3", /* 任务名称 */(uint16_t )TASK3_STK_SIZE, /* 任务堆栈大小 */(void* )NULL, /* 传入给任务函数的参数 */(UBaseType_t )TASK3_PRIO, /* 任务优先级 */(TaskHandle_t* )&Task3Task_Handler); /* 任务句柄 */vTaskDelete(StartTask_Handler); /* 删除开始任务 */taskEXIT_CRITICAL(); /* 退出临界区 */}/*** @brief task1* @param pvParameters : 传入参数(未用到)* @retval 无*/void task1(void *pvParameters){uint32_t task1_num = 0;while (1){lcd_fill(6, 131, 114, 313, lcd_discolor[++task1_num % 11]);lcd_show_xnum(71, 111, task1_num, 3, 16, 0x80, BLUE);vTaskDelay(500);}}/*** @brief task2* @param pvParameters : 传入参数(未用到)* @retval 无*/
void task2(void *pvParameters)
{uint32_t task2_num = 0;while (1){lcd_fill(126, 131, 233, 313, lcd_discolor[11 - (++task2_num % 11)]);lcd_show_xnum(191, 111, task2_num, 3, 16, 0x80, BLUE);vTaskDelay(500);}
}
/*** @brief task3* @param pvParameters : 传入参数(未用到)* @retval 无*/void task3(void *pvParameters){uint8_t key = 0;while (1){key = key_scan(0);switch (key){case KEY0_PRES: /* 删除任务1 */{if (Task1Task_Handler != NULL){vTaskDelete(Task1Task_Handler);Task1Task_Handler = NULL;}break;}case KEY1_PRES: /* 删除任务2 */{if (Task2Task_Handler != NULL){vTaskDelete(Task2Task_Handler);Task2Task_Handler = NULL;}break;}default:{break;}}vTaskDelay(10);}}
三、任务创建和删除(静态方法)(掌握)
1、实验目的:学会 xTaskCreateStatic( ) 和 vTaskDelete( ) 的使用
2、实验设计:将设计四个任务:start_task、task1、task2、task3
四个任务的功能如下:
#include "freertos_demo.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"
/******************************************************************************************************/
/*FreeRTOS配置*/
static StackType_t IdleTaskStack[configMINIMAL_STACK_SIZE]; /* 空闲任务任务堆栈 */
static StaticTask_t IdleTaskTCB; /* 空闲任务控制块 */
static StackType_t TimerTaskStack[configTIMER_TASK_STACK_DEPTH]; /* 定时器服务任务堆栈 */
static StaticTask_t TimerTaskTCB; /* 定时器服务任务控制块 *//*** @brief 获取空闲任务地任务堆栈和任务控制块内存,因为本例程使用的静态内存,因此空闲任务的任务堆栈和任务控制块的内存就应该有用户来提供,FreeRTOS提供了接口函数vApplicationGetIdleTaskMemory()实现此函数即可。* @param ppxIdleTaskTCBBuffer:任务控制块内存ppxIdleTaskStackBuffer:任务堆栈内存pulIdleTaskStackSize:任务堆栈大小* @retval 无*/void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize)
{*ppxIdleTaskTCBBuffer = &IdleTaskTCB;*ppxIdleTaskStackBuffer = IdleTaskStack;*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}/*** @brief 获取定时器服务任务的任务堆栈和任务控制块内存* @param ppxTimerTaskTCBBuffer:任务控制块内存ppxTimerTaskStackBuffer:任务堆栈内存pulTimerTaskStackSize:任务堆栈大小* @retval 无*/
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,StackType_t **ppxTimerTaskStackBuffer,uint32_t *pulTimerTaskStackSize)
{*ppxTimerTaskTCBBuffer = &TimerTaskTCB;*ppxTimerTaskStackBuffer= TimerTaskStack;*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}/* START_TASK 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define START_TASK_PRIO 1 /* 任务优先级 */
#define START_STK_SIZE 128 /* 任务堆栈大小 */
StackType_t StartTaskStack[START_STK_SIZE]; /* 任务堆栈 */
StaticTask_t StartTaskTCB; /* 任务控制块 */
TaskHandle_t StartTask_Handler; /* 任务句柄 */
void start_task(void *pvParameters); /* 任务函数 *//* TASK1 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK1_PRIO 2 /* 任务优先级 */
#define TASK1_STK_SIZE 128 /* 任务堆栈大小 */
StackType_t Task1TaskStack[TASK1_STK_SIZE]; /* 任务堆栈 */
StaticTask_t Task1TaskTCB; /* 任务控制块 */
TaskHandle_t Task1Task_Handler; /* 任务句柄 */
void task1(void *pvParameters); /* TASK2 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK2_PRIO 3 /* 任务优先级 */
#define TASK2_STK_SIZE 128 /* 任务堆栈大小 */
StackType_t Task2TaskStack[TASK2_STK_SIZE]; /* 任务堆栈 */
StaticTask_t Task2TaskTCB; /* 任务控制块 */
TaskHandle_t Task2Task_Handler; /* 任务句柄 */
void task2(void *pvParameters); /* 任务函数 */ /* TASK3 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK3_PRIO 4 /* 任务优先级 */
#define TASK3_STK_SIZE 128 /* 任务堆栈大小 */
StackType_t Task3TaskStack[TASK3_STK_SIZE]; /* 任务堆栈 */
StaticTask_t Task3TaskTCB; /* 任务控制块 */
TaskHandle_t Task3Task_Handler; /* 任务句柄 */
void task3(void *pvParameters); /* 任务函数 *//******************************************************************************************************//* LCD刷屏时使用的颜色 */
uint16_t lcd_discolor[11] = {WHITE, BLACK, BLUE, RED,MAGENTA, GREEN, CYAN, YELLOW,BROWN, BRRED, GRAY};/*** @brief FreeRTOS例程入口函数* @param 无* @retval 无*/
void freertos_demo(void)
{lcd_show_string(10, 10, 220, 32, 32, "STM32", RED);lcd_show_string(10, 47, 220, 24, 24, "Task Create & Del", RED);lcd_show_string(10, 76, 220, 16, 16, "ATOM@ALIENTEK", RED);lcd_draw_rectangle(5, 110, 115, 314, BLACK);lcd_draw_rectangle(125, 110, 234, 314, BLACK);lcd_draw_line(5, 130, 115, 130, BLACK);lcd_draw_line(125, 130, 234, 130, BLACK);lcd_show_string(15, 111, 110, 16, 16, "Task1: 000", BLUE);lcd_show_string(135, 111, 110, 16, 16, "Task2: 000", BLUE);StartTask_Handler = xTaskCreateStatic((TaskFunction_t )start_task, /* 任务函数 */(const char* )"start_task", /* 任务名称 */(uint32_t )START_STK_SIZE, /* 任务堆栈大小 */(void* )NULL, /* 传递给任务函数的参数 */(UBaseType_t )START_TASK_PRIO, /* 任务优先级 */(StackType_t* )StartTaskStack, /* 任务堆栈 */(StaticTask_t* )&StartTaskTCB); /* 任务控制块 */vTaskStartScheduler();
}/*** @brief start_task* @param pvParameters : 传入参数(未用到)* @retval 无*/void start_task(void *pvParameters)
{taskENTER_CRITICAL(); /* 进入临界区 *//* 创建任务1 */Task1Task_Handler = xTaskCreateStatic((TaskFunction_t )task1, /* 任务函数 */(const char* )"task1", /* 任务名称 */(uint32_t )TASK1_STK_SIZE,/* 任务堆栈大小 */(void* )NULL, /* 传递给任务函数的参数 */(UBaseType_t )TASK1_PRIO, /* 任务优先级 */(StackType_t* )Task1TaskStack,/* 任务堆栈 */(StaticTask_t* )&Task1TaskTCB);/* 任务控制块 *//* 创建任务2 */Task2Task_Handler = xTaskCreateStatic((TaskFunction_t )task2, /* 任务函数 */(const char* )"task2", /* 任务名称 */(uint32_t )TASK2_STK_SIZE,/* 任务堆栈大小 */(void* )NULL, /* 传递给任务函数的参数 */(UBaseType_t )TASK2_PRIO, /* 任务优先级 */(StackType_t* )Task2TaskStack,/* 任务堆栈 */(StaticTask_t* )&Task2TaskTCB);/* 任务控制块 *//* 创建任务3 */Task3Task_Handler = xTaskCreateStatic((TaskFunction_t )task3, /* 任务函数 */(const char* )"task3", /* 任务名称 */(uint32_t )TASK3_STK_SIZE,/* 任务堆栈大小 */(void* )NULL, /* 传递给任务函数的参数 */(UBaseType_t )TASK3_PRIO, /* 任务优先级 */(StackType_t* )Task3TaskStack,/* 任务堆栈 */(StaticTask_t* )&Task3TaskTCB);/* 任务控制块 */vTaskDelete(StartTask_Handler); /* 删除开始任务 */taskEXIT_CRITICAL(); /* 退出临界区 */
}/*** @brief task1* @param pvParameters : 传入参数(未用到)* @retval 无*/
void task1(void *pvParameters)
{uint32_t task1_num = 0;while (1){lcd_fill(6, 131, 114, 313, lcd_discolor[++task1_num % 11]);lcd_show_xnum(71, 111, task1_num, 3, 16, 0x80, BLUE);vTaskDelay(500);}
}/*** @brief task2* @param pvParameters : 传入参数(未用到)* @retval 无*/
void task2(void *pvParameters)
{uint32_t task2_num = 0;while (1){lcd_fill(126, 131, 233, 313, lcd_discolor[11 - (++task2_num % 11)]);lcd_show_xnum(191, 111, task2_num, 3, 16, 0x80, BLUE);vTaskDelay(500);}
}/*** @brief task3* @param pvParameters : 传入参数(未用到)* @retval 无*/
void task3(void *pvParameters)
{uint8_t key = 0;while (1){key = key_scan(0);switch (key){case KEY0_PRES: /* 删除任务1 */{if (Task1Task_Handler != NULL){vTaskDelete(Task1Task_Handler);Task1Task_Handler = NULL;}break;}case KEY1_PRES: /* 删除任务2 */{if (Task2Task_Handler != NULL){vTaskDelete(Task2Task_Handler);Task2Task_Handler = NULL;}break;}default:{break;}}vTaskDelay(10);}
}