FreeRTOS任务相关API

目录

一、任务创建和删除

二、临界区解析

三、任务挂起与解挂


一、任务创建和删除

任务创建函数有三个,分别为

xTaskCreate() 动态创建函数和

xTaskCreateStatic() 静态创建函数

xTaskCreateRestricted()受到 MPU 的保护的创建,

1、xTaskCreate()函数

该函数功能是创建一个任务 使用该函数 宏 configSUPPORT_DYNAMIC_ALLOCATION 必须为 1 

BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,          //任务函数入口,类型为void*
                        const char * const pcName,          //任务函数名,类型为字符串
                        const uint16_t usStackDepth,        //任务堆栈大小
                        void * const pvParameters,          //传递给任务函数的参数
                        UBaseType_t uxPriority,             //任务优先级
                        TaskHandle_t * const pxCreatedTask  //用来保存任务句柄
                      )
  • 参数:

pxTaskCode: 任务函数。

pcName: 任务名字,一般用于追踪和调试,任务名字长度不能超过。configMAX_TASK_NAME_LEN。

usStackDepth: 任务堆栈大小,注意实际申请到的堆栈是 usStackDepth 的 4 倍。其中空闲任务的任务堆栈大 小为 configMINIMAL_STACK_SIZE。

pvParameters: 传递给任务函数的参数。可以为NULL

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

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

  • 返回值:

pdPASS: 任务创建成功。

errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY: 任务创建失败,因为堆内存不足!

《示例代码》

#include "stm32f10x.h"  
#include "FreeRTOS.h"
#include "task.h"
​
#define TASK1_STACK_SIZE 128        //栈区大小宏定义
#define Task1_Priority   3          //任务1优先级宏定义
TaskHandle_t Task1_Handle;          //任务句柄存放定义
    void Task1(void * pvParaeters); //任务函数声明
int main(void)
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
    taskENTER_CRITICAL();//进入临界区
    xTaskCreate((TaskFunction_t  ) Task1,           //函数入口
                (char *          ) "Task1",         //函数名
                (uint16_t        ) TASK1_STACK_SIZE,//栈区大小
                (void *          ) NULL,            //传递给任务函数的参数
                (UBaseType_t     ) Task1_Priority,  //任务优先级
                (TaskHandle_t *  ) &Task1_Handle    //函数句柄
                );
    taskEXIT_CRITICAL();//退出临界区
}
void Task1(void * pvParaeters)//任务函数
{
        while(1)
        {
        }
}

2、xTaskCreateStatic()函数

此函数用来静态创建任务,使用时应将configSUPPORT_STATIC_ALLOCATION 定义为 1

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 )//任务控制块
  • 参数:

pxTaskCode: 任务函数。

pcName: 任务名字,一般用于追踪和调试,任务名字长度不能超过。configMAX_TASK_NAME_LEN。

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

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

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

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

pxTaskBuffer: 任务控制块。

  • 返回值:

任意值 :成功返回任务句柄

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

注意事项:

  • 1、在静态创建时,需要用户自己实现两个函数,通过这两个函数来给空闲任务和定时器服务任务的任务堆

栈和任务控制块分配内存,在FreeRTOS中有定义分别为

vAPPlicationGetIdleTaskMomory();    //
vApplicationGetTimerTaskMemory();   //
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, 
                                    StackType_t **ppxIdleTaskStackBuffer, 
                                    uint32_t *pulIdleTaskStackSize)
{
*ppxIdleTaskTCBBuffer=&IdleTaskTCB;
*ppxIdleTaskStackBuffer=IdleTaskStack;
*pulIdleTaskStackSize=configMINIMAL_STACK_SIZE;
}
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer, 
                                    StackType_t **ppxTimerTaskStackBuffer, 
                                    uint32_t *pulTimerTaskStackSize)
{
    *ppxTimerTaskTCBBuffer=&TimerTaskTCB;
    *ppxTimerTaskStackBuffer=TimerTaskStack;
    *pulTimerTaskStackSize=configTIMER_TASK_STACK_DEPTH;
}
  • 2、还需要定义空闲任务的堆栈和定时器的堆栈

//空闲任务任务堆栈
static StackType_t IdleTaskStack[configMINIMAL_STACK_SIZE];
//空闲任务控制块
static StaticTask_t IdleTaskTCB;
//定时器服务任务堆栈
static StackType_t TimerTaskStack[configTIMER_TASK_STACK_DEPTH];
//定时器服务任务控制块
static StaticTask_t TimerTaskTCB;

