抢占式调度

  1. 高优先级的可以优先运行,即使以及有低优先级的在运行,会先停止低的再运行高的(优先级按数字大小分大小)
  2. 高优先级任务不停止,低优先级的任务无法运行
  3. 被抢占的任务会进入就绪态

时间片调度

  1. 同等优先级任务轮流享有相同的CPU占用时间(可设置),叫时间片,在Free RTOS中一个时间片等于SysTick(系统/滴答定时器)中断周期
  2. 没有用完的时间直接丢掉,不会补偿,永远都是一个时间片

任务状态:运行态,就绪态,阻塞态,挂起态(类似暂停,调用vTaskSuspend()进入挂起态,调用vTaskResume()解除挂起态进入就绪态)

仅就绪态可以直接进入运行态

任务创建与删除:

  1. 使用xTaskCreate() 动态方法创建任务
  2. 使用xTaskCreateStatic() 多了一个Static(静态)表示静态方法创建任务
  3. 使用vTaskDelete() 删除任务
  4. 动态静态区别在分配内存的方法不同,静态由用户自己分配,动态由Free RTOS自己分配,在它管理的堆中

任务控制块也就是TCB,可以看作是任务的身份证,用于辨识任务。

创建任务具体流程:

一:内存准备

  1. 申请任务堆栈内存(获取首地址)
  2. 申请任务控制块TCB内存(获取首地址)
  3. 将堆栈地址绑定到TCB的栈成员

二:TCB初始化

4. 调用 prvInitialiseNewTask()

1 初始化堆栈(可选填0xA5)

2 记录栈顶地址 → pxTopOfStack

3 保存任务名称 → pcTaskName[]

4 保存任务优先级 → uxPriority

5 绑定状态列表项/事件列表项与TCB关系

三:加入就绪列表
5. 调用 prvAddNewTaskToReadyList()

1 全局操作​:

    • 任务计数器 uxCurrentNumberOfTasks++
    • 若是首个任务 → 初始化任务列表

​ 2 非首任务时​:

    • 若调度器未启动:比较新任务与当前任务优先级,更高则切换当前TCB指向
    • 优先级位图操作:将 uxTopReadyPriority 对应优先级位置1(标记就绪)
    • 按优先级升序插入就绪列表末尾(值越小优先级越高)

​ 3 栈与句柄初始化​:

    • 调用 pxPortInitialiseStack 初始化寄存器上下文空间
    • 任务句柄指向TCB地址

四:动态响应

触发任务切换条件​:
若调度器已运行 ​​ 新任务优先级 > 当前任务 → 立即执行任务切换

​删除任务具体流程:​​

​一:任务定位​

  1. 获取目标TCB​
    • 通过任务句柄判断删除对象:
      • NULL → 删除当前任务(自身)
      • ​有效句柄​ → 删除指定任务

​二:解除任务关联​

  1. 移除任务所有关联列表​
    • 将任务从所属队列中移除,包括:
      • 就绪列表(Ready List)
      • 阻塞列表(Blocked List)
      • 挂起列表(Suspended List)
      • 事件等待列表(Event List)

​三:删除类型分流​

  1. 根据删除类型执行操作​
    • ​情况A:删除自身任务​
      1. 将当前任务加入 ​等待删除列表​
      2. ​内存释放委托​:由空闲任务(Idle Task)后续执行 prvDeleteTCB() 释放TCB及栈内存
    • ​情况B:删除其他任务​
      1. 立即调用 prvDeleteTCB() ​直接释放内存​
      2. ​全局更新​:
        ○ 任务计数器减一(uxCurrentNumberOfTasks--)
        ○ ​阻塞超时校准​:检查被删任务是否为下一个待唤醒的阻塞任务 → 更新超时计时器

​四:调度响应​

  1. 强制切换条件​:
    • 若 ​调度器正在运行​ 且 ​删除的是自身任务​ → 立即触发一次任务切换(上下文切换)

R11-R4寄存器实际是内存,就是存放任务的具体内容,任务要运行就是把任务函数地址赋值给PC寄存器,M4,M7的EXC_RETURN的bit4可以修改,1表示不支持浮点数,0表示支持

每个优先级前有一位,用来判断是不是有任务,有就置1,方便后续任务切换

挂起与恢复

挂起:类似暂停,可以恢复

FromISP后缀:中断中专用,Free RTOS管理的中断优先级为5-15,要注意中断时调用Free RTOS的API函数要保证中断优先级不高于它管理的最高优先级(数字低为高)

建议把所有优先级位指定为抢占优先级位,方便FreeRTOS管理

​任务挂起函数流程:​​

