Explorar o código

Merge branch 'ci/ulp_i2c_multi_device_tests' into 'master'

ci(lp_core): added multi-device test for lp core i2c

See merge request espressif/esp-idf!25278
Marius Vikhammer %!s(int64=2) %!d(string=hai) anos
pai
achega
78c4a7dcf2

+ 4 - 0
components/ulp/test_apps/lp_core/CMakeLists.txt

@@ -3,5 +3,9 @@ cmake_minimum_required(VERSION 3.16)
 
 list(PREPEND SDKCONFIG_DEFAULTS "$ENV{IDF_PATH}/tools/test_apps/configs/sdkconfig.debug_helpers" "sdkconfig.defaults")
 
+set(EXTRA_COMPONENT_DIRS
+    "$ENV{IDF_PATH}/tools/unit-test-app/components"
+)
+
 include($ENV{IDF_PATH}/tools/cmake/project.cmake)
 project(lp_core_test)

+ 6 - 2
components/ulp/test_apps/lp_core/main/CMakeLists.txt

@@ -1,16 +1,20 @@
-set(app_sources "test_app_main.c" "test_lp_core.c")
+set(app_sources "test_app_main.c" "test_lp_core.c" "test_lp_core_i2c.c")
+
 set(lp_core_sources         "lp_core/test_main.c")
 set(lp_core_sources_counter "lp_core/test_main_counter.c")
 set(lp_core_sources_set_timer_wakeup "lp_core/test_main_set_timer_wakeup.c")
 set(lp_core_sources_gpio "lp_core/test_main_gpio.c")
+set(lp_core_sources_i2c "lp_core/test_main_i2c.c")
 
 idf_component_register(SRCS ${app_sources}
                        INCLUDE_DIRS "lp_core"
-                       REQUIRES ulp unity esp_timer
+                       REQUIRES ulp unity esp_timer test_utils
                        WHOLE_ARCHIVE)
 
 set(lp_core_exp_dep_srcs ${app_sources})
+
 ulp_embed_binary(lp_core_test_app "${lp_core_sources}" "${lp_core_exp_dep_srcs}")
 ulp_embed_binary(lp_core_test_app_counter "${lp_core_sources_counter}" "${lp_core_exp_dep_srcs}")
 ulp_embed_binary(lp_core_test_app_set_timer_wakeup "${lp_core_sources_set_timer_wakeup}" "${lp_core_exp_dep_srcs}")
 ulp_embed_binary(lp_core_test_app_gpio "${lp_core_sources_gpio}" "${lp_core_exp_dep_srcs}")
+ulp_embed_binary(lp_core_test_app_i2c "${lp_core_sources_i2c}" "${lp_core_exp_dep_srcs}")

+ 35 - 0
components/ulp/test_apps/lp_core/main/lp_core/test_main_i2c.c

@@ -0,0 +1,35 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdint.h>
+#include "test_shared.h"
+#include "ulp_lp_core_utils.h"
+#include "ulp_lp_core_i2c.h"
+
+#define LP_I2C_TRANS_WAIT_FOREVER   -1
+
+volatile lp_core_test_command_reply_t read_test_reply = LP_CORE_COMMAND_INVALID;
+volatile lp_core_test_command_reply_t write_test_cmd = LP_CORE_COMMAND_INVALID;
+
+uint8_t data_rd[DATA_LENGTH] = {};
+uint8_t data_wr[DATA_LENGTH] = {};
+
+int main (void)
+{
+    lp_core_i2c_master_read_from_device(LP_I2C_NUM_0, I2C_SLAVE_ADDRESS, data_rd, RW_TEST_LENGTH, LP_I2C_TRANS_WAIT_FOREVER);
+    read_test_reply = LP_CORE_COMMAND_OK;
+
+    /* Wait for write command from main CPU */
+    while(write_test_cmd != LP_CORE_COMMAND_OK) {
+    }
+
+    lp_core_i2c_master_write_to_device(LP_I2C_NUM_0, I2C_SLAVE_ADDRESS, data_wr, RW_TEST_LENGTH, LP_I2C_TRANS_WAIT_FOREVER);
+
+    write_test_cmd = LP_CORE_COMMAND_NOK;
+
+    while(1) {
+    }
+}

