test: move spi related unit-test into pytest app

This commit is contained in:
wanlei
2022-11-02 11:39:29 +08:00
parent 312bc6cb3a
commit f31ecbb42b
38 changed files with 503 additions and 80 deletions

View File

@@ -452,6 +452,14 @@ component_ut_pytest_esp32c2_adc:
- build_pytest_components_esp32c2
tags: [ esp32c2, adc ]
component_ut_pytest_esp32c2_generic_multi_device:
extends:
- .pytest_components_dir_template
- .rules:test:component_ut-esp32c2
needs:
- build_pytest_components_esp32c2
tags: [ esp32c2, generic_multi_device, xtal_40mhz ]
component_ut_pytest_esp32c2_xtal_26mhz:
extends:
- .pytest_components_dir_template

View File

@@ -1,7 +1,7 @@
idf_component_register(
SRC_DIRS .
PRIV_INCLUDE_DIRS include
PRIV_REQUIRES cmock test_utils test_driver_utils driver nvs_flash spi_flash esp_timer esp_adc esp_event esp_wifi
PRIV_REQUIRES cmock test_utils test_driver_utils driver nvs_flash esp_timer esp_adc esp_event esp_wifi
)
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")

View File

@@ -6,7 +6,7 @@
#include "unity.h"
#include "test_utils.h"
#include "param_test.h"
#include "test_spi_utils.h"
#include "esp_log.h"
#include "esp_timer.h"
#include "soc/soc_caps.h"
@@ -115,8 +115,6 @@ const sdio_test_config_t* default_config = &test_cfg_array[0];
#define TEST_SIZE (sizeof(test_cfg_array)/sizeof(sdio_test_config_t))
static const char MASTER_TAG[] = "master";
static const char SLAVE_TAG[] = "slave";
/*******************************************************************************
* Master

View File

@@ -0,0 +1,10 @@
# This is the project CMakeLists.txt file for the test subproject
cmake_minimum_required(VERSION 3.16)
set(EXTRA_COMPONENT_DIRS
"$ENV{IDF_PATH}/tools/unit-test-app/components"
"$ENV{IDF_PATH}/components/driver/test_apps/components"
)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(spi_master_test)

View File

@@ -0,0 +1,2 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- |

View File

@@ -0,0 +1,16 @@
set(srcs
"test_app_main.c"
"test_spi_master.c"
"test_spi_sio.c"
"test_spi_bus_lock.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}
PRIV_REQUIRES test_utils driver test_driver_utils spi_flash
WHOLE_ARCHIVE
)

View File

@@ -0,0 +1,49 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "unity.h"
#include "unity_test_utils.h"
#include "esp_heap_caps.h"
// iterator to load partition tables in `test spi bus lock, with flash` will lead memory not free
#define TEST_MEMORY_LEAK_THRESHOLD (250)
static size_t before_free_8bit;
static size_t before_free_32bit;
void setUp(void)
{
before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
}
void tearDown(void)
{
esp_reent_cleanup(); //clean up some of the newlib's lazy allocations
size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
printf("\n");
unity_utils_check_leak(before_free_8bit, after_free_8bit, "8BIT", TEST_MEMORY_LEAK_THRESHOLD);
unity_utils_check_leak(before_free_32bit, after_free_32bit, "32BIT", TEST_MEMORY_LEAK_THRESHOLD);
}
void app_main(void)
{
// ____ ____ ___ __ __ _
// / ___|| _ \_ _| | \/ | __ _ ___| |_ ___ _ __
// \___ \| |_) | | | |\/| |/ _` / __| __/ _ \ '__|
// ___) | __/| | | | | | (_| \__ \ || __/ |
// |____/|_| |___| |_| |_|\__,_|___/\__\___|_|
printf("\n");
printf(" ____ ____ ___ __ __ _ \n");
printf(" / ___|| _ \\_ _| | \\/ | __ _ ___| |_ ___ _ __ \n");
printf(" \\___ \\| |_) | | | |\\/| |/ _` / __| __/ _ \\ '__|\n");
printf(" ___) | __/| | | | | | (_| \\__ \\ || __/ | \n");
printf(" |____/|_| |___| |_| |_|\\__,_|___/\\__\\___|_| \n");
unity_run_menu();
}

View File

@@ -8,9 +8,9 @@
#include "driver/spi_master.h"
#include "driver/gpio.h"
#include "esp_flash_spi_init.h"
#include "test_utils.h"
#include "test_spi_utils.h"
#include "spi_flash_mmap.h"
#include "test/test_common_spi.h"
#include "unity.h"
@@ -283,14 +283,13 @@ static void test_bus_lock(bool test_flash)
TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST) );
}
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32C3, ESP32S3, ESP32C2)
//no runners
//IDF-5049
TEST_CASE("spi bus lock, with flash","[spi][test_env=UT_T1_ESP_FLASH]")
#if CONFIG_IDF_TARGET_ESP32
// no need this case in other target, only esp32 need buslock to split MSPI and GPSPI2 action
TEST_CASE("spi bus lock, with flash","[spi][test_env=external_flash]")
{
test_bus_lock(true);
}
#endif //!TEMPORARY_DISABLED_FOR_TARGETS(...)
#endif //CONFIG_IDF_TARGET_ESP32
TEST_CASE("spi bus lock","[spi]")

View File

@@ -7,21 +7,13 @@
Tests for the spi_master device driver
*/
#include <esp_types.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "unity.h"
#include "sdkconfig.h"
#include "driver/spi_master.h"
#include "driver/spi_slave.h"
#include "driver/gpio.h"
#include "soc/gpio_periph.h"
#include "soc/spi_periph.h"
#include "soc/soc_memory_layout.h"
#include "esp_private/cache_utils.h"
#include "esp_private/spi_common_internal.h"
@@ -29,7 +21,7 @@
#include "esp_heap_caps.h"
#include "esp_log.h"
#include "test_utils.h"
#include "test/test_common_spi.h"
#include "test_spi_utils.h"
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C6)
@@ -913,7 +905,7 @@ void test_cmd_addr(spi_slave_task_context_t *slave_context, bool lsb_first)
addr_got = addr_got >> (64 - addr_bits);
}
ESP_LOGI(SLAVE_TAG, "cmd_got: %04X, addr_got: %08X%08X", cmd_got, (uint32_t)(addr_got >> 32), (uint32_t)addr_got);
ESP_LOGI(SLAVE_TAG, "cmd_got: %" PRIX16 ", addr_got: %" PRIX32 "%" PRIX32, cmd_got, (uint32_t)(addr_got >> 32), (uint32_t)addr_got);
TEST_ASSERT_EQUAL_HEX16(cmd_expected, cmd_got);
if (addr_bits > 0) {
@@ -932,7 +924,7 @@ void test_cmd_addr(spi_slave_task_context_t *slave_context, bool lsb_first)
TEST_CASE("SPI master variable cmd & addr test", "[spi]")
{
spi_slave_task_context_t slave_context = {};
esp_err_t err = init_slave_context( &slave_context );
esp_err_t err = init_slave_context( &slave_context, TEST_SLAVE_HOST );
TEST_ASSERT( err == ESP_OK );
TaskHandle_t handle_slave;
xTaskCreate( spitest_slave_task, "spi_slave", 4096, &slave_context, 0, &handle_slave);
@@ -1301,7 +1293,7 @@ static void fd_slave(void)
TEST_ASSERT(spi_slave_free(SPI2_HOST) == ESP_OK);
}
TEST_CASE_MULTIPLE_DEVICES("SPI Master: FD, DMA, Master Single Direction Test", "[spi_ms][test_env=Example_SPI_Multi_device]", fd_master, fd_slave);
TEST_CASE_MULTIPLE_DEVICES("SPI Master: FD, DMA, Master Single Direction Test", "[spi_ms][test_env=generic_multi_device]", fd_master, fd_slave);
#endif //#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32) //TODO: IDF-3494
#endif //#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C2) //TODO: IDF-3494
@@ -1416,7 +1408,6 @@ TEST_CASE("spi_speed", "[spi]")
//release the bus
spi_device_release_bus(spi);
master_free_device_bus(spi);
speed_setup(&spi, !use_dma);
@@ -1437,6 +1428,7 @@ TEST_CASE("spi_speed", "[spi]")
//acquire the bus to send polling transactions faster
ret = spi_device_acquire_bus(spi, portMAX_DELAY);
TEST_ESP_OK(ret);
//record flight time by polling, without DMA
t_flight_num = 0;
for (int i = 0; i < TEST_TIMES; i++) {
@@ -1541,13 +1533,6 @@ void test_add_device_slave(void)
.spics_io_num = CS_REAL_DEV,
.queue_size = 3,
};
#if CONFIG_IDF_TARGET_ESP32
//now esp32 runners use SPI3 pin group to test gpio matrix together on CI.
bus_cfg.miso_io_num = SPI3_IOMUX_PIN_NUM_MISO;
bus_cfg.mosi_io_num = SPI3_IOMUX_PIN_NUM_MOSI;
bus_cfg.sclk_io_num = SPI3_IOMUX_PIN_NUM_CLK;
slvcfg.spics_io_num = SPI3_IOMUX_PIN_NUM_CS;
#endif
TEST_ESP_OK(spi_slave_initialize(TEST_SPI_HOST, &bus_cfg, &slvcfg, SPI_DMA_CH_AUTO));
spi_slave_transaction_t slave_trans = {};
@@ -1573,5 +1558,5 @@ void test_add_device_slave(void)
spi_bus_free(TEST_SPI_HOST);
}
TEST_CASE_MULTIPLE_DEVICES("SPI_Master:Test multiple devices", "[spi_ms][test_env=Example_SPI_Multi_device]", test_add_device_master, test_add_device_slave);
TEST_CASE_MULTIPLE_DEVICES("SPI_Master:Test multiple devices", "[spi_ms][test_env=generic_multi_device]", test_add_device_master, test_add_device_slave);
#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32C6)

