当前位置:   article > 正文

FreeRTOS任务API函数的使用_xtaskcreate xtaskcreatestatic

xtaskcreate xtaskcreatestatic

这篇文章最后的demo工程可以在网盘中自行下载:
链接:https://pan.baidu.com/s/1o1U-niMKu0RuDAFio1nKMA 密码:ysev

本文是《ALIENTEK STM32F429 FreeRTOS 开发教程》第六章学习笔记
第一章笔记–FreeRTOS简介与源码下载
第二章笔记–FreeRTOS在STM32F4上移植
第三章笔记-FreeRTOS系统配置
第四章笔记-FreeRTOS中断分析
第四章笔记补充-FreeRTOS临界段代码
第五章笔记-FreeRTOS任务基础

1. 任务创建和删除API函数

1.1 xTaskCreate()

函数xTaskCreate()使用动态的方法创建一个任务,创建人物所需的RAM自动从FreeRTOS的堆中分配,宏configSUPPORT_DYNAMIC_ALLOCATION必须为1

函数原型:

    BaseType_t xTaskCreate( 
    TaskFunction_t pxTaskCode,
    const char * const pcName,
    const uint16_t usStackDepth,
    void * const pvParameters,
    UBaseType_t uxPriority,
    TaskHandle_t * const pxCreatedTask ) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

pxTaskCode: 任务函数

pcName: 任务名字,任务名字长度不能超过 configMAX_TASK_NAME_LEN

usStackDepth: 任务堆栈大小,实际申请堆栈是usStackDepth的4倍(因为这里是uint16,而申请时的类型是uint32).空闲任务的堆栈大小为configMINIMAL_STACK_SIZE

pvParameters: 传递给任务函数的参数

uxPriotiry: 任务优先级,范围0~configMAX_PRIORITIES-1

pxCreatedTask: 任务句柄,任务创建成功以后返回此任务的任务句柄,任务句柄其实就是这个任务的任务堆栈。此参数就是用来保存这个任务句柄,其他API函数可能会使用到这个任务句柄。

返回值:

pdPASS: 任务创建成功

errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY: 任务创建失败,堆内存不足。

1.2 xTaskCreateStatic()

此函数与xTaskCreate()的功能相同,但是创建任务所需的RAM需要用户来提供,宏configSUPPORT_STATIC_ALLOCATION必须定义为1

函数原型:

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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

pxTaskCode: 任务函数

pcName:任务名字,任务名字长度不能超过 configMAX_TASK_NAME_LEN

usStackDepth: 任务堆栈大小,由于此函数是用静态方法创建任务,所以任务堆栈由用户给出,一般是一个数组,此参数就是这个数组的大小

pvParameters: 传递给任务函数的参数

uxPriotiry: 任务优先级,范围0~configMAX_PRIORITIES-1

puxStackBuffer: 任务堆栈,一般为数组,类型为StackType_t

pxTaskBuffer: 任务控制块

返回值:

NULL: 任务创建失败,pxTaskBuffer或puxStackBuffer为NULL时会导致错误发生

其他值:任务创建成功,返回任务的任务句柄

1.3 VTaskDelete()

删除一个已经创建乐的任务,被删除的任务不再存在(不会进入运行态)。任务被删除后不能再使用此任务的句柄。

若是用动态方法创建,删除任务后,此任务之前申请的堆栈和控制块内存会在空闲任务中被释放掉,因此当调用函数vTaskDelete()删除任务以后必须给空闲任务一定的运行时间

若是静态方法创建任务,删除任务后用户分配给任务的内存需要用户自行释放掉。

函数原型:

void vTaskDelete( TaskHandle_t xTaskToDelete )
  • 1

xTaskDelete: 要删除的任务的任务句柄

2. 任务创建和删除

2.1 任务相关声明:

//任务优先级
#define START_TASK_PRIO         1
//任务堆栈大小    
#define START_STK_SIZE          256  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);

//任务优先级
#define LED0_TASK_PRIO      2
//任务堆栈大小    
#define LED0_STK_SIZE       50  
//任务句柄
TaskHandle_t LED0Task_Handler;
//任务函数
void led0_task(void *pvParameters);

//任务优先级
#define LED1_TASK_PRIO      3
//任务堆栈大小    
#define LED1_STK_SIZE       50  
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

声明了每个任务的优先级,堆栈大小和句柄,以及任务函数

2.2 main()

int main(void)
{
  HAL_Init();                     //初始化HAL库   
  Stm32_Clock_Init(360,25,2,8);   //设置时钟,180Mhz
    delay_init(180);                //初始化延时函数
    uart_init(115200);              //初始化串口
  LED_Init();                     //初始化LED 

    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();//开启任务调度
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

用来初始化相关硬件,并且调用函数xTaskCreate()创建start_task任务,再调用函数vTaskStartScheduler()开启FreeRTOS的任务调度器,FreeRTOS开始运行

2.3 任务函数

//开始任务任务函数
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //进入临界区
    //创建LED0任务
    xTaskCreate((TaskFunction_t )led0_task,         
                (const char*    )"led0_task",       
                (uint16_t       )LED0_STK_SIZE, 
                (void*          )NULL,              
                (UBaseType_t    )LED0_TASK_PRIO,    
                (TaskHandle_t*  )&LED0Task_Handler);   
    //创建LED1任务
    xTaskCreate((TaskFunction_t )led1_task,     
                (const char*    )"led1_task",   
                (uint16_t       )LED1_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )LED1_TASK_PRIO,
                (TaskHandle_t*  )&LED1Task_Handler);        
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
}
//LED0任务函数 
void led0_task(void *pvParameters)
{
    while(1)
    {
        LED0=~LED0;
        vTaskDelay(500);
    }
}   

