From 4f87a62f1856c3a2d5ddbcbc881c17b1f2a663a5 Mon Sep 17 00:00:00 2001 From: "Michael (XIAO Xufeng)" Date: Mon, 20 Aug 2018 18:30:40 +0800 Subject: [PATCH] spi_slave: add new menuconfig item to decide whether spi slave should be put into IRAM --- components/driver/Kconfig | 28 +++++++++++++++++++++++---- components/driver/spi_slave.c | 36 +++++++++++++++++++++++++---------- 2 files changed, 50 insertions(+), 14 deletions(-) diff --git a/components/driver/Kconfig b/components/driver/Kconfig index bff45a46bf..eaf61508d9 100644 --- a/components/driver/Kconfig +++ b/components/driver/Kconfig @@ -6,8 +6,8 @@ config ADC_FORCE_XPD_FSM bool "Use the FSM to control ADC power" default n help - ADC power can be controlled by the FSM instead of software. This allows the ADC to - be shut off when it is not working leading to lower power consumption. However + ADC power can be controlled by the FSM instead of software. This allows the ADC to + be shut off when it is not working leading to lower power consumption. However using the FSM control ADC power will increase the noise of ADC. config ADC2_DISABLE_DAC @@ -20,7 +20,7 @@ config ADC2_DISABLE_DAC endmenu # ADC Configuration -menu "SPI master configuration" +menu "SPI configuration" config SPI_MASTER_IN_IRAM bool "Place transmitting functions of SPI master into IRAM" @@ -44,6 +44,26 @@ config SPI_MASTER_ISR_IN_IRAM Place the SPI master ISR in to IRAM to avoid possibly cache miss, or being disabled during flash writing access. -endmenu # SPI Master Configuration +config SPI_SLAVE_IN_IRAM + bool "Place transmitting functions of SPI slave into IRAM" + default n + select SPI_SLAVE_ISR_IN_IRAM + help + Normally only the ISR of SPI slave is placed in the IRAM, so that it + can work without the flash when interrupt is triggered. + For other functions, there's some possibility that the flash cache + miss when running inside and out of SPI functions, which may increase + the interval of SPI transactions. + Enable this to put ``queue_trans``, ``get_trans_result`` and + ``transmit`` functions into the IRAM to avoid possible cache miss. + +config SPI_SLAVE_ISR_IN_IRAM + bool "Place SPI slave ISR function into IRAM" + default y + help + Place the SPI slave ISR in to IRAM to avoid possibly cache miss, or + being disabled during flash writing access. + +endmenu # SPI Configuration endmenu # Driver configurations diff --git a/components/driver/spi_slave.c b/components/driver/spi_slave.c index 7ff89e6c8a..e563ef0743 100644 --- a/components/driver/spi_slave.c +++ b/components/driver/spi_slave.c @@ -47,6 +47,18 @@ static const char *SPI_TAG = "spi_slave"; #define VALID_HOST(x) (x>SPI_HOST && x<=VSPI_HOST) +#ifdef CONFIG_SPI_SLAVE_ISR_IN_IRAM +#define SPI_SLAVE_ISR_ATTR IRAM_ATTR +#else +#define SPI_SLAVE_ISR_ATTR +#endif + +#ifdef CONFIG_SPI_SLAVE_IN_IRAM +#define SPI_SLAVE_ATTR IRAM_ATTR +#else +#define SPI_SLAVE_ATTR +#endif + typedef struct { spi_slave_interface_config_t cfg; intr_handle_t intr; @@ -79,7 +91,7 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b spi_chan_claimed=spicommon_periph_claim(host); SPI_CHECK(spi_chan_claimed, "host already in use", ESP_ERR_INVALID_STATE); - + if ( dma_chan != 0 ) { dma_chan_claimed=spicommon_dma_chan_claim(dma_chan); if ( !dma_chan_claimed ) { @@ -138,7 +150,11 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b goto cleanup; } - err = esp_intr_alloc(spicommon_irqsource_for_host(host), ESP_INTR_FLAG_INTRDISABLED, spi_intr, (void *)spihost[host], &spihost[host]->intr); + int flags = ESP_INTR_FLAG_INTRDISABLED; +#ifdef CONFIG_SPI_SLAVE_ISR_IN_IRAM + flags |= ESP_INTR_FLAG_IRAM; +#endif + err = esp_intr_alloc(spicommon_irqsource_for_host(host), flags, spi_intr, (void *)spihost[host], &spihost[host]->intr); if (err != ESP_OK) { ret = err; goto cleanup; @@ -250,14 +266,14 @@ esp_err_t spi_slave_free(spi_host_device_t host) } -esp_err_t spi_slave_queue_trans(spi_host_device_t host, const spi_slave_transaction_t *trans_desc, TickType_t ticks_to_wait) +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) { BaseType_t r; SPI_CHECK(VALID_HOST(host), "invalid host", ESP_ERR_INVALID_ARG); SPI_CHECK(spihost[host], "host not slave", ESP_ERR_INVALID_ARG); - SPI_CHECK(spihost[host]->dma_chan == 0 || trans_desc->tx_buffer==NULL || esp_ptr_dma_capable(trans_desc->tx_buffer), + SPI_CHECK(spihost[host]->dma_chan == 0 || trans_desc->tx_buffer==NULL || esp_ptr_dma_capable(trans_desc->tx_buffer), "txdata not in DMA-capable memory", ESP_ERR_INVALID_ARG); - SPI_CHECK(spihost[host]->dma_chan == 0 || trans_desc->rx_buffer==NULL || esp_ptr_dma_capable(trans_desc->rx_buffer), + SPI_CHECK(spihost[host]->dma_chan == 0 || trans_desc->rx_buffer==NULL || esp_ptr_dma_capable(trans_desc->rx_buffer), "rxdata not in DMA-capable memory", ESP_ERR_INVALID_ARG); SPI_CHECK(trans_desc->length <= spihost[host]->max_transfer_sz * 8, "data transfer > host maximum", ESP_ERR_INVALID_ARG); @@ -268,7 +284,7 @@ esp_err_t spi_slave_queue_trans(spi_host_device_t host, const spi_slave_transact } -esp_err_t spi_slave_get_trans_result(spi_host_device_t host, spi_slave_transaction_t **trans_desc, TickType_t ticks_to_wait) +esp_err_t SPI_SLAVE_ATTR spi_slave_get_trans_result(spi_host_device_t host, spi_slave_transaction_t **trans_desc, TickType_t ticks_to_wait) { BaseType_t r; SPI_CHECK(VALID_HOST(host), "invalid host", ESP_ERR_INVALID_ARG); @@ -279,7 +295,7 @@ esp_err_t spi_slave_get_trans_result(spi_host_device_t host, spi_slave_transacti } -esp_err_t spi_slave_transmit(spi_host_device_t host, spi_slave_transaction_t *trans_desc, TickType_t ticks_to_wait) +esp_err_t SPI_SLAVE_ATTR spi_slave_transmit(spi_host_device_t host, spi_slave_transaction_t *trans_desc, TickType_t ticks_to_wait) { esp_err_t ret; spi_slave_transaction_t *ret_trans; @@ -316,7 +332,7 @@ static void dumpll(lldesc_t *ll) } #endif -static void IRAM_ATTR spi_slave_restart_after_dmareset(void *arg) +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); @@ -325,7 +341,7 @@ static void IRAM_ATTR spi_slave_restart_after_dmareset(void *arg) //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 //no muxes in this code. -static void IRAM_ATTR spi_intr(void *arg) +static void SPI_SLAVE_ISR_ATTR spi_intr(void *arg) { BaseType_t r; BaseType_t do_yield = pdFALSE; @@ -342,7 +358,7 @@ static void IRAM_ATTR spi_intr(void *arg) if (host->cur_trans) { //when data of cur_trans->length are all sent, the slv_rdata_bit - //will be the length sent-1 (i.e. cur_trans->length-1 ), otherwise + //will be the length sent-1 (i.e. cur_trans->length-1 ), otherwise //the length sent. host->cur_trans->trans_len = host->hw->slv_rd_bit.slv_rdata_bit; if ( host->cur_trans->trans_len == host->cur_trans->length - 1 ) {