第一部分:FreeRTOS 任务是如何执行的?

FreeRTOS 是一个抢占式的实时操作系统内核。其任务执行遵循一个核心原则:调度器(Scheduler)总是选择当前处于“就绪态”(Ready)的最高优先级任务来运行。

1. 任务的形态:一个永不返回的函数

每个 FreeRTOS 任务本质上是一个永不返回void 函数,通常是一个无限的 for(;;) 循环或 while(1) 循环。

void vMyTask( void * pvParameters ) // 任务函数原型
{// 可选的初始化代码for( ;; ) // 无限循环,任务的主体{// 任务要做的实际工作...do_work();// 关键点:必须调用一个能让任务“放弃”CPU的FreeRTOS API// 例如,等待一个事件或延迟一段时间vTaskDelay( pdMS_TO_TICKS( 1000 ) ); // 延迟1秒}// 理论上任务不应结束,但如果结束,必须调用 vTaskDelete(NULL) 来删除自己。
}
2. 任务的状态

一个任务在任何时刻都处于以下几种状态之一,理解这些状态是理解调度的关键:

  • 运行态(Running):任务正在 CPU 上执行。在单核处理器上,任何时候都只有一个任务处于此状态。
  • 就绪态(Ready):任务已经准备好可以运行(不被阻塞或挂起),但当前没有运行,因为有一个更高优先级的任务正在运行,或者一个同等优先级的任务正在其时间片内运行。
  • 阻塞态(Blocked):任务正在等待某个事件。事件可以是:
    • 时间相关:例如调用 vTaskDelay() 等待一段时间。
    • 同步事件:例如等待一个信号量(Semaphore)队列(Queue) 消息、任务通知(Task Notification) 等。
    • 处于阻塞态的任务不会被调度器选择执行。当事件发生时,任务会自动离开阻塞态,进入就绪态。
  • 挂起态(Suspended):任务被主动挂起,通过 vTaskSuspend() 实现。被挂起的任务对调度器“不可见”,无论发生什么事件都不会被执行,除非其他任务调用 vTaskResume() 来恢复它。它不参与调度。
3. 任务的控制块(TCB)和栈
  • TCB(Task Control Block):FreeRTOS 为每个任务创建一个数据结构(TCB),用来存储任务的所有元信息,如优先级、堆栈指针、状态、事件列表项等。
  • 栈(Stack):每个任务都有自己独立的堆栈空间,用于存储函数调用链、局部变量和任务挂起时的上下文(CPU寄存器值)。这是实现多任务并发的基石。

第二部分:优先级任务切换的详细过程

任务切换,也称为上下文切换(Context Switch),即保存当前任务的运行环境(上下文),恢复另一个任务的运行环境,并开始执行它。

核心原则:抢占(Preemption)

FreeRTOS 是抢占式调度器。这意味着:

  1. 如果一个更高优先级的任务进入就绪态(例如,它等待的事件发生了),调度器会立即停止当前运行的任务(即使它还没执行完),并切换到更高优先级的任务。
  2. 这保证了系统对高优先级事件的响应是即时的。
触发任务切换的四大场景
  1. 系统时钟节拍(SysTick)中断

    • 这是时间片轮转的基础。SysTick 定时器定期产生中断(例如每1ms一次)。
    • 在中断服务程序(ISR)中,内核会:
      • 递增系统时钟计数器 xTickCount
      • 检查是否有因延时到期而需要从阻塞态唤醒的任务。
      • 检查是否需要任务切换:如果当前任务的时间片已用完,并且存在同等优先级的就绪任务,则会触发切换(同优先级任务轮转)。如果发现了一个更高优先级的任务就绪了,也会触发切换。
    • 这是周期性的自动切换。
  2. 任务主动进入阻塞态

    • 这是最常见、最推荐的切换方式,体现了事件驱动编程思想。
    • 当一个高优先级任务执行到 xQueueReceive(), xSemaphoreTake(), vTaskDelay() 等函数时,因为它要等待的事件尚未发生,它会主动放弃CPU,将自己置于阻塞态
    • 一旦它进入阻塞态,它就不再是“就绪态”的任务,调度器会立刻寻找当前最高优先级的就绪任务来执行。这通常是低优先级或同等优先级的任务。
    • 示例:一个高优先级任务等待一个按键消息。在它等待(阻塞)期间,CPU 会去执行低优先级的 LED 闪烁任务、显示刷新任务等。
  3. 中断服务程序(ISR)使更高优先级任务就绪

    • 这是一个硬件外部中断(如 GPIO 引脚中断、UART 接收中断、定时器中断)触发的切换。
    • 流程:
      1. 硬件中断发生,CPU 跳转到对应的 ISR。
      2. 在 ISR 中,代码通过 xSemaphoreGiveFromISR(), xQueueSendToBackFromISR(), xTaskResumeFromISR()FromISR 系列的 API 给出一个信号量、发送一条消息或恢复一个任务。
      3. 这些 API 会通知调度器:一个更高优先级的任务因为此事件而就绪了。
      4. 在 ISR 的末尾,FreeRTOS 会进行上下文判断:如果被唤醒的任务优先级高于被中断的任务,ISR 退出时会直接触发一次上下文切换,让更高优先级的任务立即运行,而不是先返回被中断的任务。
  4. 任务主动让步(Yield)

    • 任务可以调用 taskYIELD()主动请求调度器立即进行任务切换。
    • 注意:taskYIELD() 并不会使任务进入阻塞态,它只是让任务从运行态变为就绪态,参与下一轮调度。
    • 如果存在同等或更高优先级的任务处于就绪态,则调度器会切换到那个任务。否则,它可能继续执行当前任务。
