From 1f085b1a3b1380b82096662e49c0fc849320e500 Mon Sep 17 00:00:00 2001 From: "Michael (XIAO Xufeng)" Date: Tue, 24 Apr 2018 01:23:12 +0800 Subject: [PATCH 1/3] feat(gpio): add function allowing switching input source from GPIO back to IOMUX --- components/driver/gpio.c | 15 ++++++++++++++- components/driver/include/driver/gpio.h | 22 +++++++++++++++++++--- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/components/driver/gpio.c b/components/driver/gpio.c index 9563b1506..e017cd87d 100644 --- a/components/driver/gpio.c +++ b/components/driver/gpio.c @@ -546,4 +546,17 @@ esp_err_t gpio_hold_dis(gpio_num_t gpio_num) r = ESP_ERR_NOT_SUPPORTED; } return r == ESP_OK ? ESP_OK : ESP_ERR_NOT_SUPPORTED; -} \ No newline at end of file +} + +void gpio_iomux_in(uint32_t gpio, uint32_t signal_idx) +{ + GPIO.func_in_sel_cfg[signal_idx].sig_in_sel = 0; + PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[gpio]); +} + +void gpio_iomux_out(uint8_t gpio_num, int func, bool oen_inv) +{ + GPIO.func_out_sel_cfg[gpio_num].oen_sel = 0; + GPIO.func_out_sel_cfg[gpio_num].oen_inv_sel = oen_inv; + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio_num], func); +} diff --git a/components/driver/include/driver/gpio.h b/components/driver/include/driver/gpio.h index f8900d32e..d5cb7c08c 100644 --- a/components/driver/include/driver/gpio.h +++ b/components/driver/include/driver/gpio.h @@ -31,11 +31,11 @@ extern "C" { #define GPIO_SEL_0 (BIT(0)) /*!< Pin 0 selected */ #define GPIO_SEL_1 (BIT(1)) /*!< Pin 1 selected */ -#define GPIO_SEL_2 (BIT(2)) /*!< Pin 2 selected +#define GPIO_SEL_2 (BIT(2)) /*!< Pin 2 selected @note There are more macros like that up to pin 39, excluding pins 20, 24 and 28..31. - They are not shown here + They are not shown here to reduce redundant information. */ /** @cond */ #define GPIO_SEL_3 (BIT(3)) /*!< Pin 3 selected */ @@ -172,7 +172,7 @@ typedef enum { GPIO_NUM_38 = 38, /*!< GPIO38, input mode only */ GPIO_NUM_39 = 39, /*!< GPIO39, input mode only */ GPIO_NUM_MAX = 40, -/** @endcond */ +/** @endcond */ } gpio_num_t; typedef enum { @@ -550,6 +550,22 @@ esp_err_t gpio_hold_en(gpio_num_t gpio_num); */ esp_err_t gpio_hold_dis(gpio_num_t gpio_num); +/** + * @brief Set pad input to a peripheral signal through the IOMUX. + * @param gpio_num GPIO number of the pad. + * @param signal_idx Peripheral signal id to input. One of the ``*_IN_IDX`` signals in ``soc/gpio_sig_map.h``. + */ +void gpio_iomux_in(uint32_t gpio_num, uint32_t signal_idx); + +/** + * @brief Set peripheral output to an GPIO pad through the IOMUX. + * @param gpio_num gpio_num GPIO number of the pad. + * @param func The function number of the peripheral pin to output pin. + * One of the ``FUNC_X_*`` of specified pin (X) in ``soc/io_mux_reg.h``. + * @param oen_inv True if the output enable needs to be inversed, otherwise False. + */ +void gpio_iomux_out(uint8_t gpio_num, int func, bool oen_inv); + #ifdef __cplusplus } #endif From 28beafc624628ab5841903478efcb10c1d0c07f4 Mon Sep 17 00:00:00 2001 From: michael Date: Tue, 24 Apr 2018 15:34:07 +0800 Subject: [PATCH 2/3] fix(spi): fix the issue that native pins don't work after SPI initialized before --- components/driver/spi_common.c | 57 ++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/components/driver/spi_common.c b/components/driver/spi_common.c index 0aab4ee02..d6a2dbd82 100644 --- a/components/driver/spi_common.c +++ b/components/driver/spi_common.c @@ -46,6 +46,9 @@ static const char *SPI_TAG = "spi"; typedef struct spi_device_t spi_device_t; +#define FUNC_SPI 1 //all pins of HSPI and VSPI shares this function number +#define FUNC_GPIO PIN_FUNC_GPIO + /* Stores a bunch of per-spi-peripheral data. */ @@ -220,7 +223,7 @@ 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. If a pin is set to non-negative value, +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, uint32_t flags, uint32_t* flags_o) @@ -250,7 +253,7 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf } 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; + 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); @@ -277,11 +280,11 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf } else { 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)) && + //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. @@ -291,17 +294,32 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf //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 (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); + if (bus_config->mosi_io_num >= 0) { + gpio_iomux_in(bus_config->mosi_io_num, io_signal[host].spid_in); + gpio_iomux_out(bus_config->mosi_io_num, FUNC_SPI, false); + } + if (bus_config->miso_io_num >= 0) { + gpio_iomux_in(bus_config->miso_io_num, io_signal[host].spiq_in); + gpio_iomux_out(bus_config->miso_io_num, FUNC_SPI, false); + } + if (bus_config->quadwp_io_num >= 0) { + gpio_iomux_in(bus_config->quadwp_io_num, io_signal[host].spiwp_in); + gpio_iomux_out(bus_config->quadwp_io_num, FUNC_SPI, false); + } + if (bus_config->quadhd_io_num >= 0) { + gpio_iomux_in(bus_config->quadhd_io_num, io_signal[host].spihd_in); + gpio_iomux_out(bus_config->quadhd_io_num, FUNC_SPI, false); + } + if (bus_config->sclk_io_num >= 0) { + gpio_iomux_in(bus_config->sclk_io_num, io_signal[host].spiclk_in); + gpio_iomux_out(bus_config->sclk_io_num, FUNC_SPI, false); + } temp_flag |= SPICOMMON_BUSFLAG_NATIVE_PINS; } else { //Use GPIO matrix - ESP_LOGD(SPI_TAG, "SPI%d use gpio matrix.", host ); + 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); + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->mosi_io_num], FUNC_GPIO); 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); @@ -311,29 +329,29 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf 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); + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->miso_io_num], FUNC_GPIO); 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); + gpio_matrix_in(bus_config->miso_io_num, io_signal[host].spiq_in, false); } if (bus_config->quadwp_io_num >= 0) { - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->quadwp_io_num], PIN_FUNC_GPIO); + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->quadwp_io_num], 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 (bus_config->quadhd_io_num >= 0) { - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->quadhd_io_num], PIN_FUNC_GPIO); + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->quadhd_io_num], 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); gpio_matrix_in(bus_config->quadhd_io_num, io_signal[host].spihd_in, false); } if (bus_config->sclk_io_num >= 0) { - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->sclk_io_num], PIN_FUNC_GPIO); + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->sclk_io_num], FUNC_GPIO); gpio_set_direction(bus_config->sclk_io_num, GPIO_MODE_INPUT_OUTPUT); gpio_matrix_out(bus_config->sclk_io_num, io_signal[host].spiclk_out, false, false); gpio_matrix_in(bus_config->sclk_io_num, io_signal[host].spiclk_in, false); @@ -377,10 +395,11 @@ void spicommon_cs_initialize(spi_host_device_t host, int cs_io_num, int cs_num, { if (!force_gpio_matrix && cs_io_num == io_signal[host].spics0_native && cs_num == 0) { //The cs0s for all SPI peripherals map to pin mux source 1, so we use that instead of a define. - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[cs_io_num], 1); + gpio_iomux_in(cs_io_num, io_signal[host].spics_in); + gpio_iomux_out(cs_io_num, FUNC_SPI, false); } else { //Use GPIO matrix - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[cs_io_num], PIN_FUNC_GPIO); + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[cs_io_num], FUNC_GPIO); gpio_matrix_out(cs_io_num, io_signal[host].spics_out[cs_num], false, false); if (cs_num == 0) gpio_matrix_in(cs_io_num, io_signal[host].spics_in, false); } From 197f594b0673c40fc92c130842264d9939ff24e0 Mon Sep 17 00:00:00 2001 From: michael Date: Thu, 26 Apr 2018 15:38:21 +0800 Subject: [PATCH 3/3] fix(spi): fix the issue when bus flag not set, dual mode cannot be used. --- components/driver/spi_common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/driver/spi_common.c b/components/driver/spi_common.c index d6a2dbd82..52f239af3 100644 --- a/components/driver/spi_common.c +++ b/components/driver/spi_common.c @@ -320,7 +320,7 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf 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], FUNC_GPIO); - if (mosi_output) { + if (mosi_output || (temp_flag&SPICOMMON_BUSFLAG_DUAL)) { 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 { @@ -330,7 +330,7 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf } if (bus_config->miso_io_num >= 0) { PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->miso_io_num], FUNC_GPIO); - if (miso_output) { + if (miso_output || (temp_flag&SPICOMMON_BUSFLAG_DUAL)) { 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 {