ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

F´(F Prime)框架全面导读:从 NASA 深空起源到组件化飞行软件架构

2026/9/16 18:26:58 拓冰建站 浏览量
F´(F Prime)框架全面导读:从 NASA 深空起源到组件化飞行软件架构 F´F Prime框架全面导读从 NASA 深空起源到组件化飞行软件架构【免费下载链接】fprimeF´ - A flight software and embedded systems framework项目地址: https://gitcode.com/GitHub_Trending/fpr/fprimeF´F Prime是 NASA 喷气推进实验室JPL为小型航天任务打造的开源嵌入式飞行软件框架本仓库即为 F´ 的完整源码与文档。本文基于 docs/user-manual/overview/01-full-intro.md 展开系统讲解 F´ 的起源与设计目标、面向太空系统 Command Data HandlingCDH的核心数据模型以及 Components、Ports、Topologies 三大核心构造在项目与部署中的组织方式并深入线程模型在多核与裸机环境下的适配方案。读完后你将掌握 F´ 的全局架构图景、理解其模块化思想的底层设计并知道如何从仓库中继续深挖各子主题。F´ 的起源与设计目标F´ 是一个嵌入式系统框架其诞生初衷是为了满足小型嵌入式飞行任务如 CubeSats、小卫星和可部署载荷对高可靠组件与现成基础设施的需求从而最大化降低开发成本、缩短研制周期、减少人力投入。尽管它诞生于 NASA 任务F´ 并不局限于航天领域——任何嵌入式系统无论项目规模与领域都可以使用 F´ 进行建模与开发。F´ 的开发围绕以下八个明确目标展开见原文档捕获可复用性将嵌入式项目中可复用的部分沉淀为框架能力解耦可共享组件简化系统组件的拆分与重组组件隔离让每个组件易于独立测试快速适配新场景能够轻松适应新的应用上下文可移植性方便移植到新的体系结构与平台易用性降低使用门槛可扩展可配置按需伸缩与配置以匹配新用例资源受限下高性能在资源受限环境中保持良好的运行性能。从仓库顶层 README.md 可以看到 F´ 的官方定位A Flight-Proven, Multi-Platform, Open-Source Flight Software Framework——一个经过飞行验证、多平台、开源的飞行软件框架其提供的核心能力包括将飞行软件分解为具有明确定义接口的离散组件、提供消息队列与线程等核心能力的 C 框架、用于描述组件与连接并自动生成代码的建模工具、不断扩充的即用组件库以及单元级与集成级的测试工具。理解这八个目标是理解 F´ 全部设计决策的钥匙。太空系统视角F´ 为谁而建虽然 F´ 可以建模任意嵌入式系统但它的血脉源于太空。要完整理解 F´先要理解太空系统的基本形态在本指南语境下太空系统就是运行在太空中的嵌入式系统通常负责整颗航天器的完整控制与运行以完成某个科学任务。F´ 通常是这类系统中唯一完整的软件因此它把一个航天器的全部软件分解为若干离散的Components组件每个组件管理系统的一个部分。例如一个 Radio 组件负责控制无线电硬件以完成通信。组件之间通过Ports端口互联——端口承载组件间的通信。由 Ports 连接起来的完整 Components 图/网络被称为Topology拓扑它封装了整个系统。F´ 从设计之初就瞄准这些太空系统的Command and Data HandlingCDH指令与数据处理以及作为其一部分的科学仪器。这意味着 F´ 开箱即用地支持两类交互Commands命令从地面发往系统、控制系统行为的指令Telemetry遥测系统回传给地面的数据进一步分为Events事件与Channels通道Events代表系统行为的历史记录例如已建立通信Established CommunicationsChannels代表系统当前状态被拆分为一个个命名通道每个通道承载状态的一部分例如当前温度3°C。值得强调的是F´并不强制用户使用 Commands、Events、Channels 这套控制模型但它们是 F´ 项目的典型用法且内建于框架之中。因此要真正掌握 F´ 的能力既需要理解 Components、Ports、Topologies 三大结构构造也需要理解 Commands、Events、Channels 这套数据构造。F´ 部署的组织方式项目、部署与拓扑原文档用一个框架自带的例子——Command Dispatcher命令分发器——来说明一个 F´ 项目是如何组织的。该组件接收地面通信、将其翻译为动作、把动作分发给系统中另一个组件处理并等待其完成它会发出 Events 来标记动作被分发和完成的时刻并通过 Channels 统计已分发的命令数。从这个例子可以看到Components 是系统模块化的关键每个组件拥有一组用于通信的 Ports每个组件还可以定义一组它能够处理的Commands、一组它能上报的Events以及一组它将发出的Channels当系统由这些模块组装而成时功能被分布到各个组件中而Topology 负责建立通信连接使整个系统得以运转。仓库中 Svc/CmdDispatcher/CmdDispatcher.fpp 给出了该组件的 FPPF´ 的建模语言定义可印证上述描述它声明了compCmdSend/compCmdReg/compCmdStat等分发与注册端口、CMD_NO_OP等命令、OpCodeRegistered/OpCodeDispatched等事件以及CommandsDispatched/CommandErrors等遥测通道——正是原文档所描述的接收命令、分发、响应、上报事件与遥测的完整形态。项目Project、部署Deployment与拓扑Topology的层级结合 docs/user-manual/overview/proj-dep.md可以进一步理清三个层次的概念项目Project一组紧密相关部署的容器用于组织关系密切的 F´ 代码。一个项目定义至少一个部署也可能定义多个部署组件设计与源码可在这些相关部署间共享。项目包含多个部署的典型原因包括系统由多台航天器/电子平台/CPU 组成或项目拥有测试部署、mock 部署等专用测试配置。原文档所举的例子是火星直升机Mars Helicopter——一个项目定义了两个部署一个用于地面基站一个用于直升机本体。部署Deployment与构建一一对应——每次代码构建对应一个部署。部署可以在项目内共享组件与端口但其拓扑和 F´ 的具体构建通常是唯一的部署可以定义仅自身使用的自定义组件与端口也可以继承 F´ 框架提供的组件。部署还包含构建框架、组件、端口与拓扑所需的构建系统工件最终生成可部署到嵌入式硬件或运行在开发机上的可执行文件。拓扑Topology一组互联组件的集合代表一个具体系统的设计。拓扑包含每个组件的实例化并列出组件端口之间的连接关系。原文档中的核心架构图docs/img/core13.png直观展示了多个组件经由端口互联而成的拓扑图样可结合阅读。三大核心构造Ports、Components、Topologies为了充分理解部署组织方式需要深入这三个构造本身详见 docs/user-manual/overview/03-port-comp-top.md。Ports端口组件之间的互联点封装了架构中的类型化接口。每个端口定义都有特定类型如 CommandDispatchPort只有同类型的端口才能互相连接一次端口调用invocation是组件间的一次通信。端口可以携带零个或多个任意 F´ 数据类型或原始类型int、float、U8 等的参数部分端口还能向调用方返回值出于性能考虑也允许指针/引用参数但此时底层内存的所有权实质上是共享的需要谨慎管理。端口具有以下使用属性Port Kind端口种类方向同步/异步是否加锁Guarded可否返回数据output输出———sync_input输入同步否可async_input输入异步否否guarded_input输入同步是可方向性输入/输出来自调用发起方向而非数据流方向多个输出端口可连接到一个输入端口但一个输出端口同一时刻只能连接一个输入端口同步/异步同步端口如同函数调用运行在调用组件的执行上下文线程中Guarded加锁端口调用受组件级互斥锁保护同一时刻只允许一次调用进入。此外F´ 还有序列化端口Serialized Ports将端口调用的参数序列化到数据缓冲区从而可以跨越地址空间传输。任何强类型输出端口都可连接到序列化输入端口反之亦然这使只搬运数据、不关心类型的通用组件成为可能Hub 模式等跨进程/跨分区通信模式正依赖于此见 docs/user-manual/framework/run-multi-core.md 中的 Hub Pattern。Components组件封装行为、互不感知对方存在的模块。组件间不应存在任何非端口通信组件负责处理其端口调用也可定义并处理命令、发射遥测与事件。按有无队列、有无线程组件分为三种 kindComponent Kind组件种类有队列有线程支持的输入端口Passive被动否否sync/guarded不支持异步Queued排队是否至少 1 个 sync/guarded 至少 1 个 asyncActive主动是是三种皆可但至少需要 1 个异步端口每个组件的实现被划分为三层类核心框架基类active/passive/queued 三种基类之一→ 自动生成的组件专用基类承载框架功能的全部实现→ 开发者手写的组件实现类仅含用户特定逻辑。Topologies拓扑组件在运行时被实例化并通过端口连接这张互联图就是拓扑。拓扑在设计期被规划好但端口的实际连接发生在 F´ 软件运行时的构造与初始化阶段。组件之间不应存在代码级依赖只依赖端口接口类型——因此替换组件的替代实现例如仿真版本变得非常简单。CDH 数据构造Commands、Events、Channels 与 Parameters原文档强调F´ 开箱即用地支持地面指令下发与遥测回报。这些数据构造由 F´ 的Svc组件家族负责处理并有内建的自动编码器autocoder支持详见 docs/user-manual/overview/04-cmd-evt-chn-prm.md。Commands命令与面向组件间通信的 Ports 不同Commands 面向用户与组件的交互。每个组件可定义一组命令通过以下属性描述opcode唯一标识命令的数值自动相对于组件 base id 偏移避免与其他组件的命令冲突mnemonic唯一标识命令的文本组件实例名会被前置以确保系统内唯一arguments一组原始类型与 F´ 数据类型由地面随命令发送供命令处理器调整执行行为同步种类sync/async/guarded 三者控制命令的执行上下文——sync 与 guarded 命令运行在命令分发器的执行上下文中async 命令运行在组件线程上并可以指定优先级guarded 命令受互斥锁保护防止重入。命令分发Command Dispatching命令经Svc::CmdDispatcher分发——它接收包含命令与参数的原始缓冲区提取 opcode通过查找表定位处理组件将参数缓冲区传给该组件然后非阻塞地等待组件返回状态。每个处理命令的组件都应把注册registration、分发dispatch、响应response三类端口并行连接到命令分发器。仓库中的 Svc/CmdDispatcher/CmdDispatcher.fpp 完整展示了这套端口与命令模型command recv port CmdDisp、command reg port CmdReg、command resp port CmdStatus等特殊端口。命令序列化Command Sequencing许多项目需要按顺序执行命令。Svc::CmdSequencer从文件系统加载序列文件逐条向命令分发器发送命令并等待其执行状态失败响应会终止序列成功响应则进入下一条命令。通过命令序列器发送命令缓冲区是区别于地面外部发送的另一条命令路径。Events事件Events 是系统活动日志类似于程序执行日志用于追溯系统执行过程。事件由Svc::EventManager组件送出系统若需要控制台日志可将文本日志端口接到Svc::PassiveConsoleTextLogger。事件按组件定义通常用于捕获组件正在做什么可能零星发生但都应被捕获用于下行传输。事件由以下属性定义id数值唯一标识自动按组件 base id 偏移以保证全局唯一name唯一文本标识前置组件实例名以保证唯一severity严重级别取值包括——DIAGNOSTIC类似调试消息通常不下发地面ACTIVITY_LO类似细粒度 info 消息通常来自后台任务ACTIVITY_HI类似 info 消息通常来自前台任务WARNING_LO较低严重度的警告事件WARNING_HI高严重度警告事件系统仍可运行FATAL致命事件表示系统必须重启COMMAND追踪命令执行的事件arguments与命令参数类似是注入格式串以还原完整文本表示的变量数据format stringC 风格格式串用于重建事件的文本版本。事件日志Event Logging事件先获取时间标签time tag再发送给Svc::EventManager组件以待下行。该日志组件既处理事件也负责识别 FATAL 级事件并启动响应。自动编码器为每个组件自动添加两个独立的事件发送端口二进制日志输出端口发送到系统外与文本日志输出端口面向机载控制台。Channels遥测通道Channels 表示系统某部分状态的当前读数状态更新要么被限制为变化时发送on change要么每次更新都发送per update。通道是id、time、value三元组按组件定义通常以设定速率被采样并下行。其属性包括id按 base id 偏移保证全局唯一、name前置实例名保证全局唯一、data_type通道值类型可为原始或复杂类型、updateon_change表示仅在值变化时更新省略则总是下行。遥测数据库Telemetry DatabaseSvc::TlmChan充当遥测值的双缓冲存储——组件可随时更新通道值但当前值会以设定速率从数据库被读出并下行。对数据库的周期性调用通常由 rate group 模式速率组触发。Parameters参数Parameters 是嵌入式系统存储非易失状态的经典手段。参数属性包括id按 base id 偏移、name前置实例名、data type存储值的类型、default value参数无法获取时使用的默认值。自动编码器自动添加参数获取端口初始化期间会调用loadParameters()之类的公开方法获取参数并本地保存副本参数更新时可再次调用。参数数据库Parameter DatabaseSvc::PrmDb提供 get/set 参数的端口参数存储于文件中以跨重启持久化。初始化时它从文件系统加载参数文件随后调用带参数组件的loadParameters()组件可设置与获取参数而每个参数自动生成的 set 与 save 命令负责set 命令在所属组件本地更新参数值save 命令将参数当前值写入非易失存储使其在系统重置后依然存在。线程、多核架构与 F´原文档明确指出 F´ 的首要运行假设运行在带操作系统OS、单核的平台上这类系统自带线程调度器。同时F´ 完全可以在裸机baremetal或多核系统上运行但设计时需要格外注意执行上下文execution context的理解与处理。单核 OS 环境默认的线程模型在标准的 OS 部署中F´ 的Active 组件拥有自己的线程与消息队列异步端口调用与异步命令进入队列由组件线程在自身执行上下文中分派而同步与 guarded 调用则在调用方线程中执行。这是 F´ 最常见的执行模型。OS 抽象层OSAL为Os::Task、Os::Mutex、Os::Queue等提供了跨平台封装可参考 Os/docs/sdd.md 对 OS 抽象层的说明。多核环境SMP 与 AMP现代处理器普遍多核每个核独立执行代码允许多个执行上下文并行。多核管理主要有两种架构思路SMP对称多核单个 OS 将全部核作为共享处理器池统一管理提供 API 将线程钉到特定核或由 OS 根据负载动态分配。所有核共享同一内存空间单内核管理全部核OS 负责负载均衡与核分配AMP非对称多核多个 OS 各自运行每个 OS 分得一部分核通常由 hypervisor 在 OS 实例间划分核。每个 OS 实例拥有专用核内存可能在实例间分区。AMP 提供强分区隔离适合安全关键/混合关键系统但分区间通信需要专用中间件跨分区调试更难且每个分区需要独立的 OS 配置与部署。F´ 的多核支持F´ 在 OS 抽象层提供将线程固定到指定核的 API。Os::Task的Arguments类中的cpuAffinity参数默认TASK_DEFAULT即由 OS 动态分配用于指定核索引0、1、2…以完成绑定POSIX 实现通过pthread_attr_setaffinity_np设置 CPU 亲和掩码。职责分工上F´ 负责平台无关地抽象线程属性优先级、栈大小、CPU 亲和性并提供同步原语Os::Mutex、Os::Queue与组件线程模型OS 负责实际的线程调度、上下文切换、核分配、内存保护与同步执行。在多核环境中同步对象如互斥锁被委托给 OS 实现其 SMP 安全性取决于 OS 实现F´ 本身并非天生 SMP安全——必须依靠 OS 实现与开发者的设计来保证多核安全运行。原文档给出的核分配实践建议包括为执行一致性把承担特定功能的线程分配到各自核上如 I/O 线程、GNC 线程、数据处理线程分离可获得可预测的确定性行为适合安全关键/实时系统为执行效率允许 OS 动态分配线程最大化 CPU 利用率与吞吐量适合负载多变、确定性时序要求不高的场景为内存性能将共享大数据集的线程分配到同一核上避免缓存颠簸thrashing与内存总线争用混合模式将时间关键线程钉到专用核让后台处理线程在其余核上游走I/O 线程钉到处理相关中断的核数据共享与可重入必须用互斥锁等同步机制保护共享数据理解目标平台的内存模型警惕伪共享false sharing酌情使用无锁数据结构。裸机环境无 OS 的部署模式在裸机无 OS处理器上没有可运行进程/线程的软件资源通常受限只有一个入口——通常是一个连续控制循环while(true) { ... }也可使用中断服务例程ISR。F´ 并不强制要求 OS应用可以完全由 passive 组件组成用一个定时器组件通过 passive 速率组驱动整个应用详见 docs/user-manual/framework/run-baremetal.md。裸机模式的核心原则是尽量回避 Active 组件因为其线程需要 OS 级支持改用 passive/queued 组件由速率组或主循环驱动。典型架构是硬件定时器 →Svc.RateGroupDriver→ PassiveRateGroup → 各被动组件以固定间隔顺序执行没有并发调度系统表现为每个时钟节拍上分派的一串顺序工作。裸机支持包fprime-baremetal以 F´ 库形式提供还包含 Baremetal OS 模块模拟线程、消息队列等 OSAL 特性与 MicroFs内存文件系统供数据产品、参数存储、序列文件加载等需要文件接口的组件使用。资源受限时可通过 docs/user-manual/framework/configuring-fprime.md 中的配置选项裁剪框架开关特性、调整缓冲区/字符串/队列深度等或使用FW_DIRECT_PORT_CALLS编译选项优化端口调用开销。若裸机系统仍必须使用 Active 组件F´ 提供了**线程虚拟化Thread Virtualization**技术基于 protothreading用 CMake 选项FPRIME_USE_BAREMETAL_SCHEDULER开启见 cmake/options.cmake把每个组件线程的阻塞等消息 → 分派循环改写成非阻塞的 run_once 切片再由主循环对全部组件依次调用 run_once实现协作式轮转调度从而在单核上虚拟出并发。其前提是每个任务只运行一小片即返回、绝不循环、绝不阻塞。平台支持与结论原文档在结论中给出了 F´ 的成熟度证据框架以开源形式发布已被移植到 Linux、macOS、WindowsWSL、VxWorks、ARINC 653、裸机无 OS、PPC、Leon3、x86、ARMA15/A7与 MSP430 等平台一套成熟的 CDH 组件已经按飞行流程代码审查、静态分析、全覆盖率单元测试开发就绪。仓库中的 docs/user-manual/framework/supported-platforms.md 记录了更完整的支持平台清单可结合参考。综上所述F´ 的本质是一套组件联邦式的飞行软件框架系统被分解为离散组件组件仅通过类型化端口互联成拓扑图从而获得模块化、可测试性与可复用性在此结构之上Commands、Events、Channels 与 Parameters 构成完整的地面交互数据模型覆盖航天器 CDH 的全部典型需求而线程模型从单核 OS 出发通过 OS 抽象层与明确的执行上下文约定延伸覆盖多核SMP/AMP与裸机环境。继续深入阅读F´ 软件架构总览 与 Core Constructs: Ports, Components, and Topologies三大构造的完整细节Data Constructs: Commands, Events, Channels, and ParametersCDH 数据模型全解Projects and Deployments项目/部署/拓扑的分层组织F´ on Multi-Core Systems 与 F´ on Baremetal Systems多核与裸机部署指南命令分发器的源码级实例见 Svc/CmdDispatcher/CmdDispatcher.fpp 及其实现 Svc/CmdDispatcher/CommandDispatcherImpl.cpp可对照理解组件的端口/命令/事件/遥测声明语法。【免费下载链接】fprimeF´ - A flight software and embedded systems framework项目地址: https://gitcode.com/GitHub_Trending/fpr/fprime创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考