FreeRTOS学习--10讲 任务的创建与删除

FreeRTOS学习--10讲 任务的创建与删除_第1张图片

FreeRTOS学习--10讲 任务的创建与删除_第2张图片

FreeRTOS学习--10讲 任务的创建与删除_第3张图片

动态创建任务API:

portBASE_TYPE xTaskCreate( pdTASK_CODE pvTaskCode,         
                            //pvTaskCode只一个指向任务的实现函数的指针(效果上仅仅是函数名)。
                            const char * const pcName, 
                            //pcName 具有描述性的任务名,只在调试时使用(可以用 config_MAX_TASK_NAME_LEN定义最大长度,超过会被截断)
                            unsigned portSHORT usStackDepth,
                            //分配多少字的空间,一个字等于4个字节
                            void *pvParameters, 
                            //接受传入void的参数,可以是字符串
                            unsigned portBASE_TYPE uxPriority, 
                            //设置优先级,一般取符合需求的最小值
                            xTaskHandle *pxCreatedTask );
                            //用于传出任务的句柄,也是任务控制块,在API调用删除修改该函数时使用,不用可以设为NULL
返回值可以是

           a.pdTRUE 表明任务创建成功
           b.errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY 由于内存堆空间不足,分配不出,所以无法创建

静态创建任务API

portBASE_TYPE xTaskCreateStatic( pdTASK_CODE pvTaskCode,         
                            //pvTaskCode只一个指向任务的实现函数的指针(效果上仅仅是函数名)。
                            const signed portCHAR * const pcName, 
                            //pcName 具有描述性的任务名,只在调试时使用(可以用config_MAX_TASK_NAME_LEN定义最大长度,超过会被截断)
                            unsigned portSHORT usStackDepth,
                            //需要多少字的空间,一个字等于4个字节
                            void *pvParameters, 
                            //接受传入void的参数,可以是字符串
                            unsigned portBASE_TYPE uxPriority, 
                            //设置优先级,一般取符合需求的最小值
                            StackType_t* const puxStackBuffer,
                            //任务堆栈,一般为数组,用户自己给堆栈分配大小
                            StaticTask_t* const pxTaskBuffer)
                            //任务控制块指针,又用户分配
返回值可以是

           a.其他值 表明任务创建成功
           b.NULL 内存不足,分配不出,任务失败

删除任务API

void vTaskDelete(xTaskHandle pxTaskToDelete);
           参数:目标任务的句柄
a.任务可以通过传入NULL删除自己
b.通过空闲任务将分配给已删除任务的内存释放掉
c.静态任务的删除,需要用户在任务被删除前提前释放之前申请的内存
d.使用删除任务函数需将洪INCLUDE_vTaskDelete配置为1

任务控制块结构成员

typedef struct tskTaskConlBlock
{
    volatile StackType_t       *pxTopOfStack;           //任务栈顶,必须为TCB的第一个成员
    Listltem_t                        xStateListltem;            //任务状态列表项
    Listltem_t                        xRvevtListltem;           //任务事件列表项
    UBaseType_t                  uxPriority;                   //任务优先级,数值越大,优先级越高
    StackType_t                   *pxStack;                     //任务栈起始地址
    portCHAR                        pcTaskName[configMAX_TASK_NAME_LEN];//任务名字
}tskTCB

任务执行中的原则

a.高优先级抢占低优先级,实现资源利用
b.通过阻塞高优先级,运行较低优先级,实现资源利用
c.然后解除阻塞,又运行高优先级(优先级数值越低,优先级越低)
d.优先级任务是个容器,把要运行的任务放进去,优先级任务会置1,表示里面有任务,在就绪列表中就能被选中,变成运行态

一个用rtos点亮LED的程序

主函数:

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
#include "./BSP/SRAM/sram.h"
#include "./MALLOC/malloc.h"
#include "freertos_demo.h"


