ARTICLE DETAIL

建站实战干货

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

F´ 组件字典深度解析:fprime 代码生成器中的遥测通道与枚举类型(以 TestTlm.md 为例)

2026/9/25 10:23:49 拓冰建站 浏览量
F´ 组件字典深度解析:fprime 代码生成器中的遥测通道与枚举类型(以 TestTlm.md 为例) 嵌入式系统编程【免费下载链接】fprimeF´ - A flight software and embedded systems framework项目地址https://gitcode.com/gh_mirrors/fp/fprime点击查看免费下载导读本文以 fprime 仓库中由代码生成器自动产出的组件字典文档 TestTlm.md 为切入点完整拆解 F´fprime飞行软件与嵌入式框架中**遥测通道Telemetry Channel**从 XML 模型定义、文档自动生成、C 基类代码生成到端到端发送与接收的完整链路。读完本文你将掌握如何阅读组件字典文档、如何用 XML 声明一个枚举类型的遥测通道以及生成器模板与底层序列化逻辑是如何配合工作的。一、TestTlm.md 是什么一份自动生成的组件字典TestTlm.md位于 Autocoders/Python/test/tlm_enum/docs/是 fprime 代码生成器测试套件tlm_enum的产出物之一。它属于 F´ 框架中的标准文档形态——组件字典Component Dictionary用于向地面系统GDS、测试人员与维护者描述一个组件对外暴露的遥测通道、事件与命令。该文档全文如下完整继承titleTestTlm Component Dictionary/title # TestTlm Component Dictionary ## Telemetry Channel List |Channel Name|ID|Type|Description| |---|---|---|---| |somechan|100 (0x64)|SomeEnum|A test channel|几点值得注意的细节文档第一行保留了title.../title形式的 HTML 风格标题行——这与生成它的模板实现完全一致见第三节文档只有Telemetry Channel List遥测通道列表一个章节因为测试组件只声明了遥测没有命令与事件表格四列分别为Channel Name通道名、ID十进制 十六进制、Type数据类型、Description描述。这份文档虽然只有一张表但它背后对应着完整的 XML 组件模型、代码生成器模板与可编译的 C 实现下面逐层展开。二、字典的来源XML 组件模型定义组件字典不是手写的而是由代码生成器Autocoder从组件模型定义中渲染出来的。tlm_enum测试用例的模型定义在 TestComponentAi.xmlcomponent nameTestTlm kindpassive namespaceTlm import_port_typeAutocoders/Python/test/tlm_enum/TestPortAi.xml/import_port_type commentA component with a single telemetry channel/comment ports port nameaport data_typeAnother::Test kindsync_input A test port /port /ports telemetry channel id100 namesomechan abbrevA444-7654 data_typeENUM enum nameSomeEnum item nameMEM1/ item nameMEM2 value7 commentA comment/ item nameMEM3 value15/ /enum commentA test channel/comment /channel /telemetry /component2.1 遥测通道的 XML 语法telemetry节点下每个channel声明一条遥测通道其关键属性为属性取值本用例含义id100通道 ID与文档表格中的100 (0x64)对应十进制 100 十六进制 0x64namesomechan通道名会直接参与生成 C 方法名tlmWrite_somechanabbrevA444-7654通道缩写供地面系统/外部工具索引使用data_typeENUM通道数据类型此处为枚举类型具体枚举体通过内嵌enum定义comment子节点的内容即文档表格 Description 列中的 A test channel。2.2 内嵌枚举SomeEnumdata_typeENUM时通道体内需内嵌enum声明枚举成员enum nameSomeEnum item nameMEM1/ item nameMEM2 value7 commentA comment/ item nameMEM3 value15/ /enum成员取值规则从生成模板 enum_hpp.tmpl 可以确认未显式声明value的成员按 C 枚举规则自动递增。因此MEM1取值 0MEM2显式取 7MEM3显式取 15。这也是文章第三部分实现代码中static_castSomeEnum(7)能对应到MEM2的根源。2.3 端口类型定义组件同步输入端口aport引用了 TestPortAi.xml 中定义于Another命名空间的Test接口携带I32 arg4、F32 arg5、U8 arg6三个参数。该端口在本用例中仅作占位用于验证组件生成的完整性。三、字典文档的生成机制从模板到 Markdown组件字典文档由 Autocoder 的 Markdown/HTML 生成器产出核心模板如下。3.1 Markdown 通道表模板MdChannelTablePage.tmpl 渲染了TestTlm.md的标题与表格title${name} Component Dictionary/title \#\# ${name} Component Dictionary #if $has_telemetry \#\# Telemetry Channels: ${name} |Channel Name|ID|Type|Description| |---|---|---|---| #for $id, $tlmname, $type, $size, $update, $comment, $typeinfo in $channels: |$tlmname|$id ($hexid)|$type|$comment| #end for #end if对照前文可确认文档中的100 (0x64)即模板中$id ($hexid)的渲染结果——ID 同时以十进制与十六进制呈现。3.2 ID 计算规则模板中 ID 的换算逻辑MdChannelTablePage.tmpl 与 HtmlChannelTablePage.tmpl 完全一致若id字符串包含x即声明为十六进制则按int($id, 16) $base_id计算否则按int($id) $base_id计算最终 ID 还会叠加拓扑级的base_id避免多实例/多组件通道 ID 冲突。本用例id100为十进制且无额外 base故最终 ID 为 1000x64。3.3 生成器 Visitor通道表 HTML 的生成由 InstanceTopologyChannelsHTMLVisitor.py 完成它为每个存在遥测的组件实例在channels/目录下生成instance_channels.html文件L106-L124并在publicVisit中填充name、base_id、has_telemetry、channel_enums、channels等模板变量L164-L179。Markdown 侧对应的生成器为 MdDocPage.py。这套机制说明组件字典是模型驱动文档Model-Driven Documentation的一部分XML/FPP 模型变更后重新运行生成器即可同步更新。四、枚举类型遥测通道的 C 生成代码组件字典表格中的 Type 列为SomeEnum与之对应Autocoder 还会生成两套 C 代码枚举类型定义与组件的遥测写入方法。4.1 tlmWrite 方法签名组件基类头文件模板 component/hpp.tmpl 为每个通道生成受保护方法//! Write telemetry channel somechan void tlmWrite_somechan( SomeEnum arg, // The telemetry value Fw::Time _tlmTime Fw::Time() // Timestamp. Default: unspecified, request from getTime port );4.2 tlmWrite 实现序列化与端口调用component/cpp.tmpl 中实现的tlmWrite_${tlmname}逻辑链为on_change 过滤仅当通道声明updateon_change时先比较上次值未变化则直接返回L898-L913。本用例未声明该属性因此每次调用都会发送。时间戳获取若_tlmTime为零时间且 Time 输出端口已连接则先从m_${Time_Name}_OutputPort[0]请求当前时间L915-L917。枚举序列化关键一步——枚举类型通道通过_tlmBuff.serialize(static_castFwEnumStoreType(arg))序列化L921-L922即以FwEnumStoreType为存储宽度将枚举值写入Fw::TlmBuffer。ID 计算与端口调用_id getIdBase() CHANNELID_...随后m_${Tlm_Name}_OutputPort[0].invoke(_id, _tlmTime, _tlmBuff)L931-L956。4.3 Tlm 端口协议端口调用签名与框架级端口定义严格对应。Fw/Tlm/Tlm.fpp 中声明port Tlm( $id: FwChanIdType Telemetry Channel ID ref timeTag: Fw.Time Time Tag ref val: TlmBuffer Buffer containing serialized telemetry value )即一次遥测发送携带通道 ID、时间标签、序列化后的值缓冲区三个要素——这正是接收端tlmRecvPort_handler的参数来源。五、端到端运行演示发送与接收测试用例 main.cpp 演示了完整的数据流。5.1 发送侧genTlmTestTelemImpl.cpp 中组件实现类通过调用生成的写入方法发送遥测void TestTlmImpl::genTlm(I32 val) { printf(Writing value %d to telemetry.\n, val); SomeEnum argVal static_castSomeEnum(val); this-tlmWrite_somechan(argVal); }注意SomeEnum类型正是 XML 中声明的内嵌枚举生成后作为独立类型被使用见 TestTelemImpl.hpp。若传入val 7实际发送的即MEM2。5.2 拓扑连接main.cpp 将三个组件实例连接成最小遥测链testImpl发送方Tlm::TestTlmComponentBase子类tlmRecv接收方来自 telem_tester 的TelemTester组件输入端口tlmRecvPort类型为Fw::TlmtimeSource时间源来自time_tester关键连接调用testImpl.set_Tlm_OutputPort(0, tlmRecv.get_tlmRecvPort_InputPort(0)); testImpl.set_Time_OutputPort(0, timeSource.get_timeGetPort_InputPort(0)); timeSource.setTime(Fw::Time(TB_NONE, 2, 3)); testImpl.genTlm(7);5.3 接收侧反序列化TestTelemRecvImpl.cpp 的端口处理函数展示了枚举通道值的消费方式void TestTelemRecvImpl::tlmRecvPort_handler(NATIVE_INT_TYPE portNum, FwChanIdType id, Fw::Time timeTag, Fw::TlmBuffer val) { U32 tlmVal; val.deserialize(tlmVal); printf(ID: %d TLM value is %d. Time is %d:%d base: %d\n, id, tlmVal, timeTag.getSeconds(), timeTag.getUSeconds(), timeTag.getTimeBase()); }发送方以FwEnumStoreType序列化枚举接收方以U32反序列化二者存储宽度一致值 7 可被还原。六、自动化测试验证tlm_enum同时提供构建与测试接入CMakeLists.txt 将该用例注册为register_fprime_module()并声明telem_tester、time_tester两个模块依赖该模块默认从全量构建中排除EXCLUDE_FROM_ALL TRUE仅作为生成器回归测试使用。test/ut/main.cpp 通过Tlm::TestTlmGTestBase实例化测试基类——该基类同样由生成器产出见 test/cpp.tmpl 中的遥测历史记录初始化逻辑。注释明确写道 Very minimal to test autocoder说明该目录的核心目的是验证枚举类型遥测通道的代码生成链路可编译、可实例化。七、小结与延伸阅读TestTlm.md虽只有一张表格却是 F´ 模型驱动开发全链路的缩影XML 模型 → Autocoder 生成组件字典文档与 C 基类 → 组件实现调用tlmWrite_*→ Tlm 端口携带 ID/时间/缓冲发送 → 接收端反序列化。枚举类型通道的特殊性在于模型层以内嵌enum声明成员生成层以SomeEnum : Fw::Serializable产出类型序列化层统一走FwEnumStoreType存储。需要继续深挖的读者可对照以下路径文档本身TestTlm.md本文主体模型定义TestComponentAi.xml、TestPortAi.xml实现与运行TestTelemImpl.cpp、TestTelemRecvImpl.cpp、main.cpp生成模板MdChannelTablePage.tmpl、HtmlChannelTablePage.tmpl、component/hpp.tmpl、component/cpp.tmpl、enum_hpp.tmpl框架端口协议Fw/Tlm/Tlm.fpp构建与测试CMakeLists.txt、test/ut/main.cpp需要说明的是本用例演示的是 XMLAi.xml建模路径当前仓库的主流建模语言是 FPP如 Tlm.fpp 以及Svc/、Ref/下大量.fpp/.fppi文件两种路径最终都汇入同一套代码生成与组件字典体系。赞分享嵌入式系统编程【免费下载链接】fprimeF´ - A flight software and embedded systems framework项目地址https://gitcode.com/gh_mirrors/fp/fprime点击查看免费下载相关推荐F´ 框架遥测组件字典解析以 TestTlm 为例掌握通道定义与字符串遥测实现F´ 框架遥测组件字典解析以 TestTlm 为例掌握通道定义与字符串遥测实现 本指南以 F´F Prime飞行软件与嵌入式系统框架中 autocoder嵌入式系统编程F´ 遥测通道字典与 on_change 更新模式从 tlm_onchange 测试组件解析 Telemetry 自动代码生成F´ 遥测通道字典与 on_change 更新模式从 tlm_onchange 测试组件解析 Telemetry 自动代码生成 F´F Prime是 NA嵌入式系统编程F´ 遥测通道字典深度解析从 XML 通道定义到自动生成 Component DictionaryF´ 遥测通道字典深度解析从 XML 通道定义到自动生成 Component Dictionary 本篇技术指南聚焦 F´Flight Software F嵌入式系统编程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考