From 818579b78dbfb286d37e6842163668a748d1ff66 Mon Sep 17 00:00:00 2001 From: "C.S.M" Date: Wed, 6 Aug 2025 18:03:27 +0800 Subject: [PATCH] test(i3c_master): Add multi test for i3c master --- components/esp_driver_i3c/i3c_master.c | 6 +- .../test_apps/i3c_test_apps/CMakeLists.txt | 4 +- .../i3c_test_apps/main/CMakeLists.txt | 5 +- .../i3c_test_apps/main/test_app_main.c | 2 +- .../i3c_test_apps/main/test_i3c_board.h | 27 ++ ...er_common.c => test_i3c_master_common.cpp} | 74 +++++- .../i3c_test_apps/main/test_i3c_multi.cpp | 247 ++++++++++++++++++ .../test_apps/i3c_test_apps/pytest_i3c.py | 14 + .../include/esp_private/periph_ctrl.h | 2 +- 9 files changed, 361 insertions(+), 20 deletions(-) create mode 100644 components/esp_driver_i3c/test_apps/i3c_test_apps/main/test_i3c_board.h rename components/esp_driver_i3c/test_apps/i3c_test_apps/main/{test_i3c_master_common.c => test_i3c_master_common.cpp} (57%) create mode 100644 components/esp_driver_i3c/test_apps/i3c_test_apps/main/test_i3c_multi.cpp diff --git a/components/esp_driver_i3c/i3c_master.c b/components/esp_driver_i3c/i3c_master.c index 06e18f035b..d53d2c6ad3 100644 --- a/components/esp_driver_i3c/i3c_master.c +++ b/components/esp_driver_i3c/i3c_master.c @@ -332,14 +332,14 @@ static esp_err_t i3c_pins_config(const i3c_master_bus_config_t *bus_config) { esp_err_t ret = ESP_OK; // SDA pin configurations - ESP_RETURN_ON_ERROR(gpio_set_level(bus_config->sda_io_num, 1), TAG, "i2c sda pin set level failed"); + ESP_RETURN_ON_ERROR(gpio_set_level(bus_config->sda_io_num, 1), TAG, "i3c sda pin set level failed"); gpio_input_enable(bus_config->sda_io_num); gpio_func_sel(bus_config->sda_io_num, PIN_FUNC_GPIO); gpio_matrix_output(bus_config->sda_io_num, i3c_master_periph_signal->sda_out_sig, 0, 0); gpio_matrix_input(bus_config->sda_io_num, i3c_master_periph_signal->sda_in_sig, 0); // SCL pin configurations - ESP_RETURN_ON_ERROR(gpio_set_level(bus_config->scl_io_num, 1), TAG, "i2c scl pin set level failed"); + ESP_RETURN_ON_ERROR(gpio_set_level(bus_config->scl_io_num, 1), TAG, "i3c scl pin set level failed"); gpio_input_enable(bus_config->scl_io_num); gpio_func_sel(bus_config->scl_io_num, PIN_FUNC_GPIO); gpio_matrix_output(bus_config->scl_io_num, i3c_master_periph_signal->scl_out_sig, 0, 0); @@ -445,7 +445,6 @@ static esp_err_t do_dma_transaction_handler(i3c_master_bus_handle_t bus_handle, { esp_err_t err = ESP_OK; bus_handle->cur_trans = trans; - printf("here, do dma\n"); portENTER_CRITICAL_SAFE(&bus_handle->spinlock); if (trans->scl_freq_hz > 400 * 1000) { @@ -509,7 +508,6 @@ static esp_err_t do_dma_transaction_handler(i3c_master_bus_handle_t bus_handle, portENTER_CRITICAL_SAFE(&bus_handle->spinlock); i3c_master_ll_start_transaction(bus_handle->hal.dev); portEXIT_CRITICAL_SAFE(&bus_handle->spinlock); - printf("here, start transaction\n"); return ESP_OK; } diff --git a/components/esp_driver_i3c/test_apps/i3c_test_apps/CMakeLists.txt b/components/esp_driver_i3c/test_apps/i3c_test_apps/CMakeLists.txt index 02b47e6f69..8341f9aa6d 100644 --- a/components/esp_driver_i3c/test_apps/i3c_test_apps/CMakeLists.txt +++ b/components/esp_driver_i3c/test_apps/i3c_test_apps/CMakeLists.txt @@ -27,5 +27,5 @@ endif() message(STATUS "Checking i3c registers are not read-write by half-word") include($ENV{IDF_PATH}/tools/ci/check_register_rw_half_word.cmake) -check_register_rw_half_word(SOC_MODULES "i3c_mst" "i3c_mst_mem" "hp_sys_clkrst" "lpperi" "lp_clkrst" - HAL_MODULES "i3c_master") +check_register_rw_half_word(SOC_MODULES "i3c_mst" "i3c_mst_mem" "hp_sys_clkrst" "i3c_slv" + HAL_MODULES "i3c_master" "i3c_slave") diff --git a/components/esp_driver_i3c/test_apps/i3c_test_apps/main/CMakeLists.txt b/components/esp_driver_i3c/test_apps/i3c_test_apps/main/CMakeLists.txt index a0e58cf55e..b5a62ea5d0 100644 --- a/components/esp_driver_i3c/test_apps/i3c_test_apps/main/CMakeLists.txt +++ b/components/esp_driver_i3c/test_apps/i3c_test_apps/main/CMakeLists.txt @@ -1,7 +1,8 @@ set(srcs "test_app_main.c" - "test_i3c_master_common.c" + "test_i3c_master_common.cpp" + "test_i3c_multi.cpp" ) idf_component_register(SRCS ${srcs} - PRIV_REQUIRES unity test_utils esp_driver_i3c + PRIV_REQUIRES unity test_utils esp_driver_i3c esp_driver_uart esp_driver_gpio WHOLE_ARCHIVE) diff --git a/components/esp_driver_i3c/test_apps/i3c_test_apps/main/test_app_main.c b/components/esp_driver_i3c/test_apps/i3c_test_apps/main/test_app_main.c index b9f22e5153..68c944844d 100644 --- a/components/esp_driver_i3c/test_apps/i3c_test_apps/main/test_app_main.c +++ b/components/esp_driver_i3c/test_apps/i3c_test_apps/main/test_app_main.c @@ -10,7 +10,7 @@ #include "esp_heap_caps.h" #include "sdkconfig.h" -#define LEAKS (100) +#define LEAKS (150) void setUp(void) { diff --git a/components/esp_driver_i3c/test_apps/i3c_test_apps/main/test_i3c_board.h b/components/esp_driver_i3c/test_apps/i3c_test_apps/main/test_i3c_board.h new file mode 100644 index 0000000000..eeacb6d37a --- /dev/null +++ b/components/esp_driver_i3c/test_apps/i3c_test_apps/main/test_i3c_board.h @@ -0,0 +1,27 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include "sdkconfig.h" +#include "soc/gpio_num.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define I3C_SLAVE_SCL_IO GPIO_NUM_32 /*! +#include +#include "sdkconfig.h" +#include "unity.h" +#include "esp_err.h" +#include "soc/clk_tree_defs.h" +#include "esp_private/periph_ctrl.h" +#include "driver/i3c_master.h" +#include "driver/i3c_master_i2c.h" +#include "hal/i3c_slave_ll.h" +#include "esp_log.h" +#include "test_utils.h" +#include "test_i3c_board.h" +#include "esp_private/gpio.h" +#include "driver/gpio.h" +#include "esp_heap_caps.h" +#include "soc/gpio_sig_map.h" +#include "soc/io_mux_reg.h" +#include "soc/i3c_slv_struct.h" +#include "soc/i3c_slv_reg.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +static const char TAG[] = "test-i3c"; + +static esp_err_t i3c_slave_pins_config(void) +{ + esp_err_t ret = ESP_OK; + // SDA pin configurations + gpio_input_enable(I3C_SLAVE_SDA_IO); + gpio_func_sel(I3C_SLAVE_SDA_IO, PIN_FUNC_GPIO); + gpio_matrix_output(I3C_SLAVE_SDA_IO, I3C_SLV_SDA_PAD_OUT_IDX, 0, 0); + gpio_matrix_input(I3C_SLAVE_SDA_IO, I3C_SLV_SDA_PAD_IN_IDX, 0); + + // SCL pin configurations + gpio_input_enable(I3C_SLAVE_SCL_IO); + gpio_func_sel(I3C_SLAVE_SCL_IO, PIN_FUNC_GPIO); + gpio_matrix_output(I3C_SLAVE_SCL_IO, I3C_SLV_SCL_PAD_OUT_IDX, 0, 0); + gpio_matrix_input(I3C_SLAVE_SCL_IO, I3C_SLV_SCL_PAD_IN_IDX, 0); + return ret; +} + +static void i3c_slave_init(void) +{ + PERIPH_RCC_ATOMIC() { + i3c_slave_ll_enable_bus_clock(&I3C_SLV, true); + i3c_slave_ll_reset_register(&I3C_SLV); + } + + i3c_slave_pins_config(); + i3c_slave_ll_config_static_address(&I3C_SLV, TEST_STATIC_ADDRESS); + i3c_slave_ll_enable_intr_mask(&I3C_SLV, I3C_SLAVE_LL_EVENT_INTR); + + i3c_slave_ll_unlock_register(&I3C_SLV, true); + i3c_slave_ll_set_transmit_fifo_threshold(&I3C_SLV, 1); + i3c_slave_ll_set_receive_fifo_threshold(&I3C_SLV, 1); +} + +static void i3c_i2c_slave_read_test(void) +{ + unity_wait_for_signal("i2c master init first"); + + uint8_t *temp_data = (uint8_t*)heap_caps_malloc(DATA_LENGTH, MALLOC_CAP_DEFAULT); + assert(temp_data); + + i3c_slave_init(); + + unity_send_signal("i2c slave init finish"); + + unity_wait_for_signal("master write"); + + i3c_slave_ll_read_data(&I3C_SLV, temp_data, DATA_LENGTH); + + ESP_LOG_BUFFER_HEX(TAG, temp_data, DATA_LENGTH); + + for (int i = 0; i < DATA_LENGTH; i++) { + TEST_ASSERT(temp_data[i] == i); + } + + unity_send_signal("ready to delete"); + free(temp_data); +} + +static void i3c_i2c_master_write_test(void) +{ + uint8_t data_wr[DATA_LENGTH] = { 0 }; + int i; + + i3c_master_bus_config_t i3c_mst_config = { + .sda_io_num = I3C_MASTER_SDA_IO, + .scl_io_num = I3C_MASTER_SCL_IO, + .clock_source = I3C_MASTER_CLK_SRC_DEFAULT, + .trans_queue_depth = 1, + .intr_priority = 0, + .flags = {0} + }; + i3c_master_bus_handle_t bus_handle; + gpio_pullup_en(I3C_MASTER_SCL_IO); + gpio_pullup_en(I3C_MASTER_SDA_IO); + + TEST_ESP_OK(i3c_new_master_bus(&i3c_mst_config, &bus_handle)); + + i3c_device_i2c_config_t dev_cfg = { + .device_address = TEST_STATIC_ADDRESS, + .scl_freq_hz = 100 * 1000 + }; + i3c_master_i2c_device_handle_t dev; + TEST_ESP_OK(i3c_master_bus_add_i2c_device(bus_handle, &dev_cfg, &dev)); + + unity_send_signal("i2c master init first"); + + unity_wait_for_signal("i2c slave init finish"); + + unity_send_signal("master write"); + for (i = 0; i < DATA_LENGTH; i++) { + data_wr[i] = i; + } + + ESP_LOG_BUFFER_HEX(TAG, data_wr, i); + + i3c_master_i2c_device_transmit(dev, data_wr, DATA_LENGTH, -1); + + unity_wait_for_signal("ready to delete"); + + TEST_ESP_OK(i3c_master_bus_rm_i2c_device(dev)); + TEST_ESP_OK(i3c_del_master_bus(bus_handle)); +} + +TEST_CASE_MULTIPLE_DEVICES("I3C-I2C master write slave test in fifo mode", "[i3c][test_env=generic_multi_device][timeout=150]", i3c_i2c_master_write_test, i3c_i2c_slave_read_test); + +static void i3c_i2c_master_read_slave_test(void) +{ + uint8_t data_rd[DATA_LENGTH] = {0}; + i3c_master_bus_config_t i3c_mst_config = { + .sda_io_num = I3C_MASTER_SDA_IO, + .scl_io_num = I3C_MASTER_SCL_IO, + .clock_source = I3C_MASTER_CLK_SRC_DEFAULT, + .trans_queue_depth = 1, + .intr_priority = 0, + .flags = {0} + }; + i3c_master_bus_handle_t bus_handle; + gpio_pullup_en(I3C_MASTER_SCL_IO); + gpio_pullup_en(I3C_MASTER_SDA_IO); + + TEST_ESP_OK(i3c_new_master_bus(&i3c_mst_config, &bus_handle)); + + i3c_device_i2c_config_t dev_cfg = { + .device_address = TEST_STATIC_ADDRESS, + .scl_freq_hz = 100 * 1000 + }; + i3c_master_i2c_device_handle_t dev; + TEST_ESP_OK(i3c_master_bus_add_i2c_device(bus_handle, &dev_cfg, &dev)); + + unity_wait_for_signal("i2c slave init finish"); + + i3c_master_i2c_device_receive(dev, data_rd, DATA_LENGTH, -1); + vTaskDelay(100 / portTICK_PERIOD_MS); + for (int i = 0; i < DATA_LENGTH; i++) { + printf("%x\n", data_rd[i]); + TEST_ASSERT(data_rd[i] == i); + } + unity_send_signal("ready to delete master read test"); + + TEST_ESP_OK(i3c_master_bus_rm_i2c_device(dev)); + TEST_ESP_OK(i3c_del_master_bus(bus_handle)); +} + +static void i3c_i2c_slave_write_buffer_test(void) +{ + + uint8_t data_wr[DATA_LENGTH]; + + i3c_slave_init(); + + for (int i = 0; i < DATA_LENGTH; i++) { + data_wr[i] = i; + } + + i3c_slave_ll_write_data(&I3C_SLV, data_wr, DATA_LENGTH); + + unity_send_signal("i2c slave init finish"); + + unity_wait_for_signal("ready to delete master read test"); +} + +TEST_CASE_MULTIPLE_DEVICES("I3C-I2C master read slave test in fifo mode", "[i3c][test_env=generic_multi_device][timeout=150]", i3c_i2c_master_read_slave_test, i3c_i2c_slave_write_buffer_test); + +static void i3c_i2c_master_write_via_dma_test(void) +{ + __attribute__((aligned(4))) uint8_t data_wr[DATA_LENGTH] = { 0 }; + int i; + + i3c_master_bus_config_t i3c_mst_config = { + .sda_io_num = I3C_MASTER_SDA_IO, + .scl_io_num = I3C_MASTER_SCL_IO, + .clock_source = I3C_MASTER_CLK_SRC_DEFAULT, + .trans_queue_depth = 1, + .intr_priority = 0, + .flags = {0} + }; + i3c_master_bus_handle_t bus_handle; + gpio_pullup_en(I3C_MASTER_SCL_IO); + gpio_pullup_en(I3C_MASTER_SDA_IO); + + TEST_ESP_OK(i3c_new_master_bus(&i3c_mst_config, &bus_handle)); + + i3c_device_i2c_config_t dev_cfg = { + .device_address = TEST_STATIC_ADDRESS, + .scl_freq_hz = 100 * 1000 + }; + i3c_master_i2c_device_handle_t dev; + TEST_ESP_OK(i3c_master_bus_add_i2c_device(bus_handle, &dev_cfg, &dev)); + + i3c_master_dma_config_t dma_config = { + .max_transfer_size = 50, + .dma_burst_size = 16, + }; + + i3c_master_bus_decorate_dma(bus_handle, &dma_config); + + unity_send_signal("i2c master init first"); + + unity_wait_for_signal("i2c slave init finish"); + + unity_send_signal("master write"); + for (i = 0; i < DATA_LENGTH; i++) { + data_wr[i] = i; + } + + ESP_LOG_BUFFER_HEX(TAG, data_wr, i); + i3c_master_i2c_device_transmit(dev, data_wr, DATA_LENGTH, -1); + + unity_wait_for_signal("ready to delete"); + + TEST_ESP_OK(i3c_master_bus_rm_i2c_device(dev)); + TEST_ESP_OK(i3c_master_bus_decorate_dma(bus_handle, NULL)); + TEST_ESP_OK(i3c_del_master_bus(bus_handle)); +} + +TEST_CASE_MULTIPLE_DEVICES("I3C-I2C master write slave test in dma mode", "[i3c][test_env=generic_multi_device][timeout=150]", i3c_i2c_master_write_via_dma_test, i3c_i2c_slave_read_test); diff --git a/components/esp_driver_i3c/test_apps/i3c_test_apps/pytest_i3c.py b/components/esp_driver_i3c/test_apps/i3c_test_apps/pytest_i3c.py index a7369b37ab..670f670b1f 100644 --- a/components/esp_driver_i3c/test_apps/i3c_test_apps/pytest_i3c.py +++ b/components/esp_driver_i3c/test_apps/i3c_test_apps/pytest_i3c.py @@ -18,3 +18,17 @@ from pytest_embedded_idf.utils import soc_filtered_targets @idf_parametrize('target', soc_filtered_targets('SOC_I3C_MASTER_SUPPORTED == 1'), indirect=['target']) def test_i3c(dut: Dut) -> None: dut.run_all_single_board_cases() + + +@pytest.mark.generic_multi_device +@pytest.mark.parametrize( + 'count, config', + [ + (2, 'release'), + (2, 'cache_safe'), + ], + indirect=True, +) +@idf_parametrize('target', soc_filtered_targets('SOC_I3C_MASTER_SUPPORTED == 1'), indirect=['target']) +def test_i3c_multi_device(case_tester) -> None: # type: ignore + case_tester.run_all_multi_dev_cases(reset=True) diff --git a/components/esp_hw_support/include/esp_private/periph_ctrl.h b/components/esp_hw_support/include/esp_private/periph_ctrl.h index a126750ba1..ea9910c315 100644 --- a/components/esp_hw_support/include/esp_private/periph_ctrl.h +++ b/components/esp_hw_support/include/esp_private/periph_ctrl.h @@ -84,7 +84,7 @@ void periph_rcc_exit(void); #ifdef __PERIPH_CTRL_ALLOW_LEGACY_API #define __PERIPH_CTRL_DEPRECATE_ATTR #else -#define __PERIPH_CTRL_DEPRECATE_ATTR __attribute__((deprecated("This function is not functional on "CONFIG_IDF_TARGET))) +#define __PERIPH_CTRL_DEPRECATE_ATTR __attribute__((deprecated("This function is not functional on " CONFIG_IDF_TARGET))) #endif /**