From 6e4354c83eeea0f3b5c627508978a077ddcb7f0e Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Tue, 24 Feb 2026 20:32:09 +0800 Subject: [PATCH] feat(regi2c): add test app for esp_hal_regi2c component --- .../test_apps/.build-test-rules.yml | 9 ++ .../esp_hal_regi2c/test_apps/CMakeLists.txt | 6 ++ components/esp_hal_regi2c/test_apps/README.md | 3 + .../test_apps/main/CMakeLists.txt | 8 ++ .../test_apps/main/test_app_main.c | 37 ++++++++ .../test_apps/main/test_regi2c.c | 91 +++++++++++++++++++ .../test_apps/main/test_regi2c.h | 84 +++++++++++++++++ .../esp_hal_regi2c/test_apps/pytest_regi2c.py | 16 ++++ .../test_apps/sdkconfig.ci.default | 0 .../test_apps/sdkconfig.defaults | 2 + 10 files changed, 256 insertions(+) create mode 100644 components/esp_hal_regi2c/test_apps/.build-test-rules.yml create mode 100644 components/esp_hal_regi2c/test_apps/CMakeLists.txt create mode 100644 components/esp_hal_regi2c/test_apps/README.md create mode 100644 components/esp_hal_regi2c/test_apps/main/CMakeLists.txt create mode 100644 components/esp_hal_regi2c/test_apps/main/test_app_main.c create mode 100644 components/esp_hal_regi2c/test_apps/main/test_regi2c.c create mode 100644 components/esp_hal_regi2c/test_apps/main/test_regi2c.h create mode 100644 components/esp_hal_regi2c/test_apps/pytest_regi2c.py create mode 100644 components/esp_hal_regi2c/test_apps/sdkconfig.ci.default create mode 100644 components/esp_hal_regi2c/test_apps/sdkconfig.defaults diff --git a/components/esp_hal_regi2c/test_apps/.build-test-rules.yml b/components/esp_hal_regi2c/test_apps/.build-test-rules.yml new file mode 100644 index 0000000000..4f4f52f29d --- /dev/null +++ b/components/esp_hal_regi2c/test_apps/.build-test-rules.yml @@ -0,0 +1,9 @@ +components/esp_hal_regi2c/test_apps: + enable: + - if: INCLUDE_DEFAULT == 1 + disable: + - if: IDF_TARGET in ["esp32s31"] + temporary: true + reason: not support yet # TODO: [ESP32S31] IDF-14680 + depends_components: + - esp_hal_regi2c diff --git a/components/esp_hal_regi2c/test_apps/CMakeLists.txt b/components/esp_hal_regi2c/test_apps/CMakeLists.txt new file mode 100644 index 0000000000..abb9f1d457 --- /dev/null +++ b/components/esp_hal_regi2c/test_apps/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.22) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(test_regi2c) diff --git a/components/esp_hal_regi2c/test_apps/README.md b/components/esp_hal_regi2c/test_apps/README.md new file mode 100644 index 0000000000..e0c2bb1e27 --- /dev/null +++ b/components/esp_hal_regi2c/test_apps/README.md @@ -0,0 +1,3 @@ +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | + diff --git a/components/esp_hal_regi2c/test_apps/main/CMakeLists.txt b/components/esp_hal_regi2c/test_apps/main/CMakeLists.txt new file mode 100644 index 0000000000..3faab1d788 --- /dev/null +++ b/components/esp_hal_regi2c/test_apps/main/CMakeLists.txt @@ -0,0 +1,8 @@ +set(srcs "test_app_main.c" + "test_regi2c.c") + +# In order for the cases defined by `TEST_CASE` to be linked into the final elf, +# the component can be registered as WHOLE_ARCHIVE +idf_component_register(SRCS ${srcs} + INCLUDE_DIRS "." + WHOLE_ARCHIVE) diff --git a/components/esp_hal_regi2c/test_apps/main/test_app_main.c b/components/esp_hal_regi2c/test_apps/main/test_app_main.c new file mode 100644 index 0000000000..1379ede145 --- /dev/null +++ b/components/esp_hal_regi2c/test_apps/main/test_app_main.c @@ -0,0 +1,37 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "unity.h" +#include "unity_test_runner.h" +#include "esp_heap_caps.h" +#include "esp_newlib.h" +#include "unity_test_utils.h" + +// Some resources are lazy allocated in the driver, the threshold is left for that case +#define TEST_MEMORY_LEAK_THRESHOLD (0) + +void setUp(void) +{ + unity_utils_record_free_mem(); +} + +void tearDown(void) +{ + esp_reent_cleanup(); //clean up some of the newlib's lazy allocations + unity_utils_evaluate_leaks_direct(TEST_MEMORY_LEAK_THRESHOLD); +} + +void app_main(void) +{ + printf(" _ ____ \n"); + printf(" _ __ ___ __ _(_)___ \\ ___ \n"); + printf(" | '__/ _ \\/ _` | | __) / __| \n"); + printf(" | | | __/ (_| | |/ __/ (__ \n"); + printf(" |_| \\___|\\__, |_|_____\\___| \n"); + printf(" |___/ \n"); + + unity_run_menu(); +} diff --git a/components/esp_hal_regi2c/test_apps/main/test_regi2c.c b/components/esp_hal_regi2c/test_apps/main/test_regi2c.c new file mode 100644 index 0000000000..a69a8ea7d4 --- /dev/null +++ b/components/esp_hal_regi2c/test_apps/main/test_regi2c.c @@ -0,0 +1,91 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "unity.h" +#include "test_regi2c.h" +#include "esp_private/regi2c_ctrl.h" + +TEST_CASE("regi2c basic read/write test", "[regi2c]") +{ +#if CONFIG_IDF_TARGET_ESP32 + // For ESP32, we need to enable the APLL clock before accessing the APLL regi2c registers + periph_rtc_apll_acquire(); +#endif + + /* ---- Part 1: full-register read / write ---- */ + printf("Test regi2c read/write: block=0x%02X host=%d reg=%d\n", + TEST_BLOCK, TEST_HOST_ID, TEST_REG_FULL); + + uint8_t orig_full = regi2c_ctrl_read_reg(TEST_BLOCK, TEST_HOST_ID, TEST_REG_FULL); + printf(" Original value: 0x%02X\n", orig_full); + + const uint8_t patterns[] = {0xA5, 0x5A, 0xFF, 0x00}; + for (size_t i = 0; i < sizeof(patterns) / sizeof(patterns[0]); i++) { + regi2c_ctrl_write_reg(TEST_BLOCK, TEST_HOST_ID, TEST_REG_FULL, patterns[i]); + uint8_t rb = regi2c_ctrl_read_reg(TEST_BLOCK, TEST_HOST_ID, TEST_REG_FULL); + printf(" Write 0x%02X -> Read 0x%02X\n", patterns[i], rb); + TEST_ASSERT_EQUAL_HEX8(patterns[i], rb); + } + + /* ---- Part 2: masked read / write ---- */ + const uint8_t field_width = TEST_REG_MASK_MSB - TEST_REG_MASK_LSB + 1; + const uint8_t field_max = (uint8_t)((1U << field_width) - 1); + const uint8_t reg_mask = (uint8_t)(field_max << TEST_REG_MASK_LSB); + + printf("Test regi2c read_mask/write_mask: block=0x%02X host=%d reg=%d bits[%d:%d]\n", + TEST_BLOCK, TEST_HOST_ID, TEST_REG_MASK, + TEST_REG_MASK_MSB, TEST_REG_MASK_LSB); + + uint8_t orig_mask = regi2c_ctrl_read_reg(TEST_BLOCK, TEST_HOST_ID, TEST_REG_MASK); + printf(" Original full reg value: 0x%02X\n", orig_mask); + + /* Write all-ones to masked field */ + regi2c_ctrl_write_reg_mask(TEST_BLOCK, TEST_HOST_ID, TEST_REG_MASK, + TEST_REG_MASK_MSB, TEST_REG_MASK_LSB, field_max); + uint8_t mval = regi2c_ctrl_read_reg_mask(TEST_BLOCK, TEST_HOST_ID, TEST_REG_MASK, + TEST_REG_MASK_MSB, TEST_REG_MASK_LSB); + printf(" write_mask(0x%02X) -> read_mask=0x%02X\n", field_max, mval); + TEST_ASSERT_EQUAL_HEX8(field_max, mval); + uint8_t full = regi2c_ctrl_read_reg(TEST_BLOCK, TEST_HOST_ID, TEST_REG_MASK); + TEST_ASSERT_EQUAL_HEX8(orig_mask & (uint8_t)(~reg_mask), full & (uint8_t)(~reg_mask)); + + /* Write all-zeros to masked field */ + regi2c_ctrl_write_reg_mask(TEST_BLOCK, TEST_HOST_ID, TEST_REG_MASK, + TEST_REG_MASK_MSB, TEST_REG_MASK_LSB, 0x00); + mval = regi2c_ctrl_read_reg_mask(TEST_BLOCK, TEST_HOST_ID, TEST_REG_MASK, + TEST_REG_MASK_MSB, TEST_REG_MASK_LSB); + printf(" write_mask(0x00) -> read_mask=0x%02X\n", mval); + TEST_ASSERT_EQUAL_HEX8(0x00, mval); + full = regi2c_ctrl_read_reg(TEST_BLOCK, TEST_HOST_ID, TEST_REG_MASK); + TEST_ASSERT_EQUAL_HEX8(orig_mask & (uint8_t)(~reg_mask), full & (uint8_t)(~reg_mask)); + + /* Write a mid-range value */ + uint8_t mid = field_max >> 1; + if (mid == 0 && field_max > 0) { + mid = 1; + } + regi2c_ctrl_write_reg_mask(TEST_BLOCK, TEST_HOST_ID, TEST_REG_MASK, + TEST_REG_MASK_MSB, TEST_REG_MASK_LSB, mid); + mval = regi2c_ctrl_read_reg_mask(TEST_BLOCK, TEST_HOST_ID, TEST_REG_MASK, + TEST_REG_MASK_MSB, TEST_REG_MASK_LSB); + printf(" write_mask(0x%02X) -> read_mask=0x%02X\n", mid, mval); + TEST_ASSERT_EQUAL_HEX8(mid, mval); + + /* Restore all modified registers to their original values */ + regi2c_ctrl_write_reg(TEST_BLOCK, TEST_HOST_ID, TEST_REG_FULL, orig_full); + TEST_ASSERT_EQUAL_HEX8(orig_full, + regi2c_ctrl_read_reg(TEST_BLOCK, TEST_HOST_ID, TEST_REG_FULL)); + regi2c_ctrl_write_reg(TEST_BLOCK, TEST_HOST_ID, TEST_REG_MASK, orig_mask); + TEST_ASSERT_EQUAL_HEX8(orig_mask, + regi2c_ctrl_read_reg(TEST_BLOCK, TEST_HOST_ID, TEST_REG_MASK)); + +#if CONFIG_IDF_TARGET_ESP32 + // Disable APLL clock + periph_rtc_apll_release(); +#endif +} diff --git a/components/esp_hal_regi2c/test_apps/main/test_regi2c.h b/components/esp_hal_regi2c/test_apps/main/test_regi2c.h new file mode 100644 index 0000000000..2558126ca3 --- /dev/null +++ b/components/esp_hal_regi2c/test_apps/main/test_regi2c.h @@ -0,0 +1,84 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Target-specific regi2c test configuration + * + * For ESP32: test with the APLL regi2c block (I2C_APLL) + * For other targets: test with the SAR ADC calibration regi2c block (I2C_SAR_ADC / I2C_SARADC) + * + * Each target configuration selects: + * - A full 8-bit register for testing read/write + * - A partial bit-field register for testing read_mask/write_mask + */ + +#if CONFIG_IDF_TARGET_ESP32 + +#include "clk_ctrl_os.h" +#include "soc/regi2c_apll.h" +#define TEST_BLOCK I2C_APLL +#define TEST_HOST_ID I2C_APLL_HOSTID +/* I2C_APLL_DSDM0: register 9, bits [7:0] — full 8-bit SDM parameter */ +#define TEST_REG_FULL I2C_APLL_DSDM0 +/* I2C_APLL_OC_DVDD: register 6, bits [4:0] — 5-bit output voltage divider */ +#define TEST_REG_MASK I2C_APLL_OC_DVDD +#define TEST_REG_MASK_MSB I2C_APLL_OC_DVDD_MSB +#define TEST_REG_MASK_LSB I2C_APLL_OC_DVDD_LSB + +#elif CONFIG_IDF_TARGET_ESP32H4 + +#include "soc/regi2c_saradc.h" +#define TEST_BLOCK I2C_SARADC +#define TEST_HOST_ID I2C_SARADC_HOSTID +/* I2C_SARADC_SAR1_INIT_CODE_LSB: register 0, bits [7:0] — full 8-bit */ +#define TEST_REG_FULL I2C_SARADC_SAR1_INIT_CODE_LSB +/* I2C_SARADC_SAR1_INIT_CODE_MSB: register 1, bits [3:0] — 4-bit field */ +#define TEST_REG_MASK I2C_SARADC_SAR1_INIT_CODE_MSB +#define TEST_REG_MASK_MSB I2C_SARADC_SAR1_INIT_CODE_MSB_MSB +#define TEST_REG_MASK_LSB I2C_SARADC_SAR1_INIT_CODE_MSB_LSB + +#elif CONFIG_IDF_TARGET_ESP32H21 // TODO: IDF-11590 Replace with standard SARADC register field macros once they are defined in esp32h21/regi2c_saradc.h + +#include "soc/regi2c_saradc.h" +#define TEST_BLOCK I2C_SAR_ADC +#define TEST_HOST_ID I2C_SAR_ADC_HOSTID +/* + * ESP32-H21 regi2c_saradc.h only defines block and host ID without individual + * register field macros. Use the standard SARADC register layout directly: + * register 0 bits [7:0] = SAR1 initial code low byte + * register 1 bits [3:0] = SAR1 initial code high nibble + */ +#define TEST_REG_FULL 0 +#define TEST_REG_MASK 1 +#define TEST_REG_MASK_MSB 3 +#define TEST_REG_MASK_LSB 0 + +#else +/* Standard SARADC register naming */ + +#include "soc/regi2c_saradc.h" +#define TEST_BLOCK I2C_SAR_ADC +#define TEST_HOST_ID I2C_SAR_ADC_HOSTID +/* ADC_SAR1_INITIAL_CODE_LOW_ADDR: register 0x0, bits [7:0] — full 8-bit */ +#define TEST_REG_FULL ADC_SAR1_INITIAL_CODE_LOW_ADDR +/* ADC_SAR1_DREF_ADDR: register 0x2, bits [6:4] — 3-bit reference voltage */ +#define TEST_REG_MASK ADC_SAR1_DREF_ADDR +#define TEST_REG_MASK_MSB ADC_SAR1_DREF_ADDR_MSB +#define TEST_REG_MASK_LSB ADC_SAR1_DREF_ADDR_LSB + +#endif + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hal_regi2c/test_apps/pytest_regi2c.py b/components/esp_hal_regi2c/test_apps/pytest_regi2c.py new file mode 100644 index 0000000000..338f34fa43 --- /dev/null +++ b/components/esp_hal_regi2c/test_apps/pytest_regi2c.py @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 +import pytest +from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize + + +@pytest.mark.generic +@pytest.mark.parametrize( + 'config', + ['default'], + indirect=True, +) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) +def test_regi2c(dut: Dut) -> None: + dut.run_all_single_board_cases() diff --git a/components/esp_hal_regi2c/test_apps/sdkconfig.ci.default b/components/esp_hal_regi2c/test_apps/sdkconfig.ci.default new file mode 100644 index 0000000000..e69de29bb2 diff --git a/components/esp_hal_regi2c/test_apps/sdkconfig.defaults b/components/esp_hal_regi2c/test_apps/sdkconfig.defaults new file mode 100644 index 0000000000..fa8ac618b9 --- /dev/null +++ b/components/esp_hal_regi2c/test_apps/sdkconfig.defaults @@ -0,0 +1,2 @@ +CONFIG_FREERTOS_HZ=1000 +CONFIG_ESP_TASK_WDT_EN=n