Merge branch 'feat/sdio_cross_chip_test_apps' into 'master'

sdio: cross chip test apps

Closes IDF-8459

See merge request espressif/esp-idf!26670
This commit is contained in:
Armando (Dou Yiwen) 2023-11-13 18:58:54 +08:00
commit 035d5d17cf
39 changed files with 1204 additions and 980 deletions

View File

@ -725,6 +725,37 @@ pytest_components_esp32_sdio:
artifacts: false
tags: [ esp32, sdio_master_slave ]
pytest_components_esp32_esp32c6_sdio:
extends:
- .pytest_components_dir_template
- .rules:test:component_ut-esp32-sdio
needs:
- job: build_pytest_components_esp32
artifacts: false
- job: build_pytest_components_esp32c6
artifacts: false
tags: [ esp32c6, sdio_multidev_32_c6 ]
script:
- retry_failed git clone $KNOWN_FAILURE_CASES_REPO known_failure_cases
# get runner env config file
- retry_failed git clone $TEST_ENV_CONFIG_REPO
- python $CHECKOUT_REF_SCRIPT ci-test-runner-configs ci-test-runner-configs
# using runner tags as markers to filter the test cases
# Runner tags are comma separated, replace the comma with " and " for markers
- job_tags=$(python tools/ci/python_packages/gitlab_api.py get_job_tags $CI_PROJECT_ID --job_id $CI_JOB_ID)
- markers=$(echo $job_tags | sed -e "s/,/ and /g")
# download the artifacts, requires esp32 and esp32c6 chips
- run_cmd python tools/ci/artifacts_handler.py download --job-name "build_pytest_components_esp32"
- run_cmd python tools/ci/artifacts_handler.py download --job-name "build_pytest_components_esp32c6"
- run_cmd pytest $TEST_DIR
-m \"${markers}\"
--junitxml=XUNIT_RESULT.xml
--ignore-result-files known_failure_cases/known_failure_cases.txt
--parallel-count ${CI_NODE_TOTAL:-1}
--parallel-index ${CI_NODE_INDEX:-1}
${PYTEST_EXTRA_FLAGS}
--app-info-filepattern \"list_job_*.txt\"
pytest_components_esp32_ip101:
extends:
- .pytest_components_dir_template

View File

@ -125,13 +125,15 @@ components/driver/test_apps/rs485:
temporary: true
reason: lack of runners
components/driver/test_apps/sdio:
components/driver/test_apps/sdio/sdio_common_tests/host_sdmmc:
enable:
- if: IDF_TARGET == "esp32"
temporary: false
reason: always use ESP32 SDMMC as host
components/driver/test_apps/sdio/sdio_common_tests/sdio:
disable:
- if: SOC_SDIO_SLAVE_SUPPORTED != 1
disable_test:
- if: IDF_TARGET == "esp32c6"
temporary: true
reason: lack of runners
components/driver/test_apps/sigma_delta:
disable:

View File

@ -1,5 +1,5 @@
idf_component_register(
SRCS test_spi_utils.c param_test.c
SRCS test_spi_utils.c param_test.c test_dualboard_utils.c
INCLUDE_DIRS include
REQUIRES driver unity
)

View File

@ -0,0 +1,57 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <esp_types.h>
#include <stdio.h>
#include <stdlib.h>
/**
* Fill tx_buffers used in dual-board test with random numbers
*
* dut0_buffer and dut1_buffer will be filled with random data
*
* this can be used by a fullduplex dualboard transaction
*
* @param seed Random number seed
* @param dut0_buffer TX buffer used by dut0
* @param dut1_buffer TX buffer used by dut1
* @param buffer_size Buffer size
*/
void test_fill_random_to_buffers_dualboard(uint32_t seed, uint8_t *dut0_buffer, uint8_t *dut1_buffer, size_t buffer_size);
/**
* Fill tx buffer with random numbers
*
* @param seed Random number seed
* @param buffer Buffer
* @param buffer_size Buffer size
*/
void test_fill_random_to_buffer(uint32_t seed, uint8_t *buffer, size_t buffer_size);
/**
* Calloc a pool, filled with random numbers
*
* @param pool_size Size of the pool
* @param flags Calloc flags, see `esp_heap_caps.h`
*/
void test_prepare_buffer_pool(size_t pool_size, uint32_t flags);
/**
* Get a buffer from the pool
*
* @param offset A random offset
* @param size Buffer size
* @param[out] out_buffer Out buffer
*/
void test_get_buffer_from_pool(uint32_t offset, size_t size, void **out_buffer);
/**
* Destroy the pool
*/
void test_destroy_buffer_pool(void);

View File

@ -22,6 +22,7 @@
#include "sdkconfig.h"
#include "soc/spi_periph.h"
#include "driver/spi_master.h"
#include "test_dualboard_utils.h"
// All the tests using the header should use this definition as much as possible,
// so that the working host can be changed easily in the future.
@ -292,15 +293,4 @@ void spitest_gpio_input_sel(uint32_t gpio_num, int func, uint32_t signal_idx);
//then the cs_num of the 1st and 2nd devices are 0 and 1 respectively.
void same_pin_func_sel(spi_bus_config_t bus, spi_device_interface_config_t dev, uint8_t cs_num);
/**
* This function is used to get tx_buffer used in dual-board test
* `master_send_buf` and `slave_send_buf` will be fulfilled with same random numbers with the seed of `seed`.
*
* @param seed Random number seed
* @param master_send_buf Master TX buffer
* @param slave_send_buf Slave TX buffer
* @param send_buf_size Buffer size
*/
void get_tx_buffer(uint32_t seed, uint8_t *master_send_buf, uint8_t *slave_send_buf, int send_buf_size);
#endif //_TEST_COMMON_SPI_H_

View File

@ -0,0 +1,61 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "unity.h"
#include "esp_log.h"
#include "esp_heap_caps.h"
#include "test_dualboard_utils.h"
/*---------------------------------------------------------------
Fill buffer with random numbers
---------------------------------------------------------------*/
void test_fill_random_to_buffers_dualboard(uint32_t seed, uint8_t *dut0_buffer, uint8_t *dut1_buffer, size_t buffer_size)
{
srand(seed);
for (int i = 0; i < buffer_size; i++) {
dut1_buffer[i] = rand() % 256;
dut0_buffer[i] = rand() % 256;
}
}
void test_fill_random_to_buffer(uint32_t seed, uint8_t *buffer, size_t buffer_size)
{
srand(seed);
for (int i = 0; i < buffer_size; i++) {
buffer[i] = rand() % 256;
}
}
/*---------------------------------------------------------------
Create a pool with random numbers, get buffer from pool
---------------------------------------------------------------*/
static uint8_t *s_pool;
static size_t s_pool_size;
void test_prepare_buffer_pool(size_t pool_size, uint32_t flags)
{
s_pool_size = pool_size;
s_pool = (uint8_t *)heap_caps_calloc(1, pool_size, flags);
TEST_ASSERT(s_pool);
test_fill_random_to_buffer(199, s_pool, pool_size);
}
void test_get_buffer_from_pool(uint32_t offset, size_t size, void **out_buffer)
{
//to make sure the out_buffer is within the pool
offset = ((offset % (s_pool_size - size)) + 3) & ~3;
// TEST_ASSERT(offset + size < (uint32_t)s_pool + s_pool_size)
*out_buffer = (void *)(s_pool + offset);
}
void test_destroy_buffer_pool(void)
{
free(s_pool);
s_pool = NULL;
s_pool_size = 0;
}

View File

@ -240,12 +240,3 @@ void same_pin_func_sel(spi_bus_config_t bus, spi_device_interface_config_t dev,
GPIO.func_in_sel_cfg[FSPIQ_IN_IDX].sig_in_sel = 1;
#endif
}
void get_tx_buffer(uint32_t seed, uint8_t *master_send_buf, uint8_t *slave_send_buf, int send_buf_size)
{
srand(seed);
for (int i = 0; i < send_buf_size; i++) {
slave_send_buf[i] = rand() % 256;
master_send_buf[i] = rand() % 256;
}
}

View File

@ -1,2 +0,0 @@
| Supported Targets | ESP32 | ESP32-C6 |
| ----------------- | ----- | -------- |

View File

@ -1,13 +0,0 @@
set(srcs
"test_app_main.c"
"test_sdio.c"
"test_sdmmc_sdspi_init.cpp"
)
# 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 test_driver_utils driver esp_timer sdmmc esp_serial_slave_link
WHOLE_ARCHIVE
)

View File

