]> granicus.if.org Git - esp-idf/commitdiff
fix(spi): allow using MISO on GPIO34-39
authorMichael (Xiao Xufeng) <xiaoxufeng@espressif.com>
Wed, 21 Mar 2018 12:42:45 +0000 (20:42 +0800)
committerMichael (Xiao Xufeng) <xiaoxufeng@espressif.com>
Thu, 12 Apr 2018 09:01:38 +0000 (17:01 +0800)
Breaking Changes: arguments of ``spicommon_bus_initialize_io`` are changed.

Closes https://github.com/espressif/esp-idf/issues/1736.

components/driver/include/driver/spi_common.h
components/driver/spi_common.c
components/driver/spi_master.c
components/driver/spi_slave.c
components/driver/test/test_spi_master.c

index 6adcc06a91d9b11339adf322c9a935a21a2474dd..9f014d2792b74ec1bd661ea16645ad364ddb4ede 100644 (file)
@@ -58,6 +58,7 @@ typedef struct {
     int quadwp_io_num;              ///< GPIO pin for WP (Write Protect) signal which is used as D2 in 4-bit communication modes, or -1 if not used.
     int quadhd_io_num;              ///< GPIO pin for HD (HolD) signal which is used as D3 in 4-bit communication modes, or -1 if not used.
     int max_transfer_sz;            ///< Maximum transfer size, in bytes. Defaults to 4094 if 0.
+    uint32_t flags;                 ///< Abilities of bus to be checked by the driver. Or-ed value of ``SPICOMMON_BUSFLAG_*`` flags.
 } spi_bus_config_t;
 
 
@@ -99,9 +100,17 @@ bool spicommon_dma_chan_claim(int dma_chan);
  */
 bool spicommon_dma_chan_free(int dma_chan);
 
-#define SPICOMMON_BUSFLAG_SLAVE  0          ///< Initialize I/O in slave mode
-#define SPICOMMON_BUSFLAG_MASTER (1<<0)     ///< Initialize I/O in master mode
-#define SPICOMMON_BUSFLAG_QUAD   (1<<1)     ///< Also initialize WP/HD pins, if specified
+
+
+#define SPICOMMON_BUSFLAG_SLAVE         0          ///< Initialize I/O in slave mode
+#define SPICOMMON_BUSFLAG_MASTER        (1<<0)     ///< Initialize I/O in master mode
+#define SPICOMMON_BUSFLAG_NATIVE_PINS   (1<<1)     ///< Check using native pins. Or indicates the pins are configured through the IO mux rather than GPIO matrix.
+#define SPICOMMON_BUSFLAG_SCLK          (1<<2)     ///< Check existing of SCLK pin. Or indicates CLK line initialized.
+#define SPICOMMON_BUSFLAG_MISO          (1<<3)     ///< Check existing of MISO pin. Or indicates MISO line initialized.
+#define SPICOMMON_BUSFLAG_MOSI          (1<<4)     ///< Check existing of MOSI pin. Or indicates CLK line initialized.
+#define SPICOMMON_BUSFLAG_DUAL          (1<<5)     ///< Check MOSI and MISO pins can output. Or indicates bus able to work under DIO mode.
+#define SPICOMMON_BUSFLAG_WPHD          (1<<6)     ///< Check existing of WP and HD pins. Or indicates WP & HD pins initialized.
+#define SPICOMMON_BUSFLAG_QUAD          (SPICOMMON_BUSFLAG_DUAL|SPICOMMON_BUSFLAG_WPHD)     ///< Check existing of MOSI/MISO/WP/HD pins as output. Or indicates bus able to work under QIO mode.
 
 /**
  * @brief Connect a SPI peripheral to GPIO pins
@@ -113,14 +122,28 @@ bool spicommon_dma_chan_free(int dma_chan);
  * @param host SPI peripheral to be routed
  * @param bus_config Pointer to a spi_bus_config struct detailing the GPIO pins
  * @param dma_chan DMA-channel (1 or 2) to use, or 0 for no DMA.
- * @param flags Combination of SPICOMMON_BUSFLAG_* flags
- * @param[out] is_native A value of 'true' will be written to this address if the GPIOs can be
- *                  routed using the IO_mux, 'false' if the GPIO matrix is used.
+ * @param flags Combination of SPICOMMON_BUSFLAG_* flags, set to ensure the pins set are capable with some functions:
+ *              - ``SPICOMMON_BUSFLAG_MASTER``: Initialize I/O in master mode
+ *              - ``SPICOMMON_BUSFLAG_SLAVE``: Initialize I/O in slave mode
+ *              - ``SPICOMMON_BUSFLAG_NATIVE_PINS``: Pins set should match the native pins of the controller.
+ *              - ``SPICOMMON_BUSFLAG_SCLK``, ``SPICOMMON_BUSFLAG_MISO``, ``SPICOMMON_BUSFLAG_MOSI``: 
+ *                  Make sure SCLK/MISO/MOSI is/are set to a valid GPIO. Also check output capability according to the mode.
+ *              - ``SPICOMMON_BUSFLAG_DUAL``: Make sure both MISO and MOSI are output capable so that DIO mode is capable.
+ *              - ``SPICOMMON_BUSFLAG_WPHD`` Make sure WP and HD are set to valid output GPIOs.
+ *              - ``SPICOMMON_BUSFLAG_QUAD``: Combination of ``SPICOMMON_BUSFLAG_DUAL`` and ``SPICOMMON_BUSFLAG_WPHD``.
+ * @param[out] flags_o A SPICOMMON_BUSFLAG_* flag combination of bus abilities will be written to this address.
+ *              Leave to NULL if not needed.
+ *              - ``SPICOMMON_BUSFLAG_NATIVE_PINS``: The bus is connected to native pins.
+ *              - ``SPICOMMON_BUSFLAG_SCLK``, ``SPICOMMON_BUSFLAG_MISO``, ``SPICOMMON_BUSFLAG_MOSI``: The bus has
+ *                  CLK/MISO/MOSI connected.
+ *              - ``SPICOMMON_BUSFLAG_DUAL``: The bus is capable with DIO mode.
+ *              - ``SPICOMMON_BUSFLAG_WPHD`` The bus has WP and HD connected.
+ *              - ``SPICOMMON_BUSFLAG_QUAD``: Combination of ``SPICOMMON_BUSFLAG_DUAL`` and ``SPICOMMON_BUSFLAG_WPHD``.
  * @return 
  *         - ESP_ERR_INVALID_ARG   if parameter is invalid
  *         - ESP_OK                on success
  */
-esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_config_t *bus_config, int dma_chan, int flags, bool *is_native);
+esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_config_t *bus_config, int dma_chan, uint32_t flags, uint32_t *flags_o);
 
 /**
  * @brief Free the IO used by a SPI peripheral
index bd78e935294fb58a91e94d3da5cc008c81307a80..4ea94a7c005bb61e4507072f6203aa7c69d3e6a1 100644 (file)
@@ -220,67 +220,113 @@ bool spicommon_dma_chan_free(int dma_chan)
 
 /*
 Do the common stuff to hook up a SPI host to a bus defined by a bunch of GPIO pins. Feed it a host number and a
-bus config struct and it'll set up the GPIO matrix and enable the device. It will set is_native to 1 if the bus
-config can be done using the IOMUX instead of using the GPIO matrix.
+bus config struct and it'll set up the GPIO matrix and enable the device. If a pin is set to non-negative value, 
+it should be able to be initialized.
 */
-esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_config_t *bus_config, int dma_chan, int flags, bool *is_native)
+esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_config_t *bus_config, int dma_chan, uint32_t flags, uint32_t* flags_o)
 {
     bool native = true;
-    bool use_quad = (flags & SPICOMMON_BUSFLAG_QUAD) != 0;
-
-    SPI_CHECK(bus_config->mosi_io_num < 0 || GPIO_IS_VALID_OUTPUT_GPIO(bus_config->mosi_io_num), "spid pin invalid", ESP_ERR_INVALID_ARG);
-    SPI_CHECK(bus_config->sclk_io_num < 0 || GPIO_IS_VALID_OUTPUT_GPIO(bus_config->sclk_io_num), "spiclk pin invalid", ESP_ERR_INVALID_ARG);
-    SPI_CHECK(bus_config->miso_io_num < 0 || GPIO_IS_VALID_GPIO(bus_config->miso_io_num), "spiq pin invalid", ESP_ERR_INVALID_ARG);
-    if (use_quad) {
-        SPI_CHECK(bus_config->quadwp_io_num < 0 || GPIO_IS_VALID_OUTPUT_GPIO(bus_config->quadwp_io_num), "spiwp pin invalid", ESP_ERR_INVALID_ARG);
-        SPI_CHECK(bus_config->quadhd_io_num < 0 || GPIO_IS_VALID_OUTPUT_GPIO(bus_config->quadhd_io_num), "spihd pin invalid", ESP_ERR_INVALID_ARG);
+    uint32_t temp_flag=0;
+    bool quad_pins_exist = true;
+    //the MISO should be output capable in slave mode, or in DIO/QIO mode.
+    bool miso_output = !(flags&SPICOMMON_BUSFLAG_MASTER) || flags&SPICOMMON_BUSFLAG_DUAL;
+    //the MOSI should be output capble in master mode, or in DIO/QIO mode.
+    bool mosi_output = (flags&SPICOMMON_BUSFLAG_MASTER)!=0 || flags&SPICOMMON_BUSFLAG_DUAL;
+
+    //check pins existence and if the selected pins correspond to the native pins of the peripheral
+    if (bus_config->sclk_io_num>=0) {
+        temp_flag |= SPICOMMON_BUSFLAG_SCLK;
+        SPI_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(bus_config->sclk_io_num), "sclk not valid", ESP_ERR_INVALID_ARG);
+        if (bus_config->sclk_io_num != io_signal[host].spiclk_native) native = false;
+    } else {
+        SPI_CHECK((flags&SPICOMMON_BUSFLAG_SCLK)==0, "sclk pin required.", ESP_ERR_INVALID_ARG);
     }
-
-    //Check if the selected pins correspond to the native pins of the peripheral
-    if (bus_config->mosi_io_num >= 0 && bus_config->mosi_io_num != io_signal[host].spid_native) native = false;
-    if (bus_config->miso_io_num >= 0 && bus_config->miso_io_num != io_signal[host].spiq_native) native = false;
-    if (bus_config->sclk_io_num >= 0 && bus_config->sclk_io_num != io_signal[host].spiclk_native) native = false;
-    if (use_quad) {
-        if (bus_config->quadwp_io_num >= 0 && bus_config->quadwp_io_num != io_signal[host].spiwp_native) native = false;
-        if (bus_config->quadhd_io_num >= 0 && bus_config->quadhd_io_num != io_signal[host].spihd_native) native = false;
+    if (bus_config->quadwp_io_num>=0) {
+        SPI_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(bus_config->quadwp_io_num), "spiwp not valid", ESP_ERR_INVALID_ARG);
+        if (bus_config->quadwp_io_num != io_signal[host].spiwp_native) native = false;
+    } else {
+        quad_pins_exist = false;
+        SPI_CHECK((flags&SPICOMMON_BUSFLAG_WPHD)==0, "spiwp pin required.", ESP_ERR_INVALID_ARG);
     }
-
-    *is_native = native;
-    if ( native ) {
-        ESP_LOGD(SPI_TAG, "SPI%d use native pins.", host );
+    if (bus_config->quadhd_io_num>=0) {
+        SPI_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(bus_config->quadhd_io_num), "spihd not valid", ESP_ERR_INVALID_ARG);
+        if (bus_config->quadhd_io_num != io_signal[host].spihd_native) native = false;        
+    } else {
+        quad_pins_exist = false;
+        SPI_CHECK((flags&SPICOMMON_BUSFLAG_WPHD)==0, "spihd pin required.", ESP_ERR_INVALID_ARG);
+    }
+    if (bus_config->mosi_io_num >= 0) {
+        temp_flag |= SPICOMMON_BUSFLAG_MOSI;
+        if (mosi_output) {
+            SPI_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(bus_config->mosi_io_num), "mosi not valid", ESP_ERR_INVALID_ARG);
+        } else {
+            SPI_CHECK(GPIO_IS_VALID_GPIO(bus_config->mosi_io_num), "mosi not valid", ESP_ERR_INVALID_ARG);
+        }
+        if (bus_config->mosi_io_num != io_signal[host].spid_native) native = false;
+    } else {
+        SPI_CHECK((flags&SPICOMMON_BUSFLAG_MOSI)==0, "mosi pin required.", ESP_ERR_INVALID_ARG);
+    }
+    if (bus_config->miso_io_num>=0) {
+        temp_flag |= SPICOMMON_BUSFLAG_MISO;
+        if (miso_output) {
+            SPI_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(bus_config->miso_io_num), "miso not valid", ESP_ERR_INVALID_ARG);
+        } else {
+            SPI_CHECK(GPIO_IS_VALID_GPIO(bus_config->miso_io_num), "miso not valid", ESP_ERR_INVALID_ARG);
+        }
+        if (bus_config->miso_io_num != io_signal[host].spiq_native) native = false;
     } else {
-        ESP_LOGD(SPI_TAG, "SPI%d use gpio matrix.", host );
+        SPI_CHECK((flags&SPICOMMON_BUSFLAG_MISO)==0, "miso pin required.", ESP_ERR_INVALID_ARG);
     }