​一:任务定位​

  1. 获取目标TCB
    • 任务句柄为 NULL → 挂起当前任务(自身)

​二:解除任务关联​

  1. 移除任务所有状态列表
    • 从以下列表中移除任务:
      • 就绪列表(Ready List)
      • 阻塞列表(Blocked List)
      • 事件列表(Event List)
  2. 加入挂起列表
    • 将任务插入 ​挂起列表(Suspended List)​​ 末尾

​三:调度环境判断​

  1. 调度器运行中操作
    • 更新下一次阻塞时间(防止被挂起任务阻塞后续任务唤醒)
    • 若挂起自身​ → 立即触发任务切换
  2. 调度器未运行操作
    • 检查挂起任务数:
      • 挂起数 = 总任务数 → 当前控制块置 NULL
      • 否则 → 激活下一个最高优先级任务

​任务恢复函数流程:​​

​一:恢复条件校验​

  1. 宏 INCLUDE_vTaskSuspend 必须配置为 1
  2. 禁止恢复运行中的任务

​二:恢复操作​

  1. 检查任务状态
    • 任务在挂起列表中 → 移出挂起列表
  2. 加入就绪列表
    • 将任务按优先级插入就绪列表末尾
  3. 触发切换判断
    • 恢复任务优先级 > 当前任务 → 触发任务切换

​中断恢复函数流程:​​

​一:中断安全操作​

  1. 关闭FreeRTOS管理的中断
    • 保存 BASEPRI 寄存器原值
    • 防止被其他中断打断

​二:恢复操作判断​

  1. 调度器状态检查
    • 调度器未挂起​:
      • 若任务在挂起列表 → 移出并加入就绪列表
      • 恢复任务优先级 > 当前任务 → 标记 xYieldRequired = pdTRUE
    • 调度器已挂起​:
      • 将任务插入 ​等待就绪列表​(延后处理)

​三:环境还原与返回​

  1. 恢复中断状态
    • 还原 BASEPRI 寄存器值
  2. 返回切换标记
    • 输出 xYieldRequired 供中断退出时判断是否切换任务

​一:系统中断优先级配置寄存器​

寄存器组​:SHPR1、SHPR2、SHPR3

  1. 关键操作​:
    • 通过 ​SHPR3​ 配置 PendSV 和 SysTick 中断优先级
    • 设定原则​:将其设为最低优先级
  2. 设计目的​:
    • 确保系统任务切换(PendSV)和心跳调度(SysTick)
    • 不阻塞其他高优先级中断的实时响应

​二:中断屏蔽寄存器组​

寄存器

功能描述

PRIMASK

屏蔽所有可配置优先级的中断

FAULTMASK

屏蔽除NMI外的所有异常和中断

BASEPRI

核心寄存器​:屏蔽优先级低于设定阈值的中断

​BASEPRI 工作机制​

  1. 阈值控制逻辑​:
    • 写入值 0xN0(N为十六进制优先级阈值)
    • 示例​:设定 BASEPRI = 0x50 时:
      • 屏蔽范围​:优先级值 5~15(值越大优先级越低)
  2. FreeRTOS依赖​:
    • 中断管理基石​:通过动态调节BASEPRI实现:
      • 临界区保护
      • 中断嵌套控制

​三:技术实质说明​

  1. 优先级数值规则​:
    • 数值越小优先级越高​(0为最高)
    • SHPR3设置最低优先级即赋予最大数值
  2. 安全隔离设计​:
    • PendSV/SysTick 低优先级 → 避免抢占关键外设中断
    • BASEPRI 阈值屏蔽 → 保障高实时性中断响应
  3. FreeRTOS应用​:
    • portDISABLE_INTERRUPTS() 本质是设置BASEPRI阈值
    • taskENTER_CRITICAL() 依赖此寄存器构建临界区

FreeRTOS中的列表实质上就是一个双向的环状链表,首尾相连,可以随意添加或删除列表项,有一个变量记录列表项数目,用于遍历,每个列表项有编号用于排序,初始化有一个末尾列表项,,它不计入列表数,编号最大。

两个校验值就是存放确定已知的常量,通过检查它是否变化来判断数据是否受到破坏,一般用于调试。

下面为迷你列表项,它也是列表项,但仅用于标记列表的末尾和挂载其他插入列表中的列 表项,用户是用不到迷你列表项的

  1. vListInitialise()初始化列表就是把列表末尾项编号赋为最大,首尾指向它自己,再初始化两个校验值,传入参数为要初始化的列表。
  2. vListInitialiseItem()初始化列表项就是把它所属列表项赋值为NULL,同样初始化两个校验值,传入参数为要初始化的列表项。
  3. vListInsertEnd()列表项末尾插入列表项是一种无序的排列,是把它插入到列表 pxIndex 指向列表项的前面,不管它的编号大小,传入参数为列表和要插入的列表项。
  4. vListInsert()列表插入列表项是一种有序排列,会根据编号来寻找合适的位置插入(如果最大就插入到末尾项前面,否则就遍历找位置)传入参数同上。
  5. uxListRemove()列表移除列表项就是跟链表删除一样,传入要删除的列表项,返回值为删除后剩余列表项数目