View File

@@ -24,7 +24,7 @@
#include "esp_log.h"
#include "soc/spi_periph.h"
#include "test_utils.h"
#include "test/test_common_spi.h"
#include "test_spi_utils.h"
#include "soc/gpio_periph.h"
#include "hal/spi_ll.h"
@@ -269,14 +269,6 @@ void test_sio_slave_emulate(bool sio_master_in)
spi_bus_config_t bus_cfg = SPI_BUS_TEST_DEFAULT_CONFIG();
spi_slave_interface_config_t slv_cfg = SPI_SLAVE_TEST_DEFAULT_CONFIG();
#if CONFIG_IDF_TARGET_ESP32
// esp32 use different pin for slave in current runner
bus_cfg.mosi_io_num = spi_periph_signal[TEST_SLAVE_HOST].spid_iomux_pin;
bus_cfg.miso_io_num = spi_periph_signal[TEST_SLAVE_HOST].spiq_iomux_pin;
bus_cfg.sclk_io_num = spi_periph_signal[TEST_SLAVE_HOST].spiclk_iomux_pin;
slv_cfg.spics_io_num = spi_periph_signal[TEST_SLAVE_HOST].spics0_iomux_pin;
#endif
TEST_ESP_OK(spi_slave_initialize(TEST_SLAVE_HOST, &bus_cfg, &slv_cfg, SPI_DMA_CH_AUTO));
printf("CS:CLK:MO:MI: %d\t%d\t%d\t%d\n", slv_cfg.spics_io_num, bus_cfg.sclk_io_num, bus_cfg.mosi_io_num, bus_cfg.miso_io_num);
@@ -334,5 +326,5 @@ void test_slave_run(void)
test_sio_slave_emulate(true);
}
TEST_CASE_MULTIPLE_DEVICES("SPI_Master:Test_SIO_Mode_Multi_Board", "[spi_ms][test_env=Example_SPI_Multi_device]", test_master_run, test_slave_run);
TEST_CASE_MULTIPLE_DEVICES("SPI_Master:Test_SIO_Mode_Multi_Board", "[spi_ms][test_env=generic_multi_device]", test_master_run, test_slave_run);
#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32C6)