切换的核心机制:PendSV 异常

为了让切换过程高效且不干扰中断的实时性,FreeRTOS 在 ARM Cortex-M 架构上使用 PendSV(可挂起的系统调用) 异常来执行实际的上下文切换工作。

  1. 触发:上述任何一种场景(如 SysTick ISR、FromISR API)判断需要切换后,并不立刻切换,而是简单地挂起(Pend)一个 PendSV 异常
  2. 延迟执行:PendSV 被设置为最低优先级的中断。这意味着 CPU 会先完成所有高优先级的 ISR 处理(保证中断响应及时)。
  3. 执行切换:当所有高优先级中断处理完毕后,CPU 才来执行 PendSV 异常处理程序(xPortPendSVHandler)。在这里,才会进行繁重的上下文保存和恢复工作
    • 保存上下文:将当前任务的 CPU 寄存器(R4-R11等)压入该任务自己的堆栈
    • 切换TCB:将当前任务的控制块(TCB)指针指向下一个要运行的任务。
    • 恢复上下文:从下一个任务的堆栈中弹出 CPU 寄存器值。
  4. 退出并运行:当 PendSV 异常处理程序退出时,CPU 会自动使用刚刚恢复的寄存器,程序计数器(PC)也随之跳转,于是自然而然就开始执行新的任务了

总结与最佳实践

场景触发方式说明
时间片到期SysTick 中断同优先级任务轮转的基础
任务等待事件vTaskDelay(), xSemaphoreTake(), 等最推荐的方式,事件驱动,高效节能
中断唤醒任务xSemaphoreGiveFromISR(), 等保证高优先级任务对硬件事件的即时响应
主动让步taskYIELD()较少使用,用于计算密集型任务中主动让步

核心设计哲学一个设计良好的 FreeRTOS 应用,其高优先级任务的大部分时间都应处于阻塞态,等待事件发生。 事件到来后(来自中断或其他任务),高优先级任务被唤醒,快速处理事件,处理完毕后立刻又返回阻塞态。这样,低优先级任务就能获得充足的 CPU 时间片来运行。

错误示范(绝对要避免)

