200字
RTOS任务的创建和删除
2023-12-16
2026-03-23

04-FreeRTOS任务创建与删除(课堂总结).pdf

任务的创建和删除分为动态方式和静态方式两种

动态创建任务

任务的任务控制块以及任务的栈空间所需的内存,均由 FreeRTOS 从 FreeRTOS 管理的堆中分配(用户仅指定stack大小)

静态创建任务

任务的任务控制块以及任务的栈空间所需的内存,需用户分配提供

什么是临界区保护

答:临界区保护,保护那些不想被打断的程序段,关闭freertos所管理的中断,中断无法打断,滴答中断和PendSV中断无法进行不能实现任务调度 。

动态创建优点

答:动态创建使用起来相对简单。在实际的应用中,动态方式创建任务是比较常用的,除非有特殊的需求,一般都会使用动态方式创建任务 。

静态创建优点

答:静态创建可将任务堆栈放置在特定的内存位置,并且无需关心对内存分配失败的处理 。

动态创建任务简要流程

主程序()
{
	创建start_task

	vTaskStartScheduler();//开启调度器
}
start_task()
{
	*taskENTER_CRITICAL();//进入临界区*

	创建task1、task2……

	vTaskDelete(NULL);

	taskEXIT_CRITICAL();//退出临界区
}

动态创建任务

  1. 将宏配置为configSUPPORT_DYNAMIC_ALLOCATION 1(FreeRTOSConfig.h中):开启动态分配

  2. 定义函数的入口参数

    1. pxTaskCode :指向任务函数的指针
    2. pcName : 任务名字,最大长度configMAX_TASK_NAME_LEN
    3. usStackDepth :任务堆栈大小,注意字为单位(内部*4)
    4. pvParameters :传递给任务函数的参数(常用NULL)
    5. uxPriority :任务优先级,范围:0 ~ configMAX_PRIORITIES - 1
    6. pxCreatedTask :任务句柄,就是任务的任务控制块
  3. 编写任务函数

    任务代码

此函数创建的任务会立刻进入就绪态,由任务调度器调度运行

以下为动态创建任务函数内部实现(了解)

  1. 申请堆栈内存&任务控制块内存

  2. TCB结构体成员赋值

  3. 添加新任务到就绪列表中

    image

附动态分配基础代码

/*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            TASK1_Handler;  /* 任务句柄 */
void TASK1(void *pvParameters);        /* 任务函数 */

/* TASK2 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK2_PRIO 3                   /* 任务优先级 */
#define TASK2_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            TASK2_Handler;  /* 任务句柄 */
void TASK2(void *pvParameters);        /* 任务函数 */

/* TASK3 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK3_PRIO 4                   /* 任务优先级 */
#define TASK3_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            TASK3_Handler;  /* 任务句柄 */
void TASK3(void *pvParameters);        /* 任务函数 */

void freertos_demo(void)
{
    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();
}

void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();
    xTaskCreate((TaskFunction_t )TASK1,            /* 任务函数 */
                (const char*    )"TASK1",          /* 任务名称 */
                (uint16_t       )TASK1_STK_SIZE,        /* 任务堆栈大小 */
                (void*          )NULL,                  /* 传入给任务函数的参数 */
                (UBaseType_t    )TASK1_PRIO,       /* 任务优先级 */
                (TaskHandle_t*  )&TASK1_Handler);   /* 任务句柄 */
          
    xTaskCreate((TaskFunction_t )TASK2,            /* 任务函数 */
                (const char*    )"TASK2",          /* 任务名称 */
                (uint16_t       )TASK2_STK_SIZE,        /* 任务堆栈大小 */
                (void*          )NULL,                  /* 传入给任务函数的参数 */
                (UBaseType_t    )TASK2_PRIO,       /* 任务优先级 */
                (TaskHandle_t*  )&TASK2_Handler);   /* 任务句柄 */
          
    xTaskCreate((TaskFunction_t )TASK3,            /* 任务函数 */
                (const char*    )"TASK3",          /* 任务名称 */
                (uint16_t       )TASK3_STK_SIZE,        /* 任务堆栈大小 */
                (void*          )NULL,                  /* 传入给任务函数的参数 */
                (UBaseType_t    )TASK3_PRIO,       /* 任务优先级 */
                (TaskHandle_t*  )&TASK3_Handler);   /* 任务句柄 */
          
    vTaskDelete(NULL);
    taskEXIT_CRITICAL();
}

void TASK1(void *pvParameters)
{
    while(1)
    {
        printf("task1 ruing!!!\n");
        LED0_TOGGLE();
        vTaskDelay(500);
    }
}