+    //set flags for DUAL mode according to output-capability of MOSI and MISO pins.   
+    if ( (bus_config->mosi_io_num < 0 || GPIO_IS_VALID_OUTPUT_GPIO(bus_config->mosi_io_num)) && 
+        (bus_config->miso_io_num < 0 || GPIO_IS_VALID_OUTPUT_GPIO(bus_config->miso_io_num)) ) {
+        temp_flag |= SPICOMMON_BUSFLAG_DUAL;
+    }    
+    //set flags for QUAD mode according to the existence of wp and hd
+    if (quad_pins_exist) temp_flag |= SPICOMMON_BUSFLAG_WPHD;
+    //check native pins if required.
+    SPI_CHECK((flags&SPICOMMON_BUSFLAG_NATIVE_PINS)==0 || native, "not using native pins", ESP_ERR_INVALID_ARG);
 
     if (native) {
         //All SPI native pin selections resolve to 1, so we put that here instead of trying to figure
         //out which FUNC_GPIOx_xSPIxx to grab; they all are defined to 1 anyway.
+        ESP_LOGD(SPI_TAG, "SPI%d use native pins.", host );
         if (bus_config->mosi_io_num >= 0) PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->mosi_io_num], 1);
         if (bus_config->miso_io_num >= 0) PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->miso_io_num], 1);
