F´ 平台移植指南:为 F´(F Prime)飞行软件框架适配新硬件平台的完整方案
嵌入式系统编程【免费下载链接】fprimeF´ - A flight software and embedded systems framework项目地址https://gitcode.com/gh_mirrors/fpri/fprime点击查看免费下载本文是一份面向 F´F Prime飞行软件与嵌入式系统框架的平台移植Porting实操指南。它围绕框架官方移植文档展开讲解将 F´ 迁移到新硬件平台所需的四个核心开发部分——CMake 工具链与平台文件、Fw::Types数值类型与配置、硬件驱动、OSAL操作系统抽象层支持并深入结合仓库源码如 cmake/platform、cmake/toolchain、Fw/Types、Os给出可复制、可运行的具体实现。读完本文你将掌握为 F´ 编写平台文件、交叉编译工具链、PlatformTypes.hpp类型头文件以及为裸机baremetal系统提供 OSAL 实现的完整技术方案。F´ 被设计为与硬件基本无关的框架绝大多数飞行软件代码只依赖一套明确定义的接口与抽象只有少量平台相关部分需要为新硬件单独开发。根据 docs/UsersGuide/dev/porting-guide.md将 F´ 移植到新平台需要完成以下四个部分CMake Toolchain 与 F´ platform 文件指定编译器等构建工具的路径与编译选项供 CMake 为给定平台编译 F´。Fw::Types与配置当硬件需要不同于默认设置时可能需要提供Fw::Types头文件及相应配置。硬件驱动超出框架自带 Linux Driver 包范围的驱动需针对硬件特定接口自行开发。OSAL 支持若平台需要非 Linux 操作系统则需开发 OSAL 支持文件详见 docs/UsersGuide/dev/os-docs.md。以上四个部分全部实现后用户即可在新的系统或平台上运行 F´。下文将逐一展开并给出仓库内可直接对照的源码证据。一、CMake Toolchain 与 F´ platform 文件F´ 的 CMake 构建系统将工具链toolchain与平台platform两个概念分开Toolchain 文件cmake/toolchain/指定目标系统名称、C/C 交叉编译器路径、查找根路径等解决用什么工具编译的问题Platform 文件cmake/platform/设置 F´ 特有的构建选项如全局头文件包含目录、编译器宏定义如TGT_OS_TYPE_*、线程库等解决为这个 OS/平台编译成什么样的问题。1.1 平台文件的加载规则根据 cmake/platform/platform.cmake.template平台文件的加载遵循以下规则用户很少需要直接指定若指定了 CMake Toolchain 文件则平台文件为${CMAKE_SYSTEM_NAME}.cmake。CMAKE_SYSTEM_NAME在工具链文件中设置通常为Linux、Darwin这类通用名称如需更细分也可取更具体的名字否则CMake 将CMAKE_SYSTEM_NAME自动设为宿主机系统名并使用对应平台文件。例如在 Linux 上构建时使用Linux.cmake。仓库中 cmake/platform/platform.cmake 的加载逻辑证实了这一点它遍历FPRIME_PROJECT_ROOT、FPRIME_LIBRARY_LOCATIONS、FPRIME_FRAMEWORK_PATH三个搜索位置依次查找${ROOT}/cmake/platform/${CMAKE_SYSTEM_NAME}.cmake找到即include并停止若最终仍未找到则报错并提示创建${CMAKE_SYSTEM_NAME}.cmakeforeach(ROOT ${FPRIME_PROJECT_ROOT};${FPRIME_LIBRARY_LOCATIONS};${FPRIME_FRAMEWORK_PATH} ) set(EXPECTED_PLATFORM_FILE ${ROOT}/cmake/platform/${CMAKE_SYSTEM_NAME}.cmake) if (EXISTS ${EXPECTED_PLATFORM_FILE}) message(STATUS Including ${EXPECTED_PLATFORM_FILE}) include(${EXPECTED_PLATFORM_FILE}) break() endif() endforeach() if (NOT EXISTS ${EXPECTED_PLATFORM_FILE}) message(FATAL_ERROR \n[F-PRIME] No platform config for ${CMAKE_SYSTEM_NAME}. Please create: ${CMAKE_SYSTEM_NAME}.cmake\n) endif()因此新平台文件应放在项目或库、框架的cmake/platform/目录下并以系统名称命名例如MyOS.cmake。同时可看到输出目录也按工具链名组织lib/${TOOLCHAIN_NAME}、bin/${TOOLCHAIN_NAME}便于同一部署为多平台产出不同的构建产物。1.2 编写 Platform 文件platform.cmake.templatecmake/platform/platform.cmake.template 是官方提供的平台文件模板按照其中的步骤填写即可生成一个可用的平台文件。核心要点STEP 1必做删除模板开头的message(FATAL_ERROR ...)失效保护行——这是防止未填写的原始模板被当作有效平台文件加载的保险丝STEP 2指定 OS 类型宏例如add_definitions(-DTGT_OS_TYPE_PLATFORM-NAME)实际各平台文件使用LINUX、DARWIN、RTEMS等值STEP 3设置 C/C 编译标志注意不要清空已有标志应追加set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} ADD-C-FLAGS-HERE) set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} ADD-CXX-FLAGS-HERE)STEP 4声明是否需要线程包。使用FPRIME_USE_BAREMETAL_SCHEDULER区分裸机调度无线程与线程化系统if (NOT DEFINED FPRIME_USE_BAREMETAL_SCHEDULER) set(FPRIME_USE_BAREMETAL_SCHEDULER OFF) message(STATUS Requiring thread library) FIND_PACKAGE ( Threads REQUIRED ) endif()若使用裸机调度器则不要设置该变量为 OFF从而跳过FIND_PACKAGE(Threads)STEP 5指定包含PlatformTypes.hpp及系统头文件的目录。模板注释明确建议通常Linux目录是不错的选择因为它从cstdint获取标准类型include_directories(SYSTEM ${FPRIME_FRAMEWORK_PATH}/Fw/Types/Linux)模板还特别说明如果目标系统与 Linux 相似可包含已有的*-common.cmakeLinux 相关公共设置以节省时间编译器的路径等 CMake 工具链设置则应交给 toolchain 文件处理见 cmake/toolchain/toolchain.cmake.template。1.3 仓库内现有平台文件对照仓库 cmake/platform 目录下已有三个平台文件可作为移植时的参照cmake/platform/Linux.cmake标准 Linux 目标。设置FPRIME_USE_BAREMETAL_SCHEDULER OFF并要求Threads包添加-DTGT_OS_TYPE_LINUX宏设置FPRIME_USE_POSIX ON把平台头文件目录cmake/platform/types加入系统包含路径。cmake/platform/Darwin.cmakemacOS 目标。设置-DTGT_OS_TYPE_DARWIN、FPRIME_USE_POSIX ON默认开启FPRIME_USE_STUBBED_DRIVERS使用桩驱动同样包含cmake/platform/types目录Darwin 可兼容使用 Linux/Posix 类型的PlatformTypes.hpp。cmake/platform/rtems5.cmakeRTEMS 5 实时操作系统目标是非 Linux POSIX 系统移植的范例。它设置-DTGT_OS_TYPE_RTEMS与FPRIME_USE_POSIX ON加入 RTEMS 的头文件路径${RTEMS_INCLUDE_DIRS}、${RTEMS_BSP_INCLUDE_DIRS}等、编译选项与链接选项并追加__rtems__、_POSIX_THREADS编译宏定义。这三个文件共同展示了平台文件需要回答的问题OS 类型宏、POSIX/裸机选择、线程需求、系统头文件路径、编译器/链接器附加选项。1.4 编写 Toolchain 文件toolchain.cmake.template当需要交叉编译cross-compile时需要编写工具链文件。官方模板 cmake/toolchain/toolchain.cmake.template 的步骤与示例STEP 1必做删除message(FATAL_ERROR ...)失效保护行STEP 2设置目标系统名set(CMAKE_SYSTEM_NAME NAME-OF-TARGET-SYSTEM)STEP 3指定 C/C 交叉编译器路径set(CMAKE_C_COMPILER PATH-TO-C-CROSS-COMPILER) set(CMAKE_CXX_COMPILER PATH-TO-CXX-CROSS-COMPILER)STEP 4设置工具链包根路径供查找库、可执行文件等使用set(CMAKE_FIND_ROOT_PATH PATH-TO-TOOLCHAIN-ROOT)不要编辑以下查找模式设置F´ 的交叉编译约定# F prime 从宿主机查找程序而不是交叉编译工具链 set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # 交叉编译时从工具链中查找库、头文件与包 set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)模板中给出的 Raspberry Pi 示例片段是理解这一流程的最佳案例CMAKE_SYSTEM_NAME RaspberryPI # 指定交叉编译器 set(CMAKE_C_COMPILER /opt/rpi/bin/arm-linux-gnueabihf-gcc) set(CMAKE_CXX_COMPILER /opt/rpi/bin/arm-linux-gnueabihf-g) # 目标环境在哪里 set(CMAKE_FIND_ROOT_PATH /opt/rpi)仓库中提供了完整的 Raspberry Pi 工具链实现 cmake/toolchain/raspberrypi.cmake它是真实可用的交叉编译配置设置CMAKE_SYSTEM_NAME Linux、CMAKE_SYSTEM_PROCESSOR arm通过find_program查找arm-linux-gnueabihf-gcc、arm-linux-gnueabihf-g、arm-linux-gnueabihf-ar、arm-linux-gnueabihf-objcopy、arm-linux-gnueabihf-objdump等工具并支持通过环境变量RPI_TOOLCHAIN_DIR或CMAKE_SYSROOT指定工具链位置。其注释说明宿主机上可通过sudo apt install gcc-arm-linux-gnueabihf g-arm-linux-gnueabihf gdb-multiarch安装交叉编译器。使用方法在部署目录下通过fprime-util或 CMake 传递# 通过 fprime-util 使用工具链示例 fprime-util build --toolchain 路径/cmake/toolchain/raspberrypi.cmake # 或直接传递给 CMake cmake -DCMAKE_TOOLCHAIN_FILE路径/cmake/toolchain/raspberrypi.cmake ...二、Fw::Types与配置为平台提供数值类型定义F´ 的数值类型体系是平台无关代码 平台相关定义的关键分界。移植时平台开发者需要提供PlatformTypes.hpp头文件并视需要调整配置。2.1PlatformTypes.hpp的职责根据 cmake/platform/types/PlatformTypes.hppLinux/Darwin 系统使用的平台类型头文件的文件头注释PlatformTypes.hpp由平台开发者发布用于定义 F´ 可用的标准算术类型。该 Linux/Darwin 版本面向运行在 x86/x86_64 上、使用系统自带 gcc/clang 的标准发行版。其内容结构如下Section 0C 标准类型。F´ 依赖intN_t/uintN_t及对应的 min/max 值。平台开发者必须要么定义这些类型要么包含定义了这些类型的头文件。同时通过开关控制各类型宽度是否可用#define FW_HAS_64_BIT 1 //! 架构支持 64 位整数 #define FW_HAS_32_BIT 1 //! 架构支持 32 位整数 #define FW_HAS_16_BIT 1 //! 架构支持 16 位整数 #define FW_HAS_F64 1 //! 架构支持 64 位浮点数F´ 消费这些信息并生成代码中常见的UN、IN、FN系列类型。Section 1逻辑类型Logical Types。F´ 要求平台实现者定义形如Platform*的逻辑类型完整清单见 docs/Design/numerical-types.md例如typedef int PlatformIntType; #define PRI_PlatformIntType d typedef unsigned int PlatformUIntType; #define PRI_PlatformUIntType u typedef PlatformIntType PlatformIndexType; #define PRI_PlatformIndexType PRI_PlatformIntType typedef PlatformUIntType PlatformSizeType;头文件还定义了这些类型的 min/max 常量供FpLimits继承使用并以注释说明使用 C struct 静态常量的两个原因静态上下文引用不占用存储无需优化、可被私有继承传递给派生类型。2.2 逻辑类型与框架类型的分层docs/Design/numerical-types.md 详细阐述了数值类型的设计哲学固定宽度类型Fixed Width TypesI8/I16/I32/I64、U8/U16/U32/U64、F32/F64映射到 C 标准类型编译器不支持的宽度可通过将 config/FpConfig.hpp 中的FW_HAS_*字段置0关闭默认全部开启。平台配置的逻辑类型PlatformIndexType端口索引、PlatformSizeType尺寸、PlatformPointerCastType以整数存储的指针、PlatformAssertArgTypeFW_ASSERT参数、以及已废弃的PlatformIntType/PlatformUIntType。每个类型都必须提供PRI_*格式说明符并在PlatformLimits结构体中定义type_MIN/type_MAX静态常量typedef int32_t PlatformIndexType; #define PRI_PlatformIndexType PRId32 struct PlatformLimits { static const PlatformIndexType PlatformIndexType_MIN 0; static const PlatformIndexType PlatformIndexType_MAX INT32_MAX; };可配置的框架类型Configurable Integer Types项目可通过自定义FpConfig.hpp配置框架使用的类型。默认配置直接复用平台类型typedef PlatformIndexType FwIndexType; #define PRI_FwIndexType PRI_PlatformIndexType typedef PlatformSizeType FwSizeType; #define PRI_FwSizeType PRI_PlatformSizeType typedef PlatformAssertArgType FwAssertArgType; #define PRI_FwAssertArgType PRI_PlatformAssertArgType上述即 config/FpConfig.hpp 中真实存在的定义。此外GDS地面数据系统相关类型如FwBuffSizeType、FwEnumStoreType、FwOpcodeType、FwChanIdType、FwEventIdType、FwPacketDescriptorType等在FpConfig.hpp中默认基于平台无关的固定宽度类型U16/I32/U32 等。2.3 备用默认实现DefaultTypes.hpp若平台文件的头文件搜索路径未找到自定义PlatformTypes.hpp仓库在 Fw/Types/default/DefaultTypes.hpp 提供了基于 x86_64 Linux 的回退默认实现。它使用#ifndef PLATFORM_*_TYPE_DEFINED守卫只有当平台头文件未定义对应类型时才填充默认 typedef 与PRI_*宏。其中PlatformPointerCastType的默认实现通过__SIZEOF_POINTER__判断指针宽度8/4/2 字节分别映射uint64_t/uint32_t/uint16_t否则退化为uint8_t若编译器不支持该宏则直接#error。移植时平台开发者应自行定义并置位这些PLATFORM_*_TYPE_DEFINED守卫或直接提供完整头文件覆盖默认值。2.4 打印与约束平台逻辑类型在printf家族中使用PRI_*宏格式化依赖字符串常量拼接例如PlatformIndexType index 3; printf(Index % PRI_PlatformIndexType is bound by % PRI_PlatformIndexType, index, FpLimits::PlatformIndexType_MIN);另一个关键约束是为保证无警告编译平台类型必须是 C 标准整数集合的元素int8_t、int16_t、int32_t、int64_t或其无符号对应。在int/unsigned int不属于该集合的编译器上PlatformIntType与PlatformUIntType必须被设置为某个固定宽度类型。类型定义链可继续追溯Fw/Types/BasicTypes.hpp 以#include PlatformTypes.hpp开头并在FW_HAS_*开关控制下定义I8/I16/I32/I64、U8/U16/U32/U64、F32/F64以及NATIVE_INT_TYPE、NATIVE_UINT_TYPE、POINTER_CAST等别名——这正是PlatformTypes.hpp定义的逻辑类型进入框架代码的入口。三、硬件驱动为平台特定接口开发驱动F´ 的驱动层位于 Drv 目录包含BlockDriver、LinuxGpioDriver、LinuxI2cDriver、LinuxSpiDriver、LinuxUartDriver、TcpClient/TcpServer/Udp、Ip网络套接字等。移植指南明确指出任何超出框架自带 Linux Driver 包范围的驱动都需要针对新硬件开发。编写硬件驱动时的要点结合仓库现有驱动结构可以推断端口定义.fpp / .fppi驱动通过 FPPF´ 原语描述语言声明对外端口例如 Drv/GpioDriverPorts/GpioDriverPorts.fpp、Drv/SpiDriverPorts/SpiDriverPorts.fpp 定义了驱动与组件之间的端口契约组件实现类以 Drv/LinuxGpioDriver/LinuxGpioDriverComponentImpl.cpp 为代表的*ComponentImpl类实现端口回调函数具体操作底层硬件桩驱动机制CMake 选项FPRIME_USE_STUBBED_DRIVERS见 cmake/options.cmake允许使用桩驱动替代完整实现适用于尚无驱动或仅需验证编译的移植阶段。该选项默认值由平台文件设定如 Darwin 平台默认 ON。完整实现需要驱动与 OS 支持OFF。对于 Linux 之外的平台驱动层需要与 OSAL 结合例如 Os/Linux、Os/Posix 提供系统调用封装而裸机平台则需自行实现寄存器操作与中断处理。四、OSAL 支持为操作系统提供抽象实现若新平台运行非 Linux 操作系统必须开发 OSAL操作系统抽象层支持文件。详见 docs/UsersGuide/dev/os-docs.md。4.1 OSAL 提供的服务OSAL 通过薄封装thin wrappers抽象真实操作系统RTEMS、VxWorks、Azure ThreadX、QNX、FreeRTOS、Zephyr 等实时系统或 Linux、macOS 等非实时系统的公共功能共六大类服务带优先级的任务多任务管理同步互斥文件管理消息队列通信超时定时。OSAL 的存在使 F´ 组件可以在开发工作站上独立于具体 OS 开发与测试显著降低系统间迁移成本。仓库中 OSAL 头文件集中在 Os 目录已提供 UnixPOSIX与 Mac OS 变体的实现新操作系统通过补充新实现即可完成移植。4.2 需要实现的关键类按文档与源码OS 移植文档 docs/UsersGuide/dev/os-docs.md 逐一说明了各服务的接口任务Tasks接口在 Os/Task.hpp。start()的参数包括任务名、用户选择的唯一整型标识符、优先级0 最低255 最高、栈大小字节、任务例程函数、传入参数以及 SMP 系统中的cpuAffinity-1 表示不指定核。其他方法包括delay()毫秒级挂起、suspend()/resume()/isSuspended()、getIdentifier()、getOsIdentifier()、getRawHandle()、registerTaskRegistry()等。Active主动组件依赖任务实现其特性。任务注册表Task Registry用于跟踪系统中所有任务实例可遍历并对其执行操作。基类提供addTask()/removeTask()纯虚函数开发者需派生自己的注册表实现。互斥锁Mutexes接口在 Os/Mutex.hpp提供lock()/unlock()。消息队列Message Queues接口在 Os/Queue.hpp。create()参数为队列名、深度超过即丢消息、消息最大尺寸、是否阻塞标志send()/receive()各有两个重载SerializeBufferBase引用版本与字节指针版本后者需要容量、实际大小与优先级参数getNumQueues()返回系统中创建的队列数。间隔定时器Interval Timer接口在 Os/IntervalTimer.hpp。不是到期定时器而是测量时间间隔的工具start()/stop()记录起止时间getDiffUsec()返回微秒差getRawTime()用于事件时间戳。看门狗定时器Watchdog Timer接口在 Os/WatchdogTimer.hpp。一次性定时器到期回调startTicks()/startMs()指定延时与回调函数、参数restart()用原值重启cancel()取消。文档注明并非所有 OS 适配都要求实现。中断锁Interrupt Lock接口在 Os/InterruptLock.hpp。lock()/unlock()阻止中断抢占可作为轻量互斥锁定区间的代码应极短。getKey()返回中断锁键通常不需要。文件File接口在 Os/File.hpp。抽象常见文件操作open()、isOpen()、seek()absolute参数控制相对文件头还是当前位置、read()waitForFull控制是否等待读满遇 EOF 提前返回、write()、flush()、close()、getLastError()/getLastErrorString()抽象errno/strerror()、calculateCRC32()。文件系统File System接口在 Os/FileSystem.hpp包含创建/删除目录等辅助调用另有 Os/Directory.hpp 支持流式读取目录。日志Log接口在 Os/Log.hpp抽象系统日志设施是Fw::Logger的子类构造后需注册将 Os/LogDefault.cpp 编译进部署会自动创建并注册Os::Log。logMsg()接受格式串与最多 6 个POINTER_CAST参数。4.3 仓库中的 OSAL 实现布局仓库 Os 目录展示了多套实现是移植时的直接参考Os/PosixPOSIX 实现Task.cpp、Mutex.cpp、Queue.cpp、IPCQueue.cpp、IntervalTimer.cpp、LocklessQueue.cpp、TaskId.cppOs/LinuxLinux 特有实现File.cpp、FileSystem.cpp、Directory.cpp、SystemResources.cpp、InterruptLock.cpp、WatchdogTimer.cppOs/Baremetal裸机实现Task.cpp、Mutex.cpp、Queue.cpp、SystemResources.cpp、File.cpp、FileSystem.cpp、IntervalTimer.cpp及TaskRunner/子目录——这是无 OS 平台移植的核心参考Os/MacOs、Os/X86平台微调实现Os/Stubs桩实现。移植时为每个头文件Task、Mutex、Queue等提供对应平台的.cpp实现并在平台文件中加入编译即可。五、裸机平台的移植无 OS 场景的 F´移植指南与 docs/UsersGuide/dev/baremetal-multicore.md 表明F´ 同样支持裸机无操作系统平台此时由 F´ 自身提供文件系统、线程调度等基础服务。裸机移植需要特别注意以下几点优先使用 Passive被动组件裸机系统应尽量避免 Active 组件因为其需要准异步执行上下文线程。若系统可完全由 Passive 组件构成则每个端口调用都是同步的。选择执行上下文由于没有 OS 调度实现者必须保证有某个调用驱动所有组件运行。典型做法是把系统组合成由速率组rate group驱动的结构全部执行源于速率组驱动这一单一来源从而把问题简化为以设定速率向速率组驱动提供执行上下文。主程序典型结构为setup(); while (true) { execute(); // 以固定间隔触发速率组驱动 }间隔判定可通过自旋等待硬件时钟信号、读取时钟寄存器、sleep()或定时器中断ISR实现文档特别提醒ISR 不应直接执行速率组而应置标志或排队启动消息由主循环while(true)检测后启动速率组。裸机调度器与线程虚拟化仓库在 Os/Baremetal 下实现了顺序调度器——Os/Baremetal/TaskRunner/TaskRunner.hpp 是任务注册表 任务运行器的组合addTask()/removeTask()维护最多TASK_REGISTRY_CAP100个任务run()在主循环中一次遍历运行所有任务。其原理是把每个 Active 组件线程的阻塞等待消息循环改造成非阻塞的run_once()切片探测是否有消息、有则分发、随后返回再在主循环中依次调用所有组件的run_once()实现虚拟化并行protothreading 技术。FPRIME_USE_BAREMETAL_SCHEDULER见 cmake/options.cmake为 ON 时启用该替代实现可限制为单线程执行或用于在 PC 上测试裸机调度器。使用线程虚拟化时自定义任务函数必须不循环、绝不阻塞、每次只执行一片后返回。六、移植完成后的验证与运行四个部分实现完成后可通过以下路径验证移植成果平台文件加载验证配置 CMake 时观察platform.cmake输出的Target build toolchain/platform: name/system与Including ...消息确认新平台文件被正确加载数值类型验证检查 Fw/Types 与 config/FpConfig.hpp 的编译是否通过、PRI_*宏格式化输出是否符合预期构建与单元测试框架的Fw/Types模块带单元测试Fw/Types/test/ut/TypesTest.cppOSAL 各实现可结合 Os/test/ut 的测试用例验证任务、队列、互斥、定时器等行为部署运行参照仓库中的部署示例如 Ref、RPI构建目标部署在目标硬件上启动并观察遥测、事件与命令流是否正常。总结F´ 的平台移植是一项有清晰边界的工作CMake 工具链与平台文件负责构建系统适配PlatformTypes.hpp与FpConfig.hpp负责数值类型适配驱动层负责硬件接口适配OSAL 负责操作系统服务适配。四者相互配合使得平台无关的 F´ 核心代码可以在新硬件上运行。以 cmake/platform/platform.cmake.template、cmake/toolchain/toolchain.cmake.template、cmake/platform/types/PlatformTypes.hpp、Os/Baremetal 为起点对照仓库内已有的 Linux、Darwin、RTEMS、Raspberry Pi 实现开发者可以在最短时间内完成从有 OS 的 POSIX 系统到裸机嵌入式系统的完整移植。赞分享嵌入式系统编程【免费下载链接】fprimeF´ - A flight software and embedded systems framework项目地址https://gitcode.com/gh_mirrors/fpri/fprime点击查看免费下载相关推荐F´ (F Prime) 飞行软件框架中的 Svc::ActiveRateGroup 速率组调度组件详解F´ F Prime 飞行软件框架中的 Svc::ActiveRateGroup 速率组调度组件详解 Svc::ActiveRateGroup 是 F´ 飞行软嵌入式系统编程F´ 新平台移植指南Toolchain、平台文件、Fw::Types、硬件驱动与 OSAL 五步移植法F´ 新平台移植指南Toolchain、平台文件、Fw::Types、硬件驱动与 OSAL 五步移植法 F´F Prime是一个面向飞行软件与嵌入式系统的嵌入式系统编程F´ (F Prime) 入门指南组件驱动的飞行软件框架与首个应用搭建F´ F Prime 入门指南组件驱动的飞行软件框架与首个应用搭建 F´F Prime是一个组件驱动的软件框架面向航天飞行软件及各类嵌入式应用的快速开发嵌入式系统编程上一篇视频号、抖音、快手的无水印视频怎么一次拿全res-downloader 完整使用指南下一篇Checkov项目中的CycloneDX BOM生成与应用指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考