View File

@@ -0,0 +1,8 @@
# Special partition table for unit test app
#
# Name, Type, SubType, Offset, Size, Flags
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
factory, 0, 0, 0x20000, 0x260000
# flash_test partition used for SPI flash tests, WL FAT tests, and SPIFFS tests
flash_test, data, fat, , 528K
1 # Special partition table for unit test app
2 #
3 # Name, Type, SubType, Offset, Size, Flags
4 # Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
5 factory, 0, 0, 0x20000, 0x260000
6 # flash_test partition used for SPI flash tests, WL FAT tests, and SPIFFS tests
7 flash_test, data, fat, , 528K

View File

@@ -0,0 +1,34 @@
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
import pytest
# If `test_env` is define, should not run on generic runner
@pytest.mark.supported_targets
@pytest.mark.generic
def test_master_single_dev(case_tester) -> None: # type: ignore
for case in case_tester.test_menu:
if 'test_env' in case.attributes:
continue
case_tester.run_normal_case(case=case, reset=True)
# Job for test_env `external_flash` just for esp32 only
@pytest.mark.esp32
@pytest.mark.flash_mutli
def test_master_esp_flash(case_tester) -> None: # type: ignore
for case in case_tester.test_menu:
# test case `spi_bus_lock_with_flash` use difference test env
if case.attributes.get('test_env') == 'external_flash':
case_tester.run_normal_case(case=case, reset=True)
# if `test_env` not defined, will run on `generic_multi_device` by default
@pytest.mark.supported_targets
@pytest.mark.generic_multi_device
@pytest.mark.parametrize('count', [2,], indirect=True)
def test_master_multi_dev(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)

View File

@@ -0,0 +1,2 @@
CONFIG_FREERTOS_HZ=1000
CONFIG_ESP_TASK_WDT=n

View File

@@ -0,0 +1,8 @@
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
CONFIG_XTAL_FREQ_AUTO=y
CONFIG_SPI_FLASH_SHARE_SPI1_BUS=y
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partition_table_esp32_flash.csv"
CONFIG_PARTITION_TABLE_FILENAME="partition_table_esp32_flash.csv"
CONFIG_PARTITION_TABLE_OFFSET=0x8000