//LED1任务函数
void led1_task(void *pvParameters)
{
    while(1)
    {
        LED1=0;
        vTaskDelay(200);
        LED1=1;
        vTaskDelay(800);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

start_task任务的任务函数中创建了另外两个任务led0_task和led1_task。这个任务用来创建其他任务,完成之后调用vTaskDelete(StartTask_Handler)删除掉开始任务

led0_task的任务函数每隔500ms让LED0亮灭反转,led1_task的任务函数间隔200ms和800ms来回反转LED1

3. 任务挂起和恢复API函数

暂停某个任务的运行,过一段时间再重新运行。 任务挂起后任务中变量保存的值不变,而任务删除和重建后任务中变量保存的值会丢失。

3.1 vTaskSuspend()

此函数用于将某个任务设置为挂起状态。

函数原型:

void vTaskSuspend( TaskHandle_t xTaskToSuspend )
  • 1

xTaskToSuspend: 要挂起任务的任务句柄。如果参数为NULL表示挂起任务自己。

3.2 vTaskResume()

将一个任务从挂起态恢复到就绪态

函数原型:

void vTaskResume( TaskHandle_t xTaskToResume )
  • 1

xTaskToResume: 要恢复任务的任务句柄

3.3 xTaskResumeFromISR()

此函数用于在中断服务函数中恢复一个任务,是vTaskResume()的中断版本
函数原型:

BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )
  • 1

xTaskResumeFromISR:要恢复任务的任务句柄

返回值:

pdTRUE: 恢复运行的任务的任务优先级等于或高于正在运行的任务(被中断打断的任务),在退出中断服务函数以后必须进行一次上下文切换

pdFALSE: 恢复运行的任务的任务优先级低于正在运行的任务(被中断打断的任务),在退出中断服务函数以后不需要进行一次上下文切换

4. 任务挂起和恢复

4.1 任务相关声明:

#define START_TASK_PRIO         1
//任务堆栈大小    
#define START_STK_SIZE          256  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);

//任务优先级
#define KEY_TASK_PRIO   2
//任务堆栈大小    
#define KEY_STK_SIZE        128  
//任务句柄
TaskHandle_t KEYTask_Handler;
//任务函数
void key_task(void  *pvParameters);

//任务优先级
#define LED0_TASK_PRIO      3
//任务堆栈大小    
#define LED0_STK_SIZE       50  
//任务句柄
TaskHandle_t LED0Task_Handler;
//任务函数
void led0_task(void *pvParameters);

//任务优先级
#define LED1_TASK_PRIO      4
//任务堆栈大小    
#define LED1_STK_SIZE       50  
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void  *pvParameters);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

4.2 main()

int main(void)
{
  HAL_Init();                     //初始化HAL库   
  Stm32_Clock_Init(360,25,2,8);   //设置时钟,180Mhz
    delay_init(180);                //初始化延时函数
    uart_init(115200);              //初始化串口
  LED_Init();                     //初始化LED 
  KEY_Init();                     //初始化KEY

    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();//开启任务调度
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

4.3 任务函数

//开始任务任务函数
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //进入临界区
      //创建KEY任务
        xTaskCreate((TaskFunction_t )key_task,      
                (const char*    )"key_task",    
                (uint16_t       )KEY_STK_SIZE, 
                (void*          )NULL,              
                (UBaseType_t    )KEY_TASK_PRIO, 
                (TaskHandle_t*  )&KEYTask_Handler);  
    //创建LED0任务
    xTaskCreate((TaskFunction_t )led0_task,         
                (const char*    )"led0_task",       
                (uint16_t       )LED0_STK_SIZE, 
                (void*          )NULL,              
                (UBaseType_t    )LED0_TASK_PRIO,    
                (TaskHandle_t*  )&LED0Task_Handler);   
    //创建LED1任务
    xTaskCreate((TaskFunction_t )led1_task,     
                (const char*    )"led1_task",   
                (uint16_t       )LED1_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )LED1_TASK_PRIO,
                (TaskHandle_t*  )&LED1Task_Handler);        
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
}
//KEY任务函数
void key_task(void *pvParameters)
{
    u8 key;
    while(1)
    {
        key=KEY_Scan(0);
        switch(key)
        {
            case WKUP_PRES:
                vTaskSuspend(LED0Task_Handler);//挂起任务led0
                printf("挂起LED0!\r\n");
                break;
            case KEY0_PRES:
                vTaskResume(LED0Task_Handler);  //恢复任务led0
                printf("恢复LED0!\r\n");
                break;
            case KEY1_PRES:
                vTaskSuspend(LED1Task_Handler);//挂起任务led1
                printf("挂起LED1!\r\n");
                break;
            case KEY2_PRES:
                vTaskResume(LED1Task_Handler);//恢复任务led1
                printf("恢复LED1!\r\n");
                break;  
        }
        vTaskDelay(10);         //延时10ms 
    }
}
//LED0任务函数 
void led0_task(void *pvParameters)
{
    while(1)
    {
        LED0=~LED0;
        vTaskDelay(500);
    }
}   

//LED1任务函数
void led1_task(void *pvParameters)
{
    while(1)
    {
        LED1=0;
        vTaskDelay(200);
        LED1=1;
        vTaskDelay(800);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78

start_task任务创建了三个任务函数后删除自己;

key_task任务函数进行按键扫描,当WKUP按下 挂起任务led0_task;当KEY0按下,恢复任务led0_task;当KEY1按下,挂起任务led1_task;当KEY2按下,恢复任务led1_task;并且串口输出打印在电脑端显示
这里写图片描述

led0_task和led1_task 分别控制LED0和LED1闪烁

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号