From 9061efd3d110dda383dcaeaafc98393bbba36e48 Mon Sep 17 00:00:00 2001 From: Armando Date: Thu, 15 Sep 2022 18:26:12 +0800 Subject: [PATCH] spi: limit esp32 dma workaround only on esp32 --- .../include/driver/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/driver/spi_common_internal.h b/components/driver/include/driver/spi_common_internal.h index b490efeb7e..cc0c92cab1 100644 --- a/components/driver/include/driver/spi_common_internal.h +++ b/components/driver/include/driver/spi_common_internal.h @@ -252,7 +252,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 * @@ -307,6 +308,7 @@ void spicommon_dmaworkaround_idle(int dmachan); * @note This public API is deprecated. */ 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 d9c78062af..162aebf589 100644 --- a/components/driver/spi_common.c +++ b/components/driver/spi_common.c @@ -783,11 +783,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); @@ -804,24 +803,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) { @@ -833,14 +823,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 11ffafd569..bbd4d20afe 100644 --- a/components/driver/spi_master.c +++ b/components/driver/spi_master.c @@ -609,10 +609,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); @@ -662,11 +665,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), @@ -882,10 +887,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; } @@ -899,11 +908,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 5b05192b2a..f8e3b06553 100644 --- a/components/driver/spi_slave.c +++ b/components/driver/spi_slave.c @@ -325,11 +325,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 @@ -352,18 +354,25 @@ 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); //Okay, transaction is done. //Return transaction descriptor. xQueueSendFromISR(host->ret_queue, &host->cur_trans, &do_yield); 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. @@ -372,6 +381,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); @@ -388,10 +398,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 3ad5f485f1..49d8b0ca12 100644 --- a/components/hal/include/hal/spi_slave_hal.h +++ b/components/hal/include/hal/spi_slave_hal.h @@ -150,6 +150,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 +162,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