F Prime 速率组调度(Rate Group Scheduling)完全指南:从时钟分频到相位调度
2026/9/16 12:24:51 网站建设 项目流程

F Prime 速率组调度(Rate Group Scheduling)完全指南:从时钟分频到相位调度

【免费下载链接】fprimeF´ - A flight software and embedded systems framework项目地址: https://gitcode.com/GitHub_Trending/fpr/fprime

导读

本文基于 F´(F Prime)飞行软件框架的系统功能参考文档,系统讲解其周期性执行机制——速率组调度(Rate Group Scheduling)。这是 F´ 中遥测采集、传感器读取、控制回路等所有周期性任务的驱动骨架:一个系统时钟源产生主 tick,经过分频后驱动多个速率组(Rate Group),再由速率组按序调用其成员组件。读完本文,你将掌握 RateGroupDriver 的分频原理与配置方法、Active/Passive Rate Group 的执行模型与超时检测(Overrun/Slip)机制、ActivePhaser 的相位调度模型,以及速率组的遥测与统计清除命令的实战用法。

概述:F´ 的周期执行骨架

速率组调度提供了以定义速率周期性执行组件的能力。其基本思想是:

  1. 一个系统时钟源生成主 tick(primary tick);
  2. 该主 tick 被分频,驱动多个以不同频率运行的速率组;
  3. 每个速率组按定义好的顺序调用一组组件。

这是 F´ 中循环处理的基础执行模式——遥测收集、传感器读取、控制回路以及其他周期性任务都通过速率组驱动。

该能力由一串协作组件构成:

  • 周期源(cycle source):生成主 tick(如LinuxTimerPosixTimeChronoTime等,详见 Time Services);
  • 速率组驱动器(Rate Group Driver):将主 tick 分频为多个子速率;
  • 速率组组件(Rate Group):将周期调用分发给其成员组件。

时钟分频:RateGroupDriver

速率组驱动器接收一个主系统 tick,并将其分频产生不同速率的输出。其典型用法是:一个 1 Hz 的 tick 经分频后产生 1 Hz、0.5 Hz、0.25 Hz 的输出。分频比例(divider)在构造/配置时指定。RateGroupDriver 是被动组件,运行在调用者的线程上下文中。

配置接口与约束

驱动器通过configure()传入一组分频器(DividerSet):

RateGroupDriverImpl::configure(const DividerSet& dividerSet);

从 源码实现 可以看到配置过程中的关键约束与内部处理:

  • 表大小校验static_assert保证分频表大小与NUM_CYCLEOUT_OUTPUT_PORTS一致;
  • offset 合法性:任何端口的 offset 必须小于其 divisor(offset == 0offset < divisor),否则FW_ASSERT失败——因为 offset 大于等于 divisor 的端口永远不会被调用;
  • rollover 防溢出m_rollover为所有非零 divisor 的乘积,并断言乘积不会溢出FwSizeType;每次 tick 后m_ticks = (m_ticks + 1) % m_rollover,避免整数回绕导致跳周期;
  • 内容拷贝DividerSet的内容在调用时被复制,因此传入的数组可以是临时变量;
  • 必须在构造之后、任何端口调用之前调用configure(),否则CycleIn_handler中的FW_ASSERT(this->m_configured)会失败。

分频逻辑

CycleIn_handler(源码)对每个配置了非零 divisor 且已连接的输出端口,判断(m_ticks % divisor) == offset是否成立,成立则调用该输出端口。文档中的分频示例:

SchedIn 速率divider[0]SchedOut[0]divider[1]SchedOut[1]divider[2]SchedOut[2]
1 Hz11 Hz20.5 Hz40.25 Hz

即:divisor 为 4 的端口每第 4 次CycleIn调用被触发一次。每个输出端口通常连接到某个速率组组件的输入。

设计约束

RateGroupDriver 被设计为可在 ISR 上下文运行(其需求 RGD-002 通过 Inspection 验证),因此实现避免:浮点计算、获取互斥锁、调用未知副作用的库、过长的实现路径。

速率组执行:三种变体

速率组按序调用其成员组件,并传递一个指示调用顺序的上下文值(context)。F´ 提供三种变体:

变体线程模型输入端口类型适用场景
Active Rate Group独立线程异步(入队唤醒线程)需要将速率组执行与时钟源解耦的重负载处理
Passive Rate Group调用者线程同步无需独立线程开销的轻量处理
Active Phaser独立线程异步需要在周期内精确分配各组件执行时刻的相位调度

Active 与 Passive 速率组都会跟踪每个周期完成所需时间,并以遥测形式上报。

Active Rate Group:独立线程 + 超时检测

Svc::ActiveRateGroup是一个主动组件,驱动连接到Svc::Sched输出端口的一组组件。其输入Svc::Cycle端口是异步的:调用该端口会向队列投递一条消息,唤醒组件任务;任务随后按序调用所有成员输出端口。这使速率组执行与时钟源解耦

上下文配置:一组上下文值以数组形式传入configure()

void configure(U32 contexts[], FwIndexType numContexts);

每个 context 值可供组件区分速率组内的多次调用(组件头文件 提供了基于ContextArray的新签名,旧签名已标记DEPRECATED)。

超时/滑移(Slip)检测机制:组件在 CycleIn 被调用时置位标志,在速率组执行开始时清除该标志;若在周期结束时检测到标志再次被置位,则声明一次 cycle slip,发出RateGroupCycleSlip警告事件(WARNING_HI,源码),并递增RgCycleSlips遥测计数(fpp 定义)。这表示新周期在前一周期完成前就已开始——系统未满足时序要求,需要关注(速率过快或成员组件耗时过长)。其单元测试(ActiveRateGroupTester.cpp)验证了滑移事件与计数遥测的行为,包括节流计数。

Passive Rate Group:同步执行 + 每端口时序遥测

Svc::PassiveRateGroup被动组件,在调用者线程上下文中执行(通常由 RateGroupDriver 直接同步调用)。输入Svc::Cycle端口是同步的,成员组件直接在调用速率组的那一方上下文中被调用。

configure()接受两个参数(fpp 定义):

  • 一个 U32 上下文数组(每个输出端口一个值),传给每个速率组成员;
  • 可选的Os::RawTimeSource,指定用于周期执行时间测量的计时器源(默认为Os::RAWTIME_DEFAULT)。
计时源限制(重要)

关键限制configure()中的RawTimeSource参数只影响每个周期的结束时间戳。周期的开始时间戳来自周期驱动器(如RateGroupDriverLinuxTimer),它们以RAWTIME_DEFAULT构造Os::RawTime。当两者源不同时,Os::RawTime会拒绝该时间间隔(POSIX 实现返回INVALID_PARAMS),周期时间被上报为零。该特性仅在以下情况正确

  1. 使用默认值RAWTIME_DEFAULT;或
  2. 周期驱动器使用相同的非默认源。

要部署级地更换时钟,应覆盖config/Os/RawTimeSource.hpp并设置RAWTIME_DEFAULT,而不是在此处传入非默认源。参见 Configuring F´ 中的 OSAL 配置。

默认配置 中的枚举展示了可选源:

  • RAWTIME_DEFAULT = CLOCK_REALTIME—— 默认构造 RawTime 对象使用的时钟(POSIX 上即传给clock_gettime()clockid_t);
  • RAWTIME_REALTIME = CLOCK_REALTIME—— 墙钟时间,系统时间调整时可能跳变或渐变;
  • RAWTIME_MONOTONIC = CLOCK_MONOTONIC—— 单调时钟,不受系统时间调整影响;
  • RAWTIME_BOOTTIME = CLOCK_BOOTTIME—— 挂起期间也继续前进的单调时钟(仅 Linux)。
命令与原子统计

PassiveRateGroup支持CLEAR_STATISTICS同步命令(实现):将所有端口时长高水位(high water marks)和最大周期时间清零。周期计数不会被清除,因为它表示运行总数。所有统计量由无锁原子操作保护(m_maxTime与各端口 HWM),从而ISR 安全且消除了互斥锁开销。