View File

@@ -0,0 +1,2 @@
# test_case `spi_speed` need freq 240M
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y

View File

@@ -0,0 +1,2 @@
# test_case `spi_speed` need freq 240M
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y

View File

@@ -0,0 +1,10 @@
# This is the project CMakeLists.txt file for the test subproject
cmake_minimum_required(VERSION 3.16)
set(EXTRA_COMPONENT_DIRS
"$ENV{IDF_PATH}/tools/unit-test-app/components"
"$ENV{IDF_PATH}/components/driver/test_apps/components"
)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(spi_param_test)

View File

@@ -0,0 +1,2 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- |

View File

@@ -0,0 +1,14 @@
set(srcs
"test_app_main.c"
"test_spi_param.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}
PRIV_REQUIRES test_utils driver test_driver_utils
WHOLE_ARCHIVE
)

View File

@@ -0,0 +1,48 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "unity.h"
#include "unity_test_utils.h"
#include "esp_heap_caps.h"
#define TEST_MEMORY_LEAK_THRESHOLD (150)
static size_t before_free_8bit;
static size_t before_free_32bit;
void setUp(void)
{
before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
}
void tearDown(void)
{
esp_reent_cleanup(); //clean up some of the newlib's lazy allocations
size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
printf("\n");
unity_utils_check_leak(before_free_8bit, after_free_8bit, "8BIT", TEST_MEMORY_LEAK_THRESHOLD);
unity_utils_check_leak(before_free_32bit, after_free_32bit, "32BIT", TEST_MEMORY_LEAK_THRESHOLD);
}
void app_main(void)
{
// ____ ____ ___ ____
// / ___|| _ \_ _| | _ \ __ _ _ __ __ _ _ __ ___
// \___ \| |_) | | | |_) / _` | '__/ _` | '_ ` _ `.
// ___) | __/| | | __/ (_| | | | (_| | | | | | |
// |____/|_| |___| |_| \__,_|_| \__,_|_| |_| |_|
printf("\n");
printf(" ____ ____ ___ ____ \n");
printf(" / ___|| _ \\_ _| | _ \\ __ _ _ __ __ _ _ __ ___ \n");
printf(" \\___ \\| |_) | | | |_) / _` | '__/ _` | '_ ` _ \\ \n");
printf(" ___) | __/| | | __/ (_| | | | (_| | | | | | |\n");
printf(" |____/|_| |___| |_| \\__,_|_| \\__,_|_| |_| |_|\n");
unity_run_menu();
}

View File

