Files
DLD154Pro/docs/modbus-active-report-analysis.md
T
wangfq 2088cc267c docs: Modbus 主动上报 MCU 资源占用分析
- ISR 层不受 TX 阻塞影响 (TMR0/TMR1 独立运行)
- @9600 活动态 TX 阻塞 45ms (30% CPU), 余量 55ms/150ms → 可行但临界
- @19200 TX 阻塞减半至 22ms (15% CPU) → 推荐
- RAM 增量 <170B, Flash 增量 ~8.5KB
- 优化建议: 提高波特率 / TX FIFO 成组填充 / 间隔参数可配
2026-07-30 17:34:17 +08:00

249 lines
9.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# DLD154Pro Modbus 主动上报 — MCU 资源占用分析
> CH591R RISC-V @60MHz | 18KB RAM | BLE + 单路线圈 + RS485
---
## 1. 系统并发任务概览
```
┌──────────────────────────────────────────────────────┐
│ ISR 层 (抢占式, 不受主循环阻塞影响) │
│ │
│ TMR0 捕获 ISR ──── 线圈频率测量 (每周期触发) │
│ TMR1 5ms ISR ──── 50ms tick / 继电器 / LED / PWM │
│ UART0 RX ISR ──── RS485 接收缓冲 │
│ BLE RF ISR ──── 蓝牙链路层 │
│ │
├──────────────────────────────────────────────────────┤
│ 主循环 (round-robin, 被 rs485_send 阻塞时可暂停 45ms) │
│ │
│ TMOS_SystemProcess() ── BLE 协议栈调度 │
│ poll_dbn_ble() ── BLE 数据收发 │
│ cjq_srv() ── 线圈算法 / 进出车检测 │
│ opt_input_poll() ── 光耦防抖 / 状态机 │
│ modbus_poll() ── Modbus 帧处理 + 主动上报 TX │
└──────────────────────────────────────────────────────┘
```
**关键事实**: ISR 层永远不受 `rs485_send` 阻塞影响。线圈捕获/继电器输出/光耦消抖(TMR1 部分)在中断上下文运行,实时性有保证。
---
## 2. CPU 时间预算分析
### 2.1 中断负载 (固定开销,不可压缩)
| 中断源 | 频率 | 单次耗时 | CPU 占比 |
|--------|------|---------|---------|
| TMR0 捕获 | ~60 kHz (50120 kHz 线圈) | ~25 cycles | **~2.5%** |
| TMR1 5ms | 200 Hz | ~200 cycles (含 PWM 呼吸) | ~0.07% |
| UART0 RX | 主机轮询时偶发 | ~50 cycles | 可忽略 |
| BLE RF | 连接维护 ~30ms 间隔 | ~500 cycles | ~0.03% |
| **ISR 合计** | | | **~2.6%** |
> TMR0 捕获 ISR 是最重的固定负载。线圈频率越高,中断越密。
### 2.2 主循环 (正常状态,无主动上报 TX)
| 任务 | 单次耗时 | 说明 |
|------|---------|------|
| TMOS_SystemProcess | ~1.5 ms | BLE 协议栈 (底层在 ISR,这里是调度) |
| poll_dbn_ble | ~0.5 ms | 无待发数据时快速返回 |
| cjq_srv | ~1.0 ms | CAP_OK 触发时跑 vd1_task (IIR+基线+检测) |
| opt_input_poll | ~0.3 ms | 3 样本多数表决 + 状态机分支 |
| modbus_poll (RX only) | ~0.1 ms | 检查缓冲 + CRC 校验 |
主循环一次约 **3.4 ms**。两次 CAP_OK 间隔 ~8.74ms,主循环约跑 2.5 次/测量窗,时间充裕。
### 2.3 主动上报 TX 阻塞时间
`rs485_send` 是逐字节忙等的:
```c
for (i = 0; i < len; i++) {
while (R8_UART0_TFC != 0); // ← 等 TX FIFO 全空 (→ 等上一个字节发完)
R8_UART0_THR = data[i]; // 写 1 字节到 FIFO
}
```
UART0 TX FIFO 容量 8 字节,但代码**不等 FIFO 有空间就写满 8 字节**,而是每写 1 字节就等 FIFO 全空。这意味着每字节都经历完整的 1.04ms 传输等待。
| 帧类型 | 字节数 | 传输时间 @9600 | 传输时间 @19200 | 传输时间 @38400 |
|--------|--------|---------------|-----------------|-----------------|
| 全数据块上报 (FC 0x04) | 43B | **44.8 ms** | 22.4 ms | 11.2 ms |
| 异常响应 | 5B | 5.2 ms | 2.6 ms | 1.3 ms |
| 写回显 | 8B | 8.3 ms | 4.2 ms | 2.1 ms |
### 2.4 主动上报各速率下的 CPU 占用
**150ms 活动间隔 (最坏情况)**:
```
每 150ms 窗口:
TX 阻塞 44.8 ms ← rs485_send(43B)
主循环正常计算 ~50 ms ← 150 - 44.8 - 余量
可用于 BLE/算法 ~55 ms ← 剩余预算
主循环 CPU 占比: (44.8 + 50) / 150 = 63%
其中 TX 阻塞占比: 44.8 / 150 = 30%
```
**800ms 空闲间隔**:
```
TX 阻塞占比: 44.8 / 800 = 5.6%
主循环 CPU 占比: ~30%
```
**继电器翻转事件 (立即上报)**:
```
TX 阻塞 44.8ms,单次冲击。翻转频率低(最多每秒数次进出车),不构成持续负载。
```
---
## 3. 关键风险点
### 3.1 ⚠️ 主循环阻塞 45ms 期间的影响
`rs485_send` 阻塞期间,以下主循环任务被暂停:
| 任务 | 影响 | 严重程度 |
|------|------|---------|
| **cjq_srv** (线圈算法) | CAP_OK 积压 ~5 次 (45ms ÷ 8.74ms)。恢复后主循环逐次消化,算法不丢数据,但响应延迟 +45ms | 🟡 轻微 |
| **opt_input_poll** (光耦) | 防抖采样暂停 45ms。光耦输入若在此期间变高又变低,可能丢失 <45ms 的短脉冲 | 🟡 轻微 |
| **TMOS_SystemProcess** (BLE) | BLE 协议栈调度延迟 45ms。连接监控超时通常 ≥2s,**不受影响** | 🟢 安全 |
| **modbus_poll** (RX) | 主机若在 TX 期间发来命令,UART ISR 正常收进缓冲,TX 结束后才处理 → 响应延迟 +45ms | 🟡 轻微 |
### 3.2 ✅ 不受影响的部分
| 机制 | 原因 |
|------|------|
| 继电器输出 | TMR1 ISR (5ms) 独立运行,不经过主循环 |
| 线圈频率测量 | TMR0 捕获 ISR 独立运行 |
| 光耦复位 (模式 6) | `opt_input_poll` 中的复位逻辑暂停 45ms,但 400ms 的复位门槛远大于阻塞时间 |
| UART 接收 | ISR 独立填充 `_rx_buf` |
### 3.3 🟢 结论
**@9600 波特率,150ms 主动上报可行。** 30% TX 阻塞是临界值——主循环仍有 ~55ms/150ms 的余量处理线圈算法和 BLE。不会丢检测事件,不会断蓝牙,继电器输出不受影响。
---
## 4. RAM 占用
### 4.1 新增静态变量 (BSS)
| 变量 | 大小 | 说明 |
|------|------|------|
| `_auto_rpt_enable` | 1B | 主动上报使能标志 |
| `_active_threshold` | 2B | 活动阈值 |
| `_rpt_last_ms` | 4B | 上次上报时刻 |
| `_rpt_active` / `_rpt_hyst_cnt` | 2B | 速率状态机 |
| `_last_relay_off_10ms` | 4B | 继电器释放时刻 |
| `_last_relay_on_10ms` | 4B | 继电器吸合时刻 |
| `_last_relay_state` | 1B | 继电器边沿检测 |
| `_misc_time_type` | 2B | 时间类型 |
| `_misc_time_value` | 4B | 时间值 10ms |
| `_relay_engage_cnt` | 4B | 继电器累计次数 |
| **合计** | **28B** | |
### 4.2 栈峰值
| 调用链 | 栈占用 |
|--------|--------|
| `modbus_poll()` 局部变量 | ~20B |
| → `send_full_data()` 局部 buf[43] | 43B |
| → `build_full_data()` 局部 buf[38] + 临时变量 | ~60B |
| → `rs485_send()` 局部变量 | ~10B |
| → `crc16()` 局部变量 | ~4B |
| **调用链合计** | **~140B** |
> 加中断嵌套预留 ~200B,栈峰值约 **350B**。CH591R 默认栈 2KB(可配置),余量充足。
### 4.3 总体 RAM
| 项目 | 大小 |
|------|------|
| 新增 BSS | 28B |
| 栈峰值增量 | ~140B (Modbus 调用链) |
| CRC16 表 | 512B (const → Flash,不计 RAM) |
| **RAM 增量** | **~170B** |
CH591R 共 18KB RAM(含 BLE 协议栈 + 应用),Modbus 模块新增 < 1%。
---
## 5. Flash 占用
| 文件 | 大小 |
|------|------|
| `rs485_modbus.c` | ~8.5 KB |
| `rs485_modbus.h` | ~2.2 KB |
| `rs485_700bs.c` 增量 (去 static) | ~0 |
| `peripheral_main.c` 增量 (分派) | ~20B |
| **合计** | **~8.5 KB** |
CH591R Flash: 256KB (应用区 28KB 或 18KB,取决于 OTA 配置)。增量约占应用区 30%28KB 配置)或 47%18KB 配置)。**18KB OTA 配置下偏紧**。
---
## 6. 优化建议
### 6.1 提高波特率 (影响最大)
| 波特率 | TX 阻塞 (43B) | 活动态 CPU 占比 | 改善 |
|--------|--------------|----------------|------|
| 9600 | 44.8 ms | 30% | 基线 |
| **19200** | **22.4 ms** | **15%** | **↓50%** |
| 38400 | 11.2 ms | 7.5% | ↓75% |
| 115200 | 3.7 ms | 2.5% | ↓92% |
> **建议**: 开启主动上报时,波特率至少用 19200。CH591R UART0 支持到 6 Mbps,硬件无瓶颈。
### 6.2 优化 TX FIFO 利用率 (代码级)
当前每字节等 FIFO 全空,改为填充 8 字节后再等:
```c
void rs485_send_fast(const uint8_t *data, uint8_t len) {
RS485_RE_TX();
mDelayuS(100);
uint8_t i = 0;
while (i < len) {
uint8_t space = 8 - R8_UART0_TFC; // FIFO 剩余空间
uint8_t chunk = (len - i < space) ? (len - i) : space;
for (uint8_t j = 0; j < chunk; j++)
R8_UART0_THR = data[i + j];
i += chunk;
if (i < len)
while (R8_UART0_TFC >= 8); // 等至少 1 字节空间
}
while (R8_UART0_TFC != 0);
mDelayuS(500);
RS485_RE_RX();
}
```
效果:不减少总 TX 时间(波特率决定),但减少忙等循环次数 43→6 次,降低指令开销。
### 6.3 活动上报间隔可调
当前硬编码 150ms/800ms。可考虑通过 HR 寄存器暴露间隔参数,让主机根据场景调优。
---
## 7. 总结
| 维度 | 评估 | 说明 |
|------|------|------|
| **实时性** | ✅ 安全 | ISR 层不受 TX 阻塞影响;主循环延迟 45ms 可接受 |
| **CPU** | 🟡 @9600 临界 | 活动态 30% TX 阻塞,主循环仍有 55ms 余量 |
| **CPU** | 🟢 @19200 充裕 | 活动态 15% TX 阻塞,余量充足 |
| **RAM** | 🟢 充裕 | 增量 < 170B, < 1% 总 RAM |
| **Flash** | 🟡 18KB OTA 配置偏紧 | 增量 ~8.5KB,占应用区 47% |
| **BLE** | 🟢 安全 | 45ms 远小于连接超时 (≥2s) |
| **线圈检测** | 🟢 安全 | TMR0/TMR1 ISR 独立,不丢边沿 |