-        if (use_quad && bus_config->quadwp_io_num >= 0) PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->quadwp_io_num], 1);
-        if (use_quad && bus_config->quadhd_io_num >= 0) PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->quadhd_io_num], 1);
+        if (bus_config->quadwp_io_num >= 0) PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->quadwp_io_num], 1);
+        if (bus_config->quadhd_io_num >= 0) PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->quadhd_io_num], 1);
         if (bus_config->sclk_io_num >= 0) PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->sclk_io_num], 1);
+        temp_flag |= SPICOMMON_BUSFLAG_NATIVE_PINS;
     } else {
-        //Use GPIO
+        //Use GPIO matrix
+        ESP_LOGD(SPI_TAG, "SPI%d use gpio matrix.", host );        
         if (bus_config->mosi_io_num >= 0) {
             PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->mosi_io_num], PIN_FUNC_GPIO);
-            gpio_set_direction(bus_config->mosi_io_num, GPIO_MODE_INPUT_OUTPUT);
-            gpio_matrix_out(bus_config->mosi_io_num, io_signal[host].spid_out, false, false);
+            if (mosi_output) {
+                gpio_set_direction(bus_config->mosi_io_num, GPIO_MODE_INPUT_OUTPUT);
+                gpio_matrix_out(bus_config->mosi_io_num, io_signal[host].spid_out, false, false);
+            } else {
+                gpio_set_direction(bus_config->mosi_io_num, GPIO_MODE_INPUT);
+            }
             gpio_matrix_in(bus_config->mosi_io_num, io_signal[host].spid_in, false);
         }
         if (bus_config->miso_io_num >= 0) {
             PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->miso_io_num], PIN_FUNC_GPIO);
-            gpio_set_direction(bus_config->miso_io_num, GPIO_MODE_INPUT_OUTPUT);
-            gpio_matrix_out(bus_config->miso_io_num, io_signal[host].spiq_out, false, false);
-            gpio_matrix_in(bus_config->miso_io_num, io_signal[host].spiq_in, false);
+            if (miso_output) {
+                gpio_set_direction(bus_config->miso_io_num, GPIO_MODE_INPUT_OUTPUT);
+                gpio_matrix_out(bus_config->miso_io_num, io_signal[host].spiq_out, false, false);
+            } else {
+                gpio_set_direction(bus_config->miso_io_num, GPIO_MODE_INPUT);
+            }
+            gpio_matrix_in(bus_config->miso_io_num, io_signal[host].spiq_in, false);                
         }
-        if (use_quad && bus_config->quadwp_io_num >= 0) {
+        if (bus_config->quadwp_io_num >= 0) {
             PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->quadwp_io_num], PIN_FUNC_GPIO);
             gpio_set_direction(bus_config->quadwp_io_num, GPIO_MODE_INPUT_OUTPUT);
             gpio_matrix_out(bus_config->quadwp_io_num, io_signal[host].spiwp_out, false, false);
             gpio_matrix_in(bus_config->quadwp_io_num, io_signal[host].spiwp_in, false);
         }
