https://www.freertos.org/a00106.html

1,freertos任务管理

是让初学者从裸机的,单任务编程过渡到带 OS 的,多任务编程上来,搞清楚了这一点, 那么 FreeRTOS 学习就算入门了。

1.1单任务系统

前后台系统:循环是后台,中断是前台。

1.1.1查询方式

1.1.2中断方式

优缺点:

  • 必须在中断(ISR)内处理时间关键运算:
    • ISR 函数变得非常复杂,并且需要很长执行时间。
    • ISR 嵌套可能产生不可预测的执行时间和堆栈需求。
  • 超级循环和 ISR 之间的数据交换是通过全局共享变量进行的:
    • 应用程序的程序员必须确保数据一致性。
  • 超级循环可以与系统计时器轻松同步,但:
    • 如果系统需要多种不同的周期时间,则会很难实现。
    • 超过超级循环周期的耗时函数需要做拆分。
    • 增加软件开销,应用程序难以理解。
  • 超级循环使得应用程序变得非常复杂,因此难以扩展:
    • 一个简单的更改就可能产生不可预测的副作用,对这种副作用进行分析非常耗时。
    • 超级循环概念的这些缺点可以通过使用实时操作系统 (RTOS) 来解决。

1.2多任务系统

多任务系统运行过程

FreeRTOS 就是一款支持多任务运行的实时操作系统,具有时间片,抢占式和合作式三种调度方法。

1.3 freertos 任务栈设置

任务栈大小,单位 word,也就是 4 字节

任务栈空间是在 任务创建的时候从 FreeRTOSConfig.h 文件中定义的 heap 空间中申请的

#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 17 * 1024 ) )

xTaskCreate( vTaskTaskUserIF, /* 任务函数 */
 "vTaskUserIF", /* 任务名 */
 512, /* 任务栈大小,单位 word,也就是 4 字节 */
 NULL, /* 任务参数 */
 1, /* 任务优先级*/
 &xHandleTaskUserIF ); /* 任务句柄 */

1.4freertos系统栈设置

1,由于 Cortex-M3 和 M4 内核具有双堆栈指针,MSP 主堆栈指针和 PSP 进程堆栈指针,或者叫 PSP 任务堆栈指针也是可以的。在 FreeRTOS 操作系统中,主堆栈指针 MSP 是给系统栈空间使用的,进 程堆栈指针 PSP 是给任务栈使用的。也就是说,在 FreeRTOS 任务中,所有栈空间的使用都是通过 PSP 指针进行指向的。一旦进入了中断函数以及可能发生的中断嵌套都是用的 MSP 指针。这个知识 点要记住它,当前可以不知道这是为什么,但是一定要记住。
2,实际应用中系统栈空间分配多大,主要是看可能发生的中断嵌套层数

综上,普通是任务栈,中断是系统栈。

1.5freertos任务状态

FreeRTOS 的运行支持以下四种状态:

  • Running—运行态
    • 当任务处于实际运行状态被称之为运行态,即 CPU 的使用权被这个任务占用。
  • Ready—就绪态
    • 处于就绪态的任务是指那些能够运行(没有被阻塞和挂起),但是当前没有运行的任务。
  • Blocked—阻塞态
    • 由于等待信号量,消息队列,事件标志组等而处于的状态被称之为阻塞态
  • Suspended—挂起态
    • 类似阻塞态,通过调用函数 vTaskSuspend()对指定任务进行挂起,可用xTaskResume()恢复

1.6freertos启动

启动 FreeRTOS:vTaskStartScheduler();

1.7FreeRTOS 的任务创建

FreeRTOS 的任务创建:xTaskCreate()

函数原型:
BaseType_t xTaskCreate( 
 TaskFunction_t pvTaskCode, /* 任务函数 */
 const char * const pcName, /* 任务名 */
 unsigned short usStackDepth, /* 任务栈大小,单位 word,也就是 4 字节 */
 void *pvParameters, /* 任务参数 */
 UBaseType_t uxPriority, /* 任务优先级 */
 TaskHandle_t *pvCreatedTask /* 任务句柄 */
 );
 
第 1 个参数填创建任务的函数名。
第 2 个参数是任务名,这个参数主要是用于调试目的,调试的时候方便看是哪个任务。
第 3 个参数是任务栈大小,单位 word,也就是 4 字节。 
第 4 个参数是创建的任务函数的形参。
第 5 个参数是任务的优先级
第 6 个参数是任务句柄,用于区分不同的任务。