​FreeRTOS任务切换出栈流程详解(严格遵循您提供的寄存器架构图)

任务切换出栈流程如下:首先通过三重指针(TCBTop->R3->R1->R0)获取TCB栈顶地址,这时R0指向R4也就是手动恢复起始点,就开始进行手动出栈,把栈内R4-R11寄存器储存的数据出栈到CPU的R4-R11寄存器,也就是用ldmia r0!, {r4-r11}把数据弹出到CPU,每弹出一个R0地址增加4字节,完成后R0指向xPSR寄存器,然后把R0的地址加载到PSP任务进程指针,这时PSP指向硬件自动恢复区起始点xPSR,就触发硬件自动恢复,最后再把R0清零,把R0的值赋值给basepri开启中断。

栈位置

寄存器

类型

作用说明

​栈顶​
(低地址)

​R4​

通用寄存器

任务内部变量(手动恢复区起始)

​R5​

通用寄存器

任务内部变量

​R6​

通用寄存器

任务内部变量

​R7​

通用寄存器

任务内部变量

​R8​

通用寄存器

任务内部变量

​R9​

通用寄存器

任务内部变量

​R10​

通用寄存器

任务内部变量

​R11​

通用寄存器

任务内部变量(手动恢复区结束)

--------

----------

---------------------------

​xPSR​

特殊功能寄存器

​程序状态寄存器​
• 恢复任务运行状态
• 包含Thumb模式标志(bit0=1)
• 中断号等关键状态信息

​R15(PC)​​

特殊功能寄存器

​程序计数器​
• 核心跳转控制
• 恢复时立即执行任务入口函数
• 实现执行流无缝切换

​R14(LR)​​

特殊功能寄存器

​链接寄存器​
• 存储0xFFFFFFFD值
• 指示使用PSP恢复上下文
• 引导硬件自动恢复流程

​R12​

通用寄存器

临时寄存器(自动恢复)

​R3​

通用寄存器

通用寄存器(自动恢复)

​R2​

通用寄存器

通用寄存器(自动恢复)

​R1​

通用寄存器

通用寄存器(自动恢复)

​栈底​
(高地址)

​R0​

通用寄存器

​任务参数寄存器​
• 存储pvParameters任务参数
• 作为任务函数第一个参数

关键寄存器协同机制表

寄存器

作用

恢复方式

协同机制说明

​R13(PSP)​​

​任务栈指针​

软件设置

• 通过MSR PSP, R0设置
• 定位硬件恢复起始位置
• 任务运行时动态维护栈顶

​R14(LR)​​

​上下文恢复控制器​

软件设置

• 存储0xFFFFFFFD魔数
• 触发时指示硬件使用PSP恢复
• 控制处理器返回线程模式

​R15(PC)​​

​执行流切换器​

硬件自动恢复

• 恢复时立即跳转至任务代码
• 实现任务无缝切换
• 决定程序执行位置

​xPSR​

​状态同步器​

硬件自动恢复

• 恢复中断前的程序状态
• 保证Thumb模式正常运行(bit0=1)
• 维持中断/异常状态一致性

• ​压栈操作​:地址递减(栈顶向低地址移动)
• ​出栈操作​:地址递增(栈顶向高地址移动)
• ​切换流程​:手动恢复(R4-R11)后,指针↑移动到xPSR,触发硬件自动↑恢复关键寄存器

