mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-05 13:44:32 +02:00
Merge branch 'feature/_spi_slave_reset_trans_queue_api' into 'master'
spi_slave: add a private API to reset transaction queue Closes IDF-5033 See merge request espressif/esp-idf!20825
This commit is contained in:
@@ -227,7 +227,8 @@ int spicommon_irqdma_source_for_host(spi_host_device_t host);
|
||||
*/
|
||||
typedef void(*dmaworkaround_cb_t)(void *arg);
|
||||
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
//This workaround is only for esp32
|
||||
/**
|
||||
* @brief Request a reset for a certain DMA channel
|
||||
*
|
||||
@@ -274,6 +275,7 @@ void spicommon_dmaworkaround_idle(int dmachan);
|
||||
* be affected by a global SPI DMA reset, and a reset like that should not be attempted.
|
||||
*/
|
||||
void spicommon_dmaworkaround_transfer_active(int dmachan);
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
/*******************************************************************************
|
||||
* Bus attributes
|
||||
|
39
components/driver/include/esp_private/spi_slave_internal.h
Normal file
39
components/driver/include/esp_private/spi_slave_internal.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* This file contains SPI Slave private/internal APIs. Private/Internal APIs are:
|
||||
* - Visible to other IDF components
|
||||
* - Suggest NOT to use these APIs in your applications
|
||||
* - We don't provide backward compatibility on these APIs either
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
#include "hal/spi_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @note
|
||||
* This API is used to reset SPI Slave transaction queue. After calling this function:
|
||||
* - The SPI Slave transaction queue will be reset.
|
||||
*
|
||||
* @note This API shouldn't be called when the corresponding SPI Master is doing an SPI transaction.
|
||||
* If this gets called when its corresponding SPI Master is doing an SPI transaction, the SPI Slave behaviour is undefined
|
||||
*
|
||||
* @param host SPI peripheral that is acting as a slave
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG if parameter is invalid
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t spi_slave_queue_reset(spi_host_device_t host);
|
@@ -913,11 +913,10 @@ static dmaworkaround_cb_t dmaworkaround_cb;
|
||||
static void *dmaworkaround_cb_arg;
|
||||
static portMUX_TYPE dmaworkaround_mux = portMUX_INITIALIZER_UNLOCKED;
|
||||
static int dmaworkaround_waiting_for_chan = 0;
|
||||
#endif
|
||||
|
||||
bool IRAM_ATTR spicommon_dmaworkaround_req_reset(int dmachan, dmaworkaround_cb_t cb, void *arg)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
int otherchan = (dmachan == 1) ? 2 : 1;
|
||||
bool ret;
|
||||
portENTER_CRITICAL_ISR(&dmaworkaround_mux);
|
||||
@@ -934,24 +933,15 @@ bool IRAM_ATTR spicommon_dmaworkaround_req_reset(int dmachan, dmaworkaround_cb_t
|
||||
}
|
||||
portEXIT_CRITICAL_ISR(&dmaworkaround_mux);
|
||||
return ret;
|
||||
#else
|
||||
//no need to reset
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool IRAM_ATTR spicommon_dmaworkaround_reset_in_progress(void)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
return (dmaworkaround_waiting_for_chan != 0);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void IRAM_ATTR spicommon_dmaworkaround_idle(int dmachan)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
portENTER_CRITICAL_ISR(&dmaworkaround_mux);
|
||||
dmaworkaround_channels_busy[dmachan-1] = 0;
|
||||
if (dmaworkaround_waiting_for_chan == dmachan) {
|
||||
@@ -963,14 +953,12 @@ void IRAM_ATTR spicommon_dmaworkaround_idle(int dmachan)
|
||||
|
||||
}
|
||||
portEXIT_CRITICAL_ISR(&dmaworkaround_mux);
|
||||
#endif
|
||||
}
|
||||
|
||||
void IRAM_ATTR spicommon_dmaworkaround_transfer_active(int dmachan)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
portENTER_CRITICAL_ISR(&dmaworkaround_mux);
|
||||
dmaworkaround_channels_busy[dmachan-1] = 1;
|
||||
portEXIT_CRITICAL_ISR(&dmaworkaround_mux);
|
||||
#endif
|
||||
}
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32
|
||||
|
@@ -632,10 +632,13 @@ static void SPI_MASTER_ISR_ATTR spi_intr(void *arg)
|
||||
//Okay, transaction is done.
|
||||
const int cs = host->cur_cs;
|
||||
//Tell common code DMA workaround that our DMA channel is idle. If needed, the code will do a DMA reset.
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if (bus_attr->dma_enabled) {
|
||||
//This workaround is only for esp32, where tx_dma_chan and rx_dma_chan are always same
|
||||
spicommon_dmaworkaround_idle(bus_attr->tx_dma_chan);
|
||||
}
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
//cur_cs is changed to DEV_NUM_MAX here
|
||||
spi_post_trans(host);
|
||||
@@ -691,11 +694,13 @@ static void SPI_MASTER_ISR_ATTR spi_intr(void *arg)
|
||||
|
||||
if (trans_found) {
|
||||
spi_trans_priv_t *const cur_trans_buf = &host->cur_trans_buf;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if (bus_attr->dma_enabled && (cur_trans_buf->buffer_to_rcv || cur_trans_buf->buffer_to_send)) {
|
||||
//mark channel as active, so that the DMA will not be reset by the slave
|
||||
//This workaround is only for esp32, where tx_dma_chan and rx_dma_chan are always same
|
||||
spicommon_dmaworkaround_transfer_active(bus_attr->tx_dma_chan);
|
||||
}
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32
|
||||
spi_new_trans(device_to_send, cur_trans_buf);
|
||||
}
|
||||
// Exit of the ISR, handle interrupt re-enable (if sending transaction), retry (if there's coming BG),
|
||||
@@ -929,10 +934,14 @@ esp_err_t SPI_MASTER_ISR_ATTR spi_device_acquire_bus(spi_device_t *device, TickT
|
||||
//configure the device ahead so that we don't need to do it again in the following transactions
|
||||
spi_setup_device(host->device[device->id]);
|
||||
//the DMA is also occupied by the device, all the slave devices that using DMA should wait until bus released.
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if (host->bus_attr->dma_enabled) {
|
||||
//This workaround is only for esp32, where tx_dma_chan and rx_dma_chan are always same
|
||||
spicommon_dmaworkaround_transfer_active(host->bus_attr->tx_dma_chan);
|
||||
}
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -946,11 +955,13 @@ void SPI_MASTER_ISR_ATTR spi_device_release_bus(spi_device_t *dev)
|
||||
assert(0);
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if (host->bus_attr->dma_enabled) {
|
||||
//This workaround is only for esp32, where tx_dma_chan and rx_dma_chan are always same
|
||||
spicommon_dmaworkaround_idle(host->bus_attr->tx_dma_chan);
|
||||
}
|
||||
//Tell common code DMA workaround that our DMA channel is idle. If needed, the code will do a DMA reset.
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
//allow clock to be lower than 80MHz when all tasks blocked
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
|
@@ -283,6 +283,33 @@ esp_err_t spi_slave_free(spi_host_device_t host)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @note
|
||||
* This API is used to reset SPI Slave transaction queue. After calling this function:
|
||||
* - The SPI Slave transaction queue will be reset.
|
||||
*
|
||||
* Therefore, this API shouldn't be called when the corresponding SPI Master is doing an SPI transaction.
|
||||
*
|
||||
* @note
|
||||
* We don't actually need to enter a critical section here.
|
||||
* SPI Slave ISR will only get triggered when its corresponding SPI Master's transaction is done.
|
||||
* As we don't expect this function to be called when its corresponding SPI Master is doing an SPI transaction,
|
||||
* so concurrent call to these registers won't happen
|
||||
*
|
||||
*/
|
||||
esp_err_t SPI_SLAVE_ATTR spi_slave_queue_reset(spi_host_device_t host)
|
||||
{
|
||||
SPI_CHECK(is_valid_host(host), "invalid host", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK(spihost[host], "host not slave", ESP_ERR_INVALID_ARG);
|
||||
|
||||
esp_intr_disable(spihost[host]->intr);
|
||||
spi_ll_set_int_stat(spihost[host]->hal.hw);
|
||||
|
||||
spihost[host]->cur_trans = NULL;
|
||||
xQueueReset(spihost[host]->trans_queue);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t SPI_SLAVE_ATTR spi_slave_queue_trans(spi_host_device_t host, const spi_slave_transaction_t *trans_desc, TickType_t ticks_to_wait)
|
||||
{
|
||||
@@ -331,11 +358,13 @@ esp_err_t SPI_SLAVE_ATTR spi_slave_transmit(spi_host_device_t host, spi_slave_tr
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
static void SPI_SLAVE_ISR_ATTR spi_slave_restart_after_dmareset(void *arg)
|
||||
{
|
||||
spi_slave_t *host = (spi_slave_t *)arg;
|
||||
esp_intr_enable(host->intr);
|
||||
}
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
//This is run in interrupt context and apart from initialization and destruction, this is the only code
|
||||
//touching the host (=spihost[x]) variable. The rest of the data arrives in queues. That is why there are
|
||||
@@ -358,10 +387,14 @@ static void SPI_SLAVE_ISR_ATTR spi_intr(void *arg)
|
||||
spi_slave_hal_store_result(hal);
|
||||
host->cur_trans->trans_len = spi_slave_hal_get_rcv_bitlen(hal);
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
//This workaround is only for esp32
|
||||
if (spi_slave_hal_dma_need_reset(hal)) {
|
||||
//On ESP32 and ESP32S2, actual_tx_dma_chan and actual_rx_dma_chan are always same
|
||||
//On ESP32, actual_tx_dma_chan and actual_rx_dma_chan are always same
|
||||
spicommon_dmaworkaround_req_reset(host->tx_dma_chan, spi_slave_restart_after_dmareset, host);
|
||||
}
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
if (host->cfg.post_trans_cb) host->cfg.post_trans_cb(host->cur_trans);
|
||||
|
||||
if(!(host->cfg.flags & SPI_SLAVE_NO_RETURN_RESULT)) {
|
||||
@@ -369,8 +402,11 @@ static void SPI_SLAVE_ISR_ATTR spi_intr(void *arg)
|
||||
}
|
||||
host->cur_trans = NULL;
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
//This workaround is only for esp32
|
||||
if (use_dma) {
|
||||
//On ESP32 and ESP32S2, actual_tx_dma_chan and actual_rx_dma_chan are always same
|
||||
//On ESP32, actual_tx_dma_chan and actual_rx_dma_chan are always same
|
||||
spicommon_dmaworkaround_idle(host->tx_dma_chan);
|
||||
if (spicommon_dmaworkaround_reset_in_progress()) {
|
||||
//We need to wait for the reset to complete. Disable int (will be re-enabled on reset callback) and exit isr.
|
||||
@@ -379,6 +415,7 @@ static void SPI_SLAVE_ISR_ATTR spi_intr(void *arg)
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
//Disable interrupt before checking to avoid concurrency issue.
|
||||
esp_intr_disable(host->intr);
|
||||
@@ -398,10 +435,13 @@ static void SPI_SLAVE_ISR_ATTR spi_intr(void *arg)
|
||||
hal->rx_buffer = trans->rx_buffer;
|
||||
hal->tx_buffer = trans->tx_buffer;
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if (use_dma) {
|
||||
//On ESP32 and ESP32S2, actual_tx_dma_chan and actual_rx_dma_chan are always same
|
||||
//This workaround is only for esp32
|
||||
//On ESP32, actual_tx_dma_chan and actual_rx_dma_chan are always same
|
||||
spicommon_dmaworkaround_transfer_active(host->tx_dma_chan);
|
||||
}
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
spi_slave_hal_prepare_data(hal);
|
||||
|
||||
|
@@ -2,6 +2,7 @@
|
||||
set(srcs
|
||||
"test_app_main.c"
|
||||
"test_spi_slave.c"
|
||||
"test_spi_slave_queue.c"
|
||||
)
|
||||
|
||||
|
||||
|
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
/*
|
||||
Tests for the spi_master device driver
|
||||
*/
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_log.h"
|
||||
#include "test_utils.h"
|
||||
#include "test_spi_utils.h"
|
||||
#include "driver/spi_master.h"
|
||||
#include "driver/spi_slave.h"
|
||||
#include "esp_private/spi_slave_internal.h"
|
||||
#include "soc/spi_pins.h"
|
||||
#include "soc/spi_periph.h"
|
||||
|
||||
#define TEST_BUF_SIZE 32
|
||||
#define TEST_TIMES 4
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C6)
|
||||
|
||||
static void test_master(void)
|
||||
{
|
||||
spi_bus_config_t buscfg = SPI_BUS_TEST_DEFAULT_CONFIG();
|
||||
TEST_ESP_OK(spi_bus_initialize(SPI2_HOST, &buscfg, 0));
|
||||
|
||||
spi_device_handle_t spi;
|
||||
spi_device_interface_config_t devcfg = {
|
||||
.clock_speed_hz = 1 * 1000 * 1000,
|
||||
.mode = 0,
|
||||
.spics_io_num = PIN_NUM_CS,
|
||||
.queue_size = 16,
|
||||
.cs_ena_pretrans = 0,
|
||||
.cs_ena_posttrans = 0,
|
||||
.input_delay_ns = 62.5,
|
||||
};
|
||||
TEST_ESP_OK(spi_bus_add_device(SPI2_HOST, &devcfg, &spi));
|
||||
|
||||
unity_send_signal("Master ready");
|
||||
|
||||
uint8_t *mst_tx_buf[TEST_TIMES] = {};
|
||||
uint8_t *mst_rx_buf[TEST_TIMES] = {};
|
||||
uint8_t *slv_tx_buf[TEST_TIMES] = {};
|
||||
for (int i = 0; i < TEST_TIMES; i++) {
|
||||
uint32_t test_seed = i * 100 + 99;
|
||||
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);
|
||||
}
|
||||
|
||||
//Trans0
|
||||
spi_transaction_t trans0 = {
|
||||
.tx_buffer = mst_tx_buf[0],
|
||||
.rx_buffer = mst_rx_buf[0],
|
||||
.length = TEST_BUF_SIZE * 8,
|
||||
};
|
||||
unity_wait_for_signal("Slave ready");
|
||||
TEST_ESP_OK(spi_device_transmit(spi, (spi_transaction_t*)&trans0));
|
||||
//show result
|
||||
ESP_LOG_BUFFER_HEX("master tx:", mst_tx_buf[0], TEST_BUF_SIZE);
|
||||
ESP_LOG_BUFFER_HEX("master rx:", mst_rx_buf[0], TEST_BUF_SIZE);
|
||||
TEST_ASSERT_EQUAL_HEX8_ARRAY(slv_tx_buf[0], mst_rx_buf[0], TEST_BUF_SIZE);
|
||||
|
||||
//Trans1
|
||||
spi_transaction_t trans1 = {
|
||||
.tx_buffer = mst_tx_buf[1],
|
||||
.rx_buffer = mst_rx_buf[1],
|
||||
.length = TEST_BUF_SIZE * 8,
|
||||
};
|
||||
unity_wait_for_signal("Slave ready");
|
||||
TEST_ESP_OK(spi_device_transmit(spi, (spi_transaction_t*)&trans1));
|
||||
//show result
|
||||
ESP_LOG_BUFFER_HEX("master tx:", mst_tx_buf[1], TEST_BUF_SIZE);
|
||||
ESP_LOG_BUFFER_HEX("master rx:", mst_rx_buf[1], TEST_BUF_SIZE);
|
||||
TEST_ASSERT_EQUAL_HEX8_ARRAY(slv_tx_buf[1], mst_rx_buf[1], TEST_BUF_SIZE);
|
||||
|
||||
//Trans2
|
||||
spi_transaction_t trans2 = {
|
||||
.tx_buffer = mst_tx_buf[2],
|
||||
.rx_buffer = mst_rx_buf[2],
|
||||
.length = TEST_BUF_SIZE * 8,
|
||||
};
|
||||
// unity_wait_for_signal("Slave ready");
|
||||
TEST_ESP_OK(spi_device_transmit(spi, (spi_transaction_t*)&trans2));
|
||||
//show result
|
||||
ESP_LOG_BUFFER_HEX("master tx:", mst_tx_buf[2], TEST_BUF_SIZE);
|
||||
ESP_LOG_BUFFER_HEX("master rx:", mst_rx_buf[2], TEST_BUF_SIZE);
|
||||
TEST_ASSERT_EQUAL_HEX8_ARRAY(slv_tx_buf[2], mst_rx_buf[2], TEST_BUF_SIZE);
|
||||
|
||||
//Trans3
|
||||
spi_transaction_t trans3 = {
|
||||
.tx_buffer = mst_tx_buf[3],
|
||||
.rx_buffer = mst_rx_buf[3],
|
||||
.length = TEST_BUF_SIZE * 8,
|
||||
};
|
||||
// unity_wait_for_signal("Slave ready");
|
||||
TEST_ESP_OK(spi_device_transmit(spi, (spi_transaction_t*)&trans3));
|
||||
//show result
|
||||
ESP_LOG_BUFFER_HEX("master tx:", mst_tx_buf[3], TEST_BUF_SIZE);
|
||||
ESP_LOG_BUFFER_HEX("master rx:", mst_rx_buf[3], TEST_BUF_SIZE);
|
||||
TEST_ASSERT_EQUAL_HEX8_ARRAY(slv_tx_buf[3], mst_rx_buf[3], TEST_BUF_SIZE);
|
||||
|
||||
for (int i = 0; i < TEST_TIMES; i++) {
|
||||
free(mst_tx_buf[i]);
|
||||
free(mst_rx_buf[i]);
|
||||
free(slv_tx_buf[i]);
|
||||
}
|
||||
|
||||
TEST_ASSERT(spi_bus_remove_device(spi) == ESP_OK);
|
||||
TEST_ASSERT(spi_bus_free(SPI2_HOST) == ESP_OK);
|
||||
}
|
||||
|
||||
static void 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 = {
|
||||
.mode = 0,
|
||||
.spics_io_num = PIN_NUM_CS,
|
||||
.queue_size = 10,
|
||||
};
|
||||
TEST_ESP_OK(spi_slave_initialize(SPI2_HOST, &buscfg, &slvcfg, SPI_DMA_CH_AUTO));
|
||||
|
||||
uint8_t *slv_tx_buf[TEST_TIMES] = {};
|
||||
uint8_t *slv_rx_buf[TEST_TIMES] = {};
|
||||
uint8_t *mst_tx_buf[TEST_TIMES] = {};
|
||||
for (int i = 0; i < TEST_TIMES; i++) {
|
||||
uint32_t test_seed = i * 100 + 99;
|
||||
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);
|
||||
}
|
||||
|
||||
spi_slave_transaction_t trans[TEST_TIMES] = {};
|
||||
spi_slave_transaction_t *ret_trans = NULL;
|
||||
|
||||
//Trans0
|
||||
trans[0].tx_buffer = slv_tx_buf[0];
|
||||
trans[0].rx_buffer = slv_rx_buf[0];
|
||||
trans[0].length = TEST_BUF_SIZE * 8;
|
||||
TEST_ESP_OK(spi_slave_queue_trans(SPI2_HOST, &trans[0], portMAX_DELAY));
|
||||
unity_send_signal("Slave ready");
|
||||
TEST_ESP_OK(spi_slave_get_trans_result(SPI2_HOST, &ret_trans, portMAX_DELAY));
|
||||
TEST_ASSERT(ret_trans == &trans[0]);
|
||||
ESP_LOG_BUFFER_HEX("slave tx:", slv_tx_buf[0], TEST_BUF_SIZE);
|
||||
ESP_LOG_BUFFER_HEX("slave rx:", slv_rx_buf[0], TEST_BUF_SIZE);
|
||||
|
||||
/**
|
||||
* Now we push few more dummy transactions to the slave trans queue,
|
||||
* to see if `spi_slave_queue_reset()` works
|
||||
*/
|
||||
uint32_t dummy_data0 = 0xAA;
|
||||
spi_slave_transaction_t dummy_trans0 = {
|
||||
.tx_buffer = &dummy_data0,
|
||||
.length = sizeof(uint32_t) * 8,
|
||||
};
|
||||
TEST_ESP_OK(spi_slave_queue_trans(SPI2_HOST, &dummy_trans0, portMAX_DELAY));
|
||||
uint32_t dummy_data1 = 0xBB;
|
||||
spi_slave_transaction_t dummy_trans1 = {
|
||||
.tx_buffer = &dummy_data1,
|
||||
.length = sizeof(uint32_t) * 8,
|
||||
};
|
||||
TEST_ESP_OK(spi_slave_queue_trans(SPI2_HOST, &dummy_trans1, portMAX_DELAY));
|
||||
uint32_t dummy_data2 = 0xCC;
|
||||
spi_slave_transaction_t dummy_trans2 = {
|
||||
.tx_buffer = &dummy_data2,
|
||||
.length = sizeof(uint32_t) * 8,
|
||||
};
|
||||
TEST_ESP_OK(spi_slave_queue_trans(SPI2_HOST, &dummy_trans2, portMAX_DELAY));
|
||||
uint32_t dummy_data3 = 0xDD;
|
||||
spi_slave_transaction_t dummy_trans3 = {
|
||||
.tx_buffer = &dummy_data3,
|
||||
.length = sizeof(uint32_t) * 8,
|
||||
};
|
||||
TEST_ESP_OK(spi_slave_queue_trans(SPI2_HOST, &dummy_trans3, portMAX_DELAY));
|
||||
|
||||
//Trans1~3
|
||||
spi_slave_queue_reset(SPI2_HOST);
|
||||
trans[1].tx_buffer = slv_tx_buf[1];
|
||||
trans[1].rx_buffer = slv_rx_buf[1];
|
||||
trans[1].length = TEST_BUF_SIZE * 8;
|
||||
TEST_ESP_OK(spi_slave_queue_trans(SPI2_HOST, &trans[1], portMAX_DELAY));
|
||||
|
||||
trans[2].tx_buffer = slv_tx_buf[2];
|
||||
trans[2].rx_buffer = slv_rx_buf[2];
|
||||
trans[2].length = TEST_BUF_SIZE * 8;
|
||||
TEST_ESP_OK(spi_slave_queue_trans(SPI2_HOST, &trans[2], portMAX_DELAY));
|
||||
|
||||
trans[3].tx_buffer = slv_tx_buf[3];
|
||||
trans[3].rx_buffer = slv_rx_buf[3];
|
||||
trans[3].length = TEST_BUF_SIZE * 8;
|
||||
TEST_ESP_OK(spi_slave_queue_trans(SPI2_HOST, &trans[3], portMAX_DELAY));
|
||||
|
||||
unity_send_signal("Slave ready");
|
||||
for (int i = 1; i < TEST_TIMES; i++) {
|
||||
TEST_ESP_OK(spi_slave_get_trans_result(SPI2_HOST, &ret_trans, portMAX_DELAY));
|
||||
TEST_ASSERT(ret_trans == &trans[i]);
|
||||
ESP_LOG_BUFFER_HEX("slave tx:", slv_tx_buf[i], TEST_BUF_SIZE);
|
||||
ESP_LOG_BUFFER_HEX("slave rx:", slv_rx_buf[i], TEST_BUF_SIZE);
|
||||
}
|
||||
|
||||
for (int i = 0; i < TEST_TIMES; i++) {
|
||||
free(slv_tx_buf[i]);
|
||||
free(slv_rx_buf[i]);
|
||||
free(mst_tx_buf[i]);
|
||||
}
|
||||
|
||||
TEST_ESP_OK(spi_slave_free(SPI2_HOST));
|
||||
}
|
||||
|
||||
TEST_CASE_MULTIPLE_DEVICES("SPI_Slave_Reset_Queue_Test", "[spi_ms][timeout=120]", test_master, test_slave);
|
||||
#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32C6)
|
@@ -1,16 +1,8 @@
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* NOTICE
|
||||
@@ -150,6 +142,7 @@ void spi_slave_hal_store_result(spi_slave_hal_context_t *hal);
|
||||
*/
|
||||
uint32_t spi_slave_hal_get_rcv_bitlen(spi_slave_hal_context_t *hal);
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/**
|
||||
* Check whether we need to reset the DMA according to the status of last transactions.
|
||||
*
|
||||
@@ -161,3 +154,4 @@ uint32_t spi_slave_hal_get_rcv_bitlen(spi_slave_hal_context_t *hal);
|
||||
* @return true if reset is needed, else false.
|
||||
*/
|
||||
bool spi_slave_hal_dma_need_reset(const spi_slave_hal_context_t *hal);
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32
|
||||
|
@@ -98,6 +98,8 @@ uint32_t spi_slave_hal_get_rcv_bitlen(spi_slave_hal_context_t *hal)
|
||||
return hal->rcv_bitlen;
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
//This workaround is only for esp32
|
||||
bool spi_slave_hal_dma_need_reset(const spi_slave_hal_context_t *hal)
|
||||
{
|
||||
bool ret;
|
||||
@@ -114,3 +116,4 @@ bool spi_slave_hal_dma_need_reset(const spi_slave_hal_context_t *hal)
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif //#if CONFIG_IDF_TARGET_ESP32
|
||||
|
@@ -699,7 +699,6 @@ components/hal/include/hal/rtc_io_types.h
|
||||
components/hal/include/hal/sdio_slave_ll.h
|
||||
components/hal/include/hal/sha_hal.h
|
||||
components/hal/include/hal/spi_flash_encrypt_hal.h
|
||||
components/hal/include/hal/spi_slave_hal.h
|
||||
components/hal/include/hal/spi_slave_hd_hal.h
|
||||
components/hal/include/hal/uhci_types.h
|
||||
components/hal/include/hal/usb_hal.h
|
||||
|
Reference in New Issue
Block a user