Merge branch 'fix/spi_dma_config_in_iram' into 'master'

SPI: put dma config and slave functions into IRAM

See merge request idf/esp-idf!3038
This commit is contained in:
Ivan Grokhotkov 2018-08-23 22:03:28 +08:00
commit 7abed5fc9e
3 changed files with 51 additions and 15 deletions

View File

@ -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

View File

@ -330,7 +330,7 @@ void spicommon_cs_free_io(int cs_gpio_num)
}
//Set up a list of dma descriptors. dmadesc is an array of descriptors. Data is the buffer to point to.
void spicommon_setup_dma_desc_links(lldesc_t *dmadesc, int len, const uint8_t *data, bool isrx)
void IRAM_ATTR spicommon_setup_dma_desc_links(lldesc_t *dmadesc, int len, const uint8_t *data, bool isrx)
{
int n = 0;
while (len) {

View File

@ -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 ) {