嵌入式系统编程【免费下载链接】fprimeF´ - A flight software and embedded systems framework项目地址https://gitcode.com/gh_mirrors/fpri/fprime点击查看免费下载导读Fw::Time是 F´F Prime飞行软件与嵌入式系统框架中用于在系统内传递时间戳time stamp的标准端口遥测telemetry、事件events以及其他需要时间信息的组件都依赖它。本文将围绕 Fw/Time/docs/sdd.md 的设计文档结合仓库内端口定义、Fw::Time数据类型实现、配置项与单元测试完整解析该端口的作用、Fw::Time类的内部结构与运算语义以及它如何通过序列化在组件间流转。读完本文你将掌握Fw::Time端口的定义方式、时间基准Time Base与时间上下文Time Context的配置含义、时间戳序列化格式以及时间比较/加减运算的边界行为能够在自己的 F´ 组件中正确使用或扩展这一机制。1. 端口定位与核心职责根据 Fw/Time/docs/sdd.md 的说明TheFw::Timeport is used to pass time stamps around the system, either for telemetry and events or other uses.Fw::Time端口用于在系统各处传递时间戳——无论是遥测数据、事件EVENT报文还是其他需要时间信息的用途。它是 F´ 中时间信息流通的标准管道负责提供时间的组件如Svc::Time通过该端口对外输出当前时间遥测/事件采集链路则通过该端口获取时间戳并打入下行报文。1.1 FPP 端口定义端口在 FPP 语言中的定义位于 Fw/Time/Time.fppmodule Fw { type Time Time port port Time( ref $time: Fw.Time The U32 cmd argument ) }关键点端口名与数据类型同名均为Time归属Fw模块端口通过引用ref传递一个Fw.Time类型的参数$time即调用方传入一个Fw::Time对象引用由被调用方填充/读取该端口没有返回值无return子句时间值完全依靠引用参数带出这与后续Svc::Time组件中timeGetPort的同步调用模式一致。2. 端口设计上下文Design2.1 端口图设计文档给出的端口框图如上图所示图片源文件为 Fw/Time/docs/img/TimeBDD.jpg其含义可以解读为左侧PortType Time命名空间Fw描述了端口类型Time其关联操作return() : Time表明该端口最终返回一个Fw::Time类型的值右侧DataType Time是端口使用的数据类型明确标注其来源头文件为Fw/Time/Time.hpp、命名空间为Fw与左侧端口引用的Time类型完全对应。2.2 端口使用的可序列化类型Fw::Time设计文档指出Fw::Timeis a class that stores the time base (project specific), seconds and microseconds of the time stamp.即Fw::Time是一个类存储了时间戳的时间基准time base项目相关、秒与微秒三部分信息。在仓库实现中Fw/Time/Time.hpp 进一步表明它继承自Fw::Serializable是一个标准的可序列化对象内部还额外维护了一个时间上下文time context字段用于记录如重启计数、节点编号等用户自定义信息。3. Fw::Time 数据类型源码级剖析3.1 内部成员与内存布局Fw/Time/Time.hpp 定义了其序列化后的尺寸常量enum { SERIALIZED_SIZE sizeof(FwTimeBaseStoreType) sizeof(FwTimeContextStoreType) sizeof(U32) sizeof(U32) };四个成员分别为见 Fw/Time/Time.hpp成员类型含义m_secondsU32秒部分m_usecondsU32微秒部分m_timeBaseTimeBase枚举时间基准由系统/项目定义m_timeContextFwTimeContextStoreTypeU8用户可设值如重启计数、节点号等在默认配置FW_USE_TIME_BASE 1、FW_USE_TIME_CONTEXT 1下时间戳序列化占用2 1 4 4 11字节若在 config/FpConfig.hpp 中关闭时间基准或时间上下文特性序列化体积可相应缩减。3.2 时间基准与存储类型定义config/FpConfig.hpp时间基准枚举与配套存储类型定义在 config/FpConfig.hppenum TimeBase { TB_NONE, //! No time base has been established TB_PROC_TIME, //! Indicates time is processor cycle time. Not tied to external time TB_WORKSTATION_TIME, //! Time as reported on workstation where software is running. For testing. TB_DONT_CARE 0xFFFF //! Dont care value for sequences. If FwTimeBaseStoreType is changed, value should be changed }; #define FW_CONTEXT_DONT_CARE 0xFF //! Dont care value for time contexts in sequences typedef U16 FwTimeBaseStoreType; typedef U8 FwTimeContextStoreType;需要理解的关键语义TB_NONE尚未建立时间基准Fw::Time的默认构造状态即为此值Time()构造时将m_timeBase置为TB_NONETB_PROC_TIME处理器周期时间不绑定外部时钟适合嵌入式环境下的相对计时TB_WORKSTATION_TIME软件运行所在工作站的系统时间主要用于主机/桌面测试场景TB_DONT_CARE与FW_CONTEXT_DONT_CARE序列sequence等场景中表示不关心的占位值用于指令序列文件中的时间匹配FwTimeBaseStoreTypeU16与FwTimeContextStoreTypeU8是时间基准与上下文的存储类型保证其在序列化与跨平台传输时尺寸确定。此外 config/FpConfig.hpp 提供了两个特性开关直接影响Fw::Time的序列化行为与比较逻辑#ifndef FW_USE_TIME_BASE #define FW_USE_TIME_BASE 1 //! Whether or not to use the time base #endif #ifndef FW_USE_TIME_CONTEXT #define FW_USE_TIME_CONTEXT 1 //! Whether or not to serialize the time context #endif从 Fw/Time/Time.cpp 的实现可以看到当FW_USE_TIME_BASE关闭时反序列化会将m_timeBase强制置为TB_NONE当FW_USE_TIME_CONTEXT关闭时上下文被强制置 0——这说明这两个特性开关既控制序列化字节流也决定了对端解析后的默认值。3.3 构造与赋值 APIFw/Time/Time.hpp 提供了多组构造与设置方法覆盖从仅秒/微秒到基准上下文秒/微秒的完整组合Time(); // 默认构造0 秒、0 微秒、TB_NONE、上下文 0 Time(U32 seconds, U32 useconds); // 仅秒与微秒基准为 TB_NONE Time(TimeBase timeBase, U32 seconds, U32 useconds); Time(TimeBase timeBase, FwTimeContextStoreType context, U32 seconds, U32 useconds); void set(U32 seconds, U32 useconds); // 覆盖设置保留原基准与上下文 void set(TimeBase timeBase, U32 seconds, U32 useconds); void set(TimeBase timeBase, FwTimeContextStoreType context, U32 seconds, U32 useconds);配套的读取接口为getSeconds()、getUSeconds()、getTimeBase()、getContext()。set(U32, U32)这类只传秒/微秒的重载会保留对象已有的基准与上下文而不是重置为默认值这一点在复用时间对象时应特别注意。3.4 序列化与反序列化Fw::Time作为Fw::Serializable的派生类实现了serialize/deserialize见 Fw/Time/Time.cpp其字节流顺序为可选FW_USE_TIME_BASE时间基准FwTimeBaseStoreType可选FW_USE_TIME_CONTEXT时间上下文FwTimeContextStoreType秒U32微秒U32。每一步都检查SerializeStatus任一环节失败即立即返回错误状态。正是因为实现了这套标准序列化接口Fw::Time才能被嵌入遥测通道Tlm、事件Log等报文缓冲区随下行数据一起传回地面。3.5 比较运算基准不同则不可比Fw::Time实现了、!、、、、全部比较运算符底层统一委托给静态方法Time::compareFw/Time/Time.cpp比较结果类型为Time::Comparison枚举LT -1、EQ 0、GT 1、INCOMPARABLE 2在FW_USE_TIME_BASE开启时若两个时间基准不同返回INCOMPARABLE在FW_USE_TIME_CONTEXT开启时若上下文不同同样返回INCOMPARABLE仅当基准与上下文一致时才按先比秒、后比微秒的字典序给出LT/EQ/GT。因此在业务代码中跨基准例如把TB_PROC_TIME与TB_WORKSTATION_TIME的时间戳直接比较会得到不可比结论这是设计上防止语义错乱时间比较的刻意约束。3.6 时间算术add / sub / add(seconds, useconds)Fw/Time/Time.cpp 提供了三种时间运算static Time add(const Time a, const Time b)两个时间相加要求基准与上下文相同否则触发FW_ASSERT断言微秒部分相加后若 1000000则向秒进位并断言结果微秒uSeconds 1999999防止溢出static Time sub(const Time minuend, const Time subtrahend)被减数减减数断言被减数不小于减数若微秒不够减则从秒借 1等价于微秒 1000000 再减正确实现跨秒借位void add(U32 seconds, U32 useconds)就地增加秒与微秒同样处理微秒进位并断言m_useconds 1999999。这些运算在测量任务执行耗时、计算时间差等场景中非常实用其借位/进位逻辑已被单元测试覆盖见第 5 节。3.7 零时间与全局常量静态工厂方法static Time zero(TimeBase timeBase TB_NONE)返回基准可指定、秒/微秒/上下文全为 0的时间对象全局常量extern const Time ZERO_TIME;定义于 Fw/Time/Time.cpp是默认构造的零时间Fw::ZERO_TIME可直接用于时间是否已初始化的判断——例如 Fw/Time/test/ut/TimeTest.cpp 中验证了非默认构造的时间与ZERO_TIME不相等、默认构造的时间与ZERO_TIME相等。4. 在系统中的应用Svc::Time 与遥测/事件链路Fw::Time端口在实际部署中由时间服务组件对外提供。仓库中的 Svc/Time/Time.fpp 给出了标准用法passive component Time { ... sync input port timeGetPort: Fw.Time ... }Svc::Time组件暴露名为timeGetPort的同步输入端口端口类型正是Fw.Time。外部组件如遥测通道Svc::TlmChan、事件记录器Svc::ActiveLogger、命令调度器等在生成遥测或事件报文时通过该端口同步获取当前时间戳并填入报文。整套链路可以概括为时间源Svc::Time及其平台实现如Svc::LinuxTime维护并持续更新时间需要时间戳的组件通过Fw::Time端口同步调用timeGetPort传入Fw::Time引用参数时间服务填充引用对象的秒/微秒/基准/上下文后返回调用方将Fw::Time序列化进 Tlm/Log 报文缓冲区随遥测或事件下行到地面系统。这一端口传递引用 对象可序列化的组合正是Fw::Time在整个框架中通用性强的根本原因——它不绑定任何特定组件任何模块都可以声明并使用该端口获取或转发时间戳。5. 单元测试验证仓库的单元测试位于 Fw/Time/test/ut/TimeTest.cpp覆盖了该数据类型的全部核心行为测试用例验证内容InstantiateTest构造Time(TB_NONE, 1, 2)后基准、上下文、秒、微秒字段取值正确MathTest相等/不等/大于/小于/大于等于比较add求和1000s1000us 4000s2000us 5000s3000us常规减法微秒借位减法2s1us - 1s999999us 0s2usCopyTest拷贝构造、赋值运算符、set方法均能完整复制四个字段ZeroTimeEquality非零时间与Fw::ZERO_TIME不等默认构造时间与Fw::ZERO_TIME相等其中MathTest对微秒进位加法与借位减法的断言正是对 Fw/Time/Time.cpp 中进位/借位分支的直接验证可作为理解Fw::Time时间运算语义的最佳示例。6. 变更记录设计文档末尾给出了本模块的变更历史见 Fw/Time/docs/sdd.mdDateDescription6/19/2015Initial Version小结与实战要点端口形态Fw::Time是无返回值、以ref引用方式传递Fw.Time参数的端口FPP 定义见 Fw/Time/Time.fpp数据类型Fw::Time存储时间基准 时间上下文 秒 微秒四个字段序列化尺寸与字段取舍受 config/FpConfig.hpp 中的TimeBase枚举、FW_USE_TIME_BASE、FW_USE_TIME_CONTEXT控制运算语义比较运算要求基准与上下文一致否则返回INCOMPARABLEadd/sub内置微秒进位/借位逻辑均以断言保护接入方式参照 Svc/Time/Time.fpp 声明sync input port timeGetPort: Fw.Time即可在自己的组件中接收系统时间戳验证手段阅读并运行 Fw/Time/test/ut/TimeTest.cpp 可快速理解构造、比较、算术与零时间语义。如需进一步了解时间在遥测与事件报文中的落地方式可继续阅读 Fw/Tlm 与 Fw/Log 目录下的相关实现与文档。赞分享嵌入式系统编程【免费下载链接】fprimeF´ - A flight software and embedded systems framework项目地址https://gitcode.com/gh_mirrors/fpri/fprime点击查看免费下载相关推荐F´ 框架中的 Fw::Time 端口时间戳传递、Fw::Time 数据类型与序列化机制详解F´ 框架中的 Fw::Time 端口时间戳传递、Fw::Time 数据类型与序列化机制详解 导读 Fw::Time 端口是 NASA F´F Prime嵌入式系统编程F´ (F Prime) 事件日志端口深度解析Fw::Log 与 Fw::LogText 端口的设计、序列化与使用指南F´ F Prime 事件日志端口深度解析Fw::Log 与 Fw::LogText 端口的设计、序列化与使用指南 导读 本文聚焦 F´F Prime飞行嵌入式系统编程F´ 框架中的 Fw::Time 与 Fw::TimeInterval时间戳与时间间隔端口的深度解析F´ 框架中的 Fw::Time 与 Fw::TimeInterval时间戳与时间间隔端口的深度解析 本文围绕 F´F Prime飞行软件与嵌入式系统框架嵌入式系统编程上一篇模拟人生1宽屏补丁完整指南让经典游戏完美适配现代显示器下一篇ESPHome 配置避坑3 步从 YAML 跑通第一台设备固件创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考