void TASK2(void *pvParameters)
{
    while(1)
    {
        printf("task2 ruing!!!\n");
        LED1_TOGGLE();
        vTaskDelay(250);
    }
}
void TASK3(void *pvParameters)
{
    uint8_t key=0;
  
    while(1)
    {
        printf("task3 ruing!!!\n");
        key=key_scan(0);
        if(key==KEY0_PRES)
        {
            if(TASK1_Handler!=NULL)
            {
                printf("delete task1 \n");
                vTaskDelete(TASK1_Handler);
                TASK1_Handler = NULL;
            }
        }
  
        vTaskDelay(50);
    }
}

任务删除函数

void vTaskDelete(TaskHandle_t xTaskToDelete);

形参 描述
xTaskToDelete 待删除任务的任务句柄
用于删除已被创建的任务

被删除的任务将从就绪态任务列表、阻塞态任务列表、挂起态任务列表和事件列表中移除
  1. 当传入的参数为NULL,则代表删除任务自身(当前正在运行的任务)

  2. 空闲任务会负责释放被删除任务中由系统分配的内存,但是由用户在任务删除前申请的内存, 则需要由用户在任务被删除前提前释放,否则将导致内存泄

  3. 需将宏INCLUDE_vTaskDelete 配置为 1(FreeRTOSConfig.h中):开启任务删除

  4. 入口参数输入要删除的任务句柄(NULL代表删除任务本身)

    vTaskDelete(NULL);

image

静态创建任务

  1. 将宏configSUPPORT_STATIC_ALLOCATION 配置为 1

  2. 定义空闲任务&定时器任务的任务堆栈及TCB

    1. 空闲任务配置

      StaticTask_t idle_task_tcb;
      StackType_t idle_task_stack[configMINIMAL_STACK_SIZE];
      
    2. 定时器任务配置

      StaticTask_t timer_task_tcb;
      StackType_t timner_task_stack[configTIMER_TASK_STACK_DEPTH];
      
  3. 实现两个接口函数

    1. void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
                                          StackType_t ** ppxIdleTaskStackBuffer,
                                          uint32_t *pulIdleTaskStackSize )
      {
      	* ppxIdleTaskTCBBuffer=&idle_task_tcb;
          * ppxIdleTaskStackBuffer=idle_task_stack;
          * pulIdleTaskStackSize=configMINIMAL_STACK_SIZE;
      }
      
      
    2. void vApplicationGetTimerTaskMemory(    StaticTask_t ** ppxTimerTaskTCBBuffer, 
                                              StackType_t ** ppxTimerTaskStackBuffer, 
                                              uint32_t *pulTimerTaskStackSize )
      {
       	* ppxTimerTaskTCBBuffer=&timer_task_tcb;
          * ppxTimerTaskStackBuffer=timner_task_stack;
          * pulTimerTaskStackSize=configTIMER_TASK_STACK_DEPTH;
      }
      
  4. 定义函数入口参数

    #define START_TASK_PRIO 1                   /* 任务优先级 */
    #define START_STK_SIZE  128                 /* 任务堆栈大小 */
    TaskHandle_t            StartTask_Handler;  /* 任务句柄 */
    StackType_t             start_task_stack[START_STK_SIZE];
    StaticTask_t            start_task_tcb;
    void start_task(void *pvParameters);        /* 任务函数 */
    
  5. 编写任务函数

     StartTask_Handler=xTaskCreateStatic(  (TaskFunction_t) start_task,
                                                    (char * ) "start_task",
                                                    (uint32_t) START_STK_SIZE,
                                                    (void * ) NULL,
                                                    (UBaseType_t) START_TASK_PRIO,
                                                    (StackType_t * ) start_task_stack,
                                                    (StaticTask_t * ) &start_task_tcb );
    

相较于动态创建任务

多了 一个空闲任务内存分配函数和定时器内存分配函数

创建命令 多了两个入口函数

附静态创建任务代码

/*FreeRTOS配置*/

/* START_TASK 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define START_TASK_PRIO 1                   /* 任务优先级 */
#define START_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            StartTask_Handler;  /* 任务句柄 */
StackType_t             start_task_stack[START_STK_SIZE];
StaticTask_t            start_task_tcb;
void start_task(void *pvParameters);        /* 任务函数 */

/* TASK1 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK1_PRIO 2                   /* 任务优先级 */
#define TASK1_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            TASK1_Handler;  /* 任务句柄 */
StackType_t             task1_stack[START_STK_SIZE];
StaticTask_t            task1_tcb;
void TASK1(void *pvParameters);        /* 任务函数 */