int main(void)
{

    HAL_Init();                         /* 初始化HAL库 */
    sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
    delay_init(168);                    /* 延时初始化 */
    usart_init(115200);                 /* 串口初始化为115200 */
    led_init();                         /* 初始化LED */
    lcd_init();                         /* 初始化LCD */
    key_init();                         /* 初始化按键 */
    sram_init();                        /* SRAM初始化 */
    
    my_mem_init(SRAMIN);                /* 初始化内部SRAM内存池 */
    my_mem_init(SRAMEX);                /* 初始化外部SRAM内存池 */
    my_mem_init(SRAMCCM);               /* 初始化内部CCM内存池 */


    freertos_demo();                    //freertos函数

}

FreeRTOS函数做法一:

静态任务的创建和释放

需要把FreeRTOSConfig.h中的configSUPPORT_STATIC_ALLOCATION(第39行)置1     

#include "freertos_demo.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"

/* START_TASK 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务 分配数组空间 任务控制块
 */
#define START_TASK_PRIO      1                                   //优先级大小
#define START_TASK_STACK_SIZE 128                                //堆栈大小
TaskHandle_t  start_task_handler;                                //任务句柄
StackType_t start_task_stack[START_TASK_STACK_SIZE];             //创建数组,分配空间
StaticTask_t start_task_tcb;                                     //任务控制块
void start_task(void * pvParameters);                            //创建任务

/* TASK1 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务 分配数组空间 任务控制块
 */
#define TASK1_PRIO      2
#define TASK1_STACK_SIZE 128
TaskHandle_t  task1_handler;
StackType_t task1_stack[TASK1_STACK_SIZE];
StaticTask_t task1_tcb;
void task1(void* pv);

/* TASK2 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务 分配数组空间 任务控制块
 */
#define TASK2_PRIO      3
#define TASK2_STACK_SIZE 128
TaskHandle_t  task2_handler;
StackType_t task2_stack[TASK2_STACK_SIZE];
StaticTask_t task2_tcb;
void task2(void* pv);

/* TASK3 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务 分配数组空间 任务控制块
 */
#define TASK3_PRIO      4
#define TASK3_STACK_SIZE 128
TaskHandle_t  task3_handler;
StackType_t task3_stack[TASK3_STACK_SIZE];
StaticTask_t task3_tcb;
void task3(void* pv);

//空闲任务配置
//任务控制块 分配堆栈 堆栈大小
StaticTask_t idle_task_tcb;
StackType_t idle_task_stack[configMINIMAL_STACK_SIZE];

//软件定时器任务配置
//任务控制块 分配堆栈 堆栈大小
StaticTask_t timer_task_tcb;
StackType_t timer_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 = timer_task_stack;
    * pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}

void freertos_demo(void)
{    
    start_task_handler = xTaskCreateStatic( (TaskFunction_t )   start_task,                 //指向函数的指针
                                            (char *         )   "start_task",               //任务名
                                            ( uint32_t      )   START_TASK_STACK_SIZE,      //任务需要的空间大小
                                            (void *         )   NULL,                       //函数带入的参数,这里没有
                                            (UBaseType_t    )   START_TASK_PRIO,            //优先级
                                            (StackType_t *  )   start_task_stack,           //静态需要的,人为分配内存空间数组
                                            (StaticTask_t * )   &start_task_tcb);           //任务控制块
    vTaskStartScheduler();  //任务调度器,开启后系统才会自动协调任务
}

void start_task(void* pvPara)
{
    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      )   TASK1_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);
    /*创建任务也可以写成
    task3_handler = xTaskCreateStatic(task3,"task3",TASK3_STACK_SIZE,NULL,TASK3_PRIO,task3_stack,&task3_tcb)
    这里为了方便定义参数,所以保留了也做了强转
    */
    vTaskDelete(start_task_handler);   //删除任务,虽然是静态任务,但因为申请的内存是静态数组,所以不用自己释放,系统会自动释放
    taskEXIT_CRITICAL();            //退出临界区
}

//任务一 实现LED0每500ms翻转一次
void task1(void* pv)
{
    while(1)
    {
        printf("task1正在运行\r\n");
        LED0_TOGGLE();          //反转API
        vTaskDelay(500);        //阻塞500毫秒
    }
}

//任务二 实现LED1每500ms翻转一次
void task2(void* pv)
{
     while(1)
    {
        printf("task2正在运行\r\n");
        LED1_TOGGLE();
        vTaskDelay(500);
    }
}

