接口在 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
111 行
4.0 KiB
C
111 行
4.0 KiB
C
/* GPIO / PWM / 时钟三路 sim 的行为约定。 */
|
|
#include "sim_hal.h"
|
|
#include "unity.h"
|
|
|
|
void setUp(void) { sim_hal_reset(); }
|
|
void tearDown(void) {}
|
|
|
|
/* ---- GPIO ---- */
|
|
|
|
static void test_output_write_and_readback(void)
|
|
{
|
|
TEST_ASSERT_EQUAL_INT(HAL_OK, hal_gpio_config(5, HAL_GPIO_OUTPUT));
|
|
TEST_ASSERT_EQUAL_INT(0, sim_gpio_level(5)); /* 配完默认低 */
|
|
TEST_ASSERT_EQUAL_INT(HAL_OK, hal_gpio_write(5, 1));
|
|
TEST_ASSERT_EQUAL_INT(1, sim_gpio_level(5));
|
|
|
|
int level = -1;
|
|
TEST_ASSERT_EQUAL_INT(HAL_OK, hal_gpio_read(5, &level));
|
|
TEST_ASSERT_EQUAL_INT(1, level);
|
|
}
|
|
|
|
/* 「把输入脚当输出写」在板子上是静默无效的,最难查 —— sim 里必须报错。 */
|
|
static void test_write_to_input_pin_is_error(void)
|
|
{
|
|
TEST_ASSERT_EQUAL_INT(HAL_OK, hal_gpio_config(6, HAL_GPIO_INPUT));
|
|
TEST_ASSERT_EQUAL_INT(HAL_ERR_ARG, hal_gpio_write(6, 1));
|
|
TEST_ASSERT_EQUAL_INT(HAL_ERR_ARG, hal_gpio_write(7, 1)); /* 压根没配过 */
|
|
TEST_ASSERT_EQUAL_INT(HAL_ERR_ARG, hal_gpio_config(SIM_GPIO_PINS, HAL_GPIO_OUTPUT));
|
|
}
|
|
|
|
/* 五路 FLT/PG 是开漏 + 上拉:没有故障时必须读回 1,不能默认 0。 */
|
|
static void test_pullup_input_idles_high(void)
|
|
{
|
|
TEST_ASSERT_EQUAL_INT(HAL_OK, hal_gpio_config(8, HAL_GPIO_INPUT_PULLUP));
|
|
int level = -1;
|
|
TEST_ASSERT_EQUAL_INT(HAL_OK, hal_gpio_read(8, &level));
|
|
TEST_ASSERT_EQUAL_INT(1, level);
|
|
|
|
sim_gpio_drive(8, 0); /* 器件报故障,把脚拉低 */
|
|
TEST_ASSERT_EQUAL_INT(HAL_OK, hal_gpio_read(8, &level));
|
|
TEST_ASSERT_EQUAL_INT(0, level);
|
|
}
|
|
|
|
/* 写计数是给 A5「改 CH1 不动 CH2~5」那条断言准备的。 */
|
|
static void test_write_counter_is_per_pin(void)
|
|
{
|
|
TEST_ASSERT_EQUAL_INT(HAL_OK, hal_gpio_config(10, HAL_GPIO_OUTPUT));
|
|
TEST_ASSERT_EQUAL_INT(HAL_OK, hal_gpio_config(11, HAL_GPIO_OUTPUT));
|
|
hal_gpio_write(10, 1);
|
|
hal_gpio_write(10, 0);
|
|
TEST_ASSERT_EQUAL_UINT32(2, sim_gpio_writes(10));
|
|
TEST_ASSERT_EQUAL_UINT32(0, sim_gpio_writes(11));
|
|
}
|
|
|
|
/* ---- PWM ---- */
|
|
|
|
static void test_pwm_config_and_duty(void)
|
|
{
|
|
TEST_ASSERT_EQUAL_INT(HAL_ERR_ARG, hal_pwm_set_permille(0, 500)); /* 没配就用 */
|
|
TEST_ASSERT_EQUAL_INT(HAL_OK, hal_pwm_config(0, 21, 25000)); /* 风扇 25 kHz */
|
|
TEST_ASSERT_EQUAL_INT(21, sim_pwm_pin(0));
|
|
TEST_ASSERT_EQUAL_UINT32(25000, sim_pwm_freq(0));
|
|
TEST_ASSERT_EQUAL_INT(0, sim_pwm_permille(0)); /* 配完默认停转 */
|
|
|
|
TEST_ASSERT_EQUAL_INT(HAL_OK, hal_pwm_set_permille(0, 400));
|
|
uint16_t d = 0;
|
|
TEST_ASSERT_EQUAL_INT(HAL_OK, hal_pwm_get_permille(0, &d));
|
|
TEST_ASSERT_EQUAL_UINT16(400, d);
|
|
|
|
TEST_ASSERT_EQUAL_INT(HAL_ERR_ARG, hal_pwm_set_permille(0, 1001)); /* 千分比上限 */
|
|
TEST_ASSERT_EQUAL_INT(HAL_ERR_ARG, hal_pwm_config(HAL_PWM_CH_MAX, 21, 25000));
|
|
TEST_ASSERT_EQUAL_INT(HAL_ERR_ARG, hal_pwm_config(1, 21, 0));
|
|
}
|
|
|
|
/* ---- 时钟 ---- */
|
|
|
|
static void test_virtual_clock_advances_only_on_demand(void)
|
|
{
|
|
TEST_ASSERT_EQUAL_UINT64(0, hal_time_now_us());
|
|
hal_time_delay_ms(17); /* A9 的上电时序就是这个量级 */
|
|
TEST_ASSERT_EQUAL_UINT32(17, hal_time_now_ms());
|
|
TEST_ASSERT_EQUAL_UINT32(1, sim_time_delay_calls());
|
|
|
|
sim_time_advance_us(500);
|
|
TEST_ASSERT_EQUAL_UINT64(17500, hal_time_now_us());
|
|
TEST_ASSERT_EQUAL_UINT32(17, hal_time_now_ms()); /* 不满 1 ms 不进位 */
|
|
}
|
|
|
|
/* 49.7 天回绕:农场是长稳运行的,这一条迟早会被踩到。 */
|
|
static void test_elapsed_survives_wraparound(void)
|
|
{
|
|
sim_time_set_us(0xFFFFFFF0ull * 1000ull);
|
|
uint32_t t0 = hal_time_now_ms();
|
|
sim_time_advance_ms(32); /* 跨过 32 位回绕点 */
|
|
TEST_ASSERT_TRUE(hal_time_now_ms() < t0);
|
|
TEST_ASSERT_EQUAL_UINT32(32, hal_time_elapsed_ms(t0));
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
UNITY_BEGIN();
|
|
RUN_TEST(test_output_write_and_readback);
|
|
RUN_TEST(test_write_to_input_pin_is_error);
|
|
RUN_TEST(test_pullup_input_idles_high);
|
|
RUN_TEST(test_write_counter_is_per_pin);
|
|
RUN_TEST(test_pwm_config_and_duty);
|
|
RUN_TEST(test_virtual_clock_advances_only_on_demand);
|
|
RUN_TEST(test_elapsed_survives_wraparound);
|
|
return UNITY_END();
|
|
}
|