# MCU Radio valid 字段始终为 0 问题排查报告

## 基本信息

| 项目 | 内容 |
|------|------|
| 日期 | 2026-05-28 |
| 项目 | QSJNIC 车载 Android 中间件 |
| 版本 | v1.0.0-beta6 |
| MCU 固件版本 | `swVersion=0302_20260527` |
| 测试设备 | 车机 192.168.0.66 |

---

## 1. 问题描述

SDK 返回的 `valid` 字段永远为 0。具体现象：下发搜台指令后，频率回调正常（频率值在变化），但 `valid` 始终为 0，`signal`（信号强度）也始终为 0。

## 2. 涉及架构层

```
MCU → 串口帧(/dev/ttyS7) → libmcujni.so(C协议层) → JNI → QsMcuSystemService(Java)
    → RadioFeature → DomainBus → AIDL → qsmw-sdk → 收音机App
```

## 3. 协议定义（Radio.xlsx）

valid 字段位于 MCU→ARM 的 FREQ 帧（cmd=0x01）中：

| 字节 | 参数 | 内容 |
|------|------|------|
| Byte8 | P0 | 频率高 8 位 |
| Byte9 | P1 | 频率低 8 位 |
| Byte10 | P2 | band（bit3-0: 0=FM, 1=AM） |
| Byte11 | P3 | seekMode（bit3-0）+ 开关状态 |
| **Byte12** | **P4** | **bit7=valid（0=无效台, 1=有效台）** + bit0-4=其他标志 |
| Byte13 | P5 | PTY 节目类型码 [0-31] |
| Byte14 | P6 | 信号强度 |

## 4. 排查方法

在 `FrameRouter.handleRadio()` 中增加原始 hex dump 日志，直接打印 JNI 层传来的完整 body 字节数组（Byte8-Byte14），绕过所有业务逻辑层，直接观察 MCU 原始数据。

新增日志格式：
```
FREQ_BODY[len]=XX XX XX XX XX XX XX | Byte12=0xXX (valid=X) Byte14(signal)=0xXX
```

## 5. 实测数据

### 5.1 搜台前（idle 状态）

```
FREQ_BODY[7]=22 2E 00 00 00 00 00 | Byte12=0x00 (valid=0) Byte14(signal)=0x00
```
- 频率: 0x222E = 87.50 MHz FM
- seekMode = 0 (STOP)
- valid = 0, signal = 0

### 5.2 搜台中（SEEK_FF）

```
FREQ_BODY[7]=26 B0 00 42 00 00 00 | Byte12=0x00 (valid=0) Byte14(signal)=0x00
FREQ_BODY[7]=26 B1 00 42 00 00 00 | Byte12=0x00 (valid=0) Byte14(signal)=0x00
FREQ_BODY[7]=26 B2 00 42 00 00 00 | Byte12=0x00 (valid=0) Byte14(signal)=0x00
...
FREQ_BODY[7]=26 C3 00 42 00 00 00 | Byte12=0x00 (valid=0) Byte14(signal)=0x00
FREQ_BODY[7]=26 C4 00 42 00 00 00 | Byte12=0x00 (valid=0) Byte14(signal)=0x00
```
- 频率: 0x26B0→0x26C4 (99.04→99.24 MHz)，持续递增
- seekMode = 2 (SEEK_FF)，搜台进行中
- **valid = 0 全程，一秒内 40+ 帧，没有一帧出现 valid=1**
- **signal = 0 全程，所有帧信号强度均为 0x00**

### 5.3 搜台结束

```
FREQ_BODY[7]=26 D8 00 40 00 00 00 | Byte12=0x00 (valid=0) Byte14(signal)=0x00
```
- 频率: 0x26D8 = 99.44 MHz
- seekMode = 0 (STOP)，搜台已停止
- valid = 0, signal = 0（搜台结束后依然为 0）

## 6. 逐字节分析

| 字段 | 字节位置 | 搜台时的值 | 对照协议 | 状态 |
|------|---------|-----------|---------|------|
| P0-P1 频率 | Byte8-9 | `26 B0`→`26 D8` | 正确 | ✓ |
| P2 波段 | Byte10 | `00`=FM | 正确 | ✓ |
| P3 搜台模式 | Byte11 | `42`=SEEK_FF+STEREO | 正确 | ✓ |
| **P4 valid** | **Byte12** | **全部 `0x00`** | **bit7=有效台标志** | **✗ MCU 未填充** |
| P5 PTY | Byte13 | 全部 `0x00` | 节目类型 | ✗ MCU 未填充 |
| **P6 signal** | **Byte14** | **全部 `0x00`** | **信号强度** | **✗ MCU 未填充** |

## 7. 软件层排查结论

已完成从底层到顶层的完整数据流追踪：

| 层 | 检查项 | 结果 |
|----|-------|------|
| C 协议层 `mcu_protocol.c` | payload 从 `raw+6` 开始 | 正确 |
| JNI 桥接 `jni_bridge.cpp` | body = payload+2，body_len = payload_len-2 | 正确 |
| Java FrameRouter | payload 直接传递 | 正确 |
| DomainBus → RadioFeature | body 原样转发 | 正确 |
| RadioFeature.parse | `valid = (p[4]>>7)&1`, `signal = p[6]&0xFF` | 正确 |
| AIDL Parcelable | RadioState 序列化/反序列化 | 正确 |
| SDK → App | 回调传递 | 正确 |

**每一层软件解析都是正确的，字节映射与 Radio.xlsx 协议完全一致。**

## 8. 根因结论

**MCU 固件 `swVersion=0302_20260527` 的 FREQ 帧（cmd=0x01）仅正确填充了前 4 个参数字节（P0-P3：频率、波段、搜台模式/开关状态），后 3 个字节（P4 Byte12、P5 Byte13、P6 Byte14）始终为 0x00。**

这导致：
- `valid`（Byte12 bit7）= 始终 0，Android 端无法判断是否搜到有效电台
- `signal`（Byte14）= 始终 0，Android 端无法显示信号强度
- `PTY`（Byte13）= 始终 0，Android 端无法显示节目类型

## 9. 建议

1. 将本报告提供给 MCU 固件供应商
2. 要求供应商确认固件版本 `0302_20260527` 对 FREQ 帧 P4-P6 字段的支持情况
3. 如系固件已知缺陷，获取修复后的固件版本
4. 如系新协议（V2.0 等）字节位置变动，获取最新协议文档并更新 Android 端解析代码