《示例代码》

#include "stm32f10x.h"  
#include "FreeRTOS.h"
#include "task.h"
#include "bsp_leds.h"
#include "bsp_keys.h"
#include "oled.h"   
    /****************************静态创建任务*****************************/
void FreeRTOS_Static_CreateTask(void);
    static StackType_t IdleTaskStack[configMINIMAL_STACK_SIZE];         //空闲任务栈
    static StaticTask_t IdleTaskTCB;                                    //空闲任务控制块 TCB
    static StackType_t TimerTaskStack[configTIMER_TASK_STACK_DEPTH];    //定时器任务堆栈
    static StaticTask_t TimerTaskTCB;                                   //定时器任务控制TCB
   
#define START_STASK_SIZE 128
#define Start_STask_Priority 1
#define STACK_SIZE 128
    TaskHandle_t START_STASK_Handle;
    StackType_t Start_STask_Stack[STACK_SIZE];
    StaticTask_t Start_STask_TCB;
    void Start_STask(void * pvParaeters);//启动任务声明
#define STASK1_SIZE 128
#define STask1_Priority 2
#define STACK1_SIZE 128
    TaskHandle_t STASK1_Handle;
    StackType_t STask1_Stack[STACK1_SIZE];
    StaticTask_t STask1_TCB;
    void STask1(void * pvParaeters);
#define STASK2_SIZE 128
#define STask2_Priority 3
#define STACK2_SIZE 128
TaskHandle_t STASK2_Handle;
    StackType_t STask2_Stack[STACK2_SIZE];
    StaticTask_t STask2_TCB;
    void STask2(void * pvParaeters);
    
int main(void)
{
  USART_Config();
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
    printf("FreeRTOS_Start!\r\n");
    FreeRTOS_Static_CreateTask();
}
/*****************用户实现vApplicationGetIdleTaskMemory()*********************/
//            获取空闲任务的堆栈
//用户定义空闲任务的任务堆栈和定时器任务的 任务堆栈
//创建空闲任务和定时器任务时调用这些函数
//vApplicationGetIdleTaskMemory()和vApplicationGetTimerTaskMemory();
​
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, 
                                   StackType_t **ppxIdleTaskStackBuffer, 
                                   uint32_t *pulIdleTaskStackSize)
{
    *ppxIdleTaskTCBBuffer=&IdleTaskTCB;
    *ppxIdleTaskStackBuffer=IdleTaskStack;
    *pulIdleTaskStackSize=configMINIMAL_STACK_SIZE;
}
/*****************用户实现vApplicationGetTimerTaskMemory()*********************/
//            获取定时器任务的堆栈
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer, 
                                    StackType_t **ppxTimerTaskStackBuffer, 
                                    uint32_t *pulTimerTaskStackSize)
{
    *ppxTimerTaskTCBBuffer=&TimerTaskTCB;
    *ppxTimerTaskStackBuffer=TimerTaskStack;
    *pulTimerTaskStackSize=configTIMER_TASK_STACK_DEPTH;
}
void FreeRTOS_Static_CreateTask(void)
{
    printf("FreeRTOS_static_create_Task!!!\r\n");
    START_STASK_Handle = xTaskCreateStatic( (TaskFunction_t) Start_STask,//指向启动任务函数
                            (char *        ) "Start_STask",         //函数名
                            (uint32_t      ) START_STASK_SIZE,      //任务堆栈大小,单位字
                            (void *        ) NULL,                  //传递给任务的参数
                            (UBaseType_t   ) Start_STask_Priority,  //任务优先级
                            (StackType_t * ) Start_STask_Stack,     //任务堆栈一般为一个数组
                            (StaticTask_t *) &Start_STask_TCB       //控制块
                                            );
    vTaskStartScheduler();  //开始任务调度器                                           
}
​
void Start_STask(void * pvParaeters)
{
    taskENTER_CRITICAL();//进入临界区
    STASK1_Handle = xTaskCreateStatic(  (TaskFunction_t) STask1,     //指向任务函数
                                    (char *        ) "STask1",       //函数名
                                    (uint32_t      ) STASK1_SIZE,    //任务堆栈大小,单位字
                                    (void *        ) NULL,           //传递给任务的参数
                                    (UBaseType_t   ) STask1_Priority,//任务优先级
                                    (StackType_t * ) STask1_Stack,   //任务堆栈一般为一个数组
                                        (StaticTask_t *) &STask1_TCB //控制块
                                    );
    STASK2_Handle = xTaskCreateStatic(  (TaskFunction_t) STask2,   //指向任务函数
                                    (char *        ) "STask2",     //函数名
                                    (uint32_t      ) STASK2_SIZE,  //任务堆栈大小,单位字
                                    (void *        ) NULL,           //传递给任务的参数
                                    (UBaseType_t   ) STask2_Priority,//任务优先级
                                    (StackType_t * ) STask2_Stack,   //任务堆栈一般为一个数组
                                    (StaticTask_t *) &STask2_TCB     //控制块
                                    );
    
    taskEXIT_CRITICAL();//退出临界区
    vTaskDelete(START_STASK_Handle);//删除创建函数
}
void STask1(void * pvParaeters)
{
    while(1)
    {
        printf("正在执行任务1!!!\r\n");;
        vTaskDelay(3000);
    }
}
void STask2(void * pvParaeters)
{
    while(1)
    {
        printf("正在执行任务2!!!\r\n");
        vTaskDelay(1000);
    }
}

3、xTaskCreateRestricted()函数

此函数也是用来创建任务的,只不过此函数要求所使用的 MCU 有 MPU(内存保护单元),

用此函数创建的任务会受到 MPU 的保护。其他的功能和函数 xTaxkCreate()一样。

BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, 
                                  TaskHandle_t * pxCreatedTask 
                                )
  • 参数:

pxTaskDefinition: 指向一个结构体 TaskParameters_t,这个结构体描述了任务的任务函数、堆栈大小、优先级 等。此结构体在文件 task.h 中有定义。

pxCreatedTask: 任务句柄。

  • 返回值:

pdPASS: 任务创建成功。

其他值: 任务未创建成功,很有可能是因为 FreeRTOS 的堆太小了。

4、任务删除函数

使用该函数时,应该将INCLUDE_vTaskDelete配置为1 用于任务的删除

void vTaskDelete(TaskHandle_t xTaskToDelete);
  • 参数

xTaskToDelete :被删除任务的句柄,当静态任务被删除时需要手动释放任务内存,当参数为NULL时,删除当前任务。

  • 返回值

二、临界区解析

在好多操作中,都需要进入临界区执行,目的只想下面的操作时不被其他任务打断,其本质就是关闭所有中断

1、进入临界区函数

taskENTER_CRITICAL();//

这是一个两级的宏定义,最终起作用的是port.c中366行:

void vPortEnterCritical( void )
{
    portDISABLE_INTERRUPTS();   //关闭所有中断
    uxCriticalNesting++;
​
    /* This is not the interrupt safe version of the enter critical function so
    assert() if it is being called from an interrupt context.  Only API
    functions that end in "FromISR" can be used in an interrupt.  Only assert if
    the critical nesting count is 1 to protect against recursive calls if the
    assert function also uses a critical section. */
    if( uxCriticalNesting == 1 )
    {
        configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
    }
}

2、退出临界区函数

taskEXIT_CRITICAL(); //

同样的这也是一个两级的宏定义,最终起作用的是port.c中383行:

void vPortExitCritical( void )
{
    configASSERT( uxCriticalNesting );
    uxCriticalNesting--;
    if( uxCriticalNesting == 0 )
    {
        portENABLE_INTERRUPTS();  //开启所有中断
    }
}

三、任务挂起与解挂

1、任务的挂起函数

使用该函数应该将宏INCLUDE_vTaskSuspend置1

void vTaskSuspend( TaskHandle_t xTaskToSuspend );//
  • 参数

xTaskToSuspend:被挂起的任务句柄,若该参数为NULL时,挂起当前任务。

  • 返回值

2、任务的解挂函数

-任务级-

void vTaskResume( TaskHandle_t xTaskToResume);
  • 参数

xTaskToSuspend:被挂起的任务句柄。

  • 返回值

-中断级-

void TaskResumeFromISR( TaskHandle_t xTaskToResume);

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

  • 参数

xTaskToSuspend:被挂起的任务句柄。

  • 返回值

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小米和小米粥

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

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

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

打赏作者

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

抵扣说明:

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

余额充值