void vBadHighPriorityTask( void * pvParameters )
{for( ;; ){// 这是一个“忙等待”(Busy-Waiting)循环// 它永不阻塞,将永远霸占CPU,导致系统被“锁死”// 低优先级任务永远无法运行!process_data();}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/94787.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/94787.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/94787.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

区块链技术探索与应用:从密码学奇迹到产业变革引擎

🌟 Hello,我是蒋星熠Jaxonic! 🌈 在浩瀚无垠的技术宇宙中,我是一名执着的星际旅人,用代码绘制探索的轨迹。 🚀 每一个算法都是我点燃的推进器,每一行代码都是我航行的星图。 &#x…

如何监控和调优JVM的内存使用情况?

监控和调优 JVM 内存使用是保障 Java 应用稳定性和性能的核心手段,需要结合监控工具、关键指标分析和针对性调优策略。以下是具体的实施方法:一、JVM 内存监控:工具与核心指标监控的目标是掌握内存使用趋势、GC 行为、线程状态等,…

把用户输进来的明文密码做一层 MD5 哈希

这一行干的就是:把用户输进来的明文密码先做一层 MD5 哈希,再把得到的 32 位十六进制字符串存到变量 password 里。 逐段拆开:password.getBytes() 把字符串转成字节数组,MD5 算法只能对字节/字节数组做运算。DigestUtils.md5Dige…

jeecg-boot3.7.0对接钉钉登录(OAuth2.0)

当前的jeecg-boot 是3.7.0前端问题:1.前端的路由vue-router的版本需要固定死。要不然会报page_not_found router the same.这种奇奇怪怪的问题。 就是把package.json的“^”,这个符号,删掉。(或者全局搜索,这个page no…

【C#】获取不重复的编码(递增,非GUID)

获取不重复的编码:从原始实现到高效优化本文针对软件开发中“为新对象分配唯一编码”的常见需求,以C#通信设备管理场景为例,从原始代码分析入手,逐步讲解基于LINQ和哈希集合的优化方案,帮助开发者理解不同场景下的最佳…

腾讯云人脸库技术架构深度解析

腾讯云人脸库技术架构深度解析人脸库是现代人脸识别系统的核心组件,负责海量人脸特征的高效存储、检索和管理。腾讯云在人脸库设计上采用了多项创新技术,本文将深入探讨其技术实现细节。一、人脸库核心架构腾讯云人脸库采用分层架构设计:应用…

Transformer图解指南:Attention机制动画演示

点击 “AladdinEdu,同学们用得起的【H卡】算力平台”,H卡级别算力,按量计费,灵活弹性,顶级配置,学生专属优惠。 Self-Attention矩阵运算 位置编码可视化 读者收获:理解大模型基石架构 Attenti…

工业网络安全:保护制造系统和数据

近年来,制造业数字化转型加速推进。自动化生产线、智能工厂和工业物联网设备已深度融入日常运营。这些进步在提升效率的同时,也暴露出新的安全漏洞。因此,工业网络安全已成为全球制造商的首要任务之一。与主要保护办公系统和客户数据库的传统…

【RAGFlow代码详解-9】文档解析和 OCR

系统概述 文档解析和 OCR 系统提供多格式文档支持,并具有基于视觉的分析功能。它由几个关键组件组成: DeepDoc 视觉系统 :用于布局分析、表格检测和 OCR 的高级计算机视觉模型多格式解析器 :支持 PDF、DOCX、Excel、Markdown、HTM…

元宇宙与医疗健康:重构诊疗体验与健康管理模式

1 元宇宙重塑医疗诊疗核心流程1.1 远程诊疗:从 “平面沟通” 到 “沉浸式问诊”元宇宙打破远程诊疗的空间限制,将传统 “视频通话式问诊” 升级为 “沉浸式多维度交互”。在基础问诊环节,医生的数字分身可通过 AR 技术 “进入” 患者家中&…

C6.1:发射极偏置放大器

基极偏置放大器的Q点不稳定,但是学习后了解了放大器的基本运行逻辑,发射极偏置放大器则是适合大规模应用,VDB和TSEB都具有稳定的Q点。讲发射极偏置,首先要讲旁路电容,前文的耦合电容和旁路电容类似,都是直流…

lanczos算法中的基向量V的存储流程

我的问题是:这里提到的,为什么会增加V的列向量?V是怎么储存的呢? 这个问题触及了Lanczos算法实现的核心细节。 🧠 为什么会增加V的列向量? 因为Lanczos算法是一个迭代过程,它从一个初始向量开始…

Linux操作系统——TCP服务端并发模型

TCP:建立连接,一对一要实现多任务并发,就引出了并发模型一、多进程与多线程1.在相同资源情况下,进程资源开销大,但其安全性高2.线程相对于进程资源开销小,且并发量比进程大①多进程并发基础代码#include &l…

Ubuntu 22.04 插入光驱后磁盘满启动故障clean, ...files, ...blocks

硬件环境 设备型号:机械革命 Yilong15Pro Series GM5HG0A操作系统:Ubuntu 22.04.5 LTS (Jammy Jellyfish)内核版本:6.8.0-65-generic 问题经过 初始症状 连接外置光驱后,系统出现异常: 风扇持续高速运转,噪…

声网RTC稳定连麦、超分清晰,出海直播技术不再难选

我们是面向中东、南亚新兴市场的泛娱乐直播平台,主打 1V1 互动、PK 团战与语音房。首个版本落地时,前端开发最焦虑的不是业务逻辑,而是音视频底层问题 —— 延迟高、卡顿多、合唱不同步致观众秒退,我们每周改底层,单 P…

设计模式:桥接模式(Bridge Pattern)

文章目录一、桥接模式的定义二、为什么需要桥接模式?三、示例代码一、桥接模式的定义 桥接模式是一种结构型设计模式,它的主要作用是将抽象部分与实现部分分离,使它们能够独立变化。换句话说,就是把“抽象”和“实现”放到两个独立…

AI-Agent 深度科普:从概念到架构、应用与未来趋势

目录 一、Agent 究竟是什么? 二、Agent 的核心组成模块 三、Agent 架构类型与协作模式 单智能体(Single-Agent) 多智能体协作(Multi-Agent) 人机协作(Human-in-the-loop) 四、Agent 的能…

企业分支上云的常见误区与纠正方案

数字化转型的浪潮下,“上云”几乎成为所有企业的必答题。然而,在实际落地中,很多企业发现:总部上云容易,分支上云却困难重重。不是网络体验不稳定,就是合规风险频出,要么就是成本失控。这其中很…

深入解析函数栈帧创建与销毁

目录 一、函数栈帧(Stack Frame)整理 1、核心概念 2、为什么需要函数栈帧? 3、函数栈帧的主要内容 二、理解函数栈帧能解决的核心问题 1、局部变量的生命周期与本质 2、函数调用的参数传递机制 3、函数返回值的传递 三、函数栈帧的创…

广告牌安全监测系统综合解决方案

一、方案背景 广告牌作为城市户外广告的重要载体,广泛分布于城市道路、商业区及交通枢纽等人流密集区域。由于长期暴露在自然环境中,广告牌面临着风荷载、雨雪侵蚀、温度变化等多重因素的影响,其结构安全性和稳定性直接关系到公共安全。近年来…