feat(regi2c): add test app for esp_hal_regi2c component

This commit is contained in:
Song Ruo Jing
2026-02-24 20:32:09 +08:00
parent 600bf5b6d7
commit 6e4354c83e
10 changed files with 256 additions and 0 deletions
@@ -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
@@ -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)
@@ -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 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- |
@@ -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)
@@ -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();
}
@@ -0,0 +1,91 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <stdint.h>
#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
}
@@ -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
@@ -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()
@@ -0,0 +1,2 @@
CONFIG_FREERTOS_HZ=1000
CONFIG_ESP_TASK_WDT_EN=n