骑行码表面试深挖问答手册

1. 请先讲系统架构

回答顺序:硬件分工 -> 启动顺序 -> 业务任务 -> 快照 -> UI。先说明 P4 是主控、C6 是 BLE Controller,ESP-Hosted SDIO 是 HCI 通道;再说明 BLE/Wi-Fi/地图/音频都是独立 task,最终都写入运动或业务快照,LVGL 每秒/按页面周期消费。

2. 地图如何从 GeoJSON 到屏幕

GeoJSON 在 PC 端流式转 mapbin。idx 是边界和稠密网格索引,dat 是按 cell 存储的折线/三角形/点。设备从 idx 计算中心 3x3 cell,逐字段校验后把 0.1 m 局部坐标加网格原点,形成 dm 世界坐标。完整路线/PHONE 是 GCJ-02,路线 task 用两次迭代的 WGS84->GCJ02 反算统一到 WGS84,再通过同一投影函数进入路线投影。

3. 如何处理路线传输可靠性

BEGIN 固定 route_id、点数、总长度和 CRC;DATA 必须严格按 offset 递进,重复包只有内容相同才幂等;COMMIT 之后才做一次 CRC 和坐标范围校验。成功后在 mutex 内发布 LOADED + generation。手机不能把 GATT Write 成功当成业务成功,必须等待 Route Status LOADED。

4. 为什么选择 FreeRTOS queue

queue 传递的是定长、小型命令或拥有权明确的指针;它把 callback 的短路径和业务的长路径隔开。比如 GATT callback 不做 SD/CRC,Wi-Fi event 不做 HTTP,音频 callback 不做 decode。队列满时有明确策略:定位丢旧保新,OPUS 丢最旧,路线返回 timeout。

5. 如何证明 UI 不被业务阻塞

UI 线程只调用快照 getter 和 LVGL 控件 API。SD 读、NVS commit、TLS、OPUS 编解码、路线浮点预处理均在业务 task。地图页面只在 generation/version 变化时重建缓存;draw callback 不读文件、不做坐标系转换。

6. Xiaozhi 失败如何定位

先看完整日志和 backtrace,不根据最后一行判断。按阶段检查:Wi-Fi GOT_IP、HTTP info、WebSocket connected、audio channel、decoder open、第一包 packet、I2S write。再分别检查 internal DMA heap、PSRAM、任务栈余量、SDIO 错误和初始化顺序。当前 OPUS 崩溃通过源码版 libopus 和固定 960 samples 播放验证,最终证明下行链路已打通。

7. 为什么 OPUS 缓冲不能全放 PSRAM

大对象放 PSRAM,但 SDMMC/I2S/DMA 和部分 libopus 热路径需要内部 8-bit 且满足 cache 对齐。把所有 buffer 放 PSRAM会在 block-only SDIO 或 DMA 时触发参数/对齐错误;因此采用“任务栈和大队列 PSRAM、小块实时缓冲 internal”的混合策略。

8. BLE 断线和 Wi-Fi 断线有什么区别

BLE 断线会停止 notify、清 PHONE 队列、中止未完成路线传输,但保留 LOADED 路线;运动模型标记 PHONE timeout。Wi-Fi 断线只停止 Xiaozhi 音频/transport,运动、地图和 BLE 继续运行。两者都通过事件和 task 处理,不在底层回调里做复杂清理。

9. 如何控制功耗和 CPU

高频只保留必要路径:导航 20 ms timer 先比 snapshot version,地图绘制至少 33 ms;主动事件 1 s;天气和电量低频。扫描页动画离开即停;建筑大视野整类跳过;SD 地图按 3x3 换中心,不沿路线无限预取。Wi-Fi/Xiaozhi 只有用户确认才启动。

10. 当前不足怎么说

明确说没有 OTA、地图瓦片 BLE、离线唤醒词、ESP-SR 和 MCP 设备控制;当前 Xiaozhi 强制 WebSocket。不要把“协议保留字段”“文档规划”“组件能力”说成已经接入的业务。

11. 现场演示顺序

  1. 展示开机无 Wi-Fi 自动连接。
  2. 双击电源键,扫描、选择网络、连接并看到 Xiaozhi ready。
  3. 用 Web Bluetooth 发送时间、天气和定位模式。
  4. 下发 V1 Cycling 或 V2 MTB 路线,等待 Route Status LOADED。
  5. 进入路线预览,第二次 START 后观察导航跟随、转向箭头和到达判定。
  6. 触发本地 PCM 转向播报,演示 P0 打断 TTS。
  7. 结束骑行,展示历史曲线、路线缩略图和 Ride Record pending/synced。

12. 最后总结句

项目的核心不是“把功能堆在页面里”,而是把阻塞 IO、协议校验、坐标计算、音频实时路径和 UI 绘制拆成不同实时等级的任务;通过 PSRAM/内部 DMA 内存边界、快照 generation 和显式失败降级,保证圆屏 UI 在 BLE、Wi-Fi、SD 和音频同时运行时仍可用。