@ -1,814 +0,0 @@
/*
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "unity.h"
#include "test_utils.h"
#include "test_spi_utils.h"
#include "esp_serial_slave_link/essl_sdio.h"
#include "esp_log.h"
#include "sdmmc_cmd.h"
#include "esp_timer.h"
#include "ccomp_timer.h"
#include "driver/spi_common.h"
#include "driver/sdspi_host.h"
#include "soc/soc_caps.h"
#if SOC_SDMMC_HOST_SUPPORTED && SOC_SDIO_SLAVE_SUPPORTED
#include "soc/sdio_slave_pins.h"
#include "driver/sdio_slave.h"
#include "driver/sdmmc_host.h"
#define TIMEOUT_MAX UINT32_MAX
#define INT_MASK_ALL 0xff
#define SDIO_SLAVE_QUEUE_SIZE 20
#define RX_BUFFER_SIZE 2048
#define RX_BUFFER_NUM 10
#define TX_BUFFER_SIZE 2048
#define REG_ADDR_MAX 60
//the test should run accross the boundary, i.e. over 0x100000 bytes.
//TEST_CNT > 512
#define TEST_CNT 10000
#define TEST_SDSPI_HOST SPI2_HOST
#define TEST_SDSPI_DMACHAN 1
#define TEST_RESET_DATA_LEN 10
#ifndef MIN
#define MIN(a, b) ((a)<(b)? (a): (b))
#endif
typedef enum {
SDIO_1BIT = 0,
SDIO_4BIT = 1,
SDIO_SPI = 2,
} sdio_mode_t;
typedef void (*sdio_test_func)(essl_handle_t handle);
typedef struct {
const char test_name[16];
sdio_mode_t sdio_mode;
uint32_t freq;
bool check_data;
bool packet_mode;
} sdio_test_config_t;
sdio_test_config_t test_cfg_array[] = {
//the first item will be the default config used by all tests
{
.test_name = "HS4B",
.sdio_mode = SDIO_4BIT,
.freq = SDMMC_FREQ_HIGHSPEED,
.check_data = true,
},
{
.test_name = "HS1B",
.sdio_mode = SDIO_1BIT,
.freq = SDMMC_FREQ_HIGHSPEED,
.check_data = true,
},
{
.test_name = "SPI",
.sdio_mode = SDIO_SPI,
.freq = SDMMC_FREQ_HIGHSPEED,
.check_data = true,
},
//the performance test is only done when psram is not enabled
#if !CONFIG_SPIRAM && !CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE
{
.test_name = "HS4B (perf)",
.sdio_mode = SDIO_4BIT,
.freq = SDMMC_FREQ_HIGHSPEED,
},
{
.test_name = "HS1B (perf)",
.sdio_mode = SDIO_1BIT,
.freq = SDMMC_FREQ_HIGHSPEED,
},
{
.test_name = "SPI (perf)",
.sdio_mode = SDIO_SPI,
.freq = SDMMC_FREQ_HIGHSPEED,
},
#endif
};
sdio_test_config_t packet_config = {
.test_name = "HS4B packet",
.sdio_mode = SDIO_4BIT,
.freq = SDMMC_FREQ_HIGHSPEED,
.check_data = true,
.packet_mode = true,
};
const sdio_test_config_t* default_config = &test_cfg_array[0];
#define TEST_SIZE (sizeof(test_cfg_array)/sizeof(sdio_test_config_t))
/*******************************************************************************
* Master
******************************************************************************/
static sdmmc_card_t s_card;
typedef void (*test_func_t)(essl_handle_t handle, const sdio_test_config_t* config);
static void init_sdmmc_host(void);
static void init_essl(essl_handle_t *out_handle, const sdio_test_config_t *conf);
static void deinit_essl(essl_handle_t handle, const sdio_test_config_t *conf);
static void test_framework_master(test_func_t test_func, const sdio_test_config_t* config)
{
unity_send_signal("Master ready");
unity_wait_for_signal("Slave ready");
ESP_LOGI(MASTER_TAG, "### Testing %s... ####", config->test_name);
essl_handle_t handle;
esp_err_t err;
init_essl(&handle, config);
err = essl_init(handle, TIMEOUT_MAX);
TEST_ESP_OK(err);
(*test_func)(handle, config);
deinit_essl(handle, config);
}
static void init_sdmmc_host(void)
{
esp_err_t err;
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
err = sdmmc_host_init();
TEST_ESP_OK(err);
err = sdmmc_host_init_slot(SDMMC_HOST_SLOT_1, &slot_config);
TEST_ESP_OK(err);
}
static void init_essl(essl_handle_t *out_handle, const sdio_test_config_t *conf)
{
sdmmc_host_t config;
esp_err_t err;
spi_bus_config_t bus_config;
/* Probe */
switch (conf->sdio_mode) {
case SDIO_4BIT:
ESP_LOGI(MASTER_TAG, "Probe using SD 4-bit...");
config = (sdmmc_host_t)SDMMC_HOST_DEFAULT();
config.flags = SDMMC_HOST_FLAG_4BIT;
config.max_freq_khz = conf->freq;
init_sdmmc_host();
break;
case SDIO_1BIT:
ESP_LOGI(MASTER_TAG, "Probe using SD 1-bit...");
config = (sdmmc_host_t)SDMMC_HOST_DEFAULT();
config.flags = SDMMC_HOST_FLAG_1BIT;
config.max_freq_khz = conf->freq;
init_sdmmc_host();
break;
case SDIO_SPI:
bus_config = (spi_bus_config_t) {
.mosi_io_num = SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_CMD,
.miso_io_num = SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_D0,
.sclk_io_num = SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_CLK,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
};
err = spi_bus_initialize(TEST_SDSPI_HOST, &bus_config, TEST_SDSPI_DMACHAN);
TEST_ESP_OK(err);
sdspi_device_config_t device_config = SDSPI_DEVICE_CONFIG_DEFAULT();
device_config.host_id = TEST_SDSPI_HOST;
device_config.gpio_cs = SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_D3;
device_config.gpio_int= SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_D1;
err = gpio_install_isr_service(0);
TEST_ASSERT(err == ESP_OK || err == ESP_ERR_INVALID_STATE);
sdspi_dev_handle_t sdspi_handle;
err = sdspi_host_init();
TEST_ESP_OK(err);
err = sdspi_host_init_device(&device_config, &sdspi_handle);
TEST_ESP_OK(err);
ESP_LOGI(MASTER_TAG, "Probe using SPI...");
config = (sdmmc_host_t)SDSPI_HOST_DEFAULT();
config.slot = sdspi_handle;
break;
}
sdmmc_card_t *card = &s_card;
//wait for at least 5 seconds
int retry_times = 5;
do {
if (sdmmc_card_init(&config, card) == ESP_OK) {
break;
}
ESP_LOGW(MASTER_TAG, "slave init failed, retry...");
vTaskDelay(1000 / portTICK_PERIOD_MS);
} while (--retry_times);
TEST_ASSERT_MESSAGE(retry_times != 0, "Initializing slave failed.");
essl_sdio_config_t ser_config = {
.card = card,
.recv_buffer_size = RX_BUFFER_SIZE,
};
err = essl_sdio_init_dev(out_handle, &ser_config);
TEST_ESP_OK(err);
err = essl_init(*out_handle, TIMEOUT_MAX);
TEST_ESP_OK(err);
}
static void deinit_essl(essl_handle_t handle, const sdio_test_config_t *conf)
{
esp_err_t err;
essl_sdio_deinit_dev(handle);
if (conf->sdio_mode == SDIO_SPI) {
gpio_uninstall_isr_service();
err = sdspi_host_deinit();
TEST_ESP_OK(err);
err = spi_bus_free(TEST_SDSPI_HOST);
TEST_ESP_OK(err);
} else {
err = sdmmc_host_deinit();
TEST_ESP_OK(err);
}
}
static void send_finish_test(essl_handle_t handle)
{
//the slave needs a signal to quite the test
essl_send_slave_intr(handle, BIT(7), TIMEOUT_MAX);
}
static void test_int(essl_handle_t handle, const sdio_test_config_t* config)
{
esp_err_t err;
err = essl_set_intr_ena(handle, INT_MASK_ALL, TIMEOUT_MAX);
TEST_ESP_OK(err);
err = essl_wait_int(handle, 0);
TEST_ASSERT_EQUAL_HEX(ESP_ERR_TIMEOUT, err);
//tests all 8 interrupts of the slave, in which int 7 is used to terminate the test on the slave.
for (int i = 0; i < 8; i ++) {
uint32_t int_st;
err = essl_send_slave_intr(handle, BIT(i), TIMEOUT_MAX);
TEST_ESP_OK(err);
//the slave should return interrupt with the same bit in 10 ms
err = essl_wait_int(handle, 10);
TEST_ESP_OK(err);
err = essl_get_intr(handle, NULL, &int_st, TIMEOUT_MAX);
TEST_ESP_OK(err);
//check and clear the returned interrupt
TEST_ASSERT_EQUAL_HEX(BIT(i), int_st);
err = essl_clear_intr(handle, int_st, TIMEOUT_MAX);
TEST_ESP_OK(err);
}
}
static void test_sdio_interrupt_master(void)
{
test_framework_master(test_int, default_config);
}
static void test_reg(essl_handle_t handle, const sdio_test_config_t* config)
{
esp_err_t err;
uint8_t data[REG_ADDR_MAX];
srand(850);
//initialize the buffer
for (int i = 0; i < REG_ADDR_MAX; i++) {
data[i] = rand();
err = essl_write_reg(handle, i, data[i], NULL, 10);
TEST_ESP_OK(err);
}
for (int i = 0; i < 512; i++) {
//randomly write one
int offset = rand() % REG_ADDR_MAX;
uint8_t data_write = rand();
data[offset] = data_write;
err = essl_write_reg(handle, offset, data_write, NULL, 10);
TEST_ESP_OK(err);
//randomly read another one and compare
offset = rand() % REG_ADDR_MAX;
uint8_t data_read;
err = essl_read_reg(handle, offset, &data_read, 10);
TEST_ESP_OK(err);
TEST_ASSERT_EQUAL_HEX8(data[offset], data_read);
}
send_finish_test(handle);
}
static void test_sdio_reg_master(void)
{
test_framework_master(test_reg, default_config);
}
static uint8_t tx_buffer[TX_BUFFER_SIZE*2];
static uint8_t rcv_buffer[RX_BUFFER_SIZE*RX_BUFFER_NUM];
static void init_tx_buffer(void)
{
srand(776);
for (int i = 0; i < sizeof(tx_buffer); i++) {
tx_buffer[i] = rand();
}
}
static void get_master_send_data(int offset, uint8_t** out_start, int* out_len)
{
int page_cnt = offset / TX_BUFFER_SIZE;
int offset_in_page = offset % TX_BUFFER_SIZE;
srand(page_cnt);
int page_offset = (rand() % (sizeof(tx_buffer) - (TX_BUFFER_SIZE) + 1)) & (~3);
*out_start = &tx_buffer[page_offset + offset_in_page];
*out_len = TX_BUFFER_SIZE - offset_in_page;
}
static void log_performance_tohost(uint32_t speed, const sdio_test_config_t* config)
{
if (!config->check_data) {
switch (config->sdio_mode) {
case SDIO_4BIT:
TEST_PERFORMANCE_CCOMP_GREATER_THAN(SDIO_THROUGHPUT_KBSEC_TOHOST_4BIT, "%" PRIu32, speed);
break;
case SDIO_1BIT:
TEST_PERFORMANCE_CCOMP_GREATER_THAN(SDIO_THROUGHPUT_KBSEC_TOHOST_1BIT, "%" PRIu32, speed);
break;
case SDIO_SPI:
TEST_PERFORMANCE_CCOMP_GREATER_THAN(SDIO_THROUGHPUT_KBSEC_TOHOST_SPI, "%" PRIu32, speed);
break;
}
}
}
static void test_tp_tohost_master(essl_handle_t handle, const sdio_test_config_t* config)
{
esp_err_t err;
int expected_length = TEST_CNT * TX_BUFFER_SIZE;
int recv_size = 4096;
init_tx_buffer();
//wait for the slave to get ready
vTaskDelay(20);
int remain_length = expected_length;
int offset = 0;
// Two counters are used. The `esp_timer_get_time()` is for the typical time, and the
// `ccomp_timer` is for performance test to reduce influence caused by cache miss.
int64_t pre_us = esp_timer_get_time();
err = ccomp_timer_start();
assert(err == ESP_OK);
// though the flow is the same, the check of config->check_data influences the throughput much, put it outside
if (config->check_data) {
do {
size_t rcv_len;
err = essl_get_packet(handle, rcv_buffer, recv_size, &rcv_len, TIMEOUT_MAX);
TEST_ASSERT(err == ESP_OK || err == ESP_ERR_NOT_FINISHED);
TEST_ASSERT_LESS_OR_EQUAL(remain_length, rcv_len);
//compare until all received data are used
int compared_len = 0;
do {
//get the expected master sent data, there may be several segments, so get and compare
//several times
uint8_t* cmp_start;
int seg_len;
get_master_send_data(offset, &cmp_start, &seg_len);
int cmp_len = MIN(rcv_len-compared_len, seg_len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(cmp_start, &rcv_buffer[compared_len], cmp_len);
compared_len += cmp_len;
offset += cmp_len;
} while (compared_len < rcv_len);
remain_length -= rcv_len;
} while (remain_length > 0);
} else {
do {
size_t rcv_len;
err = essl_get_packet(handle, rcv_buffer, recv_size, &rcv_len, TIMEOUT_MAX);
TEST_ASSERT(err == ESP_OK || err == ESP_ERR_NOT_FINISHED);
TEST_ASSERT_LESS_OR_EQUAL(remain_length, rcv_len);
offset += rcv_len;
remain_length -= rcv_len;
} while (remain_length > 0);
}
int64_t c_time_ms = ccomp_timer_stop()/1000;
int64_t end_us = esp_timer_get_time();
uint32_t total_time_ms = (end_us - pre_us)/1000;
ESP_LOGI(MASTER_TAG, "test done, total time: %" PRIu32 " ms (%d ms compensated), bytes transferred: %d", total_time_ms, (int)c_time_ms, expected_length);
uint32_t throughput_byte_per_ms = expected_length / c_time_ms;
ESP_LOGI(MASTER_TAG, "Throughput: compensated %.2lf MB/s, typical %.2lf MB/s",
throughput_byte_per_ms/1000., expected_length/(total_time_ms*1000.));
log_performance_tohost(throughput_byte_per_ms, config);
send_finish_test(handle);
}
static void log_performance_frhost(uint32_t speed, const sdio_test_config_t* config)
{
if (!config->check_data) {
switch (config->sdio_mode) {
case SDIO_4BIT:
TEST_PERFORMANCE_CCOMP_GREATER_THAN(SDIO_THROUGHPUT_KBSEC_FRHOST_4BIT, "%" PRIu32, speed);
break;
case SDIO_1BIT:
TEST_PERFORMANCE_CCOMP_GREATER_THAN(SDIO_THROUGHPUT_KBSEC_FRHOST_1BIT, "%" PRIu32, speed);
break;
case SDIO_SPI:
TEST_PERFORMANCE_CCOMP_GREATER_THAN(SDIO_THROUGHPUT_KBSEC_FRHOST_SPI, "%" PRIu32, speed);
break;
}
}
}
static void test_tp_frhost_master(essl_handle_t handle, const sdio_test_config_t* config)
{
esp_err_t err;
int expected_length = TEST_CNT * TX_BUFFER_SIZE;
init_tx_buffer();
//wait for the slave to get ready
vTaskDelay(20);
int remain_length = expected_length;
int offset = 0;
// Two counters are used. The `esp_timer_get_time()` is for the typical time, and the
// `ccomp_timer` is for performance test to reduce influence caused by cache miss.
int64_t pre_us = esp_timer_get_time();
err = ccomp_timer_start();
assert(err == ESP_OK);
do {
int send_len;
uint8_t* send_start;
get_master_send_data(offset, &send_start, &send_len);
TEST_ASSERT_EQUAL(TX_BUFFER_SIZE, send_len);
err = essl_send_packet(handle, send_start, send_len, TIMEOUT_MAX);
TEST_ASSERT(err == ESP_OK);
remain_length -= send_len;
offset += send_len;
} while (remain_length > 0);
int64_t c_time_ms = ccomp_timer_stop()/1000;
int64_t end_us = esp_timer_get_time();
uint32_t total_time_ms = (end_us - pre_us)/1000;
ESP_LOGI(MASTER_TAG, "test done, total time: %" PRIu32 " ms (%d ms compensated), bytes transferred: %d", total_time_ms, (int)c_time_ms, expected_length);
uint32_t throughput_byte_per_ms = expected_length / c_time_ms;
ESP_LOGI(MASTER_TAG, "Throughput: compensated %.2lf MB/s, typical %.2lf MB/s",
throughput_byte_per_ms/1000., expected_length/(total_time_ms*1000.));
log_performance_frhost(throughput_byte_per_ms, config);
send_finish_test(handle);
}
void test_reset_master(essl_handle_t handle, const sdio_test_config_t* config)
{
init_tx_buffer();
//wait for the slave to stop, reset and start again
vTaskDelay(10);
for (int i = 0; i < 10; i++) {
WORD_ALIGNED_ATTR uint8_t buffer[TEST_RESET_DATA_LEN];
size_t read_len;
esp_err_t err = essl_get_packet(handle, buffer, TEST_RESET_DATA_LEN, &read_len, portMAX_DELAY);
if (err == ESP_ERR_NOT_FINISHED) {
TEST_ASSERT_LESS_THAN(10, i);
err = ESP_OK;
}
TEST_ESP_OK(err);
TEST_ASSERT_EQUAL(TEST_RESET_DATA_LEN, read_len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(tx_buffer + 4*i, buffer, read_len);
}
for (int i = 0; i < 10; i++) {
esp_err_t err = essl_send_packet(handle, tx_buffer + i * 8, TEST_RESET_DATA_LEN, portMAX_DELAY);
TEST_ESP_OK(err);
}
send_finish_test(handle);
}
void test_sdio_reset_master(void)
{
test_framework_master(test_reset_master, &packet_config);
}
/*******************************************************************************
* Slave
******************************************************************************/
typedef struct {
int queued_cnt;
bool s_finished;
} slave_context_t;
typedef void (*test_func_slave_t)(slave_context_t *context, const sdio_test_config_t* config);
static slave_context_t slave_context;
static void event_cb(uint8_t event)
{
ESP_EARLY_LOGI(SLAVE_TAG, "event: %d", event);
sdio_slave_send_host_int(event);
if (event == 7) slave_context.s_finished = true;
}
static void wait_for_finish(slave_context_t *ctx)
{
while (!ctx->s_finished) {
vTaskDelay(10);
}
//wait for host to read the respond from slave
vTaskDelay(10);
}
static void test_framework_slave(test_func_slave_t test_func, const sdio_test_config_t* config)
{
unity_wait_for_signal("Master ready");
slave_context.s_finished = false;
esp_err_t err;
sdio_slave_config_t slave_config = {
.sending_mode = (config->packet_mode? SDIO_SLAVE_SEND_PACKET: SDIO_SLAVE_SEND_STREAM),
.send_queue_size = SDIO_SLAVE_QUEUE_SIZE,
.recv_buffer_size = RX_BUFFER_SIZE,
.event_cb = event_cb,
};
err = sdio_slave_initialize(&slave_config);
TEST_ESP_OK(err);
err = sdio_slave_start();
TEST_ESP_OK(err);
unity_send_signal("Slave ready");
test_func(&slave_context, config);
sdio_slave_stop();
sdio_slave_deinit();
}
static void test_int_slave(slave_context_t* ctx, const sdio_test_config_t* config)
{
wait_for_finish(ctx);
}
static void test_sdio_interrupt_slave(void)
{
test_framework_slave(test_int_slave, default_config);
}
static void test_tp_tohost_slave(slave_context_t* ctx, const sdio_test_config_t* config)
{
#define QUEUE_FULL() (ctx->queued_cnt == SDIO_SLAVE_QUEUE_SIZE)
#define QUEUE_EMPTY() (ctx->queued_cnt == 0)
init_tx_buffer();
esp_err_t err;
int offset = 0;
for (int i = 0; i < TEST_CNT; i++) {
do {
void* arg;
//when the queue is full, do a blocking wait for 10ms, otherwise non-blocking
err = sdio_slave_send_get_finished(&arg, QUEUE_FULL()? 1: 0);
if (err == ESP_OK) {
ctx->queued_cnt --;
continue;
}
TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, err);
} while (QUEUE_FULL());
uint8_t* start;
int send_len;
get_master_send_data(offset, &start, &send_len);
TEST_ASSERT_EQUAL(TX_BUFFER_SIZE, send_len);
err = sdio_slave_send_queue(start, send_len, NULL, portMAX_DELAY);
TEST_ESP_OK(err);
ctx->queued_cnt++;
offset += TX_BUFFER_SIZE;
}
while (!QUEUE_EMPTY()) {
void* arg;
err = sdio_slave_send_get_finished(&arg, portMAX_DELAY);
TEST_ESP_OK(err);
ctx->queued_cnt--;
}
wait_for_finish(ctx);
}
static void slave_parepare_recv_buffer(void)
{
for (int i = 0; i < RX_BUFFER_NUM; i++) {
sdio_slave_buf_handle_t buf_handle = sdio_slave_recv_register_buf(&rcv_buffer[i*RX_BUFFER_SIZE]);
esp_err_t err = sdio_slave_recv_load_buf(buf_handle);
TEST_ESP_OK(err);
}
}
static void test_tp_frhost_slave(slave_context_t *ctx, const sdio_test_config_t* config)
{
esp_err_t err;
init_tx_buffer();
slave_parepare_recv_buffer();
int offset = 0;
for (int i = 0; i < TEST_CNT; i++) {
sdio_slave_buf_handle_t buf_handle;
uint8_t* buf;
size_t rcv_len;
err = sdio_slave_recv(&buf_handle, &buf, &rcv_len, portMAX_DELAY);
TEST_ESP_OK(err);
if (config->check_data) {
//compare until all received data are used
int compared_len = 0;
do {
//get the expected master sent data, there may be several segments, so get and compare
//several times
uint8_t* cmp_start;
int seg_len;
get_master_send_data(offset, &cmp_start, &seg_len);
int cmp_len = MIN(rcv_len-compared_len, seg_len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(cmp_start, &buf[compared_len], cmp_len);
compared_len += cmp_len;
offset += cmp_len;
} while (compared_len < rcv_len);
} else {
offset += rcv_len;
}
err = sdio_slave_recv_load_buf(buf_handle);
TEST_ESP_OK(err);
}
wait_for_finish(ctx);
}
static void slave_tx_rx_short_data(void)
{
esp_err_t err;
for (int i = 0; i < 10; i++) {
err = sdio_slave_send_queue(tx_buffer + 4*i, TEST_RESET_DATA_LEN, (void*)i, portMAX_DELAY);
TEST_ESP_OK(err);
}
for (int i = 0; i < 10; i++) {
uint8_t* addr;
size_t size;
sdio_slave_buf_handle_t recv_handle;
err = sdio_slave_recv(&recv_handle, &addr, &size, portMAX_DELAY);
TEST_ESP_OK(err);
TEST_ASSERT_EQUAL(TEST_RESET_DATA_LEN, size);
TEST_ASSERT_EQUAL_HEX8_ARRAY(tx_buffer+i*8, addr, size);
}
for (int i = 0; i < 10; i++) {
void* arg;
err = sdio_slave_send_get_finished(&arg, portMAX_DELAY);
TEST_ESP_OK(err);
TEST_ASSERT_EQUAL(i, arg);
}
}
void test_reset_slave(slave_context_t *context, const sdio_test_config_t* config)
{
sdio_slave_stop();
esp_err_t err = sdio_slave_reset();
TEST_ESP_OK(err);
err = sdio_slave_start();
TEST_ESP_OK(err);
init_tx_buffer();
slave_parepare_recv_buffer();
slave_tx_rx_short_data();
wait_for_finish(context);
}
void test_sdio_reset_slave(void)
{
test_framework_slave(test_reset_slave, &packet_config);
}
TEST_CASE_MULTIPLE_DEVICES("sdio interrupt", "[sdio][test_env=sdio_master_slave]", test_sdio_interrupt_master, test_sdio_interrupt_slave);
TEST_CASE_MULTIPLE_DEVICES("sdio register", "[sdio][test_env=sdio_master_slave]", test_sdio_reg_master, test_sdio_interrupt_slave);
#if !CONFIG_FREERTOS_UNICORE
TEST_CASE_MULTIPLE_DEVICES("sdio reset", "[sdio][test_env=sdio_master_slave]", test_sdio_reset_master, test_sdio_reset_slave);
#else
//Currently there is weird issue on the runner, when tested with single core config, seems to relate to receiving
TEST_CASE_MULTIPLE_DEVICES("sdio reset", "[sdio][test_env=sdio_master_slave][ignore]", test_sdio_reset_master, test_sdio_reset_slave);
#endif
static void test_sdio_frhost_master(const void* pset, void* context)
{
test_framework_master(test_tp_frhost_master, pset);
}
static void test_sdio_frhost_slave(const void* pset, void* context)
{
test_framework_slave(test_tp_frhost_slave, pset);
}
static void test_sdio_tohost_master(const void* pset, void* context)
{
test_framework_master(test_tp_tohost_master, pset);
}
static void test_sdio_tohost_slave(const void* pset, void* context)
{
test_framework_slave(test_tp_tohost_slave, pset);
}
static void null_pre(void** arg)
{
}
static void null_post(void* arg)
{
}
ptest_func_t frhost_master = {
.pre_test = null_pre,
.loop = test_sdio_frhost_master,
.post_test = null_post,
};
ptest_func_t frhost_slave = {
.pre_test = null_pre,
.loop = test_sdio_frhost_slave,
.post_test = null_post,
};
PARAM_GROUP_DECLARE_TYPE(IO_MODE, sdio_test_config_t, test_cfg_array);
#if !CONFIG_FREERTOS_UNICORE
TEST_MASTER_SLAVE(SDIO_FRHOST, test_cfg_array, "[sdio][timeout=180][test_env=sdio_master_slave]", &frhost_master, &frhost_slave);
#else
//Currently there is weird issue on the runner, when tested with single core config, seems to relate to receiving
TEST_MASTER_SLAVE(SDIO_FRHOST, test_cfg_array, "[sdio][timeout=180][test_env=sdio_master_slave][ignore]", &frhost_master, &frhost_slave);
#endif
ptest_func_t tohost_master = {
.pre_test = null_pre,
.loop = test_sdio_tohost_master,
.post_test = null_post,
};
ptest_func_t tohost_slave = {
.pre_test = null_pre,
.loop = test_sdio_tohost_slave,
.post_test = null_post,
};
TEST_MASTER_SLAVE(SDIO_TOHOST, test_cfg_array, "[sdio][timeout=180][test_env=sdio_master_slave]", &tohost_master, &tohost_slave);
#endif //SOC_SDMMC_HOST_SUPPORTED && SOC_SDIO_SLAVE_SUPPORTED

View File

@ -1,32 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/soc_caps.h"
#if SOC_SDMMC_HOST_SUPPORTED
#include "driver/sdmmc_host.h"
#endif
#include "driver/sdspi_host.h"
/**
* Check that C-style designated initializers are valid in C++ file.
*/
static void test_initializers() __attribute__((unused));
static void test_initializers()
{
#if SOC_SDMMC_HOST_SUPPORTED
sdmmc_host_t sdmmc_host = SDMMC_HOST_DEFAULT();
(void) sdmmc_host;
sdmmc_slot_config_t sdmmc_slot = SDMMC_SLOT_CONFIG_DEFAULT();
(void) sdmmc_slot;
#endif
sdmmc_host_t sdspi_host = SDSPI_HOST_DEFAULT();
(void) sdspi_host;
sdspi_device_config_t sdspi_dev = SDSPI_DEVICE_CONFIG_DEFAULT();
(void) sdspi_dev;
}

View File

@ -1,11 +0,0 @@
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
@pytest.mark.esp32
@pytest.mark.sdio_master_slave
@pytest.mark.parametrize('count', [2,], indirect=True)
def test_sdio_multi_dev(case_tester) -> None: # type: ignore
case_tester.run_all_multi_dev_cases(reset=True, timeout=180)

View File

@ -0,0 +1,7 @@
# SDIO Cross Chips Test Apps
This folder contains SDIO related tests. This folder contains two sub-folders:
- host_sdmmc: this fodler contains the ESP32 SDMMC test app which works as the host to test the SDIO Slave peripheral
- sdio: this fodler contains the ESP SDIO Slave test apps
Tests in this folder are all dual-board tests.

View File

@ -0,0 +1,13 @@
# This is the project CMakeLists.txt file for the test subproject
cmake_minimum_required(VERSION 3.16)
# "Trim" the build. Include the minimal set of components, main, and anything it depends on.
set(COMPONENTS main)
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(host_sdmmc)

View File

@ -0,0 +1,6 @@
| Supported Targets | ESP32 |
| ----------------- | ----- |
# SDIO Cross Chips Test Apps: SDMMC Host App
This test app is using ESP32 SDMMC as the host to test the SDIO Slave peripherals among ESP chips.

View File

@ -0,0 +1,6 @@
set(srcs "test_app_main.c"
"test_sdio_sdhost.c")
idf_component_register(SRCS ${srcs}
PRIV_REQUIRES unity test_driver_utils driver esp_serial_slave_link sdmmc test_utils esp_timer
WHOLE_ARCHIVE)

View File

@ -0,0 +1,52 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include "unity.h"
#include "unity_test_utils.h"
#include "esp_heap_caps.h"
// Some resources are lazy allocated, the threadhold is left for that case
#define TEST_MEMORY_LEAK_THRESHOLD (700)
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)
{
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);
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

@ -0,0 +1,359 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* This file uses ESP32 SDMMC peripheral to test SDIO Slave peripheral SD modes
*/
#include "unity.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_timer.h"
#include "ccomp_timer.h"
#include "sdmmc_cmd.h"
#include "driver/sdmmc_host.h"
#include "esp_serial_slave_link/essl_sdio.h"
#include "soc/soc_caps.h"
#include "test_utils.h"
#include "idf_performance.h"
#include "test_dualboard_utils.h"
#include "../../sdio_common_test.h"
static const char *TAG = "test_sdio_sdhost";
#define TEST_HEX_LOG_LEVEL ESP_LOG_DEBUG
#define TEST_INT_MASK_ALL 0xff
#define TEST_REG_ADDR_MAX 60
#define TEST_TIMEOUT_MAX UINT32_MAX
typedef struct {
uint32_t host_flags;
uint32_t max_freq_khz;
bool check_data;
} test_sdio_param_t;
/*---------------------------------------------------------------
Host Init Settings
---------------------------------------------------------------*/
static sdmmc_card_t s_card;
static void s_master_init(test_sdio_param_t *host_param, essl_handle_t *out_handle)
{
sdmmc_host_t host_config = (sdmmc_host_t)SDMMC_HOST_DEFAULT();
host_config.flags = host_param->host_flags;
if (host_config.flags == SDMMC_HOST_FLAG_4BIT) {
ESP_LOGI(TAG, "Probe using SD 4-bit...");
} else if (host_config.flags == SDMMC_HOST_FLAG_1BIT) {
ESP_LOGI(TAG, "Probe using SD 1-bit...");
}
host_config.max_freq_khz = host_param->max_freq_khz;
ESP_LOGI(TAG, "Host max_freq_khz: %d", host_config.max_freq_khz);
//init sdmmc host
TEST_ESP_OK(sdmmc_host_init());
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
TEST_ESP_OK(sdmmc_host_init_slot(SDMMC_HOST_SLOT_1, &slot_config));
//host init slave
sdmmc_card_t *card = &s_card;
//wait for at least 5 seconds
int retry_times = 5;
do {
if (sdmmc_card_init(&host_config, card) == ESP_OK) {
break;
}
ESP_LOGW(TAG, "slave init failed, retry...");
vTaskDelay(1000 / portTICK_PERIOD_MS);
} while (--retry_times);
TEST_ASSERT_MESSAGE(retry_times != 0, "Initializing slave failed.");
//init essl sdmmc host
essl_sdio_config_t essl_sdio_config = {
.card = card,
.recv_buffer_size = TEST_RX_BUFFER_SIZE,
};
TEST_ESP_OK(essl_sdio_init_dev(out_handle, &essl_sdio_config));
TEST_ESP_OK(essl_init(*out_handle, TEST_TIMEOUT_MAX));
}
//trigger event 7 to indicate Slave to stop the test
static void s_send_finish_test(essl_handle_t handle)
{
//the slave needs a signal to quite the test
essl_send_slave_intr(handle, BIT(7), TEST_TIMEOUT_MAX);
}
/*---------------------------------------------------------------
Function Tests
---------------------------------------------------------------*/
/*---------------------------------------------------------------
SDMMC_SDIO: test interrupt
---------------------------------------------------------------*/
TEST_CASE("SDIO_SDMMC: test interrupt", "[sdio]")
{
esp_err_t ret = ESP_FAIL;
essl_handle_t handle = NULL;
test_sdio_param_t test_param = {
.host_flags = SDMMC_HOST_FLAG_4BIT,
.max_freq_khz = SDMMC_FREQ_HIGHSPEED,
};
//essl init and sdmmc init
s_master_init(&test_param, &handle);
TEST_ESP_OK(essl_set_intr_ena(handle, TEST_INT_MASK_ALL, TEST_TIMEOUT_MAX));
ret = essl_wait_int(handle, 0);
TEST_ASSERT_EQUAL_HEX(ESP_ERR_TIMEOUT, ret);
//tests all 8 interrupts of the slave, in which int 7 is used to terminate the test on the slave.
for (int i = 0; i < 8; i ++) {
esp_rom_printf("to essl_send_slave_intr\n");
TEST_ESP_OK(essl_send_slave_intr(handle, BIT(i), TEST_TIMEOUT_MAX));
//the slave should return interrupt with the same bit in 10 ms
TEST_ESP_OK(essl_wait_int(handle, 10));
uint32_t int_st;
TEST_ESP_OK(essl_get_intr(handle, NULL, &int_st, TEST_TIMEOUT_MAX));
//check and clear the returned interrupt
TEST_ASSERT_EQUAL_HEX(BIT(i), int_st);
TEST_ESP_OK(essl_clear_intr(handle, int_st, TEST_TIMEOUT_MAX));
}
sdmmc_host_deinit();
}
/*---------------------------------------------------------------
SDMMC_SDIO: test register
---------------------------------------------------------------*/
TEST_CASE("SDIO_SDMMC: test register", "[sdio]")
{
essl_handle_t handle = NULL;
test_sdio_param_t test_param = {
.host_flags = SDMMC_HOST_FLAG_4BIT,
.max_freq_khz = SDMMC_FREQ_HIGHSPEED,
};
//essl init and sdmmc init
s_master_init(&test_param, &handle);
uint32_t init_val = 30;
srand(850);
//initialize the registers
for (int i = 0; i < TEST_REG_ADDR_MAX; i++) {
TEST_ESP_OK(essl_write_reg(handle, i, init_val, NULL, 10));
}
for (int i = 0; i < TEST_REG_ADDR_MAX; i++) {
uint8_t data_write = rand() % 0xFF;
TEST_ESP_OK(essl_write_reg(handle, i, data_write, NULL, 10));
uint8_t data_read = 0;
TEST_ESP_OK(essl_read_reg(handle, i, &data_read, 10));
TEST_ASSERT_EQUAL_HEX8(data_write, data_read);
}
s_send_finish_test(handle);
sdmmc_host_deinit();
}
/*---------------------------------------------------------------
SDMMC_SDIO: test reset
---------------------------------------------------------------*/
TEST_CASE("SDIO_SDMMC: test reset", "[sdio]")
{
essl_handle_t handle = NULL;
test_sdio_param_t test_param = {
.host_flags = SDMMC_HOST_FLAG_4BIT,
.max_freq_khz = SDMMC_FREQ_HIGHSPEED,
};
//essl init and sdmmc init
s_master_init(&test_param, &handle);
//wait for the slave to stop, reset and start again
vTaskDelay(10);
//rx
WORD_ALIGNED_ATTR uint8_t slave_tx_buffer[TEST_RESET_DATA_LEN] = {};
WORD_ALIGNED_ATTR uint8_t host_rx_buffer[TEST_RESET_DATA_LEN] = {};
size_t read_len = 0;
for (int i = 0; i < TEST_RESET_BUF_NUMS; i++) {
test_fill_random_to_buffer(i, slave_tx_buffer, TEST_RESET_DATA_LEN);
esp_err_t ret = essl_get_packet(handle, host_rx_buffer, TEST_RESET_DATA_LEN, &read_len, portMAX_DELAY);
if (ret == ESP_ERR_NOT_FINISHED) {
printf("not finished\n");
ret = ESP_OK;
}
TEST_ESP_OK(ret);
TEST_ASSERT_EQUAL(TEST_RESET_DATA_LEN, read_len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(slave_tx_buffer, host_rx_buffer, read_len);
}
//tx
WORD_ALIGNED_ATTR uint8_t host_tx_buffer[TEST_RESET_BUF_NUMS][TEST_RESET_DATA_LEN] = {};
for (int i = 0; i < TEST_RESET_BUF_NUMS; i++) {
test_fill_random_to_buffer(i, host_tx_buffer[i], TEST_RESET_DATA_LEN);
TEST_ESP_OK(essl_send_packet(handle, host_tx_buffer[i], TEST_RESET_DATA_LEN, TEST_TIMEOUT_MAX));
}
s_send_finish_test(handle);
sdmmc_host_deinit();
}
/*---------------------------------------------------------------
Transaction Tests
---------------------------------------------------------------*/
test_sdio_param_t test_param_lists[TEST_TARNS_PARAM_NUMS] = {
{
.host_flags = SDMMC_HOST_FLAG_4BIT,
.max_freq_khz = SDMMC_FREQ_HIGHSPEED,
},
{
.host_flags = SDMMC_HOST_FLAG_1BIT,
.max_freq_khz = SDMMC_FREQ_HIGHSPEED,
},
};
/*---------------------------------------------------------------
SDMMC_SDIO: test from host
---------------------------------------------------------------*/
static void test_from_host(bool check_data)
{
test_prepare_buffer_pool(TEST_RX_BUFFER_SIZE * 4, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA);
for (int i = 0; i < TEST_TARNS_PARAM_NUMS; i++) {
ESP_LOGI(TAG, "host mode: %s", (test_param_lists[i].host_flags == SDMMC_HOST_FLAG_4BIT) ? "4BIT Mode" : "1BIT Mode");
ESP_LOGI(TAG, "host speed: %"PRIu32" kHz", test_param_lists[i].max_freq_khz);
essl_handle_t handle = NULL;
s_master_init(&test_param_lists[i], &handle);
// Two counters are used. The `esp_timer_get_time()` is for the typical time, and the
// `ccomp_timer` is for performance test to reduce influence caused by cache miss.
int64_t pre_us = esp_timer_get_time();
TEST_ESP_OK(ccomp_timer_start());
uint32_t expected_length = TEST_TRANS_NUMS * TEST_RX_BUFFER_SIZE;
void *tx_buf_ptr = NULL;
for (int j = 0; j < TEST_TRANS_NUMS; j++) {
ESP_LOGD(TAG, "j: %d", j);
test_get_buffer_from_pool(j, TEST_RX_BUFFER_SIZE, &tx_buf_ptr);
ESP_LOG_BUFFER_HEX_LEVEL(TAG, tx_buf_ptr, TEST_RX_BUFFER_SIZE, TEST_HEX_LOG_LEVEL);
TEST_ESP_OK(essl_send_packet(handle, tx_buf_ptr, TEST_RX_BUFFER_SIZE, TEST_TIMEOUT_MAX));
}
int64_t c_time_ms = ccomp_timer_stop() / 1000;
int64_t end_us = esp_timer_get_time();
uint32_t total_time_ms = (end_us - pre_us) / 1000;
ESP_LOGI(TAG, "test done, total time: %" PRIu32 " ms (%d ms compensated), bytes transferred: %"PRIu32, total_time_ms, (int)c_time_ms, expected_length);
uint32_t throughput_byte_per_ms = expected_length / c_time_ms;
ESP_LOGI(TAG, "Throughput: compensated %"PRIu32"KB/s (%.2lf MB/s), typical %.2lf MB/s",
throughput_byte_per_ms, throughput_byte_per_ms / 1000., expected_length / (total_time_ms * 1000.));
esp_rom_delay_us(50 * 1000);
s_send_finish_test(handle);
sdmmc_host_deinit();
}
test_destroy_buffer_pool();
}
TEST_CASE("SDIO_SDMMC: test from host", "[sdio]")
{
test_from_host(true);
}
TEST_CASE("SDIO_SDMMC: test from host (Performance)", "[sdio_speed]")
{
test_from_host(false);
}
static void test_to_host(bool check_data)
{
//prepare buffer
test_prepare_buffer_pool(TEST_RX_BUFFER_SIZE * 21, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA);
int recv_size = 4096;
uint8_t *host_rx_buffer = (uint8_t *)heap_caps_calloc(1, recv_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA);
for (int i = 0; i < TEST_TARNS_PARAM_NUMS; i++) {
ESP_LOGI(TAG, "host mode: %s", (test_param_lists[i].host_flags == SDMMC_HOST_FLAG_4BIT) ? "4BIT Mode" : "1BIT Mode");
ESP_LOGI(TAG, "host speed: %"PRIu32" kHz", test_param_lists[i].max_freq_khz);
essl_handle_t handle = NULL;
s_master_init(&test_param_lists[i], &handle);
esp_err_t ret;
int offset = 0;
void *tx_buf_ptr = NULL;
uint32_t expected_length = TEST_TRANS_NUMS * TEST_RX_BUFFER_SIZE;
int remain_length = expected_length;
// Two counters are used. The `esp_timer_get_time()` is for the typical time, and the
// `ccomp_timer` is for performance test to reduce influence caused by cache miss.
int64_t pre_us = esp_timer_get_time();
TEST_ESP_OK(ccomp_timer_start());
do {
size_t rcv_len;
ret = essl_get_packet(handle, host_rx_buffer, recv_size, &rcv_len, TEST_TIMEOUT_MAX);
TEST_ASSERT(ret == ESP_OK || ret == ESP_ERR_NOT_FINISHED);
TEST_ASSERT_LESS_OR_EQUAL(remain_length, rcv_len);
if (check_data) {
size_t compared_len = 0;
do {
test_get_buffer_from_pool(offset, TEST_RX_BUFFER_SIZE, &tx_buf_ptr);
TEST_ASSERT_EQUAL_HEX8_ARRAY(tx_buf_ptr, &host_rx_buffer[compared_len], TEST_RX_BUFFER_SIZE);
compared_len += TEST_RX_BUFFER_SIZE;
offset += TEST_RX_BUFFER_SIZE;
} while (compared_len < rcv_len);
}
remain_length -= rcv_len;
} while (remain_length > 0);
int64_t c_time_ms = ccomp_timer_stop()/1000;
int64_t end_us = esp_timer_get_time();
uint32_t total_time_ms = (end_us - pre_us)/1000;
ESP_LOGI(TAG, "test done, total time: %" PRIu32 " ms (%d ms compensated), bytes transferred: %"PRIu32, total_time_ms, (int)c_time_ms, expected_length);
uint32_t throughput_byte_per_ms = expected_length / c_time_ms;
ESP_LOGI(TAG, "Throughput: compensated %"PRIu32"KB/s %.2lf MB/s, typical %.2lf MB/s",
throughput_byte_per_ms, throughput_byte_per_ms/1000., expected_length/(total_time_ms*1000.));
esp_rom_delay_us(50 * 1000);
s_send_finish_test(handle);
sdmmc_host_deinit();
}
free(host_rx_buffer);
test_destroy_buffer_pool();
}
TEST_CASE("SDIO_SDMMC: test to host", "[sdio]")
{
test_to_host(true);
}
TEST_CASE("SDIO_SDMMC: test to host (Performance)", "[sdio_speed]")
{
test_to_host(false);
}

View File

@ -0,0 +1,2 @@
# don't delete.
# used for CI to compile a default config when 'sdkconfig.ci.xxxx' is exist

View File

@ -0,0 +1,133 @@
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import os.path
from typing import Tuple
import pytest
from pytest_embedded_idf import IdfDut
# Normal tests
def test_sdio_flow(dut:Tuple[IdfDut, IdfDut]) -> None:
dut[1].expect('Press ENTER to see the list of tests')
dut[1].write('[sdio]')
dut[1].expect('test_sdio: slave ready')
dut[0].expect('Press ENTER to see the list of tests')
dut[0].write('[sdio]')
dut[1].expect_unity_test_output()
dut[0].expect_unity_test_output()
@pytest.mark.esp32c6
@pytest.mark.sdio_multidev_32_c6
@pytest.mark.parametrize('count', [2,], indirect=True)
@pytest.mark.parametrize('app_path, target', [
pytest.param(
f'{os.path.join(os.path.dirname(__file__), "host_sdmmc")}|{os.path.join(os.path.dirname(__file__), "sdio")}',
'esp32|esp32c6'),
], indirect=True)
def test_sdio_esp32_esp32c6(dut:Tuple[IdfDut, IdfDut]) -> None:
test_sdio_flow(dut)
@pytest.mark.esp32
@pytest.mark.sdio_master_slave
@pytest.mark.parametrize('count', [2,], indirect=True)
@pytest.mark.parametrize('app_path, target', [
pytest.param(
f'{os.path.join(os.path.dirname(__file__), "host_sdmmc")}|{os.path.join(os.path.dirname(__file__), "sdio")}',
'esp32|esp32'),
], indirect=True)
def test_sdio_esp32_esp32(dut:Tuple[IdfDut, IdfDut]) -> None:
test_sdio_flow(dut)
# From host speed tests
def test_sdio_speed_frhost_flow(dut:Tuple[IdfDut, IdfDut], expected_4b_speed:int, expected_1b_speed:int) -> None:
dut[1].expect('Press ENTER to see the list of tests')
dut[1].write('"SDIO_Slave: test from host (Performance)"')
dut[1].expect('test_sdio: slave ready')
dut[0].expect('Press ENTER to see the list of tests')
dut[0].write('"SDIO_SDMMC: test from host (Performance)"')
dut[0].expect('Probe using SD 4-bit')
res = dut[0].expect(r'Throughput: compensated (\d+)')
frhost_speed_4bit = res.group(1).decode('utf8')
assert (int(frhost_speed_4bit) > expected_4b_speed)
dut[0].expect('Probe using SD 1-bit')
res = dut[0].expect(r'Throughput: compensated (\d+)')
frhost_speed_1bit = res.group(1).decode('utf8')
assert (int(frhost_speed_1bit) > expected_1b_speed)
@pytest.mark.esp32c6
@pytest.mark.sdio_multidev_32_c6
@pytest.mark.parametrize('count', [2,], indirect=True)
@pytest.mark.parametrize('app_path, target', [
pytest.param(
f'{os.path.join(os.path.dirname(__file__), "host_sdmmc")}|{os.path.join(os.path.dirname(__file__), "sdio")}',
'esp32|esp32c6'),
], indirect=True)
def test_sdio_speed_frhost_esp32_esp32c6(dut:Tuple[IdfDut, IdfDut]) -> None:
test_sdio_speed_frhost_flow(dut, 10000, 4000)
@pytest.mark.esp32
@pytest.mark.sdio_master_slave
@pytest.mark.parametrize('count', [2,], indirect=True)
@pytest.mark.parametrize('app_path, target', [
pytest.param(
f'{os.path.join(os.path.dirname(__file__), "host_sdmmc")}|{os.path.join(os.path.dirname(__file__), "sdio")}',
'esp32|esp32'),
], indirect=True)
def test_sdio_speed_frhost_esp32_esp32(dut:Tuple[IdfDut, IdfDut]) -> None:
test_sdio_speed_frhost_flow(dut, 12200, 4000)
# To host speed tests
def test_sdio_speed_tohost_flow(dut:Tuple[IdfDut, IdfDut], expected_4b_speed:int, expected_1b_speed:int) -> None:
dut[1].expect('Press ENTER to see the list of tests')
dut[1].write('"SDIO_Slave: test to host (Performance)"')
dut[1].expect('test_sdio: slave ready')
dut[0].expect('Press ENTER to see the list of tests')
dut[0].write('"SDIO_SDMMC: test to host (Performance)"')
dut[0].expect('Probe using SD 4-bit')
res = dut[0].expect(r'Throughput: compensated (\d+)')
tohost_speed_4bit = res.group(1).decode('utf8')
assert (int(tohost_speed_4bit) > expected_4b_speed)
dut[0].expect('Probe using SD 1-bit')
res = dut[0].expect(r'Throughput: compensated (\d+)')
tohost_speed_1bit = res.group(1).decode('utf8')
assert (int(tohost_speed_1bit) > expected_1b_speed)
@pytest.mark.esp32c6
@pytest.mark.sdio_multidev_32_c6
@pytest.mark.parametrize('count', [2,], indirect=True)
@pytest.mark.parametrize('app_path, target', [
pytest.param(
f'{os.path.join(os.path.dirname(__file__), "host_sdmmc")}|{os.path.join(os.path.dirname(__file__), "sdio")}',
'esp32|esp32c6'),
], indirect=True)
def test_sdio_speed_tohost_esp32_esp32c6(dut:Tuple[IdfDut, IdfDut]) -> None:
test_sdio_speed_tohost_flow(dut, 9000, 4000)
@pytest.mark.esp32
@pytest.mark.sdio_master_slave
@pytest.mark.parametrize('count', [2,], indirect=True)
@pytest.mark.parametrize('app_path, target', [
pytest.param(
f'{os.path.join(os.path.dirname(__file__), "host_sdmmc")}|{os.path.join(os.path.dirname(__file__), "sdio")}',
'esp32|esp32'),
], indirect=True)
def test_sdio_speed_tohost_esp32_esp32(dut:Tuple[IdfDut, IdfDut]) -> None:
test_sdio_speed_tohost_flow(dut, 12200, 4000)

View File

@ -10,4 +10,4 @@ set(EXTRA_COMPONENT_DIRS
)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(sdio_test)
project(sdio)

View File

@ -0,0 +1,6 @@
| Supported Targets | ESP32 | ESP32-C6 |
| ----------------- | ----- | -------- |
# SDIO Cross Chips Test Apps: SDIO Slave App
This test app is to test ESP SDIO Slave peripheral.

View File

@ -0,0 +1,6 @@
set(srcs "test_app_main.c"
"test_sdio_slave.c")
idf_component_register(SRCS ${srcs}
PRIV_REQUIRES test_driver_utils driver
WHOLE_ARCHIVE)

View File

@ -1,19 +1,20 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include "unity.h"
#include "unity_test_utils.h"
#include "esp_heap_caps.h"
#define TEST_MEMORY_LEAK_THRESHOLD (200)
// Some resources are lazy allocated, the threadhold is left for that case
#define TEST_MEMORY_LEAK_THRESHOLD (300)
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);
@ -22,27 +23,28 @@ void setUp(void)
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");
printf(" / ___// __ \\/ _/ __ \\ / ___// /___ __ _____ \n");
printf(" \\__ \\/ / / // // / / / \\__ \\/ / __ `/ | / / _ \\\n");
printf(" ___/ / /_/ // // /_/ / ___/ / / /_/ /| |/ / __/\n");
printf("/____/_____/___/\\____/ /____/_/\\__,_/ |___/\\___/\n");
unity_run_menu();
}