/* TASK2 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK2_PRIO 3                   /* 任务优先级 */
#define TASK2_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            TASK2_Handler;  /* 任务句柄 */
StackType_t             task2_stack[START_STK_SIZE];
StaticTask_t            task2_tcb;
void TASK2(void *pvParameters);        /* 任务函数 */

/* TASK3 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK3_PRIO 4                   /* 任务优先级 */
#define TASK3_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            TASK3_Handler;  /* 任务句柄 */
StackType_t             task3_stack[START_STK_SIZE];
StaticTask_t            task3_tcb;
void TASK3(void *pvParameters);        /* 任务函数 */

/******************************************************************************************************/
/*空闲任务配置*/
StaticTask_t idle_task_tcb;
StackType_t idle_task_stack[configMINIMAL_STACK_SIZE];

/*定时器任务配置*/
StaticTask_t timer_task_tcb;
StackType_t timner_task_stack[configTIMER_TASK_STACK_DEPTH];


/*空闲任务内存分配*/
void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, 
                                    StackType_t ** ppxIdleTaskStackBuffer, 
                                    uint32_t *pulIdleTaskStackSize )
{
    * ppxIdleTaskTCBBuffer=&idle_task_tcb;
    * ppxIdleTaskStackBuffer=idle_task_stack;
    * pulIdleTaskStackSize=configMINIMAL_STACK_SIZE;
}
/*定时器任务内存分配*/
void vApplicationGetTimerTaskMemory(    StaticTask_t ** ppxTimerTaskTCBBuffer, 
                                        StackType_t ** ppxTimerTaskStackBuffer, 
                                        uint32_t *pulTimerTaskStackSize )
{
    * ppxTimerTaskTCBBuffer=&timer_task_tcb;
    * ppxTimerTaskStackBuffer=timner_task_stack;
    *pulTimerTaskStackSize=configTIMER_TASK_STACK_DEPTH;
}

void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();
    TASK1_Handler = xTaskCreateStatic(  (TaskFunction_t )TASK1,            /* 任务函数 */
                                        (char*    )"TASK1",          /* 任务名称 */
                                        (uint16_t       )TASK1_STK_SIZE,        /* 任务堆栈大小 */
                                        (void*          )NULL,                  /* 传入给任务函数的参数 */
                                        (UBaseType_t    )TASK1_PRIO,       /* 任务优先级 */
                                        (StackType_t * ) task1_stack,
                                        (StaticTask_t * ) &task1_tcb );
              
    TASK2_Handler =   xTaskCreateStatic((TaskFunction_t )TASK2,            /* 任务函数 */
                                        (char*    )"TASK2",          /* 任务名称 */
                                        (uint16_t       )TASK2_STK_SIZE,        /* 任务堆栈大小 */
                                        (void*          )NULL,                  /* 传入给任务函数的参数 */
                                        (UBaseType_t    )TASK2_PRIO,       /* 任务优先级 */
                                        (StackType_t * ) task2_stack,
                                        (StaticTask_t * ) &task2_tcb );
              
    TASK3_Handler = xTaskCreateStatic(  (TaskFunction_t )TASK3,            /* 任务函数 */
                                        (char*    )"TASK3",          /* 任务名称 */
                                        (uint16_t       )TASK3_STK_SIZE,        /* 任务堆栈大小 */
                                        (void*          )NULL,                  /* 传入给任务函数的参数 */
                                        (UBaseType_t    )TASK3_PRIO,       /* 任务优先级 */
                                        (StackType_t * ) task3_stack,
                                        (StaticTask_t * ) &task3_tcb );
              
                  
    vTaskDelete(NULL);
    taskEXIT_CRITICAL();
}

void TASK1(void *pvParameters)
{
    while(1)
    {
        printf("task1 ruing!!!\n");
        LED0_TOGGLE();
        vTaskDelay(500);
    }
}

void TASK2(void *pvParameters)
{
    while(1)
    {
        printf("task2 ruing!!!\n");
        LED1_TOGGLE();
        vTaskDelay(1000);
    }
}
void TASK3(void *pvParameters)
{
    uint8_t key=0;
  
    while(1)
    {
        printf("task3 ruing!!!\n");
        key=key_scan(0);
        if(key==KEY0_PRES)
        {
            if(TASK1_Handler!=NULL)
            {
                printf("delete task1 \n");
                vTaskDelete(TASK1_Handler);
                TASK1_Handler = NULL;
            }
        }
      
        vTaskDelay(50);
    }
}

评论