Firmware RTOS、状态机与实时调度¶
Firmware 的复杂度不在 task 数量,而在异步事件同时改变连接、信道、功耗和硬件上下文。把所有逻辑塞进 command handler 会产生不可证明的竞态。
事件来源与执行域¶
| 来源 | 示例 | 建议处理域 |
|---|---|---|
| Host | scan/connect/add key | Command dispatcher → 对应状态机 |
| MAC/PHY IRQ | RX/TX done、radar、trigger | 最小 ISR → real-time queue |
| Timer | scan dwell、auth timeout、reorder | timer event → owner state machine |
| Power | sleep request、wake | power coordinator |
| Watchdog | heartbeat/queue stall | fault manager |
优先级不是简单的“RX/TX 都最高”。SIFS response 由硬件 fast path 保证;Firmware 高优先级任务负责补充 buffer、消费 completion 和维护下一次实时动作所需上下文。日志格式化、统计汇总和 Host 大命令不能占用实时队列。
状态所有权¶
每个状态只能有一个 owner。Connect state machine 可以请求 Channel Manager 切信道,却不能直接改 RF state;Power Manager 可以等待 TX quiesce,却不能偷偷清空连接队列。跨模块通过事件和带 deadline 的 request 交互。
stateDiagram-v2
OFF --> BOOTING
BOOTING --> READY: image/OTP/calibration valid
READY --> SCANNING
SCANNING --> AUTHENTICATING: candidate selected
AUTHENTICATING --> ASSOCIATED
ASSOCIATED --> KEYING
KEYING --> CONNECTED
CONNECTED --> RECOVERING: assert/hang/bus fault
RECOVERING --> READY: contexts rebuilt
每次进入状态记录 reason、deadline、session generation;每个 event 声明允许的源状态。收到旧 session 的 Auth/Key/TX completion 时丢弃并计数,而不是“尽量处理”。
Watchdog 设计¶
单一 heartbeat 只能证明 MCU 还在调度,不能证明数据面工作。建议分别监控:command progress、TX/RX ring progress、MAC completion、Beacon/TBTT deadline、heap/stack watermark 和 real-time queue latency。
Watchdog 触发后先冻结关键 trace,保存 task/ISR 状态、pending command、Ring 指针、VIF/STA/Key/BA、MAC/PHY reason,再执行分级恢复。若先 reset 再 dump,得到的只是恢复后的正常现场。
可验证性¶
- 对每个状态转换建立 event table 和非法事件测试;
- 注入 command timeout、completion loss、重复事件和 reset;
- 用逻辑时钟测试 timer race,不依赖真实等待;
- 为 task queue 设置 latency histogram,而不只统计平均值;
- 用 generation 验证 teardown 后的异步事件不会访问旧对象。
给状态机写 Event Table¶
状态图只画允许路径,Event Table 还定义非法与迟到事件。以下为连接状态的教学片段:
| 当前状态 | 事件 | 动作 | 新状态/拒绝原因 |
|---|---|---|---|
| SCANNING | scan done(匹配请求) | 选候选/失败完成 | AUTHENTICATING/READY |
| AUTHENTICATING | disconnect | 取消 timer,终止连接请求 | READY |
| READY | 旧 auth response | 计 stale,不创建 Peer | READY |
| CONNECTED | reset | 停入口,冻结证据 | RECOVERING |
| RECOVERING | 旧 TX done | 按旧事务回收/拒绝 | 不更新新 Credit |
每行还要写 deadline、可重入性和资源变化。没有状态变化的事件也可能改变 Buffer 所有权,不能简单忽略。
实时调度的预算模型¶
对固定优先级抢占模型,可用响应时间分析检查任务 i:
C 是最坏执行时间,B 是阻塞,T 是高优先级任务的最小到达间隔。该模型假设应明确;突发 IRQ、非抢占区、DMA/总线争用不能被平均 CPU 利用率掩盖。
教学例:控制任务执行 100 μs,可能被锁阻塞 40 μs;周期 100 μs、执行 20 μs 的高优先级任务干扰。迭代得到 140→180→180 μs。若 deadline=150 μs,即便平均负载看起来不高仍违约。
优先级反转与队列耗尽¶
高优先级 TX refill 等待低优先级日志任务持有的锁,而中优先级任务持续运行,会形成优先级反转。可用缩短临界区、拆分共享数据或平台提供的优先级继承,但不能假定所有 RTOS mutex 自动继承。
Event queue 也要设计满时行为:关键控制事件不应静默丢弃;telemetry 可丢但要计数。不可在 ISR 中无限等待空槽,否则 consumer 无法获得执行时间。
Watchdog 的进展判据¶
空闲时 Ring 不移动不表示卡死;应在“有待处理工作”且超过 deadline 时判定 stall。心跳、任务执行、queue consumer、IRQ 和 MAC completion 分开监控,避免一个健康任务替整个系统喂狗。
Dump 要保存触发前历史。1 MiB ring、每条 32 byte、10,000 条/秒仅覆盖约 3.28 秒;日志速率升高会缩短现场窗口,应做采样、触发和关键事件保留。
复习追问与答案¶
CPU 没满为什么还错过 deadline? 阻塞、不可抢占区域、优先级反转、共享 SRAM/总线都能增加最坏响应时间。
非法事件都能直接丢弃吗? 还需处理其附带资源和 pending waiter,否则状态没坏但内存泄漏。
怎样复现 timer race? 使用受控事件顺序或逻辑时钟注入,验证每一种 terminal path 恰好完成一次。