-        if (use_quad && bus_config->quadhd_io_num >= 0) {
+        if (bus_config->quadhd_io_num >= 0) {
             PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->quadhd_io_num], PIN_FUNC_GPIO);
             gpio_set_direction(bus_config->quadhd_io_num, GPIO_MODE_INPUT_OUTPUT);
             gpio_matrix_out(bus_config->quadhd_io_num, io_signal[host].spihd_out, false, false);
@@ -297,6 +343,7 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf
     //Select DMA channel.
     DPORT_SET_PERI_REG_BITS(DPORT_SPI_DMA_CHAN_SEL_REG, 3, dma_chan, (host * 2));
 
+    if (flags_o) *flags_o = temp_flag;
     return ESP_OK;
 }
 
@@ -311,7 +358,6 @@ static void reset_func_to_gpio(int func)
     }
 }
 
-
 esp_err_t spicommon_bus_free_io(spi_host_device_t host)
 {
     if (REG_GET_FIELD(GPIO_PIN_MUX_REG[io_signal[host].spid_native], MCU_SEL) == 1) PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[io_signal[host].spid_native], PIN_FUNC_GPIO);
index 0fa5c9b318be5029559c7387de68420d6b511fda..4e6a51a5e54e50cddf476c7dc92818b8df3676fb 100644 (file)
@@ -84,7 +84,7 @@ typedef struct {
     int prev_cs;
     lldesc_t *dmadesc_tx;
     lldesc_t *dmadesc_rx;
-    bool no_gpio_matrix;
+    uint32_t flags;
     int dma_chan;
     int max_transfer_sz;
 #ifdef CONFIG_PM_ENABLE
@@ -121,7 +121,7 @@ static void spi_intr(void *arg);
 
 esp_err_t spi_bus_initialize(spi_host_device_t host, const spi_bus_config_t *bus_config, int dma_chan)
 {
-    bool native, spi_chan_claimed, dma_chan_claimed;
+    bool spi_chan_claimed, dma_chan_claimed;
     esp_err_t ret = ESP_OK;
     esp_err_t err;
     /* ToDo: remove this when we have flash operations cooperating with this */
@@ -155,14 +155,13 @@ esp_err_t spi_bus_initialize(spi_host_device_t host, const spi_bus_config_t *bus
         goto cleanup;
     }
 #endif //CONFIG_PM_ENABLE
-    
-    err = spicommon_bus_initialize_io(host, bus_config, dma_chan, SPICOMMON_BUSFLAG_MASTER|SPICOMMON_BUSFLAG_QUAD, &native);
+
+    err = spicommon_bus_initialize_io(host, bus_config, dma_chan, SPICOMMON_BUSFLAG_MASTER|bus_config->flags, &spihost[host]->flags);
     if (err != ESP_OK) {
         ret = err;
         goto cleanup;
     }
-    spihost[host]->no_gpio_matrix=native;
-    
+
     spihost[host]->dma_chan=dma_chan;
     if (dma_chan == 0) {
         spihost[host]->max_transfer_sz = 32;
@@ -294,7 +293,7 @@ esp_err_t spi_bus_add_device(spi_host_device_t host, const spi_device_interface_
     //Speeds >=40MHz over GPIO matrix needs a dummy cycle, but these don't work for full-duplex connections.
     duty_cycle = (dev_config->duty_cycle_pos==0? 128: dev_config->duty_cycle_pos);
     eff_clk = spi_cal_clock(apbclk, dev_config->clock_speed_hz, duty_cycle, (uint32_t*)&clk_reg);    
-    uint32_t dummy_limit = spi_dummy_limit(!spihost[host]->no_gpio_matrix);
+    uint32_t dummy_limit = spi_dummy_limit(!(spihost[host]->flags&SPICOMMON_BUSFLAG_NATIVE_PINS));
     SPI_CHECK( dev_config->flags & SPI_DEVICE_HALFDUPLEX || (eff_clk/1000/1000) < (dummy_limit/1000/1000) ||
             dev_config->flags & SPI_DEVICE_NO_DUMMY,
 "When GPIO matrix is used in full-duplex mode at frequency > 26MHz, device cannot read correct data.\n\
@@ -327,7 +326,7 @@ Specify ``SPI_DEVICE_NO_DUMMY`` to ignore this checking. Then you can output dat
     //Set CS pin, CS options
     if (dev_config->spics_io_num >= 0) {
         gpio_set_direction(dev_config->spics_io_num, GPIO_MODE_OUTPUT);
-        spicommon_cs_initialize(host, dev_config->spics_io_num, freecs, spihost[host]->no_gpio_matrix == false);
+        spicommon_cs_initialize(host, dev_config->spics_io_num, freecs, !(spihost[host]->flags&SPICOMMON_BUSFLAG_NATIVE_PINS));
     }
     if (dev_config->flags&SPI_DEVICE_CLK_AS_CS) {
         spihost[host]->hw->pin.master_ck_sel |= (1<<freecs);
@@ -519,7 +518,7 @@ static void IRAM_ATTR spi_intr(void *arg)
             //Configure polarity
             //SPI iface needs to be configured for a delay in some cases.
             int nodelay=0;
-            if (host->no_gpio_matrix) {
+            if ((host->flags&SPICOMMON_BUSFLAG_NATIVE_PINS)!=0) {
                 if (effclk >= apbclk/2) {
                     nodelay=1;
                 }
index 157829eeb3181ae33700361e780e072050ee34f1..7ee2222e201f4607e123de5f101e6178870f6548 100644 (file)
@@ -56,7 +56,7 @@ typedef struct {
     spi_slave_transaction_t *cur_trans;
     lldesc_t *dmadesc_tx;
     lldesc_t *dmadesc_rx;
-    bool no_gpio_matrix;
+    uint32_t flags;
     int max_transfer_sz;
     QueueHandle_t trans_queue;
     QueueHandle_t ret_queue;
@@ -72,7 +72,7 @@ static void IRAM_ATTR spi_intr(void *arg);
 
 esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *bus_config, const spi_slave_interface_config_t *slave_config, int dma_chan)
 {
-    bool native, spi_chan_claimed, dma_chan_claimed;
+    bool spi_chan_claimed, dma_chan_claimed;
     esp_err_t ret = ESP_OK;
     esp_err_t err;
     //We only support HSPI/VSPI, period.
@@ -98,14 +98,13 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b
     memset(spihost[host], 0, sizeof(spi_slave_t));
     memcpy(&spihost[host]->cfg, slave_config, sizeof(spi_slave_interface_config_t));
 
-    err = spicommon_bus_initialize_io(host, bus_config, dma_chan, SPICOMMON_BUSFLAG_SLAVE, &native);
+    err = spicommon_bus_initialize_io(host, bus_config, dma_chan, SPICOMMON_BUSFLAG_SLAVE|bus_config->flags, &spihost[host]->flags);
     if (err!=ESP_OK) {
         ret = err;
         goto cleanup;
     }
     gpio_set_direction(slave_config->spics_io_num, GPIO_MODE_INPUT);
-    spicommon_cs_initialize(host, slave_config->spics_io_num, 0, native == false);
-    spihost[host]->no_gpio_matrix = native;
+    spicommon_cs_initialize(host, slave_config->spics_io_num, 0, !(spihost[host]->flags&SPICOMMON_BUSFLAG_NATIVE_PINS));
     spihost[host]->dma_chan = dma_chan;
     if (dma_chan != 0) {
         //See how many dma descriptors we need and allocate them
@@ -186,7 +185,6 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b
         spihost[host]->hw->ctrl2.miso_delay_mode = nodelay ? 0 : 2;
     }
 
-
     //Reset DMA
     spihost[host]->hw->dma_conf.val |= SPI_OUT_RST | SPI_IN_RST | SPI_AHBM_RST | SPI_AHBM_FIFO_RST;
     spihost[host]->hw->dma_out_link.start = 0;
index 2744ac5643dc8b5a0e94e3f309e57c35170ecd38..da6d5a596184ca9a50461ca5c402baba43d794c9 100644 (file)
@@ -231,7 +231,7 @@ TEST_CASE("SPI Master test, interaction of multiple devs", "[spi][ignore]") {
         .clock_speed_hz=1000000,
         .duty_cycle_pos=128,
         .mode=0,
-        .spics_io_num=23,
+        .spics_io_num=23, 
         .queue_size=3,
     };
     spi_device_handle_t handle1=setup_spi_bus(80000, true);
@@ -263,6 +263,156 @@ TEST_CASE("SPI Master test, interaction of multiple devs", "[spi][ignore]") {
     destroy_spi_bus(handle1);
 }
 
+#define NATIVE_SCLK 14
+#define NATIVE_MISO 12
+#define NATIVE_MOSI 13
+#define NATIVE_WP   2
+#define NATIVE_HD   4
+
+TEST_CASE("spi bus setting with different pin configs", "[spi]")
+{
+    spi_bus_config_t cfg;
+    uint32_t flags_o;
+    uint32_t flags_expected;
+    
+    ESP_LOGI(TAG, "test 6 native output pins...");
+    flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_NATIVE_PINS | SPICOMMON_BUSFLAG_QUAD;
+    cfg = (spi_bus_config_t){.mosi_io_num = NATIVE_MOSI, .miso_io_num = NATIVE_MISO, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = NATIVE_HD, .quadwp_io_num = NATIVE_WP,
+        .max_transfer_sz = 8, .flags = flags_expected};
+    TEST_ESP_OK(spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
+    TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
+    TEST_ESP_OK(spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
+    TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
+
+    ESP_LOGI(TAG, "test 4 native output pins...");
+    flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_NATIVE_PINS | SPICOMMON_BUSFLAG_DUAL;
+    cfg = (spi_bus_config_t){.mosi_io_num = NATIVE_MOSI, .miso_io_num = NATIVE_MISO, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = -1, .quadwp_io_num = -1,
+        .max_transfer_sz = 8, .flags = flags_expected};
+    TEST_ESP_OK(spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
+    TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
+    TEST_ESP_OK(spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
+    TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
+
+    ESP_LOGI(TAG, "test 6 output pins...");
+    flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_QUAD;
+    //swap MOSI and MISO
+    cfg = (spi_bus_config_t){.mosi_io_num = NATIVE_MISO, .miso_io_num = NATIVE_MOSI, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = NATIVE_HD, .quadwp_io_num = NATIVE_WP,
+        .max_transfer_sz = 8, .flags = flags_expected};
+    TEST_ESP_OK(spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
+    TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
+    TEST_ESP_OK(spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
+    TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
+
+    ESP_LOGI(TAG, "test 4 output pins...");
+    flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO |  SPICOMMON_BUSFLAG_DUAL;
+    //swap MOSI and MISO
+    cfg = (spi_bus_config_t){.mosi_io_num = NATIVE_MISO, .miso_io_num = NATIVE_MOSI, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = -1, .quadwp_io_num = -1,
+        .max_transfer_sz = 8, .flags = flags_expected};
+    TEST_ESP_OK(spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
+    TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
+    TEST_ESP_OK(spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
+    TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
+
+    ESP_LOGI(TAG, "test master 5 output pins and MOSI on input-only pin...");
+    flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_WPHD;
+    cfg = (spi_bus_config_t){.mosi_io_num = NATIVE_MOSI, .miso_io_num = 34, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = NATIVE_HD, .quadwp_io_num = NATIVE_WP,
+        .max_transfer_sz = 8, .flags = flags_expected};
+    TEST_ESP_OK(spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
+    TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
+
+    ESP_LOGI(TAG, "test slave 5 output pins and MISO on input-only pin...");
+    flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_WPHD;
+    cfg = (spi_bus_config_t){.mosi_io_num = 34, .miso_io_num = NATIVE_MISO, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = NATIVE_HD, .quadwp_io_num = NATIVE_WP,
+        .max_transfer_sz = 8, .flags = flags_expected};    
+    TEST_ESP_OK(spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
+    TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
+
+    ESP_LOGI(TAG, "test master 3 output pins and MOSI on input-only pin...");
+    flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO;
+
+    cfg = (spi_bus_config_t){.mosi_io_num = NATIVE_MOSI, .miso_io_num = 34, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = -1, .quadwp_io_num = -1,
+        .max_transfer_sz = 8, .flags = flags_expected};
+    TEST_ESP_OK(spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
+    TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
+
+    ESP_LOGI(TAG, "test slave 3 output pins and MISO on input-only pin...");
+    flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO;
+    cfg = (spi_bus_config_t){.mosi_io_num = 34, .miso_io_num = NATIVE_MISO, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = -1, .quadwp_io_num = -1,
+        .max_transfer_sz = 8, .flags = flags_expected};    
+    TEST_ESP_OK(spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
+    TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
+
+    ESP_LOGI(TAG, "check native flag for 6 output pins...");
+    flags_expected = SPICOMMON_BUSFLAG_NATIVE_PINS;
+    //swap MOSI and MISO
+    cfg = (spi_bus_config_t){.mosi_io_num = NATIVE_MISO, .miso_io_num = NATIVE_MOSI, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = NATIVE_HD, .quadwp_io_num = NATIVE_WP,
+        .max_transfer_sz = 8, .flags = flags_expected};
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
+
+    ESP_LOGI(TAG, "check native flag for 4 output pins...");
+    flags_expected = SPICOMMON_BUSFLAG_NATIVE_PINS;
+    //swap MOSI and MISO
+    cfg = (spi_bus_config_t){.mosi_io_num = NATIVE_MISO, .miso_io_num = NATIVE_MOSI, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = -1, .quadwp_io_num = -1,
+        .max_transfer_sz = 8, .flags = flags_expected};
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
+
+    ESP_LOGI(TAG, "check dual flag for master 5 output pins and MISO/MOSI on input-only pin...");
+    flags_expected = SPICOMMON_BUSFLAG_DUAL;
+    cfg = (spi_bus_config_t){.mosi_io_num = NATIVE_MOSI, .miso_io_num = 34, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = NATIVE_HD, .quadwp_io_num = NATIVE_WP,
+        .max_transfer_sz = 8, .flags = flags_expected};
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
+    cfg = (spi_bus_config_t){.mosi_io_num = 34, .miso_io_num = NATIVE_MISO, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = NATIVE_HD, .quadwp_io_num = NATIVE_WP,
+        .max_transfer_sz = 8, .flags = flags_expected};
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
+
+    ESP_LOGI(TAG, "check dual flag for master 3 output pins and MISO/MOSI on input-only pin...");
+    flags_expected = SPICOMMON_BUSFLAG_DUAL;
+    cfg = (spi_bus_config_t){.mosi_io_num = NATIVE_MOSI, .miso_io_num = 34, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = -1, .quadwp_io_num = -1,
+        .max_transfer_sz = 8, .flags = flags_expected};
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
+    cfg = (spi_bus_config_t){.mosi_io_num = 34, .miso_io_num = NATIVE_MISO, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = -1, .quadwp_io_num = -1,
+        .max_transfer_sz = 8, .flags = flags_expected};
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
+
+    ESP_LOGI(TAG, "check sclk flag...");
+    flags_expected = SPICOMMON_BUSFLAG_SCLK;
+    cfg = (spi_bus_config_t){.mosi_io_num = NATIVE_MOSI, .miso_io_num = NATIVE_MISO, .sclk_io_num = -1, .quadhd_io_num = NATIVE_HD, .quadwp_io_num = NATIVE_WP,
+        .max_transfer_sz = 8, .flags = flags_expected};
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
+    
+    ESP_LOGI(TAG, "check mosi flag...");
+    flags_expected = SPICOMMON_BUSFLAG_MOSI;
+    cfg = (spi_bus_config_t){.mosi_io_num = -1, .miso_io_num = NATIVE_MISO, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = NATIVE_HD, .quadwp_io_num = NATIVE_WP,
+        .max_transfer_sz = 8, .flags = flags_expected};
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
+    
+    ESP_LOGI(TAG, "check miso flag...");
+    flags_expected = SPICOMMON_BUSFLAG_MISO;
+    cfg = (spi_bus_config_t){.mosi_io_num = NATIVE_MOSI, .miso_io_num = -1, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = NATIVE_HD, .quadwp_io_num = NATIVE_WP,
+        .max_transfer_sz = 8, .flags = flags_expected};
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
+
+    ESP_LOGI(TAG, "check quad flag...");
+    flags_expected = SPICOMMON_BUSFLAG_QUAD;
+    cfg = (spi_bus_config_t){.mosi_io_num = NATIVE_MOSI, .miso_io_num = NATIVE_MISO, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = -1, .quadwp_io_num = NATIVE_WP,
+        .max_transfer_sz = 8, .flags = flags_expected};
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
+    cfg = (spi_bus_config_t){.mosi_io_num = NATIVE_MOSI, .miso_io_num = NATIVE_MISO, .sclk_io_num = NATIVE_SCLK, .quadhd_io_num = NATIVE_HD, .quadwp_io_num = -1,
+        .max_transfer_sz = 8, .flags = flags_expected};
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(HSPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
+}
+
 TEST_CASE("SPI Master no response when switch from host1 (HSPI) to host2 (VSPI)", "[spi]")
 {
     //spi config