FreeRTOS学习笔记—任务基础知识


文章作者:二土电子

关注文末公众号获取其他资料和工程文件!

期待大家一起学习交流!


文章目录

  • 一、FreeRTOS任务特性
  • 二、FreeRTOS任务状态
  • 三、FreeRTOS任务优先级
  • 四、FreeRTOS任务实现
  • 五、任务控制块
  • 六、任务堆栈

一、FreeRTOS任务特性

  • 简单
  • 没有使用限制(任务数量没有限制,一个优先级下可以有多个任务)
  • 支持抢占(高优先级任务可以抢占低优先级任务的CPU使用权)
  • 支持优先级
  • 每个任务都拥有堆栈,导致RAM使用量增大
    当任务切换时,需要保护现场,保证再次执行该任务时能够从中断的地方继续执行,现场就存储在任务的RAM中。
  • 如果使用抢占,需要考虑重入问题

二、FreeRTOS任务状态

  • 运行态
    任务正在执行时,处于运行态
  • 就绪态
    任务准备就绪,可以运行
  • 阻塞态
    比如某个任务在等待某一个事件发生,此时任务处于阻塞态
  • 挂起态
    挂起态就是任务暂停运行

这四种任务状态是可以互相转换的。任务创建完成之后,处于就绪态。如果任务调度器调度了处于就绪态的任务,此时任务状态变成了就绪态。当然,运行态也可以变成就绪态。比如此时A任务正在运行,此时有一个比A任务优先级高的B任务处于就绪态。这时任务调度器会将A任务的CPU使用权转交给B任务,此时A任务从运行态转入就绪态。

由就绪态到挂起态,可以直接通过函数vTaskSuspend()实现。运行态和阻塞态也可以调用函数vTaskSuspend()进入挂起态。解挂时,调用vTaskResume()函数即可。

如果处于运行态的任务调用了一些可以阻塞的API函数,比如等待状态量,等待消息队列等,处于运行态的任务就会转到阻塞态。

FreeRTOS学习笔记—任务基础知识_第1张图片

三、FreeRTOS任务优先级

任务优先级高的任务,会先被执行。在FreeRTOS中,任务优先级可选范围在0~configMAX_PRIORITIER - 1,同一优先级下,可以有多个任务。值得注意的是,在FreeRTOS中,数字越大,优先级越大。

四、FreeRTOS任务实现

FreeRTOS官方给出了一个任务函数的模板

void vATaskFunction(void *pvParameters)
{
    for( ; ; )   // 死循环,可以用while(1)
    {
        // 任务应用程序
        vTaskDelay();   // 引起任务调度
    }
}

一般情况下,我们不会从任务中跳出。如果需要跳出,一定要将任务删除。删除任务可以调用下面的函数

vTaskDelete(NULL);   // 删除任务

需要注意的是,FreeRTOS的任务函数必须是void类型。

五、任务控制块

FreeRTOS 把任务属性集合到一起,用一个结构体来表示,这个结构体就是任务控制块——TCB_t(Task Control Block)。所以总结来说,任务控制块就是描述任务属性的结构体。任务控制块可以在“task.c”文件中找到。

六、任务堆栈

上面介绍过,当正在执行任务A,需要切换到任务B时,会将当前任务的现场(CPU寄存器值等)保存到任务的任务堆栈中。等到任务A再次运行时,根据从任务A的任务堆栈中存储的值来恢复现场。

创建任务的时候需要给任务指定堆栈。如果使用函数 xTaskCreate()创建任务(动态创建),任务堆栈就会由函数 xTaskCreate()自动创建。如果使用函数 xTaskCreateStatic()创建任务(静态方法),需要程序员自行定义任务堆栈,然后堆栈首地址作为函数的参数 puxStackBuffer 传递给函数。

不管是使用函数xTaskCreatel()还是xTaskCreateStatic0创建任务,都需要指定任务堆栈大小。任务堆栈的数据类型为 StackType_t, Stackype_t 本质上是 uint32 t,在 portmacro.h 中有定义

#define portSTACK_TYPE	uint32_t

typedef portSTACK_TYPE StackType_t;

由此可见,任务堆栈StackType_t的变量类型是u32,无符号整型。

比如之前在移植测试程序中创建LED程序时,定义任务堆栈

//任务堆栈大小	
#define LED0_STK_SIZE 		50  

这里的“50”并不是指该任务的任务堆栈大小为50个字节。而是指该任务的任务堆栈大小是50个StackType_t。一个StackType_t是四个字节。因此,该任务的任务堆栈大小应该是4 * 50 = 200 字节。

任务堆栈需要根据任务的实际大小分配,如果任务所需要的内存比较大,需要调整任务堆栈大小。如果出现任务卡死不运行的情况,大多数情况是因为任务堆栈分配太小。但是如果任务卡住,将其堆栈增大到很大,依旧卡住,那应该是其他问题。

你可能感兴趣的:(FreeRTOS学习笔记,stm32,笔记,学习)