接口在 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
87 行
3.3 KiB
C
87 行
3.3 KiB
C
/* 假板子的控制面 —— 只有宿主机测试与 sim/ 自己会包含它,应用代码一律不许包含。
|
|
(包含了就编不过:ESP 目标根本不编译 sim/。)
|
|
|
|
⚠️ 模拟器是用来证明**代码逻辑**对的,不是用来证明**设计**对的。
|
|
电压、余量、时序裕量的结论全部来自设计文档的计算与首板实测。见计划 §4.2。 */
|
|
#ifndef SIM_HAL_H
|
|
#define SIM_HAL_H
|
|
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
|
|
#include "hal_gpio.h"
|
|
#include "hal_i2c.h"
|
|
#include "hal_pwm.h"
|
|
#include "hal_time.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/* 四路 sim 全部恢复出厂:器件表清空、引脚未配置、PWM 未配置、时钟归零、
|
|
init 标志清掉。每个测试的 setUp() 里调它。 */
|
|
void sim_hal_reset(void);
|
|
|
|
/* ---------------- I²C ---------------- */
|
|
|
|
#define SIM_I2C_MAX_DEV 16
|
|
#define SIM_I2C_REGS 256
|
|
#define SIM_I2C_LOG_BYTES 8
|
|
|
|
typedef struct {
|
|
uint8_t addr;
|
|
uint8_t reg_width; /* 1 或 2 字节。2 字节按**大端**——INA226 / DAC63204 / LM75 都是 */
|
|
bool present; /* false = 器件失联(A15 降级矩阵用),事务一律 NAK */
|
|
int nak_left; /* >0:接下来 n 次事务 NAK 后自动恢复;<0:一直 NAK;0:正常 */
|
|
uint16_t regs[SIM_I2C_REGS];
|
|
uint8_t ptr; /* 器件内部的寄存器指针,跨事务保持(真器件就是这个行为) */
|
|
uint32_t n_write; /* 事务计数,可用来断言「驱动真的访问过它 / 没多访问」 */
|
|
uint32_t n_read;
|
|
uint8_t last_write[SIM_I2C_LOG_BYTES]; /* 最后一次写进去的原始字节 */
|
|
uint8_t last_write_len;
|
|
} sim_i2c_dev_t;
|
|
|
|
/* 往假总线上挂一个器件。地址重复或超出 16 个会 abort(测试写错了,不该悄悄过)。 */
|
|
sim_i2c_dev_t *sim_i2c_add(uint8_t addr, uint8_t reg_width);
|
|
sim_i2c_dev_t *sim_i2c_dev(uint8_t addr); /* 没挂就返回 NULL */
|
|
|
|
/* 预置 / 回读寄存器。地址没挂过会 abort。 */
|
|
void sim_i2c_set_reg(uint8_t addr, uint8_t reg, uint16_t val);
|
|
uint16_t sim_i2c_get_reg(uint8_t addr, uint8_t reg);
|
|
|
|
/* 故障注入。count>0:接下来 count 次事务 NAK;count<0:一直 NAK;0:清除。 */
|
|
void sim_i2c_inject_nak(uint8_t addr, int count);
|
|
void sim_i2c_set_present(uint8_t addr, bool present);
|
|
|
|
/* ---------------- GPIO ---------------- */
|
|
|
|
#define SIM_GPIO_PINS 48 /* ESP32-S3 的 GPIO 编号上限 */
|
|
|
|
/* 外部世界把某个**输入**脚拉成 level。对输出脚调用会 abort(那是总线打架)。 */
|
|
void sim_gpio_drive(int pin, int level);
|
|
|
|
/* 该脚当前电平:输出脚 = 固件驱动的值,输入脚 = 外部驱动的值。没配过返回 -1。 */
|
|
int sim_gpio_level(int pin);
|
|
|
|
/* 被 hal_gpio_write() 写成功过几次。断言「改 CH1 没动 CH2~5」用得上(A5)。 */
|
|
uint32_t sim_gpio_writes(int pin);
|
|
|
|
/* ---------------- PWM ---------------- */
|
|
|
|
int sim_pwm_pin(int ch); /* 未配置返回 -1 */
|
|
uint32_t sim_pwm_freq(int ch); /* 未配置返回 0 */
|
|
int sim_pwm_permille(int ch); /* 未配置返回 -1 */
|
|
|
|
/* ---------------- 时钟 ---------------- */
|
|
|
|
void sim_time_set_us(uint64_t us);
|
|
void sim_time_advance_us(uint64_t us);
|
|
void sim_time_advance_ms(uint32_t ms);
|
|
uint32_t sim_time_delay_calls(void); /* hal_time_delay_ms() 被调了几次 */
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* SIM_HAL_H */
|