refactor(driver_spi): test apps merge duplicat cases using soft spi

This commit is contained in:
wanckl
2025-03-03 16:22:24 +08:00
parent 51873d46aa
commit 83c09991b8
8 changed files with 182 additions and 454 deletions

View File

@@ -282,11 +282,18 @@ void spitest_gpio_input_sel(uint32_t gpio_num, int func, uint32_t signal_idx);
//Note this cs_num is the ID of the connected devices' ID, e.g. if 2 devices are connected to the bus, //Note this cs_num is the ID of the connected devices' ID, e.g. if 2 devices are connected to the bus,
//then the cs_num of the 1st and 2nd devices are 0 and 1 respectively. //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); //Enable `soft_master` to connect to soft spi master instead of hardware master.
void same_pin_func_sel(spi_bus_config_t bus, uint8_t cs_pin, uint8_t cs_dev_id, bool soft_master);
// Soft simulated spi master host for slave testing // Soft simulated spi master host for slave testing
// TODO: `speed_hz` is not implemented yet, temp to max 500Hz // `speed_hz` max 500kHz
// TODO: mode 0 only // TODO: mode 0 only
void spi_master_trans_impl_gpio(spi_bus_config_t bus, uint8_t cs_pin, uint8_t speed_hz, void *tx, void *rx, uint32_t len); void spi_master_trans_impl_gpio(spi_bus_config_t bus, uint8_t cs_pin, uint32_t speed_hz, uint8_t *tx, uint8_t *rx, uint32_t len, bool hold_cs);
// Send/Receive long buffer by soft spi master in segments to the slave_hd through its DMA, refer to `essl_spi_wrdma/essl_spi_rddma`
void essl_sspi_hd_dma_trans_seg(spi_bus_config_t bus, uint8_t cs_pin, uint32_t speed_hz, bool is_rx, void *buffer, int len, int seg_len);
// Write/Read the shared buffer of the slave_hd by soft spi master, refer to `essl_spi_wrbuf/essl_spi_rdbuf`
void essl_sspi_hd_buffer_trans(spi_bus_config_t bus, uint8_t cs_pin, uint32_t speed_hz, spi_command_t cmd, uint8_t addr, void *buffer, uint32_t len);
#endif //_TEST_COMMON_SPI_H_ #endif //_TEST_COMMON_SPI_H_

View File

@@ -9,6 +9,7 @@
#include "driver/gpio.h" #include "driver/gpio.h"
#include "esp_private/gpio.h" #include "esp_private/gpio.h"
#include "hal/gpio_hal.h" #include "hal/gpio_hal.h"
#include "hal/spi_ll.h"
#include "esp_rom_gpio.h" #include "esp_rom_gpio.h"
int test_freq_default[] = TEST_FREQ_DEFAULT(); int test_freq_default[] = TEST_FREQ_DEFAULT();
@@ -232,49 +233,81 @@ void spitest_gpio_input_sel(uint32_t gpio_num, int func, uint32_t signal_idx)
esp_rom_gpio_connect_in_signal(gpio_num, signal_idx, 0); esp_rom_gpio_connect_in_signal(gpio_num, signal_idx, 0);
} }
//Note this cs_dev_id is the ID of the connected devices' ID, e.g. if 2 devices are connected to the bus, void same_pin_func_sel(spi_bus_config_t bus, uint8_t cs_pin, uint8_t cs_dev_id, bool soft_master)
//then the cs_dev_id 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_dev_id)
{ {
spitest_gpio_output_sel(bus.mosi_io_num, FUNC_GPIO, spi_periph_signal[TEST_SPI_HOST].spid_out); spitest_gpio_output_sel(bus.mosi_io_num, FUNC_GPIO, soft_master ? SIG_GPIO_OUT_IDX : spi_periph_signal[TEST_SPI_HOST].spid_out);
spitest_gpio_input_sel(bus.mosi_io_num, FUNC_GPIO, spi_periph_signal[TEST_SLAVE_HOST].spid_in); spitest_gpio_input_sel(bus.mosi_io_num, FUNC_GPIO, spi_periph_signal[TEST_SLAVE_HOST].spid_in);
spitest_gpio_output_sel(bus.miso_io_num, FUNC_GPIO, spi_periph_signal[TEST_SLAVE_HOST].spiq_out); spitest_gpio_output_sel(bus.miso_io_num, FUNC_GPIO, spi_periph_signal[TEST_SLAVE_HOST].spiq_out);
spitest_gpio_input_sel(bus.miso_io_num, FUNC_GPIO, spi_periph_signal[TEST_SPI_HOST].spiq_in); spitest_gpio_input_sel(bus.miso_io_num, FUNC_GPIO, soft_master ? SIG_GPIO_OUT_IDX : spi_periph_signal[TEST_SPI_HOST].spiq_in);
spitest_gpio_output_sel(dev.spics_io_num, FUNC_GPIO, spi_periph_signal[TEST_SPI_HOST].spics_out[cs_dev_id]); gpio_set_level(cs_pin, 1); //ensure CS is inactive when select to soft_master and before transaction start
spitest_gpio_input_sel(dev.spics_io_num, FUNC_GPIO, spi_periph_signal[TEST_SLAVE_HOST].spics_in); spitest_gpio_output_sel(cs_pin, FUNC_GPIO, soft_master ? SIG_GPIO_OUT_IDX : spi_periph_signal[TEST_SPI_HOST].spics_out[cs_dev_id]);
spitest_gpio_input_sel(cs_pin, FUNC_GPIO, spi_periph_signal[TEST_SLAVE_HOST].spics_in);
spitest_gpio_output_sel(bus.sclk_io_num, FUNC_GPIO, spi_periph_signal[TEST_SPI_HOST].spiclk_out); spitest_gpio_output_sel(bus.sclk_io_num, FUNC_GPIO, soft_master ? SIG_GPIO_OUT_IDX : spi_periph_signal[TEST_SPI_HOST].spiclk_out);
spitest_gpio_input_sel(bus.sclk_io_num, FUNC_GPIO, spi_periph_signal[TEST_SLAVE_HOST].spiclk_in); spitest_gpio_input_sel(bus.sclk_io_num, FUNC_GPIO, spi_periph_signal[TEST_SLAVE_HOST].spiclk_in);
} }
void spi_master_trans_impl_gpio(spi_bus_config_t bus, uint8_t cs_pin, uint8_t speed_hz, void *tx, void *rx, uint32_t len) #define GPIO_MAX_FREQ 500*1000 //max of soft spi clock at delay(0)
void spi_master_trans_impl_gpio(spi_bus_config_t bus, uint8_t cs_pin, uint32_t speed_hz, uint8_t *tx, uint8_t *rx, uint32_t len, bool hold_cs)
{ {
uint8_t *u8_tx = tx, *u8_rx = rx; gpio_dev_t *hw = GPIO_LL_GET_HW(0);
gpio_set_level(cs_pin, 1); //ensure CS is inactive before transaction start uint32_t half_duty_us = speed_hz ? ((GPIO_MAX_FREQ + speed_hz / 2) / speed_hz / 2) : 0;
esp_rom_gpio_connect_out_signal(cs_pin, SIG_GPIO_OUT_IDX, 0, 0);
esp_rom_gpio_connect_out_signal(bus.sclk_io_num, SIG_GPIO_OUT_IDX, 0, 0);
esp_rom_gpio_connect_out_signal(bus.mosi_io_num, SIG_GPIO_OUT_IDX, 0, 0);
esp_rom_gpio_connect_in_signal(bus.miso_io_num, SIG_GPIO_OUT_IDX, 0);
gpio_set_level(cs_pin, 0); gpio_ll_set_level(hw, cs_pin, 0);
vTaskDelay(1); // cs_ena_pre_trans
for (uint32_t index = 0; index < len; index ++) { for (uint32_t index = 0; index < len; index ++) {
uint8_t rx_data = 0; uint8_t rx_data = 0;
for (uint8_t bit = 0x80; bit > 0; bit >>= 1) { for (uint8_t bit = 0x80; bit > 0; bit >>= 1) {
// mode 0, output data first // mode 0, output data first
gpio_set_level(bus.mosi_io_num, (u8_tx) ? (u8_tx[index] & bit) : 0); gpio_ll_set_level(hw, bus.mosi_io_num, (tx) ? (tx[index] & bit) : 0);
vTaskDelay(1); esp_rom_delay_us(half_duty_us);
gpio_set_level(bus.sclk_io_num, 1);
rx_data <<= 1; rx_data <<= 1;
rx_data |= gpio_get_level(bus.miso_io_num); rx_data |= gpio_get_level(bus.miso_io_num);
vTaskDelay(1); gpio_ll_set_level(hw, bus.sclk_io_num, 1);
gpio_set_level(bus.sclk_io_num, 0); esp_rom_delay_us(half_duty_us);
gpio_ll_set_level(hw, bus.sclk_io_num, 0);
} }
if (u8_rx) { if (rx) {
u8_rx[index] = rx_data; rx[index] = rx_data;
} }
} }
gpio_set_level(cs_pin, 1); if (!hold_cs) {
gpio_ll_set_level(hw, cs_pin, 1);
}
} }
#if SOC_SPI_SUPPORT_SLAVE_HD_VER2
void essl_sspi_hd_dma_trans_seg(spi_bus_config_t bus, uint8_t cs_pin, uint32_t speed_hz, bool is_rx, void *buffer, int len, int seg_len)
{
uint8_t cmd_addr_dummy[3] = {0, 0, 0};
uint8_t *tx = is_rx ? NULL : buffer;
uint8_t *rx = is_rx ? buffer : NULL;
seg_len = (seg_len > 0) ? seg_len : len;
cmd_addr_dummy[0] = spi_ll_get_slave_hd_base_command(is_rx ? SPI_CMD_HD_RDDMA : SPI_CMD_HD_WRDMA);
while (len > 0) {
spi_master_trans_impl_gpio(bus, cs_pin, speed_hz, cmd_addr_dummy, NULL, sizeof(cmd_addr_dummy), true);
int send_len = (seg_len <= len) ? seg_len : len;
spi_master_trans_impl_gpio(bus, cs_pin, speed_hz, tx, rx, send_len, false);
len -= send_len;
tx += tx ? send_len : 0;
rx += rx ? send_len : 0;
}
cmd_addr_dummy[0] = spi_ll_get_slave_hd_base_command(is_rx ? SPI_CMD_HD_INT0 : SPI_CMD_HD_WR_END);
spi_master_trans_impl_gpio(bus, cs_pin, speed_hz, cmd_addr_dummy, NULL, sizeof(cmd_addr_dummy), false);
}
void essl_sspi_hd_buffer_trans(spi_bus_config_t bus, uint8_t cs_pin, uint32_t speed_hz, spi_command_t cmd, uint8_t addr, void *buffer, uint32_t len)
{
uint8_t cmd_addr_dummy[3] = {0, addr, 0};
cmd_addr_dummy[0] = spi_ll_get_slave_hd_base_command(cmd);
uint8_t *tx = (cmd == SPI_CMD_HD_RDBUF) ? NULL : buffer;
uint8_t *rx = (cmd == SPI_CMD_HD_RDBUF) ? buffer : NULL;
spi_master_trans_impl_gpio(bus, cs_pin, speed_hz, cmd_addr_dummy, NULL, sizeof(cmd_addr_dummy), true);
spi_master_trans_impl_gpio(bus, cs_pin, speed_hz, tx, rx, len, false);
}
#endif //SOC_SPI_SUPPORT_SLAVE_HD_VER2

