FreeRTOS系统介绍——任务

1、任务状态

FreeRTOS中的任务总共有如下几种状态:

1、Running(运行态)

当前正在使用处理器的任务就是处于运行态。

2、Ready(就绪态)

可以运行但没有运行的任务处于就绪态。

3、Blocked(阻塞态)

任务正在等待某个事件,则称该任务处于阻塞态。事件总共有两种不同类型的事件:

1、定时事件:这类事件可以是延迟到期或是绝对时间到点,一般是使用

vTaskDelay()/vTakDelayUntil()这两个API函数实现延迟多长时间。

2、同步事件:源于其它任务或中断事件。任务可以在等待同步事件时指定一个等待超时时间,这样可以实现阻塞状态下同时等待两种类型的事件。

4、Suspended(挂起态)

调用vTaskSuspend()API函数可以把一个任务挂起,调用vTaskResume()API函数把任务重新唤醒,即退出挂起态。处于挂起态的任务对调度器是不可见的,永远不会运行。

任务状态之间的转换关系如下图所示:

2、任务优先级

应用程序在文件FreeRTOSConfig.h中设定的宏定义配置常量configMAX_PRIORITIES的值即是最多可具有优先级的数目。但这个值越大,内核花销的内存空间越多,建议将此常量设为能够用的最小值。这个值越大代表优先级越高,优先级号0表示最低优先级。

有效优先级范围从0到(configMAX_PRIORITIES-1)。

不同任务可共享同一个优先级,且不限任务数量。调度器总是在就绪任务列表中选择最高优先级的任务执行。若被选中的优先级上具有不止一个任务,调度器会以每个时间片为单位轮流执行任务。时间片的长度通过心跳中断频率进行设定,即由configTICK_RATE_HZ进行配置。此功能需要系统中开启时间片调度,即常量configUSE_TIME_SLICING配置为1,该值默认为1。

一般任务在创建时会设置优先级,但也可以在调度器启动后通过API函数vTaskPrioritySet()改变任何任务的优先级。

3、空闲任务与空闲任务钩子函数

空闲任务

空闲任务的创建是在API函数vTaskStartScheduler()启调度表中自动创建的。空闲任务大小是由宏定义常量configMINIMAL_STACK_SIZE定义的。优先级一般设置为0,以保证空闲任务最低优先级。应用任务可以设置与空闲任务相同优先级。

空闲任务钩子函数

使用空闲任务钩子函数必须将宏定义常量configUSE_IDLE_HOOK必须定义为1。空闲任务钩子函数一般被用来执行低优先的功能代码,测试系统的负载能力。配置处理器进入低功耗模式。该钩子函数不能阻塞或挂起。若应用程序调用了API函数vTaskDelete(),则钩子函数的执行时间必须足够短。因为任务删除后,空闲任务负责回收内核资源,若一直运行钩子函数,则无法进行回收工作。

4、调度算法

如下图执行流程展现抢占式调度的行为方式:

1.空闲任务

空闲任务具有最低优先级,当有更高优先级任务处于就绪态时,空闲任务就会被抢占,如图中t3,t5,t9时刻。

2.任务3

任务3为一个事件驱动任务,其工作在相对较低的优先级,但优先级高于空闲任务。每当事件发生时其就从阻塞态转移到就绪态。该类事件包括队列、信号量读写等。

3.任务2

任务2时一个周期性任务,其优先级高于任务3,并低于任务1。根据周期间隔,任务2期望在t1,t6,t9时执行。

4.任务1

任务1也是事件驱动任务。但具有最高优先级,因此可以抢占系统中任何其它任务。

5、任务创建

任务创建和删除的API函数如下图:

1、函数xTaskCreate()原型如下:

参数:

pxTaskCode:任务函数

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

usStackDepth:任务堆栈大小,实际申请的堆栈是usStackDepth的4倍。

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

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

pxCreatedTask:任务句柄,任务创建以后会返回该任务的任务句柄,该句柄就是任务的堆栈

返回值:

pdPASS:任务创建成功

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

2、函数xTaskCreateStatic()原型如下:

3、函数xTaskCreateRestricted()原型如下图:

其中参数pxTaskDefinition类型如下图:

4、函数vTaskDelete()原型如下图:

6、测试代码如下:

#include "sky_task.h"
//任务优先级
#define  Sky_Period_Priority_100ms                      5
#define  Sky_Event_Priority_One                         6
#define  Sky_Event_Priority_Two                         4

//任务堆栈
#define  Sky_Period_StackDepthSize_100ms                500
#define  Sky_Event_StackDepthSize_One                   500        
#define  Sky_Event_StackDepthSize_Two                   500   

//任务句柄
TaskHandle_t  Sky_Period_Handle_100ms;
TaskHandle_t  Sky_Event_Handle_One;
TaskHandle_t  Sky_Event_Handle_Two;

//任务队列
QueueHandle_t QueueTestOne;
QueueHandle_t QueueTestTwo;

/*
*@brief 周期任务函数
*@param null
*@retval null
*/
static void Sky_Period_Task_100ms(void)
{
    static uint8_t cnt = 0;
    while(1)
    {
        if((cnt == 5) || (cnt == 10))
        {
            xQueueSend(QueueTestTwo, &cnt, portMAX_DELAY);
            if(cnt == 10)
            {
                xQueueSend(QueueTestOne, &cnt, portMAX_DELAY);
                cnt = 0;
            }
        }
        printf("Sky_Period_Task_100ms task Running cnt:%d\r\n",cnt++);
        vTaskDelay(100);
    }


}

/*
*@brief 事件任务函数
*@param null
*@retval null
*/
static void Sky_Event_Task_One(void)
{
    uint8_t buffer = 0;
    while(1)
    {
        if(xQueueReceive(QueueTestOne, &buffer, portMAX_DELAY) == pdTRUE)
        {
            printf("Sky_Event_Task_One task Receive queue :%d",buffer);
        }
    }
}

/*
*@brief 事件任务函数
*@param null
*@retval null
*/
static void Sky_Event_Task_Two(void)
{
    uint8_t buffer = 0;
    while(1)
    {
        if(xQueueReceive(QueueTestTwo, &buffer, portMAX_DELAY) == pdTRUE)
        {
            printf("Sky_Event_Task_Two task Receive queue :%d",buffer);
        }
    }
}

/*
*@brief 空闲钩子函数
*@param null
*@retval null
*/
void vApplicationIdleHook(void)
{
    static uint32_t count = 0;
    printf("Idle Task Hook Running count:%d\r\n", count++);
}

/*
*@brief 任务创建主函数
*@param null
*@retval null
*/
void Sky_Appmain(void)
{
    BaseType_t ret;
    QueueTestOne = xQueueCreate(1, 1);
    QueueTestTwo = xQueueCreate(1, 1);
    if((QueueTestOne != NULL)&&(QueueTestTwo != NULL))
    {
        printf("QueueTestOne and QueueTestTwo create succeed\r\n");
    }
    
    ret = xTaskCreate((TaskFunction_t)Sky_Period_Task_100ms,
                      (const char*)  "Sky_Period_Task_100",
                      (const uint16_t)Sky_Period_StackDepthSize_100ms,
                      (void *)        NULL,
                      (UBaseType_t)   Sky_Period_Priority_100ms,
                      (TaskHandle_t *)&Sky_Period_Handle_100ms);
    if(ret != pdTRUE)
    {
        printf("Sky_Period_Task_100ms Create Failed\r\n");
    }

    ret = xTaskCreate((TaskFunction_t)Sky_Event_Task_One,
                      (const char*)  "Sky_Event_Task_One",
                      (const uint16_t)Sky_Event_StackDepthSize_One,
                      (void *)        NULL,
                      (UBaseType_t)   Sky_Event_Priority_One,
                      (TaskHandle_t *)&Sky_Event_Handle_One);
    if(ret != pdTRUE)
    {
        printf("Sky_Event_Task_One Create Failed\r\n");
    } 

    ret = xTaskCreate((TaskFunction_t)Sky_Event_Task_Two,
                      (const char*)  "Sky_Event_Task_Two",
                      (const uint16_t)Sky_Event_StackDepthSize_Two,
                      (void *)        NULL,
                      (UBaseType_t)   Sky_Event_Priority_Two,
                      (TaskHandle_t *)&Sky_Event_Handle_Two);
    if(ret != pdTRUE)
    {
        printf("Sky_Event_Task_Two Create Failed\r\n");
    } 

    vTaskStartScheduler();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

sky丶半导体

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

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

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

打赏作者

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

抵扣说明:

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

余额充值