View File

@ -0,0 +1,303 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* This file uses ESP32 SDMMC peripheral to test SDIO Slave peripheral SD modes
*/
#include "unity.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/sdio_slave.h"
#include "soc/soc_caps.h"
#include "soc/sdio_slave_pins.h"
#include "test_dualboard_utils.h"
#include "../../sdio_common_test.h"
#define TEST_HEX_LOG_LEVEL ESP_LOG_DEBUG
#define TEST_SDIO_SLAVE_QUEUE_SIZE 20
static const char *TAG = "test_sdio";
/*---------------------------------------------------------------
Slave Init Settings
---------------------------------------------------------------*/
typedef struct {
int queued_cnt;
bool s_finished;
} s_test_slv_ctx_t;
static s_test_slv_ctx_t s_test_slv_ctx;
//callback to event 7, indicating test finish in these tests
static void s_event_cb(uint8_t event)
{
ESP_EARLY_LOGI(TAG, "event: %d", event);
sdio_slave_send_host_int(event);
if (event == 7) {
s_test_slv_ctx.s_finished = true;
}
}
static void wait_for_finish(s_test_slv_ctx_t *ctx)
{
while (!ctx->s_finished) {
vTaskDelay(10);
}
//wait for host to read the respond from slave
vTaskDelay(10);
}
static void s_slave_init(sdio_slave_sending_mode_t mode)
{
s_test_slv_ctx.s_finished = false;
s_test_slv_ctx.queued_cnt = 0;
sdio_slave_config_t slave_config = {
.sending_mode = mode,
.send_queue_size = TEST_SDIO_SLAVE_QUEUE_SIZE,
.recv_buffer_size = TEST_RX_BUFFER_SIZE,
.event_cb = s_event_cb,
};
TEST_ESP_OK(sdio_slave_initialize(&slave_config));
}
#include "esp_rom_sys.h"
/*---------------------------------------------------------------
Function Tests
---------------------------------------------------------------*/
/*---------------------------------------------------------------
SDMMC_SDIO: test interrupt
---------------------------------------------------------------*/
TEST_CASE("SDIO_Slave: test interrupt", "[sdio]")
{
s_slave_init(SDIO_SLAVE_SEND_STREAM);
TEST_ESP_OK(sdio_slave_start());
ESP_LOGI(TAG, "slave ready");
wait_for_finish(&s_test_slv_ctx);
sdio_slave_stop();
sdio_slave_deinit();
}
/*---------------------------------------------------------------
SDMMC_SDIO: test register
---------------------------------------------------------------*/
TEST_CASE("SDIO_Slave: test register", "[sdio]")
{
s_slave_init(SDIO_SLAVE_SEND_STREAM);
TEST_ESP_OK(sdio_slave_start());
ESP_LOGI(TAG, "slave ready");
wait_for_finish(&s_test_slv_ctx);
sdio_slave_stop();
sdio_slave_deinit();
}
/*---------------------------------------------------------------
SDMMC_SDIO: test reset
---------------------------------------------------------------*/
TEST_CASE("SDIO_Slave: test reset", "[sdio]")
{
s_slave_init(SDIO_SLAVE_SEND_PACKET);
TEST_ESP_OK(sdio_slave_start());
ESP_LOGI(TAG, "slave ready");
sdio_slave_stop();
TEST_ESP_OK(sdio_slave_reset());
TEST_ESP_OK(sdio_slave_start());
//tx
WORD_ALIGNED_ATTR uint8_t slave_tx_buffer[TEST_RESET_BUF_NUMS][TEST_RESET_DATA_LEN] = {};
for (int i = 0; i < TEST_RESET_BUF_NUMS; i++) {
test_fill_random_to_buffer(i, slave_tx_buffer[i], TEST_RESET_DATA_LEN);
TEST_ESP_OK(sdio_slave_send_queue(slave_tx_buffer[i], TEST_RESET_DATA_LEN, (void *)i, portMAX_DELAY));
}
//rx
sdio_slave_buf_handle_t buf_handle[TEST_RESET_BUF_NUMS] = {};
WORD_ALIGNED_ATTR uint8_t slave_rx_buffer[TEST_RESET_BUF_NUMS][TEST_RESET_DATA_LEN] = {};
for (int i = 0; i < TEST_RESET_BUF_NUMS; i++) {
buf_handle[i] = sdio_slave_recv_register_buf(slave_rx_buffer[i]);
TEST_ASSERT(buf_handle[i]);
TEST_ESP_OK(sdio_slave_recv_load_buf(buf_handle[i]));
}
for (int i = 0; i < TEST_RESET_BUF_NUMS; i++) {
void* arg;
TEST_ESP_OK(sdio_slave_send_get_finished(&arg, portMAX_DELAY));
TEST_ASSERT_EQUAL(i, arg);
}
WORD_ALIGNED_ATTR uint8_t host_tx_buffer[TEST_RESET_DATA_LEN] = {};
for (int i = 0; i < TEST_RESET_BUF_NUMS; i++) {
test_fill_random_to_buffer(i, host_tx_buffer, TEST_RESET_DATA_LEN);
uint8_t* addr;
size_t size;
sdio_slave_buf_handle_t recv_handle;
TEST_ESP_OK(sdio_slave_recv(&recv_handle, &addr, &size, portMAX_DELAY));
TEST_ASSERT_EQUAL(TEST_RESET_DATA_LEN, size);
TEST_ASSERT_EQUAL_HEX8_ARRAY(host_tx_buffer, addr, size);
}
wait_for_finish(&s_test_slv_ctx);
sdio_slave_stop();
sdio_slave_deinit();
}
/*---------------------------------------------------------------
Transaction Tests
---------------------------------------------------------------*/
#define TEST_SLAVE_TRANS_BUF_NUMS 10
/*---------------------------------------------------------------
From Host Tests
---------------------------------------------------------------*/
static void test_from_host(bool check_data)
{
//prepare buffer
test_prepare_buffer_pool(TEST_RX_BUFFER_SIZE * 4, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA);
uint8_t *slave_rx_buffer[TEST_SLAVE_TRANS_BUF_NUMS] = {};
for (int i = 0; i < TEST_SLAVE_TRANS_BUF_NUMS; i++) {
slave_rx_buffer[i] = (uint8_t *)heap_caps_calloc(1, TEST_RX_BUFFER_SIZE, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA);
TEST_ASSERT(slave_rx_buffer[i]);
}
for (int i = 0; i < TEST_TARNS_PARAM_NUMS; i++) {
//slave init
s_slave_init(SDIO_SLAVE_SEND_STREAM);
TEST_ESP_OK(sdio_slave_start());
ESP_LOGI(TAG, "slave ready");
//slave load rx buffer
sdio_slave_buf_handle_t buf_handle[TEST_SLAVE_TRANS_BUF_NUMS] = {};
for (int j = 0; j < TEST_SLAVE_TRANS_BUF_NUMS; j++) {
buf_handle[j] = sdio_slave_recv_register_buf(slave_rx_buffer[j]);
TEST_ASSERT(buf_handle[j]);
TEST_ESP_OK(sdio_slave_recv_load_buf(buf_handle[j]));
}
void *tx_buf_ptr = NULL;
for (int j = 0; j < TEST_TRANS_NUMS; j++) {
ESP_LOGD(TAG, "j: %d", j);
sdio_slave_buf_handle_t used_buf_handle = NULL;
uint8_t* buf = NULL;
size_t rcv_len = 0;
TEST_ESP_OK(sdio_slave_recv(&used_buf_handle, &buf, &rcv_len, portMAX_DELAY));
ESP_LOGD(TAG, "rcv_len: 0d%d", rcv_len);
ESP_LOG_BUFFER_HEX_LEVEL(TAG, buf, TEST_RX_BUFFER_SIZE, TEST_HEX_LOG_LEVEL);
if (check_data) {
test_get_buffer_from_pool(j, TEST_RX_BUFFER_SIZE, &tx_buf_ptr);
ESP_LOG_BUFFER_HEX_LEVEL("Expect data", tx_buf_ptr, TEST_RX_BUFFER_SIZE, TEST_HEX_LOG_LEVEL);
TEST_ASSERT_EQUAL_HEX8_ARRAY(tx_buf_ptr, buf, rcv_len);
}
TEST_ESP_OK(sdio_slave_recv_load_buf(used_buf_handle));
}
wait_for_finish(&s_test_slv_ctx);
sdio_slave_stop();
sdio_slave_deinit();
}
for (int i = 0; i < TEST_SLAVE_TRANS_BUF_NUMS; i++) {
free(slave_rx_buffer[i]);
}
test_destroy_buffer_pool();
}
TEST_CASE("SDIO_Slave: test from host", "[sdio]")
{
test_from_host(true);
}
TEST_CASE("SDIO_Slave: test from host (Performance)", "[sdio_speed]")
{
test_from_host(false);
}
/*---------------------------------------------------------------
To Host Tests
---------------------------------------------------------------*/
#define QUEUE_FULL() (s_test_slv_ctx.queued_cnt == TEST_SDIO_SLAVE_QUEUE_SIZE)
#define QUEUE_EMPTY() (s_test_slv_ctx.queued_cnt == 0)
static void test_to_host(void)
{
//prepare buffer
test_prepare_buffer_pool(TEST_RX_BUFFER_SIZE * 21, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA);
for (int i = 0; i < TEST_TARNS_PARAM_NUMS; i++) {
//slave init
s_slave_init(SDIO_SLAVE_SEND_STREAM);
TEST_ESP_OK(sdio_slave_start());
ESP_LOGI(TAG, "slave ready");
esp_err_t err = ESP_OK;
int offset = 0;
void *tx_buf_ptr = NULL;
for (int j = 0; j < TEST_TRANS_NUMS; j++) {
do {
void* arg;
//when the queue is full, do a blocking wait for 10ms, otherwise non-blocking
err = sdio_slave_send_get_finished(&arg, QUEUE_FULL()? 1: 0);
if (err == ESP_OK) {
s_test_slv_ctx.queued_cnt --;
continue;
}
TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, err);
} while (QUEUE_FULL());
test_get_buffer_from_pool(offset, TEST_RX_BUFFER_SIZE, &tx_buf_ptr);
TEST_ESP_OK(sdio_slave_send_queue((uint8_t *)tx_buf_ptr, TEST_RX_BUFFER_SIZE, NULL, portMAX_DELAY));
s_test_slv_ctx.queued_cnt++;
offset += TEST_RX_BUFFER_SIZE;
}
while (!QUEUE_EMPTY()) {
void* arg;
TEST_ESP_OK(sdio_slave_send_get_finished(&arg, portMAX_DELAY));
s_test_slv_ctx.queued_cnt--;
}
wait_for_finish(&s_test_slv_ctx);
sdio_slave_stop();
sdio_slave_deinit();
}
test_destroy_buffer_pool();
}
TEST_CASE("SDIO_Slave: test to host", "[sdio]")
{
test_to_host();
}
TEST_CASE("SDIO_Slave: test to host (Performance)", "[sdio_speed]")
{
test_to_host();
}

