news 2026/8/18 14:17:16

FreeRTOS的学习

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
FreeRTOS的学习

1、任务函数的一般写法:

//任务函数使用void类型的返回值,但是有一个void*类型的参数 void vTask1(void*pvParameters) { //编程方式类似于main()方法,一般写一个无限循环 for(;;) { //使用vTaskDelay()而不使用HAL_Delay()进行延迟 } //坚决不能写return! vTaskDelete(NULL); //一旦退出需要删除自身 }

2、main()方法的一般写法

int main(void) { // 一些底层的初始化代码放这里 ........ //先创建任务 xTaskCreate(vTask1,"Task1",......); //任务1 xTaskCreate(vTask2,"Task2",......); //任务2 //再启动调度器 vTaskStartScheduler(); //无限循环 while(1) { } }

变量名的命名规则: 变量名 = 类型前缀 + 实际名字

函数名的命名规则

宏定义命名规则

FreeRTOS任务调度机制

三种任务调度方式:

抢占式调度:主要是针对优先级不同的任务,每个任务都有一个优先级,优先级高的任务可以抢占优先级低的任务
时间片调度:主要针对优先级相同的任务,当多个任务的优先级相同时,任务调度器都会在每一个系统时钟节拍到时候切换任务

协程式调度:当前执行任务将会一直运行,同时高优先级任务不会在抢占低优先级任务,当前任务主动放弃CPU,才会执行下一个FreeRTOS现在虽然还支持,但是官方表示不再更新协程式调度。

四种任务状态:

Running 运行态 :当任务处于实际运行状态被称之为运行态,即 CPU 的使用权被这个任务占用。
Ready 就绪态 :处于就绪态的任务是指那些 能够运行(没有被阻塞和挂起),但是当前没有运行的任务,因为同优先级或更高优先级的任务正在运行 。
一个任务要能够运行前必须先进入就绪态。
Blocked 阻塞态 :由于等待信号量,消息队列,事件标志组等而处于阻塞的状态 被称之为阻塞态,另外任务调用vTaskDelay() 延迟函数也会处于阻塞态。
Suspended 挂起态 :类似阻塞态,通过手动调用函数 vTaskSuspend()对指定任务进行挂起,挂起后这个任务不被执行,只有手动调用函数 xTaskResume()才可以将这个任务从挂起态恢复。

ldle 空闲任务
  • 优先级最低,为 0 。
  • 空闲任务要么处于就绪态,要么处于运行态永远不会阻塞

任务间的通信方式:

队列(Queues)

  • 核心作用:队列是 FreeRTOS 中任务间传递数据的主要方式,支持在任务与任务、中断与任务之间发送消息。
  • 工作原理:队列本质上是一个线程安全的先进先出(FIFO)缓冲区。消息是通过复制的方式发送的,即把数据本身(或指向数据的指针)拷贝到队列中。
  • 阻塞机制:当任务尝试读取空队列或写入已满队列时,可以指定一个阻塞时间。任务会进入“被阻止”状态,直到有数据/空间可用,或超时。处于该状态的任务不占用 CPU 时间。

2. 信号量与互斥量(Semaphores & Mutexes)

  • 核心作用:主要用于任务间的同步和互斥访问,保护共享资源。

创建函数:

xSemaphoreCreatrBinary() 二进制信号量(初始 0)

xSemaphoreCreateCounting(uxMaxCount, uxInitialCount) ———计数信号量

xSemaphoreCreateMutex() ——互斥量

操作:

xSemaphoreTask (xSemaphore, xTicksToWait) ——取,portMax_DELAY 表示永久等待

xSemaphoreGive(xSemaphore) ——释放

xSemaphoreGiveFromISR(xSemaphore, pxHigherPriorityTaskWoken) ——ISR中使用

二进制信号量(Binary Semaphore):只有 0 和 1 两个状态,常用于任务与中断之间的同步,或作为简单的信号机制。

计数信号量(Counting Semaphore):具有大于 1 的计数值,用于跟踪可用资源的数量或事件发生的次数,允许多个任务共享一组资源。

互斥量(Mutex):一种特殊的二元信号量,内置了优先级继承机制。当高优先级任务等待低优先级任务持有的互斥量时,低优先级任务的优先级会被临时提升,从而最大程度减少“优先级翻转”问题。

注意:1、别用二进制信号量做互斥——它没有优先级继承,可能出现严重的优先级反转。

2、互斥量不能在 ISR 里用——ISR 没有任务优先级,优先级继承无从谈起;ISR 通知任务请用二进制信号量GiveFromISR

3、互斥量谁拿谁放——必须由取锁的同一个任务释放;信号量则可以由任意任务/ISR 释放。

3. 任务通知(Task Notifications)

  • 核心作用:一种轻量级的事件通知机制,允许任务直接与另一个任务或中断服务例程(ISR)同步。
  • 工作原理:每个任务都有一个 32 位的通知值。发送方可以直接更新接收方的通知值并唤醒它,无需创建额外的通信对象(如队列或信号量)。
  • 优势与限制:相比于队列和信号量,任务通知在执行速度上更快,且 RAM 开销更小。但其局限性在于,只能用于事件接收方是唯一的一个任务的场景。

4. 事件组(Event Groups)

  • 核心作用:允许一个任务同时等待多个事件(组合条件)的发生。
  • 工作原理:事件组内部包含一组事件标志位(Bits)。当某个事件发生时,对应的位被置 1。任务可以阻塞等待特定的位组合被置位,从而一次性响应多个条件,这比为每个事件单独创建信号量要节省内存且逻辑更清晰。

5. 流缓冲区与消息缓冲区(Stream & Message Buffers)

  • 核心作用:主要用于传递字节流或离散的消息,特别适合在中断和任务之间传递不定长的数据。
  • 工作原理:支持一次写入或读取任意数量的字节。
  • 安全限制:流缓冲区假定只有一个写入器只有一个读取器(写入器和读取器可以是不同的任务或中断,但不能有多个写入器或多个读取器),多对多读写是不安全的。

在实际开发中:

传递具体数据使用队列(Queue)

保护共享资源使用互斥量(Mutex)

任务/中断间的简单同步使用二元信号量或更高效的任务通知

等待多个条件满足使用事件组

FreeRTOS 优先级反转

高优先级的Task2 必须等待低优先级的Task1 放弃对互斥量的控制。这种高优先
级任务被低优先级任务延迟的情况被称为“优先级反转”

优先级的继承

FreeRTOS的任务栈的大小

栈:①返回地址LR,其他寄存器:函数调用深度

②局部变量

③现场: 16x4=64byte

也就是栈用量 =上下文现场 + 调用链上所有函数的局部变量 + 寄存器压栈

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/18 14:14:25

2D游戏法线贴图还在手绘?这款免费开源神器让你告别深夜加班

2D游戏法线贴图还在手绘?这款免费开源神器让你告别深夜加班 【免费下载链接】laigter Laigter: automatic normal map generator for sprites! 项目地址: https://gitcode.com/gh_mirrors/la/laigter 凌晨一点半,我的桌面还亮着。像素骑士的披风在…

作者头像 李华
网站建设 2026/8/18 14:07:36

QMCDecode 实战解析:QQ音乐 QMC 加密音频还原 FLAC/MP3 的完整指南

QMCDecode 实战解析:QQ音乐 QMC 加密音频还原 FLAC/MP3 的完整指南 【免费下载链接】QMCDecode QQ音乐QMC格式转换为普通格式(qmcflac转flac,qmc0,qmc3转mp3, mflac,mflac0等转flac),仅支持macOS,可自动识别到QQ音乐下载目录&…

作者头像 李华
网站建设 2026/8/18 14:07:00

TVA-World架构:AGI基础算法研究启示录(9)

前沿技术探索:TVA智能体(简称TVA)TVA智能体(亦称“AI智能体视觉”或“TVA视觉智能体”)是依托Transformer架构与“因式智能体”理论构建的系统级视觉技术框架。它融合深度强化学习(DRL)、卷积神…

作者头像 李华