View File

@@ -15,4 +15,4 @@ from pytest_embedded_idf.utils import idf_parametrize
) )
@idf_parametrize('target', ['esp32'], indirect=['target']) @idf_parametrize('target', ['esp32'], indirect=['target'])
def test_touch_sensor_v1(dut: Dut) -> None: def test_touch_sensor_v1(dut: Dut) -> None:
dut.run_all_single_board_cases(timeout=60) dut.run_all_single_board_cases(timeout=60, reset=True)

View File

@@ -901,10 +901,7 @@ void test_cmd_addr(spi_slave_task_context_t *slave_context, bool lsb_first)
TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devcfg, &spi)); TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devcfg, &spi));
//connecting pins to two peripherals breaks the output, fix it. //connecting pins to two peripherals breaks the output, fix it.
spitest_gpio_output_sel(buscfg.mosi_io_num, FUNC_GPIO, spi_periph_signal[TEST_SPI_HOST].spid_out); same_pin_func_sel(buscfg, devcfg.spics_io_num, 0, false);
spitest_gpio_output_sel(buscfg.miso_io_num, FUNC_GPIO, spi_periph_signal[TEST_SLAVE_HOST].spiq_out);
spitest_gpio_output_sel(devcfg.spics_io_num, FUNC_GPIO, spi_periph_signal[TEST_SPI_HOST].spics_out[0]);
spitest_gpio_output_sel(buscfg.sclk_io_num, FUNC_GPIO, spi_periph_signal[TEST_SPI_HOST].spiclk_out);
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
//prepare slave tx data //prepare slave tx data
@@ -1089,10 +1086,7 @@ TEST_CASE("SPI master variable dummy test", "[spi]")
spi_slave_interface_config_t slave_cfg = SPI_SLAVE_TEST_DEFAULT_CONFIG(); spi_slave_interface_config_t slave_cfg = SPI_SLAVE_TEST_DEFAULT_CONFIG();
TEST_ESP_OK(spi_slave_initialize(TEST_SLAVE_HOST, &bus_cfg, &slave_cfg, SPI_DMA_DISABLED)); TEST_ESP_OK(spi_slave_initialize(TEST_SLAVE_HOST, &bus_cfg, &slave_cfg, SPI_DMA_DISABLED));
spitest_gpio_output_sel(bus_cfg.mosi_io_num, FUNC_GPIO, spi_periph_signal[TEST_SPI_HOST].spid_out); same_pin_func_sel(bus_cfg, dev_cfg.spics_io_num, 0, false);
spitest_gpio_output_sel(bus_cfg.miso_io_num, FUNC_GPIO, spi_periph_signal[TEST_SLAVE_HOST].spiq_out);
spitest_gpio_output_sel(dev_cfg.spics_io_num, FUNC_GPIO, spi_periph_signal[TEST_SPI_HOST].spics_out[0]);
spitest_gpio_output_sel(bus_cfg.sclk_io_num, FUNC_GPIO, spi_periph_signal[TEST_SPI_HOST].spiclk_out);
uint8_t data_to_send[] = {0x12, 0x34, 0x56, 0x78}; uint8_t data_to_send[] = {0x12, 0x34, 0x56, 0x78};
@@ -1135,7 +1129,7 @@ TEST_CASE("SPI master hd dma TX without RX test", "[spi]")
spi_slave_interface_config_t slave_cfg = SPI_SLAVE_TEST_DEFAULT_CONFIG(); spi_slave_interface_config_t slave_cfg = SPI_SLAVE_TEST_DEFAULT_CONFIG();
TEST_ESP_OK(spi_slave_initialize(TEST_SLAVE_HOST, &bus_cfg, &slave_cfg, SPI_DMA_CH_AUTO)); TEST_ESP_OK(spi_slave_initialize(TEST_SLAVE_HOST, &bus_cfg, &slave_cfg, SPI_DMA_CH_AUTO));
same_pin_func_sel(bus_cfg, dev_cfg, 0); same_pin_func_sel(bus_cfg, dev_cfg.spics_io_num, 0, false);
uint32_t buf_size = 32; uint32_t buf_size = 32;
uint8_t *mst_send_buf = spi_bus_dma_memory_alloc(TEST_SPI_HOST, buf_size, 0); uint8_t *mst_send_buf = spi_bus_dma_memory_alloc(TEST_SPI_HOST, buf_size, 0);

View File