+ 5 - 0
components/ulp/test_apps/lp_core/main/lp_core/test_shared.h

@@ -7,6 +7,11 @@
 
 #define XOR_MASK 0xDEADBEEF
 
+/* I2C test params */
+#define I2C_SLAVE_ADDRESS 0x28
+#define DATA_LENGTH 200
+#define RW_TEST_LENGTH       129  /*!<Data length for r/w test, any value from 0-DATA_LENGTH*/
+
 typedef enum{
     LP_CORE_READ_WRITE_TEST = 1,
     LP_CORE_DELAY_TEST,

+ 147 - 0
components/ulp/test_apps/lp_core/main/test_lp_core_i2c.c

@@ -0,0 +1,147 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "lp_core_test_app_i2c.h"
+#include "ulp_lp_core.h"
+#include "lp_core_i2c.h"
+
+#include "test_shared.h"
+#include "unity.h"
+#include "test_utils.h"
+#include "esp_log.h"
+
+#include "driver/i2c.h"
+
+extern const uint8_t lp_core_main_i2c_bin_start[] asm("_binary_lp_core_test_app_i2c_bin_start");
+extern const uint8_t lp_core_main_i2c_bin_end[]   asm("_binary_lp_core_test_app_i2c_bin_end");
+
+static const char* TAG = "lp_core_i2c_test";
+
+static void load_and_start_lp_core_firmware(ulp_lp_core_cfg_t* cfg, const uint8_t* firmware_start, const uint8_t* firmware_end)
+{
+    TEST_ASSERT(ulp_lp_core_load_binary(firmware_start,
+                        (firmware_end - firmware_start)) == ESP_OK);
+
+    TEST_ASSERT(ulp_lp_core_run(cfg) == ESP_OK);
+
+}
+
+
+#define I2C_SCL_IO     7                        /*!<gpio number for i2c clock, for C6 only GPIO7 is valid  */
+#define I2C_SDA_IO     6                        /*!<gpio number for i2c data, for C6 only GPIO6 is valid */
+#define I2C_SLAVE_NUM I2C_NUM_0                 /*!<I2C port number for slave dev */
+#define I2C_SLAVE_TX_BUF_LEN  (2*DATA_LENGTH)   /*!<I2C slave tx buffer size */
+#define I2C_SLAVE_RX_BUF_LEN  (2*DATA_LENGTH)   /*!<I2C slave rx buffer size */
+
+
+static uint8_t expected_master_write_data[DATA_LENGTH];
+static uint8_t expected_master_read_data[DATA_LENGTH];
+
+static void init_test_data(size_t len)
+{
+    /* Set up test data with some predictable patterns */
+    for (int i = 0; i < len; i++) {
+        expected_master_write_data[i] = i % 3;
+    }
+
+    for (int i = 0; i < len; i++) {
+        expected_master_read_data[i] = i/2;
+    }
+}
+
+static void i2c_master_write_read_test(void)
+{
+    init_test_data(DATA_LENGTH);
+
+    esp_err_t ret = ESP_OK;
+    /* Load ULP firmware and start the coprocessor */
+    ulp_lp_core_cfg_t cfg = {
+        .wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_HP_CPU,
+    };
+
+    const lp_core_i2c_cfg_t i2c_cfg = LP_CORE_I2C_DEFAULT_CONFIG();
+    ret = lp_core_i2c_master_init(LP_I2C_NUM_0, &i2c_cfg);
+    TEST_ASSERT_EQUAL(ret, ESP_OK);
+
+    unity_wait_for_signal("i2c slave init finish");
+
+    load_and_start_lp_core_firmware(&cfg, lp_core_main_i2c_bin_start, lp_core_main_i2c_bin_end);
+
+    /* Wait for ULP to finish reading */
+    while(ulp_read_test_reply == LP_CORE_COMMAND_INVALID) {
+    }
+
+    uint8_t *read_data = (uint8_t*)&ulp_data_rd;
+    ESP_LOGI(TAG, "Master read data:");
+    ESP_LOG_BUFFER_HEX(TAG, read_data, RW_TEST_LENGTH);
+    TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_master_read_data, read_data, RW_TEST_LENGTH);
+
+    uint8_t *wr_data = (uint8_t*)&ulp_data_wr;
+    for(int i = 0; i < RW_TEST_LENGTH; i++) {
+        wr_data[i] = expected_master_write_data[i];
+    }
+
+    unity_wait_for_signal("master write");
+
+    volatile lp_core_test_command_reply_t* write_test_cmd = (lp_core_test_command_reply_t*)&ulp_write_test_cmd;
+    *write_test_cmd = LP_CORE_COMMAND_OK;
+    unity_send_signal("slave read");
+
+    /* Wait for ULP to finish writing */
+    while( *write_test_cmd != LP_CORE_COMMAND_NOK) {
+    }
+}
+
+
+
+static i2c_config_t i2c_slave_init(void)
+{
+    i2c_config_t conf_slave = {
+        .mode = I2C_MODE_SLAVE,
+        .sda_io_num = I2C_SDA_IO,
+        .scl_io_num = I2C_SCL_IO,
+        .sda_pullup_en = GPIO_PULLUP_ENABLE,
+        .scl_pullup_en = GPIO_PULLUP_ENABLE,
+        .slave.addr_10bit_en = 0,
+        .slave.slave_addr = I2C_SLAVE_ADDRESS,
+    };
+    return conf_slave;
+}
+
+static void i2c_slave_read_write_test(void)
+{
+    init_test_data(DATA_LENGTH);
+
+    uint8_t *data_rd = (uint8_t *) malloc(DATA_LENGTH);
+    memset(data_rd, 0, DATA_LENGTH);
+    int size_rd;
+
+    i2c_config_t conf_slave = i2c_slave_init();
+    TEST_ESP_OK(i2c_param_config( I2C_SLAVE_NUM, &conf_slave));
+    TEST_ESP_OK(i2c_driver_install(I2C_SLAVE_NUM, I2C_MODE_SLAVE,
+                                   I2C_SLAVE_RX_BUF_LEN,
+                                   I2C_SLAVE_TX_BUF_LEN, 0));
+
+    unity_send_signal("i2c slave init finish");
+
+    size_rd = i2c_slave_write_buffer(I2C_SLAVE_NUM, expected_master_read_data, RW_TEST_LENGTH, 2000 / portTICK_PERIOD_MS);
+    ESP_LOG_BUFFER_HEX(TAG, expected_master_read_data, size_rd);
+
+    unity_send_signal("master write");
+    unity_wait_for_signal("slave read");
+
+    size_rd = i2c_slave_read_buffer( I2C_SLAVE_NUM, data_rd, RW_TEST_LENGTH, 10000 / portTICK_PERIOD_MS);
+    ESP_LOGI(TAG, "Slave read data:");
+    ESP_LOG_BUFFER_HEX(TAG, data_rd, size_rd);
+    TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_master_write_data, data_rd, RW_TEST_LENGTH);
+
+    free(data_rd);
+    i2c_driver_delete(I2C_SLAVE_NUM);
+}
+
+TEST_CASE_MULTIPLE_DEVICES("LP-Core I2C read and write test", "[lp_core][test_env=generic_multi_device][timeout=150]", i2c_master_write_read_test, i2c_slave_read_write_test);

+ 15 - 0
components/ulp/test_apps/lp_core/pytest_lp_core.py

@@ -9,3 +9,18 @@ from pytest_embedded import Dut
 @pytest.mark.generic
 def test_lp_core(dut: Dut) -> None:
     dut.run_all_single_board_cases()
+
+
+@pytest.mark.esp32c6
+@pytest.mark.generic_multi_device
+@pytest.mark.parametrize(
+    'count, config',
+    [
+        (2, 'defaults',),
+    ],
+    indirect=True
+)
+def test_lp_core_multi_device(case_tester) -> None:        # type: ignore
+    for case in case_tester.test_menu:
+        if case.attributes.get('test_env', 'generic_multi_device') == 'generic_multi_device':
+            case_tester.run_multi_dev_case(case=case, reset=True)

+ 0 - 0
components/ulp/test_apps/lp_core/sdkconfig.ci.defaults