//任务三 判断按键KEY0,按下KEY0删除task1
void task3(void* pv)
{
    uint8_t key = 0;
    while(1)
    {
        printf("task3正在运行\r\n");
        key = key_scan(0);      //定义按键为按键0
        if(key == KEY0_PRES)    //按键0按下
        {
            printf("删除task1任务\r\n");
            vTaskDelete(task1_handler);
        }
        vTaskDelay(10);         //阻塞10毫秒
    }
}


FreeRTOS函数做法二:

动态任务的创建与释放:

需要把FreeRTOSConfig.h中的configSUPPORT_DYNAMIC_ALLOCATION(第40行)置1 

#include "freertos_demo.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"



/* START_TASK 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define START_TASK_PRIO      1              //优先级
#define START_TASK_STACK_SIZE 128           //堆栈大小
TaskHandle_t  start_task_handler;           //任务句柄
void start_task(void * pvParameters);       //创建任务

/* TASK1 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK1_PRIO      2
#define TASK1_STACK_SIZE 128
TaskHandle_t  task1_handler;
void task1(void* pv);

/* TASK2 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK2_PRIO      3
#define TASK2_STACK_SIZE 128
TaskHandle_t  task2_handler;
void task2(void* pv);
 
/* TASK3 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK3_PRIO      4
#define TASK3_STACK_SIZE 128
TaskHandle_t  task3_handler;
void task3(void* pv);
/******************************************************************************************************/


/**
 * @brief       FreeRTOS例程入口函数
 * @param       无
 * @retval      无
 */
void freertos_demo(void)
{    
    xTaskCreate((TaskFunction_t    )    start_task,                 //任务名
                (char*             )    "start_task",               //别名
                (unsigned portSHORT)    START_TASK_STACK_SIZE,      //需要的内存大小
                (void *            )    NULL,                       //函数带入的参数,这里不需要
                (portBASE_TYPE     )    START_TASK_PRIO,            //优先级
                (TaskHandle_t*     )    &start_task_handler );      //任务控制块
    vTaskStartScheduler(); //任务调度器,开启后系统才会自动协调任务
}

void start_task(void* pvPara)
{
    taskENTER_CRITICAL();         //进入临界区
    xTaskCreate((TaskFunction_t    )    task1, 
                (char*             )    "task1", 
                (unsigned portSHORT)    TASK1_STACK_SIZE, 
                (void *            )    NULL, 
                (portBASE_TYPE     )    TASK1_PRIO, 
                (TaskHandle_t*     )    &task1_handler );
  
                
    xTaskCreate((TaskFunction_t    )    task2, 
                (char*             )    "task2", 
                (unsigned portSHORT)    TASK2_STACK_SIZE, 
                (void *            )    NULL, 
                (portBASE_TYPE     )    TASK2_PRIO, 
                (TaskHandle_t*     )    &task2_handler );

    xTaskCreate((TaskFunction_t    )    task3, 
                (char*             )    "task3", 
                (unsigned portSHORT)    TASK3_STACK_SIZE, 
                (void *            )    NULL, 
                (portBASE_TYPE     )    TASK3_PRIO, 
                (TaskHandle_t*     )    &task3_handler );

    vTaskDelete(NULL);              //删除任务自身
    taskEXIT_CRITICAL();            //退出临界区
}

//任务一 实现LED0每500ms翻转一次
void task1(void* pv)
{
    while(1)
    {
        printf("task1正在运行\r\n");
        LED0_TOGGLE();      //反转api
        vTaskDelay(500);
    }
}

//任务二 实现LED1每500ms翻转一次
void task2(void* pv)
{
     while(1)
    {
        printf("task2正在运行\r\n");
        LED1_TOGGLE();
        vTaskDelay(500);
    }
}

//任务三 判断按键KEY0,按下KEY0删除task1
void task3(void* pv)
{
    uint8_t key = 0;
    while(1)
    {
        printf("task3正在运行\r\n");
        key = key_scan(0);
        if(key == KEY0_PRES)
        {
            printf("删除task1任务\r\n");
            vTaskDelete(task1_handler);
        }
        vTaskDelay(10);
    }
}

你可能感兴趣的:(学习)