文件
phonerail/firmware/HANDOFF.md
T
zhou yang和Claude Opus 5 cac6ce47ce A2:HAL 接口(i2c/gpio/pwm/time)+ sim 与 ESP 两套实现
接口在 components/phonerail_hal/include/,宿主机链 sim/、ESP32-S3 链 esp/
(IDF v5.4 新版 i2c_master / gpio / LEDC / esp_timer)。

sim 提供 A3 起要用的假板子控制面:假 I²C 器件(寄存器表 + 大端 + 指针自增)、
可注入 NAK / 器件失联、GPIO 外部驱动与写计数、虚拟时钟。

组件名不叫 hal —— ESP-IDF 自己有 components/hal(driver 依赖它),同名会盖掉。

验收:bash host/test.sh → 3 条 ctest 全过;build_idf.ps1 → 编过且零警告。

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QYuExfgyYa6DzRRcUso8M8
2026-09-06 18:33:26 +08:00

3.5 KiB
原始文件 Blame 文件历史

交接

更新:2026-09-06 完成任务包 A2(HAL 接口 + sim 实现)

一句话现状

四路 HAL(i2c / gpio / pwm / time)的接口定死了,两套实现都在: 宿主机链 sim/(假 I²C 器件 + 虚拟时钟 + 故障注入),ESP32-S3 链 esp/(IDF v5.4 新版 i2c_master / gpio / LEDC / esp_timer)。3 条 ctest(16 个用例)全绿,idf.py build 零警告。

下一步

A3:INA226 驱动 + 六片地址表(0x40/41/44/45/42/43,设计文档 §8.2)。 驱动只准通过 hal_i2c_* 访问总线;测试用 sim_i2c_add(addr, 2) 挂假器件、 sim_i2c_set_reg() 预置值。16 位寄存器是大端,sim 已按大端实现。

本次新增/修改的文件

  • components/phonerail_hal/include/hal_{err,i2c,gpio,pwm,time}.h — 接口(唯一的对外契约)
  • components/phonerail_hal/hal_err.c — 两个目标共用的错误码字符串
  • components/phonerail_hal/esp/hal_{i2c,gpio,pwm,time}_esp.c — ESP-IDF 实现
  • components/phonerail_hal/sim/sim_hal.h — 假板子的控制面(应用代码不许包含)
  • components/phonerail_hal/sim/{sim_hal,hal_i2c_sim,hal_gpio_sim,hal_pwm_sim,hal_time_sim}.c
  • components/phonerail_hal/CMakeLists.txt — IDF 组件(只收 esp/,不收 sim/)
  • test/test_hal_i2c_sim.c、test/test_hal_sim.c — 本包的测试
  • host/CMakeLists.txt — 加 PHONERAIL_HAL_SIM_SRCS 与两个 include 目录
  • main/CMakeLists.txt — REQUIRES phonerail_hal;main/app_main.c 调一次 HAL 保证链接
  • ../固件开发计划.md §4.1 — 记下组件重名那个坑

验收命令与结果

$ bash host/test.sh
100% tests passed, 0 tests failed out of 3     # test_hal_i2c_sim / test_hal_sim / test_version

$ .\build_idf.ps1          # PowerShell
phonerail.bin binary size 0x32550 bytes. ... 0xcdab0 bytes (80%) free.
Project build complete.

踩到的坑(只写会再犯的)

  • 组件名不能叫 hal:ESP-IDF 自己有 components/hal(driver 依赖它), 工程里同名会把它盖掉。所以叫 phonerail_hal。头文件名 hal_*.h 不冲突。
  • 新增 HAL 实现要改两处 CMake:components/phonerail_hal/CMakeLists.txt(esp 那份) 和 host/CMakeLists.txt 的 PHONERAIL_HAL_SIM_SRCS(sim 那份)。漏一处 = 「宿主机绿了但上板编不过」,反之亦然。main/ 里的 .c 仍是老规矩的另外两处。
  • IDF 组件的 SRCS 是显式列举,所以 sim/ 放在组件目录里也不会被 IDF 编到。

HAL 的几条约定(写驱动前看一眼,省得回头改)

  • 16 位 I²C 寄存器一律大端;写事务的第一个字节是寄存器指针,指针跨事务保持并自增。
  • 读写长度不是 reg_width 整数倍 → HAL_ERR_ARG(真器件上是未定义行为,不许悄悄凑合)。
  • 器件不在 / present=false / 注入 NAK → HAL_ERR_NAK;没 hal_i2c_init() 就用 → HAL_ERR_STATE。
  • 写一个没配成输出的 GPIO 返回 HAL_ERR_ARG(板子上 gpio_set_level() 是静默无效的)。 HAL_GPIO_INPUT_PULLUP 配完默认读回 1 —— 五路 FLT/PG 是开漏 + 上拉,默认 0 会被当成一直有故障。
  • PWM 占空比单位是千分比 0~1000,应用层不需要知道 LEDC 是几位。
  • 时刻比较一律用 hal_time_elapsed_ms(),不要写 now - then > x(32 位毫秒 49.7 天回绕)。
  • sim 的时钟是虚拟的:hal_time_delay_ms() 只把时间往前拨,测试零耗时。 每个测试 setUp() 里调 sim_hal_reset()。