动态创建任务流程:
1:将FreeRTOSConfig.h文件 中将宏configSUPPORT_DYNAMIC_ALLOCATION 配置为1。
2:定义函数入口参数
3:编写任务函数
/*FreeRTOS配置*/
/* START_TASK 任务 配置
* 包括: 任务句柄 任务优先级 堆栈大小 创建任务
*/
#define START_TASK_PRIO 1 //数字越大,任务优先级越大
#define START_TASK_STACK_SIZE 128 //裸机默认栈大小是400B(100字)
TaskHandle_t start_task_handler;
void start_task( void * pvParameters );
#define TASK1_PRIO 2
#define TASK1_STACK_SIZE 128 //裸机默认栈大小是400B(100字)
TaskHandle_t task1_handler;
void task1( void * pvParameters );
#define TASK2_PRIO 3
#define TASK2_STACK_SIZE 128 //裸机默认栈大小是400B(100字)
TaskHandle_t task2_handler;
void task2( void * pvParameters );
#define TASK3_PRIO 4
#define TASK3_STACK_SIZE 128 //裸机默认栈大小是400B(100字)
TaskHandle_t task3_handler;
void task3( void * pvParameters );
void freertos_demo(void)
{
xTaskCreate((TaskFunction_t ) start_task,
(char * ) "start_task",
(configSTACK_DEPTH_TYPE ) START_TASK_STACK_SIZE,
(void * ) NULL,
(UBaseType_t ) START_TASK_PRIO,
(TaskHandle_t * ) &start_task_handler );
vTaskStartScheduler(); //任务调度器
}
void start_task( void * pvParameters )
{
taskENTER_CRITICAL(); //进入临界区
xTaskCreate((TaskFunction_t ) task1,
(char * ) "task1",
(configSTACK_DEPTH_TYPE ) TASK1_STACK_SIZE,
(void * ) NULL,
(UBaseType_t ) TASK1_PRIO,
(TaskHandle_t * ) &task1_handler );
xTaskCreate((TaskFunction_t ) task2,
(char * ) "task2",
(configSTACK_DEPTH_TYPE ) TASK2_STACK_SIZE,
(void * ) NULL,
(UBaseType_t ) TASK2_PRIO,
(TaskHandle_t * ) &task2_handler );
xTaskCreate((TaskFunction_t ) task3,
(char * ) "task3",
(configSTACK_DEPTH_TYPE ) TASK3_STACK_SIZE,
(void * ) NULL,
(UBaseType_t ) TASK3_PRIO,
(TaskHandle_t * ) &task3_handler );
vTaskDelete(NULL);
taskEXIT_CRITICAL(); //退出临界区,临界区保护,就是保护不想被打断的程序任务
}
//任务一,实现LED0每500ms翻转一次
void task1( void * pvParameters )
{
while(1)
{
printf("task1正在运行!!!\r\n");
LED0_TOGGLE();
vTaskDelay(500);
}
}
//任务二,实现LED1每500ms翻转一次
void task2( void * pvParameters )
{
while(1)
{
printf("task2正在运行!!!\r\n");
LED1_TOGGLE();
vTaskDelay(500);
}
}
//任务三,判断按键KEY0,按下KEY0删除task1
void task3( void * pvParameters )
{
uint8_t key =0;
while(1)
{
printf("task3正在运行!!!\r\n");
key = key_scan(0);
if(key == KEY0_PRES)
{
if(task1_handler !=NULL)
{
printf("删除task1任务\r\n");
vTaskDelete(task1_handler);
task1_handler = NULL;
}
}
vTaskDelay(10);
}
}
main函数里调用freertos_demo函数
freertos_demo函数里创建start任务并开启任务调度器
start任务里依次开启task1,task2,task3,这四个任务的优先级依次是1,2,3,4,(数字越大,优先级越高)
而且start中还调用了一对临界区函数来保护其中的程序不被打断。
我们看到程序运行的顺序是这样:start_task创建完自我删除->task3->task3阻塞->task2->task2阻塞->task1->task1阻塞
黑盒视角:task3运行次数是task2和task1的50倍
如果没有调用临界区函数,则会出现这样的情况:
这是因为在start任务中先创建task1,并且task1的优先级比start的更高所以会出现task1和task2在task3的前面运行
代码中提到的函数:
vTaskStartScheduler();任务调度器
xTaskCreate创建任务函数
taskENTER_CRITICAL();进入临界区函数
taskEXIT_CRITICAL();退出临界区函数
vTaskDelete(task1_handler);删除任务函数,如果传入参数为NULL则是删除任务本身(当前正在运行的任务)
vTaskDelay(10);任务延时函数,延时单位:系统时钟节拍