]> granicus.if.org Git - esp-idf/commitdiff
feature(spi_master): allow to place functions into IRAM to get higher efficiency
authorMichael (XIAO Xufeng) <xiaoxufeng@espressif.com>
Mon, 11 Jun 2018 11:54:18 +0000 (19:54 +0800)
committermichael <xiaoxufeng@espressif.com>
Thu, 14 Jun 2018 12:22:40 +0000 (20:22 +0800)
components/driver/Kconfig
components/driver/spi_master.c
tools/unit-test-app/sdkconfig.defaults

index a327a4e86722c6420738ddff5c3bea424ea03b4e..bff45a46bfdebed9bd75aea02b666eaeeb48b474 100644 (file)
@@ -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
index 02cb88455f12c1a82920ed4e3ad0e4204acb2c1c..3e56f7f4329d4868bd47f942e05b1cedbd7556e6 100644 (file)
@@ -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;
index a9b24b60e9c9de708d66f3e997e32f13af138da8..db4404ed4e149a270391e17aa9c5555dab19d4f8 100644 (file)
@@ -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