接口在 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
3.5 KiB
3.5 KiB
交接
更新: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}.ccomponents/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()。