View File

@ -0,0 +1,2 @@
# don't delete.
# used for CI to compile a default config when 'sdkconfig.ci.xxxx' is exist

View File

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

View File

@ -0,0 +1,42 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "sdkconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
#define TEST_RX_BUFFER_SIZE 2048
/*---------------------------------------------------------------
Function Tests
---------------------------------------------------------------*/
/*---------------------------------------------------------------
SDMMC_SDIO: test reset
---------------------------------------------------------------*/
#define TEST_RESET_DATA_LEN 12
#define TEST_RESET_BUF_NUMS 10
/*---------------------------------------------------------------
Transaction Tests
---------------------------------------------------------------*/
#define TEST_TARNS_PARAM_NUMS 2
/*---------------------------------------------------------------
SDMMC_SDIO: test from host
---------------------------------------------------------------*/
#define TEST_TRANS_NUMS 10000
#ifdef __cplusplus
}
#endif

View File

@ -1217,12 +1217,12 @@ static void fd_master(void)
//Master FD DMA, RX without TX Test
for (int i = 0; i < TEST_NUM; i++) {
// 1. Master FD DMA, only receive, with NULL tx_buffer
get_tx_buffer(FD_SEED1 + i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
test_fill_random_to_buffers_dualboard(FD_SEED1 + i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
memset(mst_recv_buf, 0x0, FD_TEST_BUF_SIZE);
master_only_rx_trans(spi, mst_recv_buf, slv_send_buf, FD_TEST_BUF_SIZE);
//2. Master FD DMA with TX and RX
get_tx_buffer(FD_SEED2 + i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
test_fill_random_to_buffers_dualboard(FD_SEED2 + i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
memset(mst_recv_buf, 0x0, FD_TEST_BUF_SIZE);
master_both_trans(spi, mst_send_buf, mst_recv_buf, slv_send_buf, FD_TEST_BUF_SIZE);
}
@ -1230,11 +1230,11 @@ static void fd_master(void)
//Master FD DMA, TX without RX Test
for (int i = 0; i < TEST_NUM; i++) {
// 1. Master FD DMA, only send, with NULL rx_buffer
get_tx_buffer(FD_SEED3 + i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
test_fill_random_to_buffers_dualboard(FD_SEED3 + i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
master_only_tx_trans(spi, mst_send_buf, FD_TEST_BUF_SIZE);
//2. Master FD DMA with TX and RX
get_tx_buffer(FD_SEED4 + i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
test_fill_random_to_buffers_dualboard(FD_SEED4 + i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
memset(mst_recv_buf, 0x0, FD_TEST_BUF_SIZE);
master_both_trans(spi, mst_send_buf, mst_recv_buf, slv_send_buf, FD_TEST_BUF_SIZE);
}
@ -1299,23 +1299,23 @@ static void fd_slave(void)
for (int i = 0; i < TEST_NUM; i++) {
//1. Slave TX without RX (rx_buffer == NULL)
get_tx_buffer(FD_SEED1 + i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
test_fill_random_to_buffers_dualboard(FD_SEED1 + i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
slave_only_tx_trans(slv_send_buf, FD_TEST_BUF_SIZE);
//2. Slave both TX and RX
get_tx_buffer(FD_SEED2 + i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
test_fill_random_to_buffers_dualboard(FD_SEED2 + i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
memset(slv_recv_buf, 0x0, FD_TEST_BUF_SIZE);
slave_both_trans(slv_send_buf, slv_recv_buf, mst_send_buf, FD_TEST_BUF_SIZE);
}
for (int i = 0; i < TEST_NUM; i++) {
// 1. Slave RX without TX (tx_buffer == NULL)
get_tx_buffer(FD_SEED3 + i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
test_fill_random_to_buffers_dualboard(FD_SEED3 + i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
memset(slv_recv_buf, 0x0, FD_TEST_BUF_SIZE);
slave_only_rx_trans(slv_recv_buf, mst_send_buf, FD_TEST_BUF_SIZE);
//2. Slave both TX and RX
get_tx_buffer(FD_SEED4 + i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
test_fill_random_to_buffers_dualboard(FD_SEED4 + i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
memset(slv_recv_buf, 0x0, FD_TEST_BUF_SIZE);
slave_both_trans(slv_send_buf, slv_recv_buf, mst_send_buf, FD_TEST_BUF_SIZE);
}
@ -1530,7 +1530,7 @@ void test_add_device_master(void)
TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &dev_cfg, &devs[i]));
memset(master_recvbuf, 0, sizeof(master_recvbuf));
get_tx_buffer(21, master_sendbuf, master_expect, TEST_TRANS_LEN);
test_fill_random_to_buffers_dualboard(21, master_sendbuf, master_expect, TEST_TRANS_LEN);
unity_send_signal("Master ready");
unity_wait_for_signal("Slave ready");
@ -1573,7 +1573,7 @@ void test_add_device_slave(void)
for (uint8_t i = 0; i < SOC_SPI_MAX_CS_NUM; i++) {
memset(slave_recvbuf, 0, sizeof(slave_recvbuf));
get_tx_buffer(21, slave_expect, slave_sendbuf, TEST_TRANS_LEN);
test_fill_random_to_buffers_dualboard(21, slave_expect, slave_sendbuf, TEST_TRANS_LEN);
unity_wait_for_signal("Master ready");
unity_send_signal("Slave ready");
@ -1671,7 +1671,7 @@ static IRAM_ATTR void test_master_iram(void)
uint8_t *master_send = heap_caps_malloc(TEST_MASTER_IRAM_TRANS_LEN, MALLOC_CAP_DMA);
uint8_t *master_recv = heap_caps_calloc(1, TEST_MASTER_IRAM_TRANS_LEN, MALLOC_CAP_DMA);
uint8_t *master_exp = heap_caps_malloc(TEST_MASTER_IRAM_TRANS_LEN, MALLOC_CAP_DEFAULT);
get_tx_buffer(211, master_send, master_exp, TEST_MASTER_IRAM_TRANS_LEN);
test_fill_random_to_buffers_dualboard(211, master_send, master_exp, TEST_MASTER_IRAM_TRANS_LEN);
spi_transaction_t trans_cfg = {
.tx_buffer = master_send,
.rx_buffer = master_recv,
@ -1698,7 +1698,7 @@ static IRAM_ATTR void test_master_iram(void)
// Test polling trans api once -------------------------------
unity_wait_for_signal("Slave ready");
get_tx_buffer(119, master_send, master_exp, TEST_MASTER_IRAM_TRANS_LEN);
test_fill_random_to_buffers_dualboard(119, master_send, master_exp, TEST_MASTER_IRAM_TRANS_LEN);
spi_flash_disable_interrupts_caches_and_other_cpu();
spi_device_polling_transmit(dev_handle, &trans_cfg);
@ -1729,7 +1729,7 @@ static void test_iram_slave_normal(void)
slave_trans.length = TEST_MASTER_IRAM_TRANS_LEN * 8;
slave_trans.tx_buffer = slave_sendbuf;
slave_trans.rx_buffer = slave_recvbuf;
get_tx_buffer(211, slave_expect, slave_sendbuf, TEST_MASTER_IRAM_TRANS_LEN);
test_fill_random_to_buffers_dualboard(211, slave_expect, slave_sendbuf, TEST_MASTER_IRAM_TRANS_LEN);
unity_wait_for_signal("Master ready");
unity_send_signal("Slave ready");
@ -1739,7 +1739,7 @@ static void test_iram_slave_normal(void)
spitest_cmp_or_dump(slave_expect, slave_recvbuf, TEST_MASTER_IRAM_TRANS_LEN);
unity_send_signal("Slave ready");
get_tx_buffer(119, slave_expect, slave_sendbuf, TEST_MASTER_IRAM_TRANS_LEN);
test_fill_random_to_buffers_dualboard(119, slave_expect, slave_sendbuf, TEST_MASTER_IRAM_TRANS_LEN);
spi_slave_transmit(TEST_SPI_HOST, &slave_trans, portMAX_DELAY);
ESP_LOG_BUFFER_HEX("slave tx", slave_sendbuf, TEST_MASTER_IRAM_TRANS_LEN);
ESP_LOG_BUFFER_HEX("slave rx", slave_recvbuf, TEST_MASTER_IRAM_TRANS_LEN);

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -1314,7 +1314,7 @@ static void test_master_fd_dma(void)
unity_send_signal("Master ready");
for (int i = 0; i < TEST_STEP; i++) {
memset(master_recive, 0x00, TEST_STEP_LEN);
get_tx_buffer(119 + mode + speed_level + i, master_send, master_expect, TEST_STEP_LEN);
test_fill_random_to_buffers_dualboard(119 + mode + speed_level + i, master_send, master_expect, TEST_STEP_LEN);
uint32_t test_trans_len = TEST_STEP_LEN;
spi_transaction_t trans_cfg = {
@ -1365,7 +1365,7 @@ static void test_slave_fd_dma(void)
unity_wait_for_signal("Master ready");
for (int i = 0; i < TEST_STEP; i++) {
memset(slave_recive, 0x00, TEST_STEP_LEN);
get_tx_buffer(119 + mode + speed_level + i, slave_expect, slave_send, TEST_STEP_LEN);
test_fill_random_to_buffers_dualboard(119 + mode + speed_level + i, slave_expect, slave_send, TEST_STEP_LEN);
uint32_t test_trans_len = TEST_STEP_LEN;
spi_slave_transaction_t trans_cfg = {
@ -1429,7 +1429,7 @@ static void test_master_fd_no_dma(void)
unity_send_signal("Master ready");
for (int i = 0; i < TEST_STEP; i++) {
memset(master_recive, 0x00, SOC_SPI_MAXIMUM_BUFFER_SIZE);
get_tx_buffer(211 + mode + speed_level + i, master_send, master_expect, SOC_SPI_MAXIMUM_BUFFER_SIZE);
test_fill_random_to_buffers_dualboard(211 + mode + speed_level + i, master_send, master_expect, SOC_SPI_MAXIMUM_BUFFER_SIZE);
uint32_t test_trans_len = SOC_SPI_MAXIMUM_BUFFER_SIZE;
spi_transaction_t trans_cfg = {
@ -1481,7 +1481,7 @@ static void test_slave_fd_no_dma(void)
unity_wait_for_signal("Master ready");
for (int i = 0; i < TEST_STEP; i++) {
memset(slave_recive, 0x00, SOC_SPI_MAXIMUM_BUFFER_SIZE);
get_tx_buffer(211 + mode + speed_level + i, slave_expect, slave_send, SOC_SPI_MAXIMUM_BUFFER_SIZE);
test_fill_random_to_buffers_dualboard(211 + mode + speed_level + i, slave_expect, slave_send, SOC_SPI_MAXIMUM_BUFFER_SIZE);
uint32_t test_trans_len = SOC_SPI_MAXIMUM_BUFFER_SIZE;
spi_slave_transaction_t trans_cfg = {
@ -1536,7 +1536,7 @@ static void test_master_hd_dma(void)
unity_send_signal("Master ready");
for (int i = 0; i < TEST_STEP; i++) {
memset(master_recive, 0x00, TEST_STEP_LEN);
get_tx_buffer(985 + mode + speed_level + i, master_send, master_expect, TEST_STEP_LEN);
test_fill_random_to_buffers_dualboard(985 + mode + speed_level + i, master_send, master_expect, TEST_STEP_LEN);
uint32_t test_trans_len = TEST_STEP_LEN;
unity_wait_for_signal("Slave ready");
@ -1580,7 +1580,7 @@ static void test_slave_hd_dma(void)
unity_wait_for_signal("Master ready");
for (int i = 0; i < TEST_STEP; i++) {
memset(slave_recive, 0x00, TEST_STEP_LEN);
get_tx_buffer(985 + mode + speed_level + i, slave_expect, slave_send, TEST_STEP_LEN);
test_fill_random_to_buffers_dualboard(985 + mode + speed_level + i, slave_expect, slave_send, TEST_STEP_LEN);
uint32_t test_trans_len = TEST_STEP_LEN;
spi_slave_hd_data_t *ret_trans, slave_trans = {
@ -1637,7 +1637,7 @@ static void test_master_hd_no_dma(void)
unity_send_signal("Master ready");
for (int i = 0; i < TEST_STEP; i++) {
memset(master_recive, 0x00, SOC_SPI_MAXIMUM_BUFFER_SIZE);
get_tx_buffer(911 + mode + speed_level + i, master_send, master_expect, SOC_SPI_MAXIMUM_BUFFER_SIZE);
test_fill_random_to_buffers_dualboard(911 + mode + speed_level + i, master_send, master_expect, SOC_SPI_MAXIMUM_BUFFER_SIZE);
uint32_t test_trans_len = SOC_SPI_MAXIMUM_BUFFER_SIZE;
unity_wait_for_signal("Slave ready");
@ -1681,7 +1681,7 @@ static void test_slave_hd_no_dma(void)
unity_wait_for_signal("Master ready");
for (int i = 0; i < TEST_STEP; i++) {
memset(slave_recive, 0x00, SOC_SPI_MAXIMUM_BUFFER_SIZE);
get_tx_buffer(911 + mode + speed_level + i, slave_expect, slave_send, SOC_SPI_MAXIMUM_BUFFER_SIZE);
test_fill_random_to_buffers_dualboard(911 + mode + speed_level + i, slave_expect, slave_send, SOC_SPI_MAXIMUM_BUFFER_SIZE);
uint32_t test_trans_len = SOC_SPI_MAXIMUM_BUFFER_SIZE;
spi_slave_hd_data_t *ret_trans, slave_trans = {
@ -1756,7 +1756,7 @@ static void test_master_sio_dma(void)
unity_send_signal("Master ready");
for (int i = 0; i < TEST_STEP; i++) {
memset(master_recive, 0x00, TEST_STEP_LEN);
get_tx_buffer(110 + mode + speed_level + i, master_send, master_expect, TEST_STEP_LEN);
test_fill_random_to_buffers_dualboard(110 + mode + speed_level + i, master_send, master_expect, TEST_STEP_LEN);
spi_transaction_t trans = {};
if (sio_master_in) {
// master input only
@ -1818,7 +1818,7 @@ static void test_slave_sio_dma(void)
unity_wait_for_signal("Master ready");
for (int i = 0; i < TEST_STEP; i++) {
memset(slave_recive, 0x00, TEST_STEP_LEN);
get_tx_buffer(110 + mode + speed_level + i, slave_expect, slave_send, TEST_STEP_LEN);
test_fill_random_to_buffers_dualboard(110 + mode + speed_level + i, slave_expect, slave_send, TEST_STEP_LEN);
spi_slave_transaction_t trans = {
.length = TEST_STEP_LEN * 8,
.tx_buffer = slave_send,
@ -1888,7 +1888,7 @@ static void test_master_sio_no_dma(void)
unity_send_signal("Master ready");
for (int i = 0; i < TEST_STEP; i++) {
memset(master_recive, 0x00, SOC_SPI_MAXIMUM_BUFFER_SIZE);
get_tx_buffer(122 + mode + speed_level + i, master_send, master_expect, SOC_SPI_MAXIMUM_BUFFER_SIZE);
test_fill_random_to_buffers_dualboard(122 + mode + speed_level + i, master_send, master_expect, SOC_SPI_MAXIMUM_BUFFER_SIZE);
spi_transaction_t trans = {};
if (sio_master_in) {
// master input only
@ -1951,7 +1951,7 @@ static void test_slave_sio_no_dma(void)
unity_wait_for_signal("Master ready");
for (int i = 0; i < TEST_STEP; i++) {
memset(slave_recive, 0x00, SOC_SPI_MAXIMUM_BUFFER_SIZE);
get_tx_buffer(122 + mode + speed_level + i, slave_expect, slave_send, SOC_SPI_MAXIMUM_BUFFER_SIZE);
test_fill_random_to_buffers_dualboard(122 + mode + speed_level + i, slave_expect, slave_send, SOC_SPI_MAXIMUM_BUFFER_SIZE);
spi_slave_transaction_t trans = {
.length = SOC_SPI_MAXIMUM_BUFFER_SIZE * 8,
.tx_buffer = slave_send,

View File

@ -409,7 +409,7 @@ static void test_slave_iram_master_normal(void)
uint8_t *master_send = heap_caps_malloc(TEST_BUFFER_SZ, MALLOC_CAP_DMA);
uint8_t *master_recv = heap_caps_calloc(1, TEST_BUFFER_SZ, MALLOC_CAP_DMA);
uint8_t *master_exp = heap_caps_malloc(TEST_BUFFER_SZ, MALLOC_CAP_DEFAULT);
get_tx_buffer(1001, master_send, master_exp, TEST_BUFFER_SZ);
test_fill_random_to_buffers_dualboard(1001, master_send, master_exp, TEST_BUFFER_SZ);
spi_transaction_t trans_cfg = {
.tx_buffer = master_send,
.rx_buffer = master_recv,
@ -490,7 +490,7 @@ static IRAM_ATTR void test_slave_isr_iram(void)
uint8_t *slave_iram_send = heap_caps_aligned_alloc(64, TEST_BUFFER_SZ, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
uint8_t *slave_iram_recv = heap_caps_aligned_alloc(64, TEST_BUFFER_SZ, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
uint8_t *slave_iram_exp = heap_caps_malloc(TEST_BUFFER_SZ, MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL);
get_tx_buffer(1001, slave_iram_exp, slave_iram_send, TEST_BUFFER_SZ);
test_fill_random_to_buffers_dualboard(1001, slave_iram_exp, slave_iram_send, TEST_BUFFER_SZ);
spi_slave_transaction_t trans_cfg[TEST_IRAM_TRANS_NUM] = {0};
unity_wait_for_signal("Master ready");
@ -570,7 +570,7 @@ static IRAM_ATTR void spi_slave_trans_in_isr(void)
uint8_t *slave_isr_send = heap_caps_aligned_alloc(64, TEST_BUFFER_SZ, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
uint8_t *slave_isr_recv = heap_caps_aligned_alloc(64, TEST_BUFFER_SZ, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
uint8_t *slave_isr_exp = heap_caps_malloc(TEST_BUFFER_SZ, MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL);
get_tx_buffer(1001, slave_isr_exp, slave_isr_send, TEST_BUFFER_SZ);
test_fill_random_to_buffers_dualboard(1001, slave_isr_exp, slave_isr_send, TEST_BUFFER_SZ);
spi_slave_transaction_t trans_cfg = {
.tx_buffer = slave_isr_send,
.rx_buffer = slave_isr_recv,
@ -654,8 +654,8 @@ static IRAM_ATTR void spi_queue_reset_in_isr(void)
uint8_t *slave_isr_recv = heap_caps_aligned_alloc(64, TEST_BUFFER_SZ, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
uint8_t *dummy_data = heap_caps_aligned_alloc(64, 64 * 2, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
uint8_t *slave_isr_exp = heap_caps_malloc(TEST_BUFFER_SZ, MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL);
get_tx_buffer(1001, slave_isr_exp, slave_isr_send, TEST_BUFFER_SZ);
get_tx_buffer(1001, dummy_data, dummy_data + 64, 64);
test_fill_random_to_buffers_dualboard(1001, slave_isr_exp, slave_isr_send, TEST_BUFFER_SZ);
test_fill_random_to_buffers_dualboard(1001, dummy_data, dummy_data + 64, 64);
spi_slave_transaction_t trans_cfg = {
.tx_buffer = slave_isr_send,
.rx_buffer = slave_isr_recv,

View File

@ -49,7 +49,7 @@ static void test_master(void)
mst_tx_buf[i] = heap_caps_calloc(TEST_BUF_SIZE, 1, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
mst_rx_buf[i] = heap_caps_calloc(TEST_BUF_SIZE, 1, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
slv_tx_buf[i] = heap_caps_calloc(TEST_BUF_SIZE, 1, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
get_tx_buffer(test_seed, mst_tx_buf[i], slv_tx_buf[i], TEST_BUF_SIZE);
test_fill_random_to_buffers_dualboard(test_seed, mst_tx_buf[i], slv_tx_buf[i], TEST_BUF_SIZE);
}
//Trans0
@ -133,7 +133,7 @@ static void test_slave(void)
slv_tx_buf[i] = heap_caps_calloc(TEST_BUF_SIZE, 1, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
slv_rx_buf[i] = heap_caps_calloc(TEST_BUF_SIZE, 1, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
mst_tx_buf[i] = heap_caps_calloc(TEST_BUF_SIZE, 1, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
get_tx_buffer(test_seed, mst_tx_buf[i], slv_tx_buf[i], TEST_BUF_SIZE);
test_fill_random_to_buffers_dualboard(test_seed, mst_tx_buf[i], slv_tx_buf[i], TEST_BUF_SIZE);
}
spi_slave_transaction_t trans[TEST_TIMES] = {};

View File

@ -12,6 +12,7 @@
#include "test_spi_utils.h"
#include "soc/spi_periph.h"
#include "esp_serial_slave_link/essl_spi.h"
#include "test_dualboard_utils.h"
#if SOC_SPI_SUPPORT_SLAVE_HD_VER2
#include "driver/spi_slave_hd.h"
@ -649,7 +650,7 @@ 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 * 2);
test_fill_random_to_buffers_dualboard(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};
@ -700,7 +701,7 @@ static void hd_slave(void)
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 * 2);
test_fill_random_to_buffers_dualboard(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};
@ -793,7 +794,7 @@ static void hd_master_quad(void)
WORD_ALIGNED_ATTR uint8_t *master_recv_buf = heap_caps_calloc(BUF_SIZE, 1, MALLOC_CAP_DMA);
//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 = heap_caps_malloc(BUF_SIZE, MALLOC_CAP_DMA);
get_tx_buffer(199, master_send_buf, slave_send_buf, BUF_SIZE);
test_fill_random_to_buffers_dualboard(199, master_send_buf, slave_send_buf, BUF_SIZE);
unity_send_signal("Master ready");
unity_wait_for_signal("slave ready");
@ -848,7 +849,7 @@ static void hd_slave_quad(void)
WORD_ALIGNED_ATTR uint8_t *slave_recv_buf = heap_caps_calloc(BUF_SIZE, 1, MALLOC_CAP_DMA);
//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 = heap_caps_malloc(BUF_SIZE, MALLOC_CAP_DMA);
get_tx_buffer(199, master_send_buf, slave_send_buf, BUF_SIZE);
test_fill_random_to_buffers_dualboard(199, master_send_buf, slave_send_buf, BUF_SIZE);
int trans_len = BUF_SIZE / 2;
spi_slave_hd_data_t slave_trans[4] = {

View File

@ -45,3 +45,31 @@
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_NO_FILTER 3
#define IDF_PERFORMANCE_MAX_ADC_ONESHOT_STD_ATTEN3 3
//SDIO
#ifndef IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_TOHOST_4BIT
#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_TOHOST_4BIT 12200
#endif
#if !CONFIG_FREERTOS_SMP // IDF-5224
#ifndef IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_FRHOST_4BIT
#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_FRHOST_4BIT 11000 // TODO: IDF-5490
#endif
#else
#ifndef IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_FRHOST_4BIT
#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_FRHOST_4BIT 12200
#endif
#endif
#ifndef IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_TOHOST_1BIT
#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_TOHOST_1BIT 4000
#endif
#ifndef IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_FRHOST_1BIT
#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_FRHOST_1BIT 4000
#endif
#ifndef IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_TOHOST_SPI
#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_TOHOST_SPI 1000
#endif
#ifndef IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_FRHOST_SPI
#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_FRHOST_SPI 1000
#endif

View File

@ -30,3 +30,23 @@
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_16 10
#define IDF_PERFORMANCE_MAX_ADC_CONTINUOUS_STD_ATTEN3_FILTER_64 10
#define IDF_PERFORMANCE_MAX_ADC_ONESHOT_STD_ATTEN3 10
//SDIO
#ifndef IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_TOHOST_4BIT
#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_TOHOST_4BIT 9000
#endif
#ifndef IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_FRHOST_4BIT
#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_FRHOST_4BIT 10000
#endif
#ifndef IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_TOHOST_1BIT
#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_TOHOST_1BIT 4000
#endif
#ifndef IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_FRHOST_1BIT
#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_FRHOST_1BIT 4000
#endif
#ifndef IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_TOHOST_SPI
#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_TOHOST_SPI 1000
#endif
#ifndef IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_FRHOST_SPI
#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_FRHOST_SPI 1000
#endif

View File

@ -95,33 +95,6 @@
#define IDF_PERFORMANCE_MAX_ISR_EXIT_CYCLES 565
#endif
#ifndef IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_TOHOST_4BIT
#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_TOHOST_4BIT 12200
#endif
#if !CONFIG_FREERTOS_SMP // IDF-5224
#ifndef IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_FRHOST_4BIT
#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_FRHOST_4BIT 11000 // TODO: IDF-5490
#endif
#else
#ifndef IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_FRHOST_4BIT
#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_FRHOST_4BIT 12200
#endif
#endif
#ifndef IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_TOHOST_1BIT
#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_TOHOST_1BIT 4000
#endif
#ifndef IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_FRHOST_1BIT
#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_FRHOST_1BIT 4000
#endif
#ifndef IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_TOHOST_SPI
#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_TOHOST_SPI 1000
#endif
#ifndef IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_FRHOST_SPI
#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_KBSEC_FRHOST_SPI 1000
#endif
//time to perform the task selection plus context switch (from task)
#ifndef IDF_PERFORMANCE_MAX_SCHEDULING_TIME
#define IDF_PERFORMANCE_MAX_SCHEDULING_TIME 2000

View File

@ -105,7 +105,8 @@ ENV_MARKERS = {
'wifi_two_dut': 'tests should be run on runners which has two wifi duts connected.',
'generic_multi_device': 'generic multiple devices whose corresponding gpio pins are connected to each other.',
'twai_network': 'multiple runners form a TWAI network.',
'sdio_master_slave': 'Test sdio multi board.',
'sdio_master_slave': 'Test sdio multi board, esp32+esp32',
'sdio_multidev_32_c6': 'Test sdio multi board, esp32+esp32c6',
}