From 9c23b8e5969ede475b2d81088109820f79ade4df Mon Sep 17 00:00:00 2001 From: "Michael (XIAO Xufeng)" Date: Mon, 11 Jun 2018 19:54:18 +0800 Subject: [PATCH] feature(spi_master): allow to place functions into IRAM to get higher efficiency --- components/driver/Kconfig | 29 ++++++++++++++++++++++++-- components/driver/spi_master.c | 26 ++++++++++++++++++----- tools/unit-test-app/sdkconfig.defaults | 1 + 3 files changed, 49 insertions(+), 7 deletions(-) diff --git a/components/driver/Kconfig b/components/driver/Kconfig index a327a4e867..bff45a46bf 100644 --- a/components/driver/Kconfig +++ b/components/driver/Kconfig @@ -1,4 +1,4 @@ -#menu "Driver configurations" +menu "Driver configurations" menu "ADC configuration" @@ -20,5 +20,30 @@ config ADC2_DISABLE_DAC endmenu # ADC Configuration -#endmenu # Driver configurations +menu "SPI master configuration" +config SPI_MASTER_IN_IRAM + bool "Place transmitting functions of SPI master into IRAM" + default n + select SPI_MASTER_ISR_IN_IRAM + help + Normally only the ISR of SPI master 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. + + During unit test, this is enabled to measure the ideal case of api. + +config SPI_MASTER_ISR_IN_IRAM + bool "Place SPI master ISR function into IRAM" + default y + help + Place the SPI master ISR in to IRAM to avoid possibly cache miss, or + being disabled during flash writing access. + +endmenu # SPI Master Configuration + +endmenu # Driver configurations diff --git a/components/driver/spi_master.c b/components/driver/spi_master.c index 02cb88455f..3e56f7f432 100644 --- a/components/driver/spi_master.c +++ b/components/driver/spi_master.c @@ -66,6 +66,18 @@ typedef typeof(SPI1.clock) spi_clock_reg_t; #define NO_CS 3 //Number of CS pins per SPI host +#ifdef CONFIG_SPI_MASTER_ISR_IN_IRAM +#define SPI_MASTER_ISR_ATTR IRAM_ATTR +#else +#define SPI_MASTER_ISR_ATTR +#endif + +#ifdef CONFIG_SPI_MASTER_IN_IRAM +#define SPI_MASTER_ATTR IRAM_ATTR +#else +#define SPI_MASTER_ATTR +#endif + /// struct to hold private transaction data (like tx and rx buffer for DMA). typedef struct { @@ -179,7 +191,11 @@ esp_err_t spi_bus_initialize(spi_host_device_t host, const spi_bus_config_t *bus } } - 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_MASTER_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; @@ -481,7 +497,7 @@ static inline void spi_set_clock(spi_dev_t *hw, spi_clock_reg_t reg) { //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_MASTER_ISR_ATTR spi_intr(void *arg) { int i; BaseType_t r; @@ -730,7 +746,7 @@ static void IRAM_ATTR spi_intr(void *arg) } -esp_err_t spi_device_queue_trans(spi_device_handle_t handle, spi_transaction_t *trans_desc, TickType_t ticks_to_wait) +esp_err_t SPI_MASTER_ATTR spi_device_queue_trans(spi_device_handle_t handle, spi_transaction_t *trans_desc, TickType_t ticks_to_wait) { esp_err_t ret = ESP_OK; BaseType_t r; @@ -822,7 +838,7 @@ clean_up: return ret; } -esp_err_t spi_device_get_trans_result(spi_device_handle_t handle, spi_transaction_t **trans_desc, TickType_t ticks_to_wait) +esp_err_t SPI_MASTER_ATTR spi_device_get_trans_result(spi_device_handle_t handle, spi_transaction_t **trans_desc, TickType_t ticks_to_wait) { BaseType_t r; spi_trans_priv trans_buf; @@ -856,7 +872,7 @@ esp_err_t spi_device_get_trans_result(spi_device_handle_t handle, spi_transactio } //Porcelain to do one blocking transmission. -esp_err_t spi_device_transmit(spi_device_handle_t handle, spi_transaction_t *trans_desc) +esp_err_t SPI_MASTER_ATTR spi_device_transmit(spi_device_handle_t handle, spi_transaction_t *trans_desc) { esp_err_t ret; spi_transaction_t *ret_trans; diff --git a/tools/unit-test-app/sdkconfig.defaults b/tools/unit-test-app/sdkconfig.defaults index a9b24b60e9..db4404ed4e 100644 --- a/tools/unit-test-app/sdkconfig.defaults +++ b/tools/unit-test-app/sdkconfig.defaults @@ -27,3 +27,4 @@ CONFIG_SUPPORT_STATIC_ALLOCATION=y CONFIG_ESP_TIMER_PROFILING=y CONFIG_ADC2_DISABLE_DAC=n CONFIG_WARN_WRITE_STRINGS=y +CONFIG_SPI_MASTER_IN_IRAM=y \ No newline at end of file