From 3dc36f622cc43a9da6613f833a7de4a5b558d5e0 Mon Sep 17 00:00:00 2001 From: Armando Date: Thu, 21 Jul 2022 21:23:31 +0800 Subject: [PATCH 1/3] spi_slave: add a private API to reset transaction queue --- .../include/esp_private/spi_slave_internal.h | 39 +++++++++++++++++++ components/driver/spi_slave.c | 27 +++++++++++++ components/hal/include/hal/spi_slave_hal.h | 18 +++------ tools/ci/check_copyright_ignore.txt | 1 - 4 files changed, 71 insertions(+), 14 deletions(-) create mode 100644 components/driver/include/esp_private/spi_slave_internal.h diff --git a/components/driver/include/esp_private/spi_slave_internal.h b/components/driver/include/esp_private/spi_slave_internal.h new file mode 100644 index 0000000000..aa5cd73ab8 --- /dev/null +++ b/components/driver/include/esp_private/spi_slave_internal.h @@ -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); diff --git a/components/driver/spi_slave.c b/components/driver/spi_slave.c index a07f83fb57..c54c89d322 100644 --- a/components/driver/spi_slave.c +++ b/components/driver/spi_slave.c @@ -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) { diff --git a/components/hal/include/hal/spi_slave_hal.h b/components/hal/include/hal/spi_slave_hal.h index 3ad5f485f1..14183a1da8 100644 --- a/components/hal/include/hal/spi_slave_hal.h +++ b/components/hal/include/hal/spi_slave_hal.h @@ -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 diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index 2a91495ea2..fee766aeda 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -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 From a7289587d332764ba44154aa548e4b5d0be6162f Mon Sep 17 00:00:00 2001 From: Armando Date: Thu, 15 Sep 2022 11:53:58 +0800 Subject: [PATCH 2/3] spi_slave: add a test to internal api spi_slave_reset_trans_queue --- .../test_apps/spi/slave/main/CMakeLists.txt | 1 + .../spi/slave/main/test_spi_slave_queue.c | 219 ++++++++++++++++++ 2 files changed, 220 insertions(+) create mode 100644 components/driver/test_apps/spi/slave/main/test_spi_slave_queue.c diff --git a/components/driver/test_apps/spi/slave/main/CMakeLists.txt b/components/driver/test_apps/spi/slave/main/CMakeLists.txt index 0093a056d8..5969fdf635 100644 --- a/components/driver/test_apps/spi/slave/main/CMakeLists.txt +++ b/components/driver/test_apps/spi/slave/main/CMakeLists.txt @@ -2,6 +2,7 @@ set(srcs "test_app_main.c" "test_spi_slave.c" + "test_spi_slave_queue.c" ) diff --git a/components/driver/test_apps/spi/slave/main/test_spi_slave_queue.c b/components/driver/test_apps/spi/slave/main/test_spi_slave_queue.c new file mode 100644 index 0000000000..3b1397b117 --- /dev/null +++ b/components/driver/test_apps/spi/slave/main/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) From ea0b8393024c7c7dd9ae0dd60102f680ec6691be Mon Sep 17 00:00:00 2001 From: Armando Date: Thu, 15 Sep 2022 18:26:12 +0800 Subject: [PATCH 3/3] spi: limit esp32 dma workaround only on esp32 --- .../include/esp_private/spi_common_internal.h | 4 +++- components/driver/spi_common.c | 16 ++-------------- components/driver/spi_master.c | 11 +++++++++++ components/driver/spi_slave.c | 19 ++++++++++++++++--- components/hal/include/hal/spi_slave_hal.h | 2 ++ components/hal/spi_slave_hal_iram.c | 3 +++ 6 files changed, 37 insertions(+), 18 deletions(-) diff --git a/components/driver/include/esp_private/spi_common_internal.h b/components/driver/include/esp_private/spi_common_internal.h index e3127d4831..83b9c1ad6b 100644 --- a/components/driver/include/esp_private/spi_common_internal.h +++ b/components/driver/include/esp_private/spi_common_internal.h @@ -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 diff --git a/components/driver/spi_common.c b/components/driver/spi_common.c index aa2c05dd61..308875172e 100644 --- a/components/driver/spi_common.c +++ b/components/driver/spi_common.c @@ -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 diff --git a/components/driver/spi_master.c b/components/driver/spi_master.c index 71a51e90bf..6e696bcc53 100644 --- a/components/driver/spi_master.c +++ b/components/driver/spi_master.c @@ -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 diff --git a/components/driver/spi_slave.c b/components/driver/spi_slave.c index c54c89d322..6ddc3369c6 100644 --- a/components/driver/spi_slave.c +++ b/components/driver/spi_slave.c @@ -358,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 @@ -385,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)) { @@ -396,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. @@ -406,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); @@ -425,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); diff --git a/components/hal/include/hal/spi_slave_hal.h b/components/hal/include/hal/spi_slave_hal.h index 14183a1da8..9d7ceec37e 100644 --- a/components/hal/include/hal/spi_slave_hal.h +++ b/components/hal/include/hal/spi_slave_hal.h @@ -142,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. * @@ -153,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 diff --git a/components/hal/spi_slave_hal_iram.c b/components/hal/spi_slave_hal_iram.c index d3a0e3924e..56288e134f 100644 --- a/components/hal/spi_slave_hal_iram.c +++ b/components/hal/spi_slave_hal_iram.c @@ -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