FreeRTOS 学习笔记(持续更新)的更多相关文章

  1. 数据分析之Pandas和Numpy学习笔记(持续更新)<1>

    pandas and numpy notebook        最近工作交接,整理电脑资料时看到了之前的基于Jupyter学习数据分析相关模块学习笔记.想着拿出来分享一下,可是Jupyter导出来h ...

  2. [读书]10g/11g编程艺术深入体现结构学习笔记(持续更新...)

    持续更新...) 第8章 1.在过程性循环中提交更新容易产生ora-01555:snapshot too old错误.P257 (这种情况我觉得应该是在高并发的情况下才会产生) 假设的一个场景是系统一 ...

  3. Semantic ui 学习笔记 持续更新

    这个semantic 更新版本好快~ 首先是代码的标识<code></code> 具体样式就是红框这样的 圈起来代码感觉不错 不过要在semantic.css里在加上如下样式~ ...

  4. Git学习笔记(持续更新)

    1.强制同步为远程的代码 远程仓库回退了commit的情况下(第2条描述之情况),强制同步远程的代码到本地 #更新远程最新的所有代码,但是不merge或者rebase git fetch --all ...

  5. R语言的学习笔记 (持续更新.....)

    1. DATE 处理 1.1 日期格式一个是as.Date(XXX) 和strptime(XXX),前者为Date格式,后者为POSIXlt格式 1.2 用法:as.Date(XXX,"%Y ...

  6. angularjs1学习笔记--持续更新

    angularJS使用的MVC为何不属于二十三种设计模式之一? MVC被GoF (Gang of Four,四人组, <Design Patterns: Elements of Reusable ...

  7. ggplot2 学习笔记 (持续更新.....)

    1. 目前有四种主题 theme_gray(), theme_bw() , theme_minimal(),theme_classic() 2. X轴设置刻度 scale_x_continuous(l ...

  8. # MongoDB学习笔记(持续更新)

    启动mongo服务 sodo mongo 显示数据库(显示数据库名称和大小,单位GB) > show dbs admin (empty) local 0.078GB test 0.078GB t ...

  9. GOF 的23种JAVA常用设计模式 学习笔记 持续更新中。。。。

    前言: 设计模式,前人总结下留给后人更好的设计程序,为我们的程序代码提供一种思想与认知,如何去更好的写出优雅的代码,23种设计模式,是时候需要掌握它了. 1.工厂模式 大白话:比如你需要一辆汽车,你无 ...

  10. BLE资料应用笔记 -- 持续更新

    BLE资料应用笔记 -- 持续更新 BLE 应用笔记 小书匠 简而言之,蓝牙无处不在,易于使用,低耗能和低使用成本.'让我们'更深入地探索这些方面吧. 蓝牙无处不在-,您可以在几乎每一台电话.笔记本电 ...

随机推荐

  1. 举个栗子之gorpc - 消息的编码和解码

    2022年的第一个rpc,比以往来的更早一些... 留杭过年...写点东西 初始化项目gorpc 借助go module我们可以轻易创建一个新的项目 mkdir gorpc go mod init g ...

  2. CSS文本超出省略

    语法: text-overflow:clip|ellipsis|"任意字符" <!DOCTYPE html> <html> <head> < ...

  3. Linux权限之基础权限

    介绍 Linux是多用户的操作系统,允许多个用户同时登录和工作,Linux权限是操作系统用来限制不同用户对资源的访问机制.这里暂且将Linux的权限分为三类: 基本权限:给文件和目录的所属者.所属组. ...

  4. 比cat更好用的命令!

    大家好,我是良许. 作为程序员,大家一定对 cat 这个命令不陌生.它主要的功能就是用来显示文本文件的具体内容. 但 cat 命令两个很重大的缺陷:1. 不能语法高亮输出:2. 文本太长的话无法翻页输 ...

  5. 在 MySQL 中建索引时需要注意哪些事项?

    在 MySQL 中建索引时需要注意哪些事项 索引在 MySQL 中是提升查询性能的关键,但不当的索引设计可能会导致性能下降或资源浪费.因此,在建索引时需要综合考虑性能.存储成本和业务需求. 1. 确定 ...

  6. 你常用哪些工具来分析 JVM 性能?

    常用的 JVM 性能分析工具 JVM 性能分析工具主要用于监控.调试和优化 Java 程序的性能,尤其是在垃圾回收.内存泄漏.线程调度等方面.以下是一些常用的 JVM 性能分析工具: 1. jvisu ...

  7. Windows系统优化 3-清理预安装软件

    事件起因: 经过我们上次 Windows系统优化 2-系统设置优化 之后,现在电脑已经基本上可以使用,不过对于有强迫症的我来说还差了一步,那就是系统预安装的软件: 对于我们刚入手的电脑你是否有 这些 ...

  8. 前端速成之——Script

    Script 1-引入js和函数调用 function函数:必然存在一个返回值,绝对不会书写 void,要么返回 undefine,要么返回 return 的数据 function etoak(val ...

  9. flutter系列(一)----- 开发环境搭建

    flutter刚刚出来的时候,当时前公司团队使用React Native开发出来项目刚刚上线半年多.当时RN刚刚出来的时候,也是相当的火爆.公司也是紧跟时代的潮流.果断使用RN做了新项目,RN出来的时 ...

  10. java.sql.sqlexception: access denied for user ‘***‘@‘localhost‘ (using password: yes)

    参考文章: 0.ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO) 的解决办法 1.M ...