/* A2 验收主项:能在假总线上挂一个器件并读回预置值。 顺带把「器件失联 / 偶发 NAK」这两种后面 A15 要用的故障注入也测掉。 */ #include #include "sim_hal.h" #include "unity.h" #define INA226_CH1 0x40 /* 设计文档 §8.2 的地址表;A3 才会真的写驱动 */ #define PCA9555 0x20 void setUp(void) { sim_hal_reset(); } void tearDown(void) {} static void init_bus(void) { TEST_ASSERT_EQUAL_INT(HAL_OK, hal_i2c_init(NULL)); } static void test_use_before_init_is_state_error(void) { sim_i2c_add(INA226_CH1, 2); uint8_t rd[2]; TEST_ASSERT_EQUAL_INT(HAL_ERR_STATE, hal_i2c_read(INA226_CH1, rd, sizeof(rd))); } /* ⭐ A2 的验收判据本身 */ static void test_read_back_preset_register(void) { init_bus(); sim_i2c_add(INA226_CH1, 2); sim_i2c_set_reg(INA226_CH1, 0x02, 0x1234); /* INA226 的 Bus Voltage 寄存器 */ const uint8_t ptr = 0x02; uint8_t rd[2] = { 0, 0 }; TEST_ASSERT_EQUAL_INT(HAL_OK, hal_i2c_write_read(INA226_CH1, &ptr, 1, rd, sizeof(rd))); TEST_ASSERT_EQUAL_HEX8(0x12, rd[0]); /* 大端 */ TEST_ASSERT_EQUAL_HEX8(0x34, rd[1]); TEST_ASSERT_EQUAL_UINT32(1, sim_i2c_dev(INA226_CH1)->n_read); } static void test_write_stores_big_endian_and_logs_bytes(void) { init_bus(); sim_i2c_add(INA226_CH1, 2); const uint8_t wr[3] = { 0x05, 0x12, 0x34 }; TEST_ASSERT_EQUAL_INT(HAL_OK, hal_i2c_write(INA226_CH1, wr, sizeof(wr))); TEST_ASSERT_EQUAL_HEX16(0x1234, sim_i2c_get_reg(INA226_CH1, 0x05)); const sim_i2c_dev_t *d = sim_i2c_dev(INA226_CH1); TEST_ASSERT_EQUAL_UINT8(3, d->last_write_len); TEST_ASSERT_EQUAL_HEX8_ARRAY(wr, d->last_write, 3); } /* 寄存器指针自增:一次事务连读两个寄存器,真器件就是这个行为。 */ static void test_pointer_auto_increments(void) { init_bus(); sim_i2c_add(INA226_CH1, 2); sim_i2c_set_reg(INA226_CH1, 0x01, 0xAAAA); sim_i2c_set_reg(INA226_CH1, 0x02, 0xBBBB); const uint8_t ptr = 0x01; uint8_t rd[4]; TEST_ASSERT_EQUAL_INT(HAL_OK, hal_i2c_write_read(INA226_CH1, &ptr, 1, rd, sizeof(rd))); TEST_ASSERT_EQUAL_HEX8(0xAA, rd[0]); TEST_ASSERT_EQUAL_HEX8(0xBB, rd[2]); } /* PCA9555 是 8 位寄存器;同一套 HAL 要能同时伺候两种宽度。 */ static void test_byte_wide_device(void) { init_bus(); sim_i2c_add(PCA9555, 1); const uint8_t wr[3] = { 0x06, 0xFF, 0x0F }; /* 配置寄存器 Port0/Port1 */ TEST_ASSERT_EQUAL_INT(HAL_OK, hal_i2c_write(PCA9555, wr, sizeof(wr))); TEST_ASSERT_EQUAL_HEX16(0x00FF, sim_i2c_get_reg(PCA9555, 0x06)); TEST_ASSERT_EQUAL_HEX16(0x000F, sim_i2c_get_reg(PCA9555, 0x07)); } static void test_absent_device_naks(void) { init_bus(); TEST_ASSERT_EQUAL_INT(HAL_ERR_NAK, hal_i2c_probe(0x77)); /* 总线上没这个地址 */ sim_i2c_add(INA226_CH1, 2); TEST_ASSERT_EQUAL_INT(HAL_OK, hal_i2c_probe(INA226_CH1)); sim_i2c_set_present(INA226_CH1, false); /* 器件失联(A15 降级矩阵) */ TEST_ASSERT_EQUAL_INT(HAL_ERR_NAK, hal_i2c_probe(INA226_CH1)); } static void test_transient_nak_then_recovers(void) { init_bus(); sim_i2c_add(INA226_CH1, 2); sim_i2c_inject_nak(INA226_CH1, 2); /* 接下来两次事务失败 */ uint8_t rd[2]; TEST_ASSERT_EQUAL_INT(HAL_ERR_NAK, hal_i2c_read(INA226_CH1, rd, sizeof(rd))); TEST_ASSERT_EQUAL_INT(HAL_ERR_NAK, hal_i2c_read(INA226_CH1, rd, sizeof(rd))); TEST_ASSERT_EQUAL_INT(HAL_OK, hal_i2c_read(INA226_CH1, rd, sizeof(rd))); /* NAK 掉的事务不该被算成一次成功访问 */ TEST_ASSERT_EQUAL_UINT32(1, sim_i2c_dev(INA226_CH1)->n_read); } /* 半个寄存器的长度:真器件上是未定义行为,这里必须当场报错而不是悄悄凑合。 */ static void test_partial_register_length_rejected(void) { init_bus(); sim_i2c_add(INA226_CH1, 2); uint8_t rd[1]; TEST_ASSERT_EQUAL_INT(HAL_ERR_ARG, hal_i2c_read(INA226_CH1, rd, 1)); const uint8_t wr[2] = { 0x05, 0x12 }; TEST_ASSERT_EQUAL_INT(HAL_ERR_ARG, hal_i2c_write(INA226_CH1, wr, sizeof(wr))); } static void test_address_out_of_range(void) { init_bus(); TEST_ASSERT_EQUAL_INT(HAL_ERR_ARG, hal_i2c_probe(0x80)); } int main(void) { UNITY_BEGIN(); RUN_TEST(test_use_before_init_is_state_error); RUN_TEST(test_read_back_preset_register); RUN_TEST(test_write_stores_big_endian_and_logs_bytes); RUN_TEST(test_pointer_auto_increments); RUN_TEST(test_byte_wide_device); RUN_TEST(test_absent_device_naks); RUN_TEST(test_transient_nak_then_recovers); RUN_TEST(test_partial_register_length_rejected); RUN_TEST(test_address_out_of_range); return UNITY_END(); }