/* I²C 的假实现:一张寄存器表 + 可注入的 NAK。宿主机专用。 */ #include #include #include "sim_hal.h" static sim_i2c_dev_t s_dev[SIM_I2C_MAX_DEV]; static int s_n; static bool s_inited; void sim_i2c_reset_internal(void); /* 只给 sim_hal_reset() 用 */ void sim_i2c_reset_internal(void) { memset(s_dev, 0, sizeof(s_dev)); s_n = 0; s_inited = false; } sim_i2c_dev_t *sim_i2c_dev(uint8_t addr) { for (int i = 0; i < s_n; i++) { if (s_dev[i].addr == addr) { return &s_dev[i]; } } return NULL; } sim_i2c_dev_t *sim_i2c_add(uint8_t addr, uint8_t reg_width) { assert(addr <= 0x7f); assert(reg_width == 1 || reg_width == 2); assert(sim_i2c_dev(addr) == NULL); /* 地址撞车:测试写错了 */ assert(s_n < SIM_I2C_MAX_DEV); sim_i2c_dev_t *d = &s_dev[s_n++]; memset(d, 0, sizeof(*d)); d->addr = addr; d->reg_width = reg_width; d->present = true; return d; } static sim_i2c_dev_t *must(uint8_t addr) { sim_i2c_dev_t *d = sim_i2c_dev(addr); assert(d != NULL); /* 先 sim_i2c_add() 再预置寄存器 */ return d; } void sim_i2c_set_reg(uint8_t addr, uint8_t reg, uint16_t val) { must(addr)->regs[reg] = val; } uint16_t sim_i2c_get_reg(uint8_t addr, uint8_t reg) { return must(addr)->regs[reg]; } void sim_i2c_inject_nak(uint8_t addr, int count) { must(addr)->nak_left = count; } void sim_i2c_set_present(uint8_t addr, bool present) { must(addr)->present = present; } /* ---- HAL 实现 ---------------------------------------------------------- */ hal_err_t hal_i2c_init(const hal_i2c_cfg_t *cfg) { (void)cfg; /* sim 不关心引脚与速率 */ s_inited = true; return HAL_OK; } /* 取器件并把「这次事务要不要 NAK」判掉。 */ static hal_err_t take(uint8_t addr, sim_i2c_dev_t **out) { if (!s_inited) { return HAL_ERR_STATE; } if (addr > 0x7f) { return HAL_ERR_ARG; } sim_i2c_dev_t *d = sim_i2c_dev(addr); if (d == NULL || !d->present) { return HAL_ERR_NAK; } if (d->nak_left != 0) { if (d->nak_left > 0) { d->nak_left--; } return HAL_ERR_NAK; } *out = d; return HAL_OK; } /* data[0] 是寄存器指针,其后按 reg_width 一格一格写,指针自增(uint8_t 自然回绕)。 */ static hal_err_t do_write(sim_i2c_dev_t *d, const uint8_t *data, size_t len) { if (len != 0 && data == NULL) { return HAL_ERR_ARG; } if (len > 1 && ((len - 1) % d->reg_width) != 0) { return HAL_ERR_ARG; /* 半个寄存器:真器件上是未定义行为,这里直接报错 */ } d->n_write++; d->last_write_len = (uint8_t)(len < SIM_I2C_LOG_BYTES ? len : SIM_I2C_LOG_BYTES); if (d->last_write_len != 0) { memcpy(d->last_write, data, d->last_write_len); } if (len == 0) { return HAL_OK; /* 只发地址 = 探测 */ } d->ptr = data[0]; for (size_t i = 1; i < len; i += d->reg_width) { uint16_t v = data[i]; if (d->reg_width == 2) { v = (uint16_t)((v << 8) | data[i + 1]); } d->regs[d->ptr++] = v; } return HAL_OK; } static hal_err_t do_read(sim_i2c_dev_t *d, uint8_t *data, size_t len) { if (len != 0 && data == NULL) { return HAL_ERR_ARG; } if ((len % d->reg_width) != 0) { return HAL_ERR_ARG; } d->n_read++; for (size_t i = 0; i < len; i += d->reg_width) { uint16_t v = d->regs[d->ptr++]; if (d->reg_width == 2) { data[i] = (uint8_t)(v >> 8); data[i + 1] = (uint8_t)(v & 0xff); } else { data[i] = (uint8_t)v; } } return HAL_OK; } hal_err_t hal_i2c_write(uint8_t addr, const uint8_t *data, size_t len) { sim_i2c_dev_t *d = NULL; hal_err_t err = take(addr, &d); return err != HAL_OK ? err : do_write(d, data, len); } hal_err_t hal_i2c_read(uint8_t addr, uint8_t *data, size_t len) { sim_i2c_dev_t *d = NULL; hal_err_t err = take(addr, &d); return err != HAL_OK ? err : do_read(d, data, len); } hal_err_t hal_i2c_write_read(uint8_t addr, const uint8_t *wr, size_t wr_len, uint8_t *rd, size_t rd_len) { sim_i2c_dev_t *d = NULL; hal_err_t err = take(addr, &d); if (err != HAL_OK) { return err; } err = do_write(d, wr, wr_len); return err != HAL_OK ? err : do_read(d, rd, rd_len); } hal_err_t hal_i2c_probe(uint8_t addr) { sim_i2c_dev_t *d = NULL; return take(addr, &d); }