@@ -7,7 +7,8 @@
#include "esp_attr.h"
#include "soc/spi_periph.h"
#include "sdkconfig.h"
#include "test/test_common_spi.h"
#include "test_utils.h"
#include "test_spi_utils.h"
#include "driver/spi_master.h"
#include "driver/spi_slave.h"
@@ -44,7 +45,7 @@ static void local_test_init(void** arg)
spitest_context_t* context = (spitest_context_t*)*arg;
TEST_ASSERT(context!=NULL);
context->slave_context = (spi_slave_task_context_t){};
esp_err_t err = init_slave_context( &context->slave_context);
esp_err_t err = init_slave_context( &context->slave_context, TEST_SLAVE_HOST);
TEST_ASSERT(err == ESP_OK);
xTaskCreate(spitest_slave_task, "spi_slave", 4096, &context->slave_context, 0, &context->handle_slave);
@@ -211,7 +212,7 @@ static void local_test_loop(const void* arg1, void* arg2)
}
if (failed) {
ESP_LOGI(SLAVE_TAG, "slave_recv_len: %d", rcv_len);
ESP_LOGI(SLAVE_TAG, "slave_recv_len: %" PRIu32, rcv_len);
spitest_master_print_data(t, len);
ESP_LOG_BUFFER_HEX("slave tx", slave_trans.tx_buffer, len);
@@ -659,9 +660,12 @@ static const ptest_func_t slave_test_func = {
.def_param = spitest_def_param,
};
//temporarily close mass data print to avoid pytest run too busy to timeout
#define TEST_LOG_DBUG false
#define TEST_SPI_MASTER_SLAVE(name, param_group, extra_tag) \
PARAM_GROUP_DECLARE(name, param_group) \
TEST_MASTER_SLAVE(name, param_group, "[spi_ms][test_env=Example_SPI_Multi_device][timeout=120]"extra_tag, &master_test_func, &slave_test_func)
TEST_MASTER_SLAVE(name, param_group, "[spi_ms][test_env=generic_multi_device][timeout=120]"extra_tag, &master_test_func, &slave_test_func)
/************ Master Code ***********************************************/
static void test_master_init(void** arg)
@@ -671,8 +675,9 @@ static void test_master_init(void** arg)
spitest_context_t* context = *arg;
TEST_ASSERT(context!=NULL);
context->slave_context = (spi_slave_task_context_t){};
esp_err_t err = init_slave_context(&context->slave_context);
esp_err_t err = init_slave_context(&context->slave_context, TEST_SPI_HOST);
TEST_ASSERT(err == ESP_OK);
unity_send_signal("Master ready");
}
static void test_master_deinit(void* arg)
@@ -685,13 +690,10 @@ static void test_master_start(spi_device_handle_t *spi, int freq, const spitest_
{
//master config
spi_bus_config_t buspset=SPI_BUS_TEST_DEFAULT_CONFIG();
buspset.miso_io_num = MASTER_IOMUX_PIN_MISO;
buspset.mosi_io_num = MASTER_IOMUX_PIN_MOSI;
buspset.sclk_io_num = MASTER_IOMUX_PIN_SCLK;
//this does nothing, but avoid the driver from using native pins
if (!pset->master_iomux) buspset.quadhd_io_num = UNCONNECTED_PIN;
spi_device_interface_config_t devpset=SPI_DEVICE_TEST_DEFAULT_CONFIG();
devpset.spics_io_num = MASTER_IOMUX_PIN_CS;
devpset.spics_io_num = SPI2_IOMUX_PIN_NUM_CS;
devpset.mode = pset->mode;
const int cs_pretrans_max = 15;
if (pset->dup==HALF_DUPLEX_MISO) {
@@ -757,7 +759,7 @@ static void test_master_loop(const void *arg1, void* arg2)
ESP_LOGI(MASTER_TAG, "==============> %dk", freq/1000);
test_master_start(&spi, freq, test_cfg, context);
unity_wait_for_signal("slave ready");
unity_wait_for_signal("Slave ready");
for( int j= 0; j < test_cfg->test_size; j ++ ) {
//wait for both master and slave end
@@ -768,11 +770,15 @@ static void test_master_loop(const void *arg1, void* arg2)
spi_transaction_t *t = &context->master_trans[j];
TEST_ESP_OK (spi_device_transmit(spi, t) );
int len = get_trans_len(test_cfg->dup, t);
spitest_master_print_data(t, len);
if(TEST_LOG_DBUG){
spitest_master_print_data(t, len);
}
size_t rcv_len;
slave_rxdata_t *rcv_data = xRingbufferReceive( context->slave_context.data_received, &rcv_len, portMAX_DELAY );
spitest_slave_print_data(rcv_data, false);
if(TEST_LOG_DBUG){
spitest_slave_print_data(rcv_data, false);
}
//check result
bool check_master_data = (test_cfg->dup != HALF_DUPLEX_MOSI &&
@@ -800,9 +806,10 @@ static void test_slave_init(void** arg)
spitest_context_t* context = (spitest_context_t*)*arg;
TEST_ASSERT(context!=NULL);
context->slave_context = (spi_slave_task_context_t){};
esp_err_t err = init_slave_context( &context->slave_context );
esp_err_t err = init_slave_context( &context->slave_context, TEST_SPI_HOST);
TEST_ASSERT( err == ESP_OK );
unity_wait_for_signal("Master ready");
xTaskCreate( spitest_slave_task, "spi_slave", 4096, &context->slave_context, 0, &context->handle_slave);
}
@@ -819,19 +826,16 @@ static void timing_slave_start(int speed, const spitest_param_set_t* pset, spite
{
//slave config
spi_bus_config_t slv_buscfg=SPI_BUS_TEST_DEFAULT_CONFIG();
slv_buscfg.miso_io_num = SLAVE_IOMUX_PIN_MISO;
slv_buscfg.mosi_io_num = SLAVE_IOMUX_PIN_MOSI;
slv_buscfg.sclk_io_num = SLAVE_IOMUX_PIN_SCLK;
//this does nothing, but avoid the driver from using native pins
if (!pset->slave_iomux) slv_buscfg.quadhd_io_num = UNCONNECTED_PIN;
spi_slave_interface_config_t slvcfg=SPI_SLAVE_TEST_DEFAULT_CONFIG();
slvcfg.spics_io_num = SLAVE_IOMUX_PIN_CS;
slvcfg.spics_io_num = SPI2_IOMUX_PIN_NUM_CS;
slvcfg.mode = pset->mode;
//Enable pull-ups on SPI lines so we don't detect rogue pulses when no master is connected.
slave_pull_up(&slv_buscfg, slvcfg.spics_io_num);
int slave_dma_chan = (pset->slave_dma_chan == 0) ? 0 : SPI_DMA_CH_AUTO;
TEST_ESP_OK(spi_slave_initialize(TEST_SLAVE_HOST, &slv_buscfg, &slvcfg, slave_dma_chan));
TEST_ESP_OK(spi_slave_initialize(TEST_SPI_HOST, &slv_buscfg, &slvcfg, slave_dma_chan));
//prepare data for the master
for (int i = 0; i < pset->test_size; i++) {
@@ -867,7 +871,7 @@ static void test_slave_loop(const void *arg1, void* arg2)
}
vTaskDelay(50/portTICK_PERIOD_MS);
unity_send_signal("slave ready");
unity_send_signal("Slave ready");
for( int i= 0; i < pset->test_size; i ++ ) {
//wait for both master and slave end
@@ -877,11 +881,15 @@ static void test_slave_loop(const void *arg1, void* arg2)
spi_transaction_t *t = &context->master_trans[i];
int len = get_trans_len(pset->dup, t);
spitest_master_print_data(t, FULL_DUPLEX);
if(TEST_LOG_DBUG){
spitest_master_print_data(t, FULL_DUPLEX);
}
size_t rcv_len;
slave_rxdata_t *rcv_data = xRingbufferReceive( context->slave_context.data_received, &rcv_len, portMAX_DELAY );
spitest_slave_print_data(rcv_data, true);
if(TEST_LOG_DBUG){
spitest_slave_print_data(rcv_data, true);
}
//check result
const bool check_master_data = false;
@@ -891,7 +899,7 @@ static void test_slave_loop(const void *arg1, void* arg2)
//clean
vRingbufferReturnItem( context->slave_context.data_received, rcv_data );
}
TEST_ASSERT(spi_slave_free(TEST_SLAVE_HOST) == ESP_OK);
TEST_ASSERT(spi_slave_free(TEST_SPI_HOST) == ESP_OK);
}
}

View File

@@ -0,0 +1,24 @@
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
import pytest
# If `test_env` is define, should not run on generic runner
@pytest.mark.supported_targets
@pytest.mark.generic
def test_param_single_dev(case_tester) -> None: # type: ignore
for case in case_tester.test_menu:
if 'test_env' in case.attributes:
continue
case_tester.run_normal_case(case=case, reset=True)
# if `test_env` not defined, will run on `generic_multi_device` by default
@pytest.mark.supported_targets
@pytest.mark.generic_multi_device
@pytest.mark.parametrize('count', [2,], indirect=True)
def test_param_multi_dev(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)

View File

@@ -0,0 +1,2 @@
CONFIG_FREERTOS_HZ=1000
CONFIG_ESP_TASK_WDT=n

View File

@@ -0,0 +1,10 @@
# This is the project CMakeLists.txt file for the test subproject
cmake_minimum_required(VERSION 3.16)
set(EXTRA_COMPONENT_DIRS
"$ENV{IDF_PATH}/tools/unit-test-app/components"
"$ENV{IDF_PATH}/components/driver/test_apps/components"
)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(spi_slave_test)

View File

@@ -0,0 +1,2 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- |

View File

@@ -0,0 +1,14 @@
set(srcs
"test_app_main.c"
"test_spi_slave.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}
PRIV_REQUIRES test_utils driver test_driver_utils
WHOLE_ARCHIVE
)

View File

@@ -0,0 +1,48 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "unity.h"
#include "unity_test_utils.h"
#include "esp_heap_caps.h"
#define TEST_MEMORY_LEAK_THRESHOLD (100)
static size_t before_free_8bit;
static size_t before_free_32bit;
void setUp(void)
{
before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
}
void tearDown(void)
{
esp_reent_cleanup(); //clean up some of the newlib's lazy allocations
size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
printf("\n");
unity_utils_check_leak(before_free_8bit, after_free_8bit, "8BIT", TEST_MEMORY_LEAK_THRESHOLD);
unity_utils_check_leak(before_free_32bit, after_free_32bit, "32BIT", TEST_MEMORY_LEAK_THRESHOLD);
}
void app_main(void)
{
// ____ ____ ___ ____ _
// / ___|| _ \_ _| / ___|| | __ ___ _____
// \___ \| |_) | | \___ \| |/ _` \ \ / / _ `
// ___) | __/| | ___) | | (_| |\ V / __/
// |____/|_| |___| |____/|_|\__,_| \_/ \___|
printf("\n");
printf(" ____ ____ ___ ____ _ \n");
printf(" / ___|| _ \\_ _| / ___|| | __ ___ _____ \n");
printf(" \\___ \\| |_) | | \\___ \\| |/ _` \\ \\ / / _ \\\n");
printf(" ___) | __/| | ___) | | (_| |\\ V / __/\n");
printf(" |____/|_| |___| |____/|_|\\__,_| \\_/ \\___|\n");
unity_run_menu();
}

View File

@@ -10,7 +10,8 @@
#include <string.h>
#include "sdkconfig.h"
#include "unity.h"
#include "test/test_common_spi.h"
#include "test_utils.h"
#include "test_spi_utils.h"
#include "driver/spi_master.h"
#include "driver/spi_slave.h"
#include "driver/gpio.h"
@@ -382,7 +383,7 @@ static void unaligned_test_slave(void)
TEST_ASSERT(spi_slave_free(TEST_SPI_HOST) == ESP_OK);
}
TEST_CASE_MULTIPLE_DEVICES("SPI_Slave_Unaligned_Test", "[spi_ms][test_env=Example_SPI_Multi_device][timeout=120]", unaligned_test_master, unaligned_test_slave);
TEST_CASE_MULTIPLE_DEVICES("SPI_Slave_Unaligned_Test", "[spi_ms][test_env=generic_multi_device][timeout=120]", unaligned_test_master, unaligned_test_slave);
#endif //#if (TEST_SPI_PERIPH_NUM == 1)
#endif //!TEMPORARY_DISABLED_FOR_TARGETS(...)

View File

@@ -0,0 +1,24 @@
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
import pytest
# If `test_env` is define, should not run on generic runner
@pytest.mark.supported_targets
@pytest.mark.generic
def test_slave_single_dev(case_tester) -> None: # type: ignore
for case in case_tester.test_menu:
if 'test_env' in case.attributes:
continue
case_tester.run_normal_case(case=case, reset=True)
# if `test_env` not defined, will run on `generic_multi_device` by default
@pytest.mark.supported_targets
@pytest.mark.generic_multi_device
@pytest.mark.parametrize('count', [2,], indirect=True)
def test_slave_multi_dev(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)

View File

@@ -0,0 +1,2 @@
CONFIG_FREERTOS_HZ=1000
CONFIG_ESP_TASK_WDT=n

View File

@@ -0,0 +1,10 @@
# This is the project CMakeLists.txt file for the test subproject
cmake_minimum_required(VERSION 3.16)
set(EXTRA_COMPONENT_DIRS
"$ENV{IDF_PATH}/tools/unit-test-app/components"
"$ENV{IDF_PATH}/components/driver/test_apps/components"
)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(spi_slave_hd_test)

View File

@@ -0,0 +1,2 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- |

View File

@@ -0,0 +1,14 @@
set(srcs
"test_app_main.c"
"test_spi_slave_hd.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}
PRIV_REQUIRES test_utils driver test_driver_utils esp_serial_slave_link sdmmc
WHOLE_ARCHIVE
)

View File

@@ -0,0 +1,48 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "unity.h"
#include "unity_test_utils.h"
#include "esp_heap_caps.h"
#define TEST_MEMORY_LEAK_THRESHOLD (200)
static size_t before_free_8bit;
static size_t before_free_32bit;
void setUp(void)
{
before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
}
void tearDown(void)
{
esp_reent_cleanup(); //clean up some of the newlib's lazy allocations
size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
printf("\n");
unity_utils_check_leak(before_free_8bit, after_free_8bit, "8BIT", TEST_MEMORY_LEAK_THRESHOLD);
unity_utils_check_leak(before_free_32bit, after_free_32bit, "32BIT", TEST_MEMORY_LEAK_THRESHOLD);
}
void app_main(void)
{
// ____ ____ ___ ____ _ _ _ ____
// / ___|| _ \_ _| / ___|| | __ ___ _____ | | | | _ `.
// \___ \| |_) | | \___ \| |/ _` \ \ / / _ \ | |_| | | | |
// ___) | __/| | ___) | | (_| |\ V / __/ | _ | |_| |
// |____/|_| |___| |____/|_|\__,_| \_/ \___| |_| |_|____/
printf("\n");
printf(" ____ ____ ___ ____ _ _ _ ____ \n");
printf(" / ___|| _ \\_ _| / ___|| | __ ___ _____ | | | | _ \\ \n");
printf(" \\___ \\| |_) | | \\___ \\| |/ _` \\ \\ / / _ \\ | |_| | | | |\n");
printf(" ___) | __/| | ___) | | (_| |\\ V / __/ | _ | |_| |\n");
printf(" |____/|_| |___| |____/|_|\\__,_| \\_/ \\___| |_| |_|____/ \n");
unity_run_menu();
}

View File

@@ -8,15 +8,10 @@
*/
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "unity.h"
#include "test_utils.h"
#include "test_spi_utils.h"
#include "soc/spi_periph.h"
#include "driver/spi_master.h"
#include "esp_serial_slave_link/essl_spi.h"
#include "test/test_common_spi.h"
#if SOC_SPI_SUPPORT_SLAVE_HD_VER2
#include "driver/spi_slave_hd.h"
@@ -631,11 +626,12 @@ static void hd_master(void)
WORD_ALIGNED_ATTR uint8_t *master_recv_buf = calloc(1, send_buf_size * 2);
//This buffer is used for 2-board test and should be assigned totally the same as the ``hd_slave`` does.
WORD_ALIGNED_ATTR uint8_t *slave_send_buf = malloc(send_buf_size * 2);
get_tx_buffer(199, master_send_buf, slave_send_buf, send_buf_size);
get_tx_buffer(199, master_send_buf, slave_send_buf, send_buf_size * 2);
//This is the same as the ``hd_slave`` sets.
int trans_len[] = {5, send_buf_size};
unity_send_signal("master ready");
unity_wait_for_signal("slave ready");
essl_spi_wrdma(spi, master_send_buf, send_buf_size, -1, 0);
@@ -676,13 +672,14 @@ static void hd_slave(void)
};
TEST_ESP_OK(spi_slave_hd_init(TEST_SLAVE_HOST, &bus_cfg, &slave_hd_cfg));
unity_wait_for_signal("master ready");
const int send_buf_size = 1024;
WORD_ALIGNED_ATTR uint8_t *slave_send_buf = malloc(send_buf_size * 2);
WORD_ALIGNED_ATTR uint8_t *slave_recv_buf = calloc(1, send_buf_size * 2);
//This buffer is used for 2-board test and should be assigned totally the same as the ``hd_master`` does.
WORD_ALIGNED_ATTR uint8_t *master_send_buf = malloc(send_buf_size * 2);
get_tx_buffer(199, master_send_buf, slave_send_buf, send_buf_size);
get_tx_buffer(199, master_send_buf, slave_send_buf, send_buf_size * 2);
//make the first transaction shorter than the actual trans length of the master, so that the second one will be loaded while the master is still doing the first transaction.
int trans_len[] = {5, send_buf_size};
@@ -739,7 +736,7 @@ static void hd_slave(void)
spi_slave_hd_deinit(TEST_SLAVE_HOST);
}
TEST_CASE_MULTIPLE_DEVICES("SPI Slave HD: segment mode, master sends too long", "[spi_ms][test_env=Example_SPI_Multi_device]", hd_master, hd_slave);
TEST_CASE_MULTIPLE_DEVICES("SPI Slave HD: segment mode, master sends too long", "[spi_ms][test_env=generic_multi_device]", hd_master, hd_slave);
#endif //#if (TEST_SPI_PERIPH_NUM == 1)
/**
@@ -776,6 +773,7 @@ static void hd_master_quad(void){
WORD_ALIGNED_ATTR uint8_t *slave_send_buf = heap_caps_malloc(BUF_SIZE, MALLOC_CAP_DMA);
get_tx_buffer(199, master_send_buf, slave_send_buf, BUF_SIZE);
unity_send_signal("Master ready");
unity_wait_for_signal("slave ready");
essl_spi_wrdma(spi, master_send_buf, BUF_SIZE / 2, -1, SPI_TRANS_MODE_QIO);
@@ -851,6 +849,7 @@ static void hd_slave_quad(void){
},
};
unity_wait_for_signal("Master ready");
for (int i = 0; i < 2; i ++) {
TEST_ESP_OK(spi_slave_hd_queue_trans(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_RX, &slave_trans[i], portMAX_DELAY));
unity_send_signal("slave ready");
@@ -880,7 +879,7 @@ static void hd_slave_quad(void){
spi_slave_hd_deinit(TEST_SLAVE_HOST);
}
TEST_CASE_MULTIPLE_DEVICES("SPI quad hd test ", "[spi_ms][test_env=Example_SPI_Quad_Multi_device]", hd_master_quad, hd_slave_quad);
TEST_CASE_MULTIPLE_DEVICES("SPI quad hd test ", "[spi_ms][test_env=generic_multi_device]", hd_master_quad, hd_slave_quad);
#endif // #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2)

View File

@@ -0,0 +1,24 @@
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
import pytest
# If `test_env` is define, should not run on generic runner
@pytest.mark.supported_targets
@pytest.mark.generic
def test_slave_hd_single_dev(case_tester) -> None: # type: ignore
for case in case_tester.test_menu:
if 'test_env' in case.attributes:
continue
case_tester.run_normal_case(case=case, reset=True)
# if `test_env` not defined, will run on `generic_multi_device` by default
@pytest.mark.supported_targets
@pytest.mark.generic_multi_device
@pytest.mark.parametrize('count', [2,], indirect=True)
def test_slave_hd_multi_dev(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)

View File

@@ -0,0 +1,2 @@
CONFIG_FREERTOS_HZ=1000
CONFIG_ESP_TASK_WDT=n

View File

@@ -95,7 +95,7 @@ class NormalCaseTester(BaseTester):
for retry in range(self.retry_times):
self.dut.write(str(case.index))
try:
self.dut.expect('Running {}...'.format(case.name), timeout=1)
self.dut.expect_exact('Running {}...'.format(case.name), timeout=1)
break
except TIMEOUT as e:
if retry >= self.retry_times - 1: