
嵌入式系统编程【免费下载链接】fprimeF´ - A flight software and embedded systems framework项目地址https://gitcode.com/gh_mirrors/fp/fprime点击查看免费下载导读Svc::CmdSplitter是 F´F Prime飞行软件框架中的一个轻量级被动组件核心职责是把一条上行链路uplink命令按操作码opcode阈值拆分为“本地local”与“远程remote”两个去向分别转发给两个独立的Svc::CmdDispatcher命令调度器。它是 F´ 分布式部署中hub 模式多部署互联命令路由链路的枢纽环节通过Svc::GenericHub与远端部署互联实现地面站对远端部署的命令控制。读完本文你将掌握该组件的端口结构、路由判定算法、启动期配置方式以及如何用单元测试验证其行为。1. 组件定位为什么需要命令拆分在单机部署中Svc::CmdDispatcher是唯一接收上行命令的组件。但在 hub 模式的多部署互联场景下地面站的上行命令既可能针对本机也可能要穿过 hub 转发给远端部署。Svc::CmdSplitter正是为这种场景而生它接收一条Fw::ComBuffer命令缓冲区通过比较命令操作码与一个启动期配置的基值base opcode把命令路由到本地命令操作码小于配置基值 → 送往本机Svc::CmdDispatcher远程命令操作码大于等于配置基值 → 送往远端Svc::CmdDispatcher通常经由 hub 组件转发。这一设计使得哪些操作码属于本机、哪些属于远端完全由配置决定部署时只需约定一个操作码分界值即可在不改动代码的前提下重新划分命令归属。2. 端口设计镜像 CmdDispatcher 的多源命令输入Svc::CmdSplitter的组件模型定义在 Svc/CmdSplitter/CmdSplitter.fpp它是一个 passive 组件全部端口均为数组端口且数组规模与命令调度器的输入端口数组保持一致从而以与Svc::CmdDispatcher完全相同的方式支持多个命令源如多个上行链路、命令序列器等。端口名类型方向说明CmdBuffFw.Comsync input array命令缓冲区输入端口数组接收上行命令seqCmdStatusFw.CmdResponsesync input array来自本地与远程调度器的命令状态响应输入数组LocalCmdFw.Comoutput array输出给本地命令调度器的命令缓冲区数组RemoteCmdFw.Comoutput array输出给远程命令调度器的命令缓冲区数组forwardSeqCmdStatusFw.CmdResponseoutput array转发给命令源的命令状态响应数组数组规模由 FPP 常量CmdSplitterPorts控制其定义于 config/AcConstants.fpp并被赋值为CmdDispatcherSequencePorts默认 5 Used for sizing the command splitter input arrays constant CmdSplitterPorts CmdDispatcherSequencePorts这意味着所有命令源共享同一套端口索引例如第 0 号上行源发出的命令经CmdBuff[0]进入若为本地命令则由LocalCmd[0]送往本地调度器本地调度器处理完毕后的状态响应又经seqCmdStatus[0]返回最后经forwardSeqCmdStatus[0]原路回传给该命令源。端口索引在整条链路上保持一致这也是多个命令源能够并行工作而不互相串扰的关键。3. 路由算法一次反序列化 一次比较Svc::CmdSplitter的核心逻辑位于 Svc/CmdSplitter/CmdSplitter.cpp组件本身没有显著的算法实际只做两件事解析命令操作码和按阈值分发。3.1 命令入口 CmdBuff_handlervoid CmdSplitter ::CmdBuff_handler(const NATIVE_INT_TYPE portNum, Fw::ComBuffer data, U32 context) { Fw::CmdPacket cmdPkt; Fw::SerializeStatus stat cmdPkt.deserialize(data); FW_ASSERT(portNum CmdSplitterPorts); if (stat ! Fw::FW_SERIALIZE_OK) { // Let the local command dispatcher deal with it this-LocalCmd_out(portNum, data, context); } else { // Check if local or remote if (cmdPkt.getOpCode() this-m_remoteBase) { this-LocalCmd_out(portNum, data, context); } else { this-RemoteCmd_out(portNum, data, context); } } }处理流程可以拆解为三条分支反序列化失败如缓冲区为空、报文格式非法stat ! FW_SERIALIZE_OK无法提取操作码组件按安全失败原则把命令交给本地调度器处理。本地CmdDispatcher会将其识别为格式错误命令并上报错误事件——这正是 sdd 中需求SVC-CMD-SPLITTER-004错误发生时路由到本地端口的实现体现操作码小于m_remoteBase走LocalCmd_out即本地命令操作码大于等于m_remoteBase走RemoteCmd_out即远程命令。注意这里的判定采用左闭右开区间本地为[0, m_remoteBase)远程为[m_remoteBase, ∞)。context参数原样透传给下游供命令源做上下文关联使用。3.2 状态响应入口 seqCmdStatus_handlervoid CmdSplitter ::seqCmdStatus_handler(const NATIVE_INT_TYPE portNum, FwOpcodeType opCode, U32 cmdSeq, const Fw::CmdResponse response) { FW_ASSERT(portNum CmdSplitterPorts); // Forward the command status this-forwardSeqCmdStatus_out(portNum, opCode, cmdSeq, response); }无论是本地还是远程调度器返回的命令状态Fw::CmdResponse携带操作码、命令序列号与响应状态CmdSplitter一律无条件原样转发回命令源不做过滤与改写对应需求SVC-CMD-SPLITTER-005转发命令状态响应。3.3 唯一的内部状态m_remoteBaseSvc::CmdSplitter只有一个内部状态变量m_remoteBase类型为FwOpcodeType声明于 Svc/CmdSplitter/CmdSplitter.hpp其注释明确了语义Opcodes greater than or equal than this value will route remotely操作码大于等于该值则路由到远端。它只能通过configure()方法在系统启动阶段设置一次void CmdSplitter ::configure(const FwOpcodeType remoteBaseOpcode) { this-m_remoteBase remoteBaseOpcode; }因此本地/远程命令的划分是部署级决策两个命令调度器各分配一段操作码区间运行期不再变化。配置时应保证本地区间留有足够的操作码空间测试代码中特意要求 base 必须大于 0must leave some room for local commands避免本地命令区间为空。4. 需求矩阵与验证方法sdd 中给出了组件需求的完整矩阵每项需求均有对应的单元测试验证需求描述验证方法SVC-CMD-SPLITTER-000组件须支持多个命令源单元测试SVC-CMD-SPLITTER-001组件须接受传入的命令缓冲区单元测试SVC-CMD-SPLITTER-002组件须将低于配置值的命令路由到“本地”端口单元测试SVC-CMD-SPLITTER-003组件须将不低于配置值的命令路由到“远程”端口单元测试SVC-CMD-SPLITTER-004发生错误时组件须将命令路由到“本地”端口单元测试SVC-CMD-SPLITTER-005组件须转发命令状态响应单元测试这些需求的测试实现集中在 Svc/CmdSplitter/test/ut/CmdSplitterTester.cpp测试用例入口为 Svc/CmdSplitter/test/ut/CmdSplitterTestMain.cpp共四个用例组Nominal.Local随机选择一个小于 base 的操作码构造合法的Fw::ComBuffer命令报文验证命令只出现在LocalCmd输出、RemoteCmd无输出且输出缓冲区与 context 与输入一致Nominal.Remote随机选择一个大于等于 base 的操作码验证命令只出现在RemoteCmd输出Nominal.Forwarding随机构造操作码、命令序列号与Fw::CmdResponse状态验证seqCmdStatus输入被完整转发到forwardSeqCmdStatusError.BadCommands传入故意留空的缓冲区反序列化必然失败验证命令被安全路由到LocalCmdRemoteCmd无输出。测试中build_command_around_opcode()展示了命令报文的真实字节布局先序列化报文类型描述符Fw::ComPacket::FW_PACKET_COMMAND再序列化操作码最后序列化Fw::CmdArgBuffer参数区——这与 Fw/Cmd/CmdPacket.cpp 中Fw::CmdPacket::deserialize()的解析顺序一一对应。测试还通过随机选择端口号、并断言回调中的端口号与命令源一致直接印证了多命令源并行需求 SVC-CMD-SPLITTER-000的端口数组设计。按 sdd 的说明可在Svc::CmdSplitter目录下运行以下命令查看单元测试覆盖率fprime-util check --coverage组件的构建与测试注册位于 Svc/CmdSplitter/CMakeLists.txtregister_fprime_module()负责将CmdSplitter.fpp自动生成端口/组件骨架与CmdSplitter.cpp实现注册为主模块register_fprime_ut()注册单元测试并声明依赖STest、启用自动辅助UT_AUTO_HELPERS ON。5. 在 hub 模式中的接入方式Svc::CmdSplitter的设计目标明确指向 hub 模式sdd 原文intended to be used as part of the hub pattern to route command to a command dispatcher in the remote deployment。在 F´ 的分布式拓扑中Svc::GenericHub负责两个部署之间的数据通路本部署的RemoteCmd输出经 hub 序列化后发送到远端远端 hub 收到的命令再交给其CmdDispatcher反之远端命令的状态响应沿相反路径回到本部署经seqCmdStatus进入组件并转发给原命令源。两个部署只要在config/AcConstants.fpp中约定的 hub 连接参数GenericHubInputPorts、GenericHubOutputPorts等保持一致即可互联。从源码结构看可以推断出该组件在设计上刻意保持零业务逻辑、零事件/遥测输出CmdSplitter.fpp中只有 5 组同步/输出端口没有命令、事件或遥测通道定义。这种纯粹性使它成为命令链路中一个可预测、易测试、几乎零开销的转发节点。6. 变更记录日期描述2023-06-12初始版本2023-09-27支持多命令输入端口数组化与 CmdDispatcher 端口结构对齐从变更记录可以看出多命令源支持是组件演进的重要里程碑——正是这次改动让CmdSplitter的端口数组从单端口升级为与Svc::CmdDispatcher完全镜像的多端口结构从而可在任意命令源上行链路、命令序列器等场景下无差别复用。赞分享嵌入式系统编程【免费下载链接】fprimeF´ - A flight software and embedded systems framework项目地址https://gitcode.com/gh_mirrors/fp/fprime点击查看免费下载相关推荐FastAPI-MVC与Kubernetes集成构建可扩展的云原生API服务FastAPI MVC与Kubernetes集成构建可扩展的云原生API服务 FastAPI MVC是一款强大的开发者生产力工具专为快速构建高质量、生产就绪嵌入式系统编程F´fprimeSvc::CmdDispatcher 命令分发组件深度解析注册、分发与状态回传机制F´fprimeSvc::CmdDispatcher 命令分发组件深度解析注册、分发与状态回传机制 导读 Svc::CmdDispatcher 是 F´嵌入式系统编程F´ 框架 Svc::PolyDb 组件深度解析基于 Fw::PolyType 的进程内测量值共享数据库F´ 框架 Svc::PolyDb 组件深度解析基于 Fw::PolyType 的进程内测量值共享数据库 Svc::PolyDb 是 F´Flight So嵌入式系统编程上一篇Gorse5分钟搭建企业级推荐系统的终极指南下一篇exVim与主流IDE对比为什么VimexVim能成为开发者的首选创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考