1.8FreeRTOS 的任务删除

FreeRTOS 的任务删除:vTaskDelete()

/* 任务句柄 */
static TaskHandle_t xHandleTaskStart = NULL;

static void AppTaskDelete (void)
{
xTaskCreate( vTaskStart,        /* 任务函数 */
            "vTaskStart",       /* 任务名 */
            512,                /* 任务栈大小,单位 word,也就是 4 字节 */
            NULL,               /* 任务参数 */
            4,                  /* 任务优先级*/
            &xHandleTaskStart ); /* 任务句柄 */
/* 删除此任务 */
if(xHandleTaskStart!= NULL)
{
vTaskDelete(xHandleTaskStart);
} }

1.9FreeRTOS 的任务挂起

FreeRTOS 的任务挂起:xTaskSuspend()

使用这个函数要注意以下问题:

  1. 使用此函数需要在 FreeRTOSConfig.h 配置文件中配置如下宏定义为 1
    • #define INCLUDE_vTaskSuspend 1
  2. 如果用往此函数里面填的任务 ID 是 NULL,即数值 0 的话,那么挂起的就是当前正在执行的任务, 此任务被挂起后,FreeRTOS 会切换到任务就绪列表里面下一个要执行的高优先级任务。
  3. 多次调用此函数的话,只需调用一次 vTaskResume 即可将任务从挂起态恢复。
/* 任务句柄 */
static TaskHandle_t xHandleTaskStart = NULL;

static void AppTaskSuspend (void)
{
xTaskCreate( vTaskStart,    /* 任务函数 */
            "vTaskStart",   /* 任务名 */
            512,            /* 任务栈大小,单位 word,也就是 4 字节 */
            NULL,           /* 任务参数 */
            4,              /* 任务优先级*/
            &xHandleTaskStart ); /* 任务句柄 */
            
            /* 挂起此任务 */
            if(xHandleTaskStart!= NULL)
            {
                vTaskSuspend(xHandleTaskStart);
            } 
}

1.10 FreeRTOS 的任务恢复

FreeRTOS 的任务恢复:vTaskResume()

此函数是用于任务代码中调用的,故不可以在中断服务程序中调用此函数,中断服务程序中使用的 xTaskResumeFromISR(),以后缀 FromISR 结尾。

1.11 FreeRTOS 的任务恢复((中断方式)

FreeRTOS 的任务恢复(中断方式):xTaskResumeFromISR()

1,使用此函数需要在 FreeRTOSConfig.h 配置文件中配置如下宏定义为 1
#define INCLUDE_xResumeFromISR 1

2. 多次调用函数 vTaskSuspend 的话,只需调用一次 vTaskResumeFromISR 即可将任务从挂起态恢复。

3. 如果用户打算采用这个函数实现中断与任务的同步,要注意一种情况,如果此函数的调用优先于函数 vTaskSuspend 被调用,那么此次同步会丢失,这种情况下建议使用信号量来实现同步。

4. 此函数是用于中断服务程序中调用的,故不可以在任务中使用此函数,任务中使用的是 vTaskResume。

/* 任务句柄 */
static TaskHandle_t xHandleTaskStart = NULL;
static void AppTaskResume (void)
{
xTaskCreate( vTaskStart,    /* 任务函数 */
             "vTaskStart", /* 任务名 */
             512,           /* 任务栈大小,单位 word,也就是 4 字节 */
             NULL,          /* 任务参数 */
             4,             /* 任务优先级*/
             &xHandleTaskStart ); /* 任务句柄 */
            /* 挂起此任务 */
            if(xHandleTaskStart!= NULL)
            {
                vTaskSuspend(xHandleTaskStart);
            } 
}

static void TIM2_IRQHandler(void)
{
    BaseType_t xYieldRequired;
    /* 中断消息处理,此处省略 */
     ……
    /* 恢复挂起任务 */
    xYieldRequired = xTaskResumeFromISR(xHandleTaskStart);
    ...

1.12 FreeRTOS 的空闲任务

空闲任务属于系统任务,是必须要执行的

空闲任务作用:

  • 用户不能让系统一直在执行各个应用任务,这样的话系统利用率就是 100%,系统就会一直超负荷运 行,所以空闲任务很有必要。
  • 为了更好的实现低功耗,空闲任务也很有必要,用户可以在空闲任务中实现睡眠,停机等低功耗措施。