遥测通道
通道类型描述发送语义
MaxCycleTimeU32速率组周期最大执行时间(微秒)。由CLEAR_STATISTICS命令清除变化时更新(仅最大值增加时)
CycleTimeU32最近一次周期的执行时间(微秒)每周期发送
CycleCountU32已执行周期总数。CLEAR_STATISTICS清除每周期发送
PortCycleTimeU32[PassiveRateGroupOutputPorts]最近一次周期中各成员端口的执行时间(微秒)每周期发送(仅当PassiveRateGroupCfg::PortCycleTime启用)
PortCycleTimeHWMU32[PassiveRateGroupOutputPorts]各端口执行时间的高水位(微秒)。由CLEAR_STATISTICS清除变化时更新(任一高水位增加时),降低带宽占用

PortCycleTime每周期发送,提供每个周期执行的完整时序快照;PortCycleTimeHWM采用"变化时更新"语义,仅在至少一个端口的高水位上升时发送,在降低遥测带宽的同时仍能捕获时序异常。每端口高水位与周期统计的启用由配置项PassiveRateGroupCfg::PortCycleTime控制(见 实现 与 测试)。

使用场景

CLEAR_STATISTICS用于:系统变更后重新建立时序基线(re-baselining)、或在特定运行阶段隔离时序行为。

Active Phaser:周期内相位调度

Svc::ActivePhaser提供更精细的调度模型:每个周期被划分为可配置数量的 tick,各个端口调用被映射到周期内特定的 tick 窗口。这允许精确控制每个组件在周期内的调用时刻,实现相位调度——不同组件在周期内不同时间点运行,以摊开处理负载。

调度示例(来自 SDD):一个相位周期由 10 个 tick 组成。端口调用 A(长度 2)从 tick 0 开始,端口调用 B(长度 3)从 tick 2 开始,端口调用 C(长度 1)在 tick 6 和 tick 8 各启动一次。调度每 10 个 tick 重复。

  • 端口调用按其注册顺序被调用;
  • 若端口调用指定了长度,组件会在运行时检查该调用是否超过其指定长度(overrun);
  • 发生超时时发出MissedDeadline警告事件(需求 AP-003,见 SDD)。

Dropped Cycles(丢周期)语义CycleIn与内部Tick端口声明为drop——队列满时到达的周期被丢弃。这是预期行为,且上报任何事件或遥测通道:与ActiveRateGroup(会发出RateGroupCycleSlip并计数RgCycleSlips)不同,ActivePhaser对丢弃周期保持静默。被丢弃的周期会使相位基准永久滞后一个周期,且MissedDeadline不会观测到它(因为它只度量已执行周期内的超时)。操作员不应将组件没有事件视为没有丢周期。

配置要点汇总

配置项配置位置/方式说明
速率组成员输出端口数量编译期配置(ActiveRateGroupOutputPorts/PassiveRateGroupOutputPorts等)输出端口数量在编译时确定
RateGroupDriver 分频比例configure(const DividerSet&)构造后、端口调用前调用;offset 必须小于 divisor
成员组件的上下文值configure(contexts, numContexts)基于端口号索引的配置表
ActivePhaser tick 数与每端口时间窗口setup 时配置决定周期内各调用的相位分配
PassiveRateGroup 计时源configure(..., Os::RawTimeSource)默认RAWTIME_DEFAULT;仅影响周期结束时间戳
全局时钟源覆盖config/Os/RawTimeSource.hppRAWTIME_DEFAULT部署级切换时钟(如改为CLOCK_MONOTONIC

深入阅读

  • 周期源(cycle source)驱动速率组调度的机制参见 Time Services;
  • 各组件完整设计文档:
    • RateGroupDriver SDD —— 分频需求 RGD-001/RGD-002、端口表与 ISR 合规设计;
    • ActiveRateGroup SDD —— 需求 ARG-001 至 ARG-004、滑移检测设计;
    • PassiveRateGroup SDD —— 需求 FPRIME-PRG-001 至 005、CLEAR_STATISTICS与遥测通道;
    • ActivePhaser SDD —— 需求 AP-001 至 003、丢周期语义;
  • 速率组端口类型定义见 Svc::Sched 与 Svc::Cycle 对应的 fpp 接口;
  • 参考实现:Ref 部署中的速率组拓扑连接示例见 Ref 拓扑 目录。

【免费下载链接】fprimeF´ - A flight software and embedded systems framework项目地址: https://gitcode.com/GitHub_Trending/fpr/fprime

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询