【FreeRTOS】FreeRTOS的任务创建和删除(三)

1,任务创建和删除的API函数

任务的创建和删除本质就是调用FreeRTOS的API函数

API函数描述
xTaskCreate()动态方式创建任务
xTaskCreateStatic()静态方式创建任务
vTaskDelete()删除任务

动态创建任务:任务的任务控制块以及任务的栈空间所需的内存,均由 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 /* 任务句柄,就是任务的任务控制块 */
)
返回值描述
pdPASS任务创建成功
errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY任务创建失败

实现动态创建任务流程(用起来只需这三步)
1、将宏configSUPPORT_DYNAMIC_ALLOCATION 配置为 1
2、定义函数入口参数
3、编写任务函数

动态创建任务函数内部实现
此函数创建的任务会立刻进入就绪态,由任务调度器调度运行
1、申请堆栈内存&任务控制块内存
2、TCB结构体成员赋值
3、添加新任务到就绪列表中

任务控制块结构体成员介绍

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 /* 任务控制块指针,由用户分配 */
);
返回值描述
NULL 用户没有提供相应的内存任务创建失败
其他值任务句柄任务创建成功

静态创建任务使用流程(静态创建内部实现)

1、需将宏configSUPPORT_STATIC_ALLOCATION 配置为1
2、定义空闲任务&定时器任务的任务堆栈及TCB
3、实现两个接口函数

  • vApplicationGetIdleTaskMemory( )
  • vApplicationGetTimerTaskMemory ( )

4、定义函数入口参数
5、编写任务函数

静态创建内部实现
此函数创建的任务会立刻进入就绪态,由任务调度器调度运行
1、TCB结构体成员赋值
2、添加新任务到就绪列表中
任务删除函数

void vTaskDelete(TaskHandle_t xTaskToDelete);
形参描述
xTaskToDelete待删除任务的任务句柄

用于删除已被创建的任务
被删除的任务将从就绪态任务列表、阻塞态任务列表、挂起态任务列表和事件列表中移除
注意:
1、当传入的参数为NULL,则代表删除任务自身(当前正在运行的任务)
2、空闲任务会负责释放被删除任务中由系统分配的内存,但是由用户在任务删除前申请的内存, 则需要由用户在任务被删除前提前释放,否则将导致内存泄露

删除任务流程
1、使用删除任务函数,需将宏INCLUDE_vTaskDelete 配置为 1
2、入口参数输入需要删除的任务句柄(NULL代表删除本身)

内部实现过程
1、获取所要删除任务的控制块:通过传入的任务句柄,判断所需要删除哪个任务,NULL代表删除自身
2、将被删除任务,移除所在列表:将该任务在所在列表中移除,包括:就绪、阻塞、挂起、事件等列表
3、判断所需要删除的任务

  • 删除任务自身,需先添加到等待删除列表,内存释放将在空闲- 任务执行
  • 删除其他任务,释放内存,任务数量–

4、更新下个任务的阻塞时间:更新下一个任务的阻塞超时时间,以防被删除的任务就是下一个阻塞超时的任务

2,任务创建和删除(动态方法)

1、实验目的:学会 xTaskCreate( ) 和 vTaskDelete( ) 的使用
2、实验设计:将设计四个任务:start_task、task1、task2、task3

四个任务的功能如下:
start_task:用来创建其他的三个任务
task1:实现LED0每500ms闪烁一次
task2:实现LED1每500ms闪烁一次
task3:判断按键KEY0是否按下,按下则删掉task1
在这里插入图片描述
代码实操:

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);
    }
}

3,任务创建和删除(静态方法)

1、实验目的:学会 xTaskCreateStatic( ) 和 vTaskDelete( ) 的使用
2、实验设计:将设计四个任务:start_task、task1、task2、task3

四个任务的功能如下:
start_task:用来创建其他的三个任务
task1:实现LED0每500ms闪烁一次
task2:实现LED1每500ms闪烁一次
task3:判断按键KEY0是否按下,按下则删掉task1

代码实操:

void start_task( void * pvParameters )
{
    taskENTER_CRITICAL();               /* 进入临界区 */
    
    task1_handler = xTaskCreateStatic(  (TaskFunction_t )   task1,
                                        (char *         )   "task1", 
                                        (uint32_t       )   TASK1_STACK_SIZE,
                                        (void *         )   NULL,
                                        (UBaseType_t    )   TASK1_PRIO,
                                        (StackType_t *  )   task1_stack,
                                        (StaticTask_t * )   &task1_tcb );
                        
    task2_handler = xTaskCreateStatic(  (TaskFunction_t )   task2,
                                        (char *         )   "task2", 
                                        (uint32_t       )   TASK2_STACK_SIZE,
                                        (void *         )   NULL,
                                        (UBaseType_t    )   TASK2_PRIO,
                                        (StackType_t *  )   task2_stack,
                                        (StaticTask_t * )   &task2_tcb );
                        
    task3_handler = xTaskCreateStatic(  (TaskFunction_t )   task3,
                                        (char *         )   "task3", 
                                        (uint32_t       )   TASK3_STACK_SIZE,
                                        (void *         )   NULL,
                                        (UBaseType_t    )   TASK3_PRIO,
                                        (StackType_t *  )   task3_stack,
                                        (StaticTask_t * )   &task3_tcb );
    
    vTaskDelete(start_task_handler);
    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);
    }
}

4,源码工程

keil源码工程链接
请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

莲花码农

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值