@@ -75,7 +75,7 @@ TEST_CASE("SPI Single Board Test SIO", "[spi]")
spi_slave_interface_config_t slv_cfg = SPI_SLAVE_TEST_DEFAULT_CONFIG(); spi_slave_interface_config_t slv_cfg = SPI_SLAVE_TEST_DEFAULT_CONFIG();
TEST_ESP_OK(spi_slave_initialize(TEST_SLAVE_HOST, &bus_cfg, &slv_cfg, SPI_DMA_DISABLED)); TEST_ESP_OK(spi_slave_initialize(TEST_SLAVE_HOST, &bus_cfg, &slv_cfg, SPI_DMA_DISABLED));
same_pin_func_sel(bus_cfg, dev_cfg, 0); same_pin_func_sel(bus_cfg, dev_cfg.spics_io_num, 0, false);
inner_connect(bus_cfg); inner_connect(bus_cfg);
WORD_ALIGNED_ATTR uint8_t master_rx_buffer[320]; WORD_ALIGNED_ATTR uint8_t master_rx_buffer[320];
@@ -178,7 +178,7 @@ void test_sio_master_trans(bool sio_master_in)
uint8_t *master_tx_max = heap_caps_calloc(TRANS_LEN * 2, 1, MALLOC_CAP_DMA); uint8_t *master_tx_max = heap_caps_calloc(TRANS_LEN * 2, 1, MALLOC_CAP_DMA);
TEST_ASSERT_NOT_NULL_MESSAGE(master_tx_max, "malloc failed, exit.\n"); TEST_ASSERT_NOT_NULL_MESSAGE(master_tx_max, "malloc failed, exit.\n");
// write somethin to a long buffer for test long transmission // write something to a long buffer for test long transmission
for (uint16_t i = 0; i < TRANS_LEN; i++) { for (uint16_t i = 0; i < TRANS_LEN; i++) {
master_tx_max[i] = i; master_tx_max[i] = i;
master_tx_max[TRANS_LEN * 2 - i - 1] = i; master_tx_max[TRANS_LEN * 2 - i - 1] = i;
@@ -252,7 +252,7 @@ void test_sio_slave_emulate(bool sio_master_in)
uint8_t *slave_tx_max = heap_caps_calloc(TRANS_LEN * 2, 1, MALLOC_CAP_DMA); uint8_t *slave_tx_max = heap_caps_calloc(TRANS_LEN * 2, 1, MALLOC_CAP_DMA);
TEST_ASSERT_NOT_NULL_MESSAGE(slave_tx_max, "malloc failed, exit.\n"); TEST_ASSERT_NOT_NULL_MESSAGE(slave_tx_max, "malloc failed, exit.\n");
// write somethin to a long buffer for test long transmission // write something to a long buffer for test long transmission
for (uint16_t i = 0; i < TRANS_LEN; i++) { for (uint16_t i = 0; i < TRANS_LEN; i++) {
slave_tx_max[i] = i; slave_tx_max[i] = i;
slave_tx_max[TRANS_LEN * 2 - i - 1] = i; slave_tx_max[TRANS_LEN * 2 - i - 1] = i;

View File

@@ -24,13 +24,6 @@
#include "esp_log.h" #include "esp_log.h"
#include "esp_rom_gpio.h" #include "esp_rom_gpio.h"
#if (TEST_SPI_PERIPH_NUM >= 2)
//These will only be enabled on chips with 2 or more SPI peripherals
#ifndef CONFIG_SPIRAM
//This test should be removed once the timing test is merged.
static spi_device_handle_t spi;
static WORD_ALIGNED_ATTR uint8_t master_txbuf[320]; static WORD_ALIGNED_ATTR uint8_t master_txbuf[320];
static WORD_ALIGNED_ATTR uint8_t master_rxbuf[320]; static WORD_ALIGNED_ATTR uint8_t master_rxbuf[320];
static WORD_ALIGNED_ATTR uint8_t slave_txbuf[320]; static WORD_ALIGNED_ATTR uint8_t slave_txbuf[320];
@@ -39,6 +32,12 @@ static WORD_ALIGNED_ATTR uint8_t slave_rxbuf[320];
static const uint8_t master_send[] = { 0x93, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0xaa, 0xcc, 0xff, 0xee, 0x55, 0x77, 0x88, 0x43 }; static const uint8_t master_send[] = { 0x93, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0xaa, 0xcc, 0xff, 0xee, 0x55, 0x77, 0x88, 0x43 };
static const uint8_t slave_send[] = { 0xaa, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x13, 0x57, 0x9b, 0xdf, 0x24, 0x68, 0xac, 0xe0 }; static const uint8_t slave_send[] = { 0xaa, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x13, 0x57, 0x9b, 0xdf, 0x24, 0x68, 0xac, 0xe0 };
#if (TEST_SPI_PERIPH_NUM >= 2)
//These will only be enabled on chips with 2 or more SPI peripherals
#ifndef CONFIG_SPIRAM
//This test should be removed once the timing test is merged.
static spi_device_handle_t spi;
static void custom_setup(void) static void custom_setup(void)
{ {
//Initialize buffers //Initialize buffers
@@ -74,7 +73,7 @@ static void custom_setup(void)
TEST_ESP_OK(spi_slave_initialize(TEST_SLAVE_HOST, &buscfg, &slvcfg, SPI_DMA_CH_AUTO)); TEST_ESP_OK(spi_slave_initialize(TEST_SLAVE_HOST, &buscfg, &slvcfg, SPI_DMA_CH_AUTO));
//Do internal connections //Do internal connections
same_pin_func_sel(buscfg, devcfg, 0); same_pin_func_sel(buscfg, devcfg.spics_io_num, 0, false);
} }
static void custom_teardown(void) static void custom_teardown(void)
@@ -145,7 +144,7 @@ TEST_CASE("Test slave rx no_dma overwrite when length below/over config", "[spi]
TEST_ESP_OK(spi_slave_initialize(TEST_SLAVE_HOST, &buscfg, &slvcfg, SPI_DMA_DISABLED)); TEST_ESP_OK(spi_slave_initialize(TEST_SLAVE_HOST, &buscfg, &slvcfg, SPI_DMA_DISABLED));
//initialize master and slave on the same pins break some of the output configs, fix them //initialize master and slave on the same pins break some of the output configs, fix them
same_pin_func_sel(buscfg, devcfg, 0); same_pin_func_sel(buscfg, devcfg.spics_io_num, 0, false);
uint8_t master_tx[TEST_SLV_RX_BUF_LEN], slave_rx[TEST_SLV_RX_BUF_LEN]; uint8_t master_tx[TEST_SLV_RX_BUF_LEN], slave_rx[TEST_SLV_RX_BUF_LEN];
for (uint8_t i = 0; i < TEST_SLV_RX_BUF_LEN; i++) { for (uint8_t i = 0; i < TEST_SLV_RX_BUF_LEN; i++) {
@@ -250,10 +249,16 @@ TEST_CASE("test fullduplex slave with only TX direction", "[spi]")
ESP_LOGI(SLAVE_TAG, "test passed."); ESP_LOGI(SLAVE_TAG, "test passed.");
} }
#endif // !CONFIG_SPIRAM
#endif // #if (TEST_SPI_PERIPH_NUM >= 2)
TEST_CASE("test slave send unaligned", "[spi]") TEST_CASE("test slave send unaligned", "[spi]")
{ {
custom_setup(); spi_bus_config_t buscfg = SPI_BUS_TEST_DEFAULT_CONFIG();
buscfg.flags |= SPICOMMON_BUSFLAG_GPIO_PINS;
spi_slave_interface_config_t slvcfg = SPI_SLAVE_TEST_DEFAULT_CONFIG();
TEST_ESP_OK(spi_slave_initialize(TEST_SLAVE_HOST, &buscfg, &slvcfg, SPI_DMA_CH_AUTO));
same_pin_func_sel(buscfg, slvcfg.spics_io_num, 0, true);
memcpy(master_txbuf, master_send, sizeof(master_send)); memcpy(master_txbuf, master_send, sizeof(master_send));
memcpy(slave_txbuf, slave_send, sizeof(slave_send)); memcpy(slave_txbuf, slave_send, sizeof(slave_send));
@@ -272,164 +277,29 @@ TEST_CASE("test slave send unaligned", "[spi]")
memset(master_rxbuf, 0x66, sizeof(master_rxbuf)); memset(master_rxbuf, 0x66, sizeof(master_rxbuf));
memset(slave_rxbuf, 0x66, sizeof(slave_rxbuf)); memset(slave_rxbuf, 0x66, sizeof(slave_rxbuf));
//mount slave trans
TEST_ESP_OK(spi_slave_queue_trans(TEST_SLAVE_HOST, &slave_t, portMAX_DELAY)); TEST_ESP_OK(spi_slave_queue_trans(TEST_SLAVE_HOST, &slave_t, portMAX_DELAY));
//start master trans
//send spi_master_trans_impl_gpio(buscfg, slvcfg.spics_io_num, 0, master_txbuf + i, master_rxbuf + i, 4 * (i + 1), false);
spi_transaction_t t = {};
t.length = 32 * (i + 1);
if (t.length != 0) {
t.tx_buffer = master_txbuf + i;
t.rx_buffer = master_rxbuf + i;
}
spi_device_transmit(spi, (spi_transaction_t *)&t);
//wait for end //wait for end
TEST_ESP_OK(spi_slave_get_trans_result(TEST_SLAVE_HOST, &out, portMAX_DELAY)); TEST_ESP_OK(spi_slave_get_trans_result(TEST_SLAVE_HOST, &out, portMAX_DELAY));
//show result //show result
ESP_LOGI(SLAVE_TAG, "trans_len: %d", slave_t.trans_len); ESP_LOGI(SLAVE_TAG, "trans_len: %d", slave_t.trans_len);
ESP_LOG_BUFFER_HEX("master tx", t.tx_buffer, t.length / 8); ESP_LOG_BUFFER_HEX("master tx", master_txbuf + i, 4 * (i + 1));
ESP_LOG_BUFFER_HEX("master rx", t.rx_buffer, t.length / 8); ESP_LOG_BUFFER_HEX("master rx", master_rxbuf + i, 4 * (i + 1));
ESP_LOG_BUFFER_HEX("slave tx", slave_t.tx_buffer, (slave_t.trans_len + 7) / 8); ESP_LOG_BUFFER_HEX("slave tx", slave_t.tx_buffer, (slave_t.trans_len + 7) / 8);
ESP_LOG_BUFFER_HEX("slave rx", slave_t.rx_buffer, (slave_t.trans_len + 7) / 8); ESP_LOG_BUFFER_HEX("slave rx", slave_t.rx_buffer, (slave_t.trans_len + 7) / 8);
TEST_ASSERT_EQUAL_HEX8_ARRAY(t.tx_buffer, slave_t.rx_buffer, t.length / 8); TEST_ASSERT_EQUAL_HEX8_ARRAY(master_txbuf + i, slave_t.rx_buffer, 4 * (i + 1));
TEST_ASSERT_EQUAL_HEX8_ARRAY(slave_t.tx_buffer, t.rx_buffer, t.length / 8); TEST_ASSERT_EQUAL_HEX8_ARRAY(slave_t.tx_buffer, master_rxbuf + i, 4 * (i + 1));
TEST_ASSERT_EQUAL(t.length, slave_t.trans_len); TEST_ASSERT_EQUAL(32 * (i + 1), slave_t.trans_len);
} }
custom_teardown(); spi_slave_free(TEST_SLAVE_HOST);
ESP_LOGI(SLAVE_TAG, "test passed."); ESP_LOGI(SLAVE_TAG, "test passed.");
} }
#endif // !CONFIG_SPIRAM
#endif // #if (TEST_SPI_PERIPH_NUM >= 2)
#if (TEST_SPI_PERIPH_NUM == 1)
//These tests are for chips which only have 1 SPI controller
/********************************************************************************
* Test By Master & Slave (2 boards)
*
* Master (C3, C2, H2) && Slave (C3, C2, H2):
* PIN | Master | Slave |
* ----| --------- | --------- |
* CS | 10 | 10 |
* CLK | 6 | 6 |
* MOSI| 7 | 7 |
* MISO| 2 | 2 |
* GND | GND | GND |
*
********************************************************************************/
#define BUF_SIZE 320
static void unaligned_test_master(void)
{
spi_bus_config_t buscfg = SPI_BUS_TEST_DEFAULT_CONFIG();
TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &buscfg, 0));
spi_device_handle_t spi;
spi_device_interface_config_t devcfg = SPI_DEVICE_TEST_DEFAULT_CONFIG();
devcfg.clock_speed_hz = 4 * 1000 * 1000;
devcfg.queue_size = 7;
TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devcfg, &spi));
unity_send_signal("Master ready");
uint8_t *master_send_buf = heap_caps_malloc(BUF_SIZE, MALLOC_CAP_DMA);
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 ``test_slave_loop`` does.
uint8_t *slave_send_buf = heap_caps_malloc(BUF_SIZE, MALLOC_CAP_DMA);
srand(199);
for (int i = 0; i < BUF_SIZE; i++) {
master_send_buf[i] = rand();
}
srand(299);
for (int i = 0; i < BUF_SIZE; i++) {
slave_send_buf[i] = rand();
}
for (int i = 0; i < 4; i++) {
uint32_t length_in_bytes = 4 * (i + 1);
spi_transaction_t t = {
.tx_buffer = master_send_buf + i,
.rx_buffer = master_recv_buf,
.length = length_in_bytes * 8,
};
vTaskDelay(50);
unity_wait_for_signal("Slave ready");
TEST_ESP_OK(spi_device_transmit(spi, (spi_transaction_t *)&t));
//show result
ESP_LOG_BUFFER_HEX("master tx:", master_send_buf + i, length_in_bytes);
ESP_LOG_BUFFER_HEX("master rx:", master_recv_buf, length_in_bytes);
TEST_ASSERT_EQUAL_HEX8_ARRAY(slave_send_buf + i, master_recv_buf, length_in_bytes);
//clean
memset(master_recv_buf, 0x00, BUF_SIZE);
}
free(master_send_buf);
free(master_recv_buf);
free(slave_send_buf);
TEST_ESP_OK(spi_bus_remove_device(spi));
TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST));
}
static void unaligned_test_slave(void)
{
unity_wait_for_signal("Master ready");
spi_bus_config_t buscfg = SPI_BUS_TEST_DEFAULT_CONFIG();
spi_slave_interface_config_t slvcfg = SPI_SLAVE_TEST_DEFAULT_CONFIG();
TEST_ESP_OK(spi_slave_initialize(TEST_SPI_HOST, &buscfg, &slvcfg, SPI_DMA_CH_AUTO));
uint8_t *slave_send_buf = heap_caps_malloc(BUF_SIZE, MALLOC_CAP_DMA);
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 ``test_slave_loop`` does.
uint8_t *master_send_buf = heap_caps_malloc(BUF_SIZE, MALLOC_CAP_DMA);
srand(199);
for (int i = 0; i < BUF_SIZE; i++) {
master_send_buf[i] = rand();
}
srand(299);
for (int i = 0; i < BUF_SIZE; i++) {
slave_send_buf[i] = rand();
}
for (int i = 0; i < 4; i++) {
uint32_t mst_length_in_bytes = 4 * (i + 1);
spi_slave_transaction_t slave_t = {
.tx_buffer = slave_send_buf + i,
.rx_buffer = slave_recv_buf,
.length = 32 * 8,
};
unity_send_signal("Slave ready");
TEST_ESP_OK(spi_slave_transmit(TEST_SPI_HOST, &slave_t, portMAX_DELAY));
//show result
ESP_LOGI(SLAVE_TAG, "trans_len: %d", slave_t.trans_len);
ESP_LOG_BUFFER_HEX("slave tx:", slave_send_buf + i, mst_length_in_bytes);
ESP_LOG_BUFFER_HEX("slave rx:", slave_recv_buf, mst_length_in_bytes);
TEST_ASSERT_EQUAL(mst_length_in_bytes * 8, slave_t.trans_len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(master_send_buf + i, slave_recv_buf, mst_length_in_bytes);
//clean
memset(slave_recv_buf, 0x00, BUF_SIZE);
}
free(slave_send_buf);
free(slave_recv_buf);
free(master_send_buf);
TEST_ESP_OK(spi_slave_free(TEST_SPI_HOST));
}
TEST_CASE_MULTIPLE_DEVICES("SPI_Slave_Unaligned_Test", "[spi_ms][timeout=120]", unaligned_test_master, unaligned_test_slave);
#endif //#if (TEST_SPI_PERIPH_NUM == 1)
#if CONFIG_SPI_SLAVE_ISR_IN_IRAM #if CONFIG_SPI_SLAVE_ISR_IN_IRAM
#define TEST_IRAM_TRANS_NUM 8 #define TEST_IRAM_TRANS_NUM 8
#define TEST_TRANS_LEN 64 #define TEST_TRANS_LEN 64
@@ -806,15 +676,14 @@ TEST_CASE("test_spi_slave_sleep_retention", "[spi]")
buscfg.flags = (allow_pd) ? SPICOMMON_BUSFLAG_SLP_ALLOW_PD : 0; buscfg.flags = (allow_pd) ? SPICOMMON_BUSFLAG_SLP_ALLOW_PD : 0;
buscfg.flags |= SPICOMMON_BUSFLAG_GPIO_PINS; buscfg.flags |= SPICOMMON_BUSFLAG_GPIO_PINS;
spi_slave_interface_config_t slvcfg = SPI_SLAVE_TEST_DEFAULT_CONFIG(); spi_slave_interface_config_t slvcfg = SPI_SLAVE_TEST_DEFAULT_CONFIG();
TEST_ESP_OK(spi_slave_initialize(TEST_SPI_HOST, &buscfg, &slvcfg, SPI_DMA_DISABLED)); TEST_ESP_OK(spi_slave_initialize(TEST_SLAVE_HOST, &buscfg, &slvcfg, SPI_DMA_DISABLED));
gpio_pullup_en(slvcfg.spics_io_num); same_pin_func_sel(buscfg, slvcfg.spics_io_num, 0, true);
vTaskDelay(1);
for (uint8_t cnt = 0; cnt < 3; cnt ++) { for (uint8_t cnt = 0; cnt < 3; cnt ++) {
printf("Going into sleep with power %s ...\n", (buscfg.flags & SPICOMMON_BUSFLAG_SLP_ALLOW_PD) ? "down" : "hold"); printf("Going into sleep with power %s ...\n", (buscfg.flags & SPICOMMON_BUSFLAG_SLP_ALLOW_PD) ? "down" : "hold");
TEST_ESP_OK(spi_slave_disable(TEST_SPI_HOST)); TEST_ESP_OK(spi_slave_disable(TEST_SLAVE_HOST));
TEST_ESP_OK(esp_light_sleep_start()); TEST_ESP_OK(esp_light_sleep_start());
TEST_ESP_OK(spi_slave_enable(TEST_SPI_HOST)); TEST_ESP_OK(spi_slave_enable(TEST_SLAVE_HOST));
printf("Waked up!\n"); printf("Waked up!\n");
// check if the sleep happened as expected // check if the sleep happened as expected
@@ -827,15 +696,15 @@ TEST_CASE("test_spi_slave_sleep_retention", "[spi]")
mst_send[11] = cnt + 'A'; mst_send[11] = cnt + 'A';
memset(mst_rexcv, 0, sizeof(mst_rexcv)); memset(mst_rexcv, 0, sizeof(mst_rexcv));
memset(slv_rexcv, 0, sizeof(slv_rexcv)); memset(slv_rexcv, 0, sizeof(slv_rexcv));
TEST_ESP_OK(spi_slave_queue_trans(TEST_SPI_HOST, &trans_cfg, portMAX_DELAY)); TEST_ESP_OK(spi_slave_queue_trans(TEST_SLAVE_HOST, &trans_cfg, portMAX_DELAY));
spi_master_trans_impl_gpio(buscfg, slvcfg.spics_io_num, 0, mst_send, mst_rexcv, sizeof(mst_send)); spi_master_trans_impl_gpio(buscfg, slvcfg.spics_io_num, 0, mst_send, mst_rexcv, sizeof(mst_send), 0);
TEST_ESP_OK(spi_slave_get_trans_result(TEST_SPI_HOST, &ret_trans, portMAX_DELAY)); TEST_ESP_OK(spi_slave_get_trans_result(TEST_SLAVE_HOST, &ret_trans, portMAX_DELAY));
spitest_cmp_or_dump(slv_send, mst_rexcv, sizeof(mst_rexcv)); spitest_cmp_or_dump(slv_send, mst_rexcv, sizeof(mst_rexcv));
spitest_cmp_or_dump(mst_send, slv_rexcv, sizeof(slv_rexcv)); spitest_cmp_or_dump(mst_send, slv_rexcv, sizeof(slv_rexcv));
} }
TEST_ESP_OK(spi_slave_free(TEST_SPI_HOST)); TEST_ESP_OK(spi_slave_free(TEST_SLAVE_HOST));
} }
esp_sleep_set_sleep_context(NULL); esp_sleep_set_sleep_context(NULL);

