salonnikov/mower-stock-reverse

GitHub: salonnikov/mower-stock-reverse

该项目从零逆向工程了一块基于 GD32 多 MCU 架构的机器人割草机控制板,涵盖固件反编译、硬件架构映射、SWD 工具链与自定义固件开发。

Stars: 0 | Forks: 0

# MOWER — SNK_MAINBOARD_CP_V11 机器人割草机控制板的逆向工程 对机器人割草机**原厂控制板**的从零开始的拆解:两份出厂固件均已反编译,包含完整的架构 / 外设 / 子系统映射图,一套可用的 SWD 烧录 / 导出 / 还原工具链,以及一个可在真实硬件上运行的自定义 chip1 固件。 没有任何原厂原理图——这里的所有内容都是从两份出厂 GD32 固件以及电路板本身恢复出来的。 这些电路板上标有 **SNK** 标识:主板为 **`SNK_MAINBOARD_CP_V11`**(PN `80102372-01`),显示板为 **`SNK_DISPLAY_CP_V11``**(PN `80102373-01`);同样的标识贯穿于出厂固件(`a4963_snk_v2.c`、`movebase_snk_v10.c`,以及更新镜像 `SNK_MB.bin` / `SNK_BB.bin`)中。 SNK 极有可能是 Sunseeker。无论外壳上贴的是什么品牌,只要主板的丝印为 `SNK_MAINBOARD_CP_V11`,本代码库描述的就是它。此处研究的这台设备是作为 VILLARTEC MI 302 出售的。 **尚未完成。** 逆向工程已在硬件上得到验证,但在我们自己的固件下车轮从未转动过——请参阅[主要未解问题](#main-unsolved-problem--the-wheels-never-spun-on-our-firmware)。 后来这块板子坏了(进水导致电源部分损坏),工作也就此停止。 继续研究所需的一切都包含在这个代码库中。 ### 本项目是如何完成的(诚实声明) 本代码库中的反编译和分析工作大量使用了 **Claude Code (Opus 4.8)** 作为辅助。我手工复核了这些发现,但仍需注意——该智能体极大地加快了工作速度,这正是*为什么*选择这种方式而不是纯手工拆解的原因。 写下这段注释是为了不让外部读者产生一种错觉,以为这一切都是历经两年纯手工打造的——事实并非如此。请将内容视为**有智能体辅助的逆向工程**,并在实际可行的地方进行了验证。任何您打算依赖的内容(地址、寄存器值、烧录步骤)在信任之前,都应根据实际的 dump / 真实硬件进行二次核对。 ## 硬件部分(通过逆向工程确立) MI 302 板 = **3 个 MCU + 3 个 BLDC 控制器**: | 节点 | 芯片 | 角色 | |---|---|---| | chip1 (主) | **GD32F305 (GD32F30x_CL)** | 割草机 FSM、驱动(通过 SPI 连接 BLDC)、BMS 通信(USART2)、连接 chip2 和显示屏 | | chip2 (边界传感器) | **GD32F4xx** | 边界线圈信号采集(ADC+DMA)、波形/区域检测、抬升传感器 → 通过 UART/cJSON 传给 chip1 | | 显示屏 | **ESP32-WROOM-32UE** (SNK DISPLAY CP V11) | 按键 / LED,ledport 协议 | | 驱动器 (×3:左/右轮 + 刀盘) | **Fortior FU6832N** | 智能 BLDC 控制器(8051 + FOC,自带 16 kB 固件),作为兼容 A4963 的从机监听 SPI | ## 发现总结 ### 1. 固件与反编译 - **两份出厂固件均从零开始反编译**(Ghidra,标准流程)——参见 [`reverse-v2/chip1`](reverse-v2/chip1) 和 [`reverse-v2/chip2`](reverse-v2/chip2) (`decompiled_all.c`,符号,字符串)。旧的 `docs/fw/` 和第一次迭代**不可靠**(仅作为历史记录保留在 `ru/archive/` 下)。 - **架构 / 外设 / 子系统映射图** —— [`reverse-v2/ARCHITECTURE.md`](reverse-v2/ARCHITECTURE.md), [`reverse-v2/reports/subsystem-findings.md`](reverse-v2/reports/subsystem-findings.md), [`reverse-v2/factory-map/`](reverse-v2/factory-map/) (逐个函数的详细解析, 请从 `00-INDEX.md` 开始看起)。 - **函数及外设参考** — [`reverse-v2/reference/`](reverse-v2/reference/) (`FUNCTIONS-chip1/2`, `PERIPHERALS-chip1/2`, `MOWING-ALGORITHM`, 启动 RAM, 寄存器映射表)。 ### 2. 启动、电源与安全 - **启动 / 上电时序与电源锁存** — [`reverse-v2/factory-map/01-boot-poweron.md`](reverse-v2/factory-map/01-boot-poweron.md)。 一个关键的操作事实是:chip1 上出现 `deadbeef` 的 DPIDR 意味着**芯片已断电** (电源锁存断开),*而不是* SWD 线路损坏。 - **PIN / 配对安全** — [`reverse-v2/factory-map/02-pin-security.md`](reverse-v2/factory-map/02-pin-security.md)。 ### 3. 割草 / 返航状态机 - **FSM(割草 ↔ 返航 ↔ 待机)与割草算法** — [`reverse-v2/factory-map/03-fsm-mow-home.md`](reverse-v2/factory-map/03-fsm-mow-home.md), [`reverse-v2/reference/MOWING-ALGORITHM.md`](reverse-v2/reference/MOWING-ALGORITHM.md)。 ### 4. 驱动(BLDC / FU6832N over SPI) - **SPI 驱动链已逐字节反编译** — [`reverse-v2/factory-map/04-motor-drivers.md`](reverse-v2/factory-map/04-motor-drivers.md), [`reverse-v2/reports/drive-chain.md`](reverse-v2/reports/drive-chain.md)。 片选信号:左 = PD5,右 = PD4,刀盘 = PD3;SPI1;PWM 位于 TIMER2 ch3。驱动器**没有 GPIO“使能”**线(待机激活 = SPI 寄存器写入 + 电源轨道)。 - **向 BLDC 的 SPI 写入已得到确认** — 轮通道通过 SPI 激活,并且**刀盘 在指令下输出了 RUN=1/0 的脉冲**。因此,SPI 路径本身已经可以端到端正常工作。 ### 5. BMS / 电池包通信 (USART2) - **已建立与电池包的通信** — USART2,19200 8N1,在 PD8/PD9 上的半双工通信;数据帧 `3A A3 len … C1 … CRC8` (CRC-8/MAXIM);连接握手 ×4;电池包作出应答 (`connected=1`)。 详情: [`reverse-v2/factory-map/05-bms-pack.md`](reverse-v2/factory-map/05-bms-pack.md)。 ### 6. 边界检测 (chip2) - **边界检测已被深入剖析** — 通过 ADC+DMA 的边界线圈,波形/区域分类; 灵敏度的调节旋钮是 `FUN_0801baf8` 中的 `|sample| > 2500` 阈值,基础电压 会自动校准,且整个镜像受到 **IEC60730 FLASH-CRC32** 的保护(因此修补 flash 会破坏 CRC)。如何针对新线圈进行调整: [`reverse-v2/factory-map/06-chip2.md`](reverse-v2/factory-map/06-chip2.md), [`reverse-v2/reports/CHIP2-BORDER-SENSITIVITY-2026-07-13.md`](reverse-v2/reports/CHIP2-BORDER-SENSITIVITY-2026-07-13.md)。 ### 7. 自定义固件 + SWD 工具链 - **自定义 chip1 固件已烧录并在实机上运行** — [`firmware/mower-own/`](firmware/mower-own/): 心跳信号、电池读取、正常待机。烧录是 **CRC 安全**的(bootloader 不会检查 应用程序的 CRC)。 - **树莓派上的 SWD 基础设施** — 通过 openocd bitbang 进行烧录 / 导出 / 还原;完整的 变砖 → 恢复周期已在工作台上验证通过。chip1 = GPIO25/24,chip2 = GPIO8/7。 脚本: [`tools/bench/`](tools/bench/), [`tools/rpi-swd/`](tools/rpi-swd/); 流程: [`reverse-v2/reports/flash-procedure.md`](reverse-v2/reports/flash-procedure.md)。 - **已验证原厂还原** — chip1 已回滚至与原厂镜像位级一致的版本 (SP `0x20017ff8`,CRC `0x0f69a878`);工具位于 [`tools/rpi-swd/restore-2026-07-14/`](tools/rpi-swd/restore-2026-07-14/). - **Dumps、固件镜像与烧录器** — [`dist/`](dist/),参见 [`dist/FLASHERS.md`](dist/FLASHERS.md) (包含出厂 chip1 dump `gd32-mainboard-dump-v1.bin`、chip2 dump 以及完整的 `factory-full.asm` 反汇编文件)。 ## 主要未解问题 — 轮子在我们的固件下从未转动 **在我们自己的固件下,车轮在物理上从未转动过**,尽管 SPI、PWM 和 GPIO 均被正确驱动,且**刀盘可控**。在工作台上,轮通道表现出**完全的寂静** ——没有运动,没有抖动——这表明问题出在轮通道驱动器未通电或未被激活,而不是在 SPI/PWM/GPIO 层(所有这些都符合出厂固件)。 在板子损坏之前,原因一直未能缩小至单一被证实的事实。 未决的假设以及解决这些假设的计划 — [`reverse-v2/reports/WHEELS-ROOT-CAUSE-AUDIT-2026-07-10.md`](reverse-v2/reports/WHEELS-ROOT-CAUSE-AUDIT-2026-07-10.md): - 为轮通道选择 FU6832 的 **快/慢配置**, - 与原厂逐字节对比的 **SPI CTL0/CTL1**, - 与原厂完全匹配的 **TIMER2**, - 可能存在的 **电源轨道门控**(一条 BMS 指令,或者一个硬件电源开关 / VBB),原厂启用了它,而我们没有。 针对出厂固件的下一次单一 SWD 捕获旨在记录一次性解决此问题所需的一切信息 — [`reverse-v2/reports/SWD-CAPTURE-PACKAGE-2026-07-13.md`](reverse-v2/reports/SWD-CAPTURE-PACKAGE-2026-07-13.md)。 ## 代码库布局 ``` reverse-v2/ ★ CORE: clean re-teardown of both firmwares ARCHITECTURE.md unified robot map (chip1 / chip2 / display / drive) chip1/ chip2/ canonical decompile (decompiled_all.c, symbols, strings) factory-map/ full factory-firmware walkthrough by function (00-INDEX) reference/ references (bring-up RAM, drivers, registers, mowing algorithm) reports/ current reports and plans — see reports/README.md analysis/ measurements/ ghidra-scripts/ supporting analysis firmware/ mower-own/ ★ custom chip1 firmware (flashed, runs; drive still under debug) coil-scope/ coil work (ESP32) esphome/mower.yaml telemetry bench for the display ESP32 (read-only) tools/ bench/ flash-script generators, CRC, packer, recovery.cfg rpi-swd/ SWD configs on the Pi (chip1 25/24, chip2 8/7) + restore-2026-07-14/ dashboard/ img/ supporting dist/ dumps, firmware images, flashers — see dist/FLASHERS.md server/ HA/MQTT glue, sniffers, scraper (telemetry) hardware/ signal-map, SWD/ESP wiring diagrams ru/ Russian originals (verbatim); ru/archive/ = historical / superseded ``` ## 历史背景:“ESP32 大脑移植”方案 在走 GD32 路线之前,该项目曾作为 ESP32-S3 覆盖层在原厂电路板上运行 (移植 Ardumower,匹配滤波器信号接收)。后来为了直接控制原厂的 GD32 而放弃了该方案。规划文档和旧的 ESP32 大脑固件保留在 [`ru/archive/old-docs/planning-esp32/`](ru/archive/old-docs/planning-esp32/) 和 [`ru/archive/`](ru/archive/) (参见 `ru/archive/README.md`) 下。
标签:ARM/GD32, SWD调试, 云资产清单, 固件分析, 客户端加密, 嵌入式开发, 机器人, 物联网硬件, 逆向工程