View File

@@ -19,8 +19,6 @@
#include "esp_private/sleep_cpu.h" #include "esp_private/sleep_cpu.h"
#include "esp_private/esp_sleep_internal.h" #include "esp_private/esp_sleep_internal.h"
#include "esp_private/esp_pmu.h" #include "esp_private/esp_pmu.h"
#if (TEST_SPI_PERIPH_NUM >= 2) //These will be only enabled on chips with 2 or more SPI peripherals
#include "esp_rom_gpio.h" #include "esp_rom_gpio.h"
#define TEST_BUFFER_SIZE 256 ///< buffer size of each wrdma buffer in fifo mode #define TEST_BUFFER_SIZE 256 ///< buffer size of each wrdma buffer in fifo mode
@@ -42,65 +40,6 @@ typedef struct {
spi_slave_hd_data_t rx_data; spi_slave_hd_data_t rx_data;
} testhd_context_t; } testhd_context_t;
static uint32_t get_hd_flags(void)
{
#if !defined(SLAVE_SUPPORT_QIO)
return 0;
#endif
int flag_id = rand() % 5;
ESP_LOGI("io mode", "%d", flag_id);
switch (flag_id) {
case 1:
return SPI_TRANS_MODE_DIO;
case 2:
return SPI_TRANS_MODE_DIO | SPI_TRANS_MODE_DIOQIO_ADDR;
case 3:
return SPI_TRANS_MODE_QIO;
case 4:
return SPI_TRANS_MODE_QIO | SPI_TRANS_MODE_DIOQIO_ADDR;
default:
return 0;
}
}
void config_single_board_test_pin(void)
{
esp_rom_gpio_connect_out_signal(PIN_NUM_MOSI, spi_periph_signal[TEST_SPI_HOST].spid_out, 0, 0);
esp_rom_gpio_connect_in_signal(PIN_NUM_MOSI, spi_periph_signal[TEST_SLAVE_HOST].spid_in, 0);
esp_rom_gpio_connect_out_signal(PIN_NUM_MISO, spi_periph_signal[TEST_SLAVE_HOST].spiq_out, 0, 0);
esp_rom_gpio_connect_in_signal(PIN_NUM_MISO, spi_periph_signal[TEST_SPI_HOST].spiq_in, 0);
esp_rom_gpio_connect_out_signal(PIN_NUM_CS, spi_periph_signal[TEST_SPI_HOST].spics_out[0], 0, 0);
esp_rom_gpio_connect_in_signal(PIN_NUM_CS, spi_periph_signal[TEST_SLAVE_HOST].spics_in, 0);
esp_rom_gpio_connect_out_signal(PIN_NUM_CLK, spi_periph_signal[TEST_SPI_HOST].spiclk_out, 0, 0);
esp_rom_gpio_connect_in_signal(PIN_NUM_CLK, spi_periph_signal[TEST_SLAVE_HOST].spiclk_in, 0);
}
static void init_master_hd(spi_device_handle_t* spi, const spitest_param_set_t* config, int freq)
{
spi_bus_config_t bus_cfg = SPI_BUS_TEST_DEFAULT_CONFIG();
bus_cfg.max_transfer_sz = TEST_DMA_MAX_SIZE * 30;
bus_cfg.quadhd_io_num = PIN_NUM_HD;
bus_cfg.quadwp_io_num = PIN_NUM_WP;
#if defined(TEST_MASTER_GPIO_MATRIX) && CONFIG_IDF_TARGET_ESP32S2
bus_cfg.flags |= SPICOMMON_BUSFLAG_GPIO_PINS;
#endif
TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &bus_cfg, SPI_DMA_CH_AUTO));
spi_device_interface_config_t dev_cfg = SPI_DEVICE_TEST_DEFAULT_CONFIG();
dev_cfg.flags = SPI_DEVICE_HALFDUPLEX;
dev_cfg.command_bits = 8;
dev_cfg.address_bits = 8;
dev_cfg.dummy_bits = 8;
dev_cfg.clock_speed_hz = freq;
dev_cfg.mode = config->mode;
dev_cfg.input_delay_ns = config->slave_tv_ns;
TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &dev_cfg, spi));
}
static void init_slave_hd(int mode, bool append_mode, const spi_slave_hd_callback_config_t* callback) static void init_slave_hd(int mode, bool append_mode, const spi_slave_hd_callback_config_t* callback)
{ {
spi_bus_config_t bus_cfg = SPI_BUS_TEST_DEFAULT_CONFIG(); spi_bus_config_t bus_cfg = SPI_BUS_TEST_DEFAULT_CONFIG();
@@ -123,6 +62,29 @@ static void init_slave_hd(int mode, bool append_mode, const spi_slave_hd_callbac
TEST_ESP_OK(spi_slave_hd_init(TEST_SLAVE_HOST, &bus_cfg, &slave_hd_cfg)); TEST_ESP_OK(spi_slave_hd_init(TEST_SLAVE_HOST, &bus_cfg, &slave_hd_cfg));
} }
#if (TEST_SPI_PERIPH_NUM >= 2) //These will be only enabled on chips with 2 or more SPI peripherals
static void init_master_hd(spi_device_handle_t* spi, const spitest_param_set_t* config, int freq)
{
spi_bus_config_t bus_cfg = SPI_BUS_TEST_DEFAULT_CONFIG();
bus_cfg.max_transfer_sz = TEST_DMA_MAX_SIZE * 30;
bus_cfg.quadhd_io_num = PIN_NUM_HD;
bus_cfg.quadwp_io_num = PIN_NUM_WP;
#if defined(TEST_MASTER_GPIO_MATRIX) && CONFIG_IDF_TARGET_ESP32S2
bus_cfg.flags |= SPICOMMON_BUSFLAG_GPIO_PINS;
#endif
TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &bus_cfg, SPI_DMA_CH_AUTO));
spi_device_interface_config_t dev_cfg = SPI_DEVICE_TEST_DEFAULT_CONFIG();
dev_cfg.flags = SPI_DEVICE_HALFDUPLEX;
dev_cfg.command_bits = 8;
dev_cfg.address_bits = 8;
dev_cfg.dummy_bits = 8;
dev_cfg.clock_speed_hz = freq;
dev_cfg.mode = config->mode;
dev_cfg.input_delay_ns = config->slave_tv_ns;
TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &dev_cfg, spi));
}
static void test_hd_init(void** arg) static void test_hd_init(void** arg)
{ {
TEST_ASSERT(*arg == NULL); TEST_ASSERT(*arg == NULL);
@@ -206,7 +168,9 @@ static void test_hd_start(spi_device_handle_t *spi, int freq, const spitest_para
init_slave_hd(cfg->mode, 0, &callback); init_slave_hd(cfg->mode, 0, &callback);
//when test with single board via same set of mosi, miso, clk and cs pins. //when test with single board via same set of mosi, miso, clk and cs pins.
config_single_board_test_pin(); spi_bus_config_t bus_cfg = SPI_BUS_TEST_DEFAULT_CONFIG();
spi_slave_hd_slot_config_t slave_hd_cfg = SPI_SLOT_TEST_DEFAULT_CONFIG();
same_pin_func_sel(bus_cfg, slave_hd_cfg.spics_io_num, 0, false);
wait_wrbuf_sig(ctx, 0); wait_wrbuf_sig(ctx, 0);
wait_rdbuf_sig(ctx, 0); wait_rdbuf_sig(ctx, 0);
@@ -256,6 +220,28 @@ void check_no_signal(testhd_context_t* context)
check_no_tx(context); check_no_tx(context);
} }
static uint32_t get_hd_flags(void)
{
#if !defined(SLAVE_SUPPORT_QIO)
return 0;
#endif
int flag_id = rand() % 5;
ESP_LOGI("io mode", "%d", flag_id);
switch (flag_id) {
case 1:
return SPI_TRANS_MODE_DIO;
case 2:
return SPI_TRANS_MODE_DIO | SPI_TRANS_MODE_DIOQIO_ADDR;
case 3:
return SPI_TRANS_MODE_QIO;
case 4:
return SPI_TRANS_MODE_QIO | SPI_TRANS_MODE_DIOQIO_ADDR;
default:
return 0;
}
}
void test_wrdma(testhd_context_t* ctx, const spitest_param_set_t *cfg, spi_device_handle_t spi) void test_wrdma(testhd_context_t* ctx, const spitest_param_set_t *cfg, spi_device_handle_t spi)
{ {
int pos = rand() % TEST_DMA_MAX_SIZE; int pos = rand() % TEST_DMA_MAX_SIZE;
@@ -459,15 +445,13 @@ static const ptest_func_t hd_test_func = {
TEST_SINGLE_BOARD(name, test_set, "[spi][timeout=120]", &hd_test_func) TEST_SINGLE_BOARD(name, test_set, "[spi][timeout=120]", &hd_test_func)
static int test_freq_hd[] = { static int test_freq_hd[] = {
// 100*1000, 500 * 1000,
// 10 * 1000 * 1000, //maximum freq MISO stable before next latch edge 10 * 1000 * 1000, //maximum freq MISO stable before next latch edge
20 * 1000 * 1000, //maximum freq MISO stable before next latch edge 20 * 1000 * 1000, //maximum freq MISO stable before next latch edge
// 40 * 1000 * 1000, //maximum freq MISO stable before next latch edge // 40 * 1000 * 1000, //maximum freq MISO stable before next latch edge
0, 0,
}; };
#define TEST_HD_IN_CONTINUOUS_MODE true
static spitest_param_set_t hd_conf[] = { static spitest_param_set_t hd_conf[] = {
{ {
.pset_name = "MODE0", .pset_name = "MODE0",
@@ -507,6 +491,7 @@ static spitest_param_set_t hd_conf[] = {
}, },
}; };
TEST_SPI_HD(HD, hd_conf); TEST_SPI_HD(HD, hd_conf);
#endif //#if (TEST_SPI_PERIPH_NUM >= 2)
/* /*
* When the previous transaction of master exceeds the length of slave prepared too long, the * When the previous transaction of master exceeds the length of slave prepared too long, the
@@ -517,20 +502,15 @@ TEST_SPI_HD(HD, hd_conf);
*/ */
TEST_CASE("test spi slave hd segment mode, master too long", "[spi][spi_slv_hd]") TEST_CASE("test spi slave hd segment mode, master too long", "[spi][spi_slv_hd]")
{ {
spi_device_handle_t spi;
spitest_param_set_t *cfg = &hd_conf[0];
int freq = 100 * 1000; // the frequency should be small enough for the slave to prepare new trans
init_master_hd(&spi, cfg, freq);
//no callback needed //no callback needed
init_slave_hd(cfg->mode, 0, NULL); init_slave_hd(0, false, NULL);
//Use GPIO matrix to connect signal of master and slave via same set of pins on one board. //Use GPIO matrix to connect signal of master and slave via same set of pins on one board.
config_single_board_test_pin(); spi_bus_config_t bus_cfg = SPI_BUS_TEST_DEFAULT_CONFIG();
spi_slave_hd_slot_config_t slave_hd_cfg = SPI_SLOT_TEST_DEFAULT_CONFIG();
same_pin_func_sel(bus_cfg, slave_hd_cfg.spics_io_num, 0, true);
const int send_buf_size = 1024; 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_send_buf = malloc(send_buf_size * 2);
WORD_ALIGNED_ATTR uint8_t* master_send_buf = malloc(send_buf_size * 2); WORD_ALIGNED_ATTR uint8_t* master_send_buf = malloc(send_buf_size * 2);
WORD_ALIGNED_ATTR uint8_t* slave_recv_buf = malloc(send_buf_size * 2); WORD_ALIGNED_ATTR uint8_t* slave_recv_buf = malloc(send_buf_size * 2);
@@ -578,11 +558,11 @@ TEST_CASE("test spi slave hd segment mode, master too long", "[spi][spi_slv_hd]"
TEST_ESP_OK(spi_slave_hd_queue_trans(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_TX, &slave_trans[i], portMAX_DELAY)); TEST_ESP_OK(spi_slave_hd_queue_trans(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_TX, &slave_trans[i], portMAX_DELAY));
} }
essl_spi_wrdma(spi, master_send_buf, send_buf_size, -1, 0); essl_sspi_hd_dma_trans_seg(bus_cfg, slave_hd_cfg.spics_io_num, 0, false, master_send_buf, send_buf_size, -1);
essl_spi_wrdma(spi, master_send_buf + send_buf_size, send_buf_size, 5, 0); essl_sspi_hd_dma_trans_seg(bus_cfg, slave_hd_cfg.spics_io_num, 0, false, master_send_buf + send_buf_size, send_buf_size, 5);
essl_spi_rddma(spi, master_recv_buf, send_buf_size, -1, 0); essl_sspi_hd_dma_trans_seg(bus_cfg, slave_hd_cfg.spics_io_num, 0, true, master_recv_buf, send_buf_size, -1);
essl_spi_rddma(spi, master_recv_buf + send_buf_size, send_buf_size, 5, 0); essl_sspi_hd_dma_trans_seg(bus_cfg, slave_hd_cfg.spics_io_num, 0, true, master_recv_buf + send_buf_size, send_buf_size, 5);
for (int i = 0; i < 2; i ++) { for (int i = 0; i < 2; i ++) {
spi_slave_hd_data_t *ret_trans; spi_slave_hd_data_t *ret_trans;
@@ -590,7 +570,6 @@ TEST_CASE("test spi slave hd segment mode, master too long", "[spi][spi_slv_hd]"
TEST_ASSERT(ret_trans == &slave_trans[i]); TEST_ASSERT(ret_trans == &slave_trans[i]);
TEST_ASSERT_EQUAL(slave_trans[i].len, ret_trans->trans_len); TEST_ASSERT_EQUAL(slave_trans[i].len, ret_trans->trans_len);
} }
for (int i = 2; i < 4; i ++) { for (int i = 2; i < 4; i ++) {
spi_slave_hd_data_t *ret_trans; spi_slave_hd_data_t *ret_trans;
TEST_ESP_OK(spi_slave_hd_get_trans_res(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_TX, &ret_trans, portMAX_DELAY)); TEST_ESP_OK(spi_slave_hd_get_trans_res(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_TX, &ret_trans, portMAX_DELAY));
@@ -608,149 +587,9 @@ TEST_CASE("test spi slave hd segment mode, master too long", "[spi][spi_slv_hd]"
free(master_send_buf); free(master_send_buf);
free(slave_send_buf); free(slave_send_buf);
spi_slave_hd_deinit(TEST_SLAVE_HOST); spi_slave_hd_deinit(TEST_SLAVE_HOST);
master_free_device_bus(spi); ESP_LOGI(SLAVE_TAG, "test passed.");
} }
#endif //#if (TEST_SPI_PERIPH_NUM >= 2)
#if (TEST_SPI_PERIPH_NUM == 1)
//These tests are for chips which only have 1 SPI controller
/********************************************************************************
* Test By Master & Slave (2 boards)
*
* Master (C3, C2, H2) && Slave (C3, C2, H2):
* PIN | Master | Slave |
* ----| --------- | --------- |
* CS | 10 | 10 |
* CLK | 6 | 6 |
* MOSI| 7 | 7 |
* MISO| 2 | 2 |
* GND | GND | GND |
*
********************************************************************************/
static void hd_master(void)
{
spi_bus_config_t bus_cfg = SPI_BUS_TEST_DEFAULT_CONFIG();
TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &bus_cfg, SPI_DMA_CH_AUTO));
spi_device_handle_t spi;
spi_device_interface_config_t dev_cfg = SPI_DEVICE_TEST_DEFAULT_CONFIG();
dev_cfg.flags = SPI_DEVICE_HALFDUPLEX;
dev_cfg.command_bits = 8;
dev_cfg.address_bits = 8;
dev_cfg.dummy_bits = 8;
dev_cfg.clock_speed_hz = 100 * 1000;
TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &dev_cfg, &spi));
const int send_buf_size = 1024;
WORD_ALIGNED_ATTR uint8_t *master_send_buf = malloc(send_buf_size * 2);
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);
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};
unity_send_signal("master ready");
unity_wait_for_signal("slave ready");
essl_spi_wrdma(spi, master_send_buf, send_buf_size, -1, 0);
unity_wait_for_signal("slave ready");
essl_spi_wrdma(spi, master_send_buf + send_buf_size, send_buf_size, 5, 0);
unity_wait_for_signal("slave ready");
essl_spi_rddma(spi, master_recv_buf, send_buf_size, -1, 0);
spitest_cmp_or_dump(slave_send_buf, master_recv_buf, trans_len[0]);
unity_wait_for_signal("slave ready");
essl_spi_rddma(spi, master_recv_buf + send_buf_size, send_buf_size, 5, 0);
spitest_cmp_or_dump(slave_send_buf + send_buf_size, master_recv_buf + send_buf_size, trans_len[1]);
free(master_recv_buf);
free(master_send_buf);
free(slave_send_buf);
master_free_device_bus(spi);
}
static void hd_slave(void)
{
spi_bus_config_t bus_cfg = SPI_BUS_TEST_DEFAULT_CONFIG();
bus_cfg.max_transfer_sz = 14000 * 30;
spi_slave_hd_slot_config_t slave_hd_cfg = SPI_SLOT_TEST_DEFAULT_CONFIG();
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);
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};
spi_slave_hd_data_t slave_trans[4] = {
//recv, the buffer size should be aligned to 4
{
.data = slave_recv_buf,
.len = (trans_len[0] + 3) & (~3),
},
{
.data = slave_recv_buf + send_buf_size,
.len = (trans_len[1] + 3) & (~3),
},
//send
{
.data = slave_send_buf,
.len = trans_len[0],
},
{
.data = slave_send_buf + send_buf_size,
.len = trans_len[1],
},
};
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");
}
for (int i = 2; i < 4; i ++) {
TEST_ESP_OK(spi_slave_hd_queue_trans(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_TX, &slave_trans[i], portMAX_DELAY));
unity_send_signal("slave ready");
}
for (int i = 0; i < 2; i ++) {
spi_slave_hd_data_t *ret_trans;
TEST_ESP_OK(spi_slave_hd_get_trans_res(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_RX, &ret_trans, portMAX_DELAY));
TEST_ASSERT(ret_trans == &slave_trans[i]);
TEST_ASSERT_EQUAL(slave_trans[i].len, ret_trans->trans_len);
}
for (int i = 2; i < 4; i ++) {
spi_slave_hd_data_t *ret_trans;
TEST_ESP_OK(spi_slave_hd_get_trans_res(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_TX, &ret_trans, portMAX_DELAY));
TEST_ASSERT(ret_trans == &slave_trans[i]);
}
spitest_cmp_or_dump(master_send_buf, slave_recv_buf, trans_len[0]);
spitest_cmp_or_dump(master_send_buf + send_buf_size, slave_recv_buf + send_buf_size, trans_len[1]);
free(slave_recv_buf);
free(slave_send_buf);
free(master_send_buf);
spi_slave_hd_deinit(TEST_SLAVE_HOST);
}
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)
/** /**
* TODO IDF-5483 * TODO IDF-5483
**/ **/
@@ -1076,12 +915,9 @@ TEST_CASE("test_spi_slave_hd_sleep_retention", "[spi]")
esp_sleep_context_t sleep_ctx; esp_sleep_context_t sleep_ctx;
esp_sleep_set_sleep_context(&sleep_ctx); esp_sleep_set_sleep_context(&sleep_ctx);
uint32_t slave_hd_cmd[2][2] = {{SPI_LL_BASE_CMD_HD_WRDMA, SPI_LL_BASE_CMD_HD_WR_END}, {SPI_LL_BASE_CMD_HD_RDDMA, SPI_LL_BASE_CMD_HD_INT0}}; uint32_t slave_share_sig = TEST_SLP_BUF_VAL, read_share_sig;
uint32_t slave_share_sig = TEST_SLP_BUF_VAL;
uint8_t slv_send[14] = "I'm slave x\n", slv_rexcv[14]; uint8_t slv_send[14] = "I'm slave x\n", slv_rexcv[14];
uint8_t mst_txbuff[17] = " I'm master x\n", mst_rxbuff[17]; //more than 3 byte to hold cmd,addrs,dummy uint8_t mst_send[14] = "I'm master x\n", mst_rexcv[14];
uint8_t share_sig_buff[7] = {0}; // cmd + addr + dummy + uint32_t
uint8_t *mst_send = &mst_txbuff[3], *mst_rexcv = &mst_rxbuff[3];
spi_slave_hd_data_t *ret_trans, tx_data = { spi_slave_hd_data_t *ret_trans, tx_data = {
.data = slv_send, .data = slv_send,
.len = sizeof(slv_send), .len = sizeof(slv_send),
@@ -1098,7 +934,7 @@ TEST_CASE("test_spi_slave_hd_sleep_retention", "[spi]")
bus_cfg.flags |= SPICOMMON_BUSFLAG_GPIO_PINS; bus_cfg.flags |= SPICOMMON_BUSFLAG_GPIO_PINS;
spi_slave_hd_slot_config_t slave_hd_cfg = SPI_SLOT_TEST_DEFAULT_CONFIG(); spi_slave_hd_slot_config_t slave_hd_cfg = SPI_SLOT_TEST_DEFAULT_CONFIG();
TEST_ESP_OK(spi_slave_hd_init(TEST_SLAVE_HOST, &bus_cfg, &slave_hd_cfg)); TEST_ESP_OK(spi_slave_hd_init(TEST_SLAVE_HOST, &bus_cfg, &slave_hd_cfg));
gpio_pullup_en(slave_hd_cfg.spics_io_num); same_pin_func_sel(bus_cfg, slave_hd_cfg.spics_io_num, 0, true);
vTaskDelay(1); vTaskDelay(1);
for (uint8_t cnt = 0; cnt < 3; cnt ++) { for (uint8_t cnt = 0; cnt < 3; cnt ++) {
@@ -1122,12 +958,8 @@ TEST_CASE("test_spi_slave_hd_sleep_retention", "[spi]")
TEST_ESP_OK(spi_slave_hd_queue_trans(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_RX, &rx_data, portMAX_DELAY)); TEST_ESP_OK(spi_slave_hd_queue_trans(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_RX, &rx_data, portMAX_DELAY));
// tx rx transaction // tx rx transaction
mst_txbuff[0] = slave_hd_cmd[0][0]; essl_sspi_hd_dma_trans_seg(bus_cfg, slave_hd_cfg.spics_io_num, 0, false, mst_send, sizeof(mst_send), -1);
spi_master_trans_impl_gpio(bus_cfg, slave_hd_cfg.spics_io_num, 0, mst_txbuff, NULL, sizeof(mst_txbuff)); essl_sspi_hd_dma_trans_seg(bus_cfg, slave_hd_cfg.spics_io_num, 0, true, mst_rexcv, sizeof(mst_rexcv), -1);
spi_master_trans_impl_gpio(bus_cfg, slave_hd_cfg.spics_io_num, 0, &slave_hd_cmd[0][1], NULL, 3);
mst_rxbuff[0] = slave_hd_cmd[1][0];
spi_master_trans_impl_gpio(bus_cfg, slave_hd_cfg.spics_io_num, 0, mst_rxbuff, mst_rxbuff, sizeof(mst_rxbuff));
spi_master_trans_impl_gpio(bus_cfg, slave_hd_cfg.spics_io_num, 0, &slave_hd_cmd[1][1], NULL, 3);
// check trans result // check trans result
TEST_ESP_OK(spi_slave_hd_get_trans_res(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_TX, &ret_trans, portMAX_DELAY)); TEST_ESP_OK(spi_slave_hd_get_trans_res(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_TX, &ret_trans, portMAX_DELAY));
@@ -1140,12 +972,10 @@ TEST_CASE("test_spi_slave_hd_sleep_retention", "[spi]")
// test slave hd share registers // test slave hd share registers
slave_share_sig += cnt; slave_share_sig += cnt;
spi_slave_hd_write_buffer(TEST_SLAVE_HOST, TEST_SLP_BUF_ID, (uint8_t *)&slave_share_sig, sizeof(uint32_t)); spi_slave_hd_write_buffer(TEST_SLAVE_HOST, TEST_SLP_BUF_ID, (uint8_t *)&slave_share_sig, sizeof(uint32_t));
memset(share_sig_buff, 0, sizeof(share_sig_buff)); read_share_sig = 0;
share_sig_buff[0] = SPI_LL_BASE_CMD_HD_RDBUF; // cmd essl_sspi_hd_buffer_trans(bus_cfg, slave_hd_cfg.spics_io_num, 0, SPI_CMD_HD_RDBUF, TEST_SLP_BUF_ID, &read_share_sig, sizeof(uint32_t));
share_sig_buff[1] = TEST_SLP_BUF_ID; // addr printf("slave reg %lX\n", read_share_sig);
spi_master_trans_impl_gpio(bus_cfg, slave_hd_cfg.spics_io_num, 0, share_sig_buff, share_sig_buff, sizeof(share_sig_buff)); TEST_ASSERT_EQUAL_UINT32(slave_share_sig, read_share_sig);
printf("slave reg %lX\n", *((uint32_t *)&share_sig_buff[3]));
TEST_ASSERT_EQUAL_UINT32(slave_share_sig, *((uint32_t *)&share_sig_buff[3]));
} }
spi_slave_hd_deinit(TEST_SLAVE_HOST); spi_slave_hd_deinit(TEST_SLAVE_HOST);
} }
@@ -1167,10 +997,8 @@ TEST_CASE("test_spi_slave_hd_append_sleep_retention", "[spi]")
esp_sleep_context_t sleep_ctx; esp_sleep_context_t sleep_ctx;
esp_sleep_set_sleep_context(&sleep_ctx); esp_sleep_set_sleep_context(&sleep_ctx);
uint32_t slave_hd_cmd[2][2] = {{SPI_LL_BASE_CMD_HD_WRDMA, SPI_LL_BASE_CMD_HD_WR_END}, {SPI_LL_BASE_CMD_HD_RDDMA, SPI_LL_BASE_CMD_HD_INT0}};
uint8_t slv_rexcv[14], slv_send[TEST_SLP_TRANS_NUM][14] = {{"I'm append x\n"}, {"I'm append x\n"}, {"I'm append x\n"}}; uint8_t slv_rexcv[14], slv_send[TEST_SLP_TRANS_NUM][14] = {{"I'm append x\n"}, {"I'm append x\n"}, {"I'm append x\n"}};
uint8_t mst_txbuff[17] = " I'm master x\n", mst_rxbuff[17]; //more than 3 byte to hold cmd,addrs,dummy uint8_t mst_send[14] = "I'm master x\n", mst_rexcv[14];
uint8_t *mst_send = &mst_txbuff[3], *mst_rexcv = &mst_rxbuff[3];
spi_slave_hd_data_t *ret_trans, tx_data[TEST_SLP_TRANS_NUM], rx_data = { spi_slave_hd_data_t *ret_trans, tx_data[TEST_SLP_TRANS_NUM], rx_data = {
.data = slv_rexcv, .data = slv_rexcv,
.len = sizeof(slv_rexcv), .len = sizeof(slv_rexcv),
@@ -1184,7 +1012,7 @@ TEST_CASE("test_spi_slave_hd_append_sleep_retention", "[spi]")
spi_slave_hd_slot_config_t slave_hd_cfg = SPI_SLOT_TEST_DEFAULT_CONFIG(); spi_slave_hd_slot_config_t slave_hd_cfg = SPI_SLOT_TEST_DEFAULT_CONFIG();
slave_hd_cfg.flags |= SPI_SLAVE_HD_APPEND_MODE; slave_hd_cfg.flags |= SPI_SLAVE_HD_APPEND_MODE;
TEST_ESP_OK(spi_slave_hd_init(TEST_SLAVE_HOST, &bus_cfg, &slave_hd_cfg)); TEST_ESP_OK(spi_slave_hd_init(TEST_SLAVE_HOST, &bus_cfg, &slave_hd_cfg));
gpio_pullup_en(slave_hd_cfg.spics_io_num); same_pin_func_sel(bus_cfg, slave_hd_cfg.spics_io_num, 0, true);
vTaskDelay(1); vTaskDelay(1);
for (uint8_t i = 0; i < 2; i++) { for (uint8_t i = 0; i < 2; i++) {
@@ -1217,12 +1045,8 @@ TEST_CASE("test_spi_slave_hd_append_sleep_retention", "[spi]")
memset(slv_rexcv, 0, sizeof(slv_rexcv)); memset(slv_rexcv, 0, sizeof(slv_rexcv));
// tx rx append transaction // tx rx append transaction
mst_txbuff[0] = slave_hd_cmd[0][0]; essl_sspi_hd_dma_trans_seg(bus_cfg, slave_hd_cfg.spics_io_num, 0, false, mst_send, sizeof(mst_send), -1);
spi_master_trans_impl_gpio(bus_cfg, slave_hd_cfg.spics_io_num, 0, mst_txbuff, NULL, sizeof(mst_txbuff)); essl_sspi_hd_dma_trans_seg(bus_cfg, slave_hd_cfg.spics_io_num, 0, true, mst_rexcv, sizeof(mst_rexcv), -1);
spi_master_trans_impl_gpio(bus_cfg, slave_hd_cfg.spics_io_num, 0, &slave_hd_cmd[0][1], NULL, 3);
mst_rxbuff[0] = slave_hd_cmd[1][0];
spi_master_trans_impl_gpio(bus_cfg, slave_hd_cfg.spics_io_num, 0, mst_rxbuff, mst_rxbuff, sizeof(mst_rxbuff));
spi_master_trans_impl_gpio(bus_cfg, slave_hd_cfg.spics_io_num, 0, &slave_hd_cmd[1][1], NULL, 3);
// check append trans result // check append trans result
TEST_ESP_OK(spi_slave_hd_get_append_trans_res(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_TX, &ret_trans, portMAX_DELAY)); TEST_ESP_OK(spi_slave_hd_get_append_trans_res(TEST_SLAVE_HOST, SPI_SLAVE_CHAN_TX, &ret_trans, portMAX_DELAY));

View File

@@ -2,6 +2,7 @@
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
import pytest import pytest
from pytest_embedded_idf.utils import idf_parametrize from pytest_embedded_idf.utils import idf_parametrize
# If `test_env` is define, should not run on generic runner # If `test_env` is define, should not run on generic runner
@@ -16,7 +17,7 @@ def test_slave_hd_single_dev(case_tester) -> None: # type: ignore
for case in case_tester.test_menu: for case in case_tester.test_menu:
if 'test_env' in case.attributes: if 'test_env' in case.attributes:
continue continue
case_tester.run_normal_case(case=case, reset=True) case_tester.run_normal_case(case=case, reset=True, timeout=180)
# if `test_env` not defined, will run on `generic_multi_device` by default # if `test_env` not defined, will run on `generic_multi_device` by default