uart: uart_set_pin function will now use IOMUX whenever possible

By using IOMUX instead of GPIO Matrix for UART, it is now possible
on ESP32 boards to use the UART as a wake up source even if it is
not used as a console.
For other boards where this issue was not present, using IOMUX has
the advantage to be faster than using GPIO matrix, so a highest
baudrate can be used
This commit is contained in:
Omar Chebib 2021-07-09 14:20:33 +08:00
parent 03fb3973a2
commit 779e7400b0
24 changed files with 697 additions and 103 deletions

View File

@ -71,8 +71,8 @@ void bootloader_console_init(void)
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_U0RXD_U, PIN_FUNC_GPIO);
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_U0TXD_U, PIN_FUNC_GPIO);
// Route GPIO signals to/from pins
const uint32_t tx_idx = uart_periph_signal[uart_num].tx_sig;
const uint32_t rx_idx = uart_periph_signal[uart_num].rx_sig;
const uint32_t tx_idx = UART_PERIPH_SIGNAL(uart_num, SOC_UART_TX_PIN_IDX);
const uint32_t rx_idx = UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[uart_rx_gpio]);
esp_rom_gpio_pad_pullup_only(uart_rx_gpio);
esp_rom_gpio_connect_out_signal(uart_tx_gpio, tx_idx, 0, 0);

View File

@ -28,7 +28,10 @@ extern "C" {
#endif
#define UART_NUM_MAX (SOC_UART_NUM) /*!< UART port max */
#define UART_PIN_NO_CHANGE (-1) /*!< Constant for uart_set_pin function which indicates that UART pin should not be changed */
/* @brief When calling `uart_set_pin`, instead of GPIO number, `UART_PIN_NO_CHANGE`
* can be provided to keep the currently allocated pin.
*/
#define UART_PIN_NO_CHANGE (-1)
#define UART_FIFO_LEN SOC_UART_FIFO_LEN ///< Length of the UART HW FIFO
#define UART_BITRATE_MAX SOC_UART_BITRATE_MAX ///< Maximum configurable bitrate
@ -380,14 +383,23 @@ esp_err_t uart_isr_register(uart_port_t uart_num, void (*fn)(void*), void * arg,
esp_err_t uart_isr_free(uart_port_t uart_num);
/**
* @brief Set UART pin number
* @brief Assign signals of a UART peripheral to GPIO pins
*
* @note If the GPIO number configured for a UART signal matches one of the
* IOMUX signals for that GPIO, the signal will be connected directly
* via the IOMUX. Otherwise the GPIO and signal will be connected via
* the GPIO Matrix. For example, if on an ESP32 the call
* `uart_set_pin(0, 1, 3, -1, -1)` is performed, as GPIO1 is UART0's
* default TX pin and GPIO3 is UART0's default RX pin, both will be
* connected to respectively U0TXD and U0RXD through the IOMUX, totally
* bypassing the GPIO matrix.
* The check is performed on a per-pin basis. Thus, it is possible to have
* RX pin binded to a GPIO through the GPIO matrix, whereas TX is binded
* to its GPIO through the IOMUX.
*
* @note Internal signal can be output to multiple GPIO pads.
* Only one GPIO pad can connect with input signal.
*
* @note Instead of GPIO number a macro 'UART_PIN_NO_CHANGE' may be provided
to keep the currently allocated pin.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param tx_io_num UART TX pin GPIO number.
* @param rx_io_num UART RX pin GPIO number.

View File

@ -276,7 +276,7 @@ TEST_CASE("uart read write test", "[uart]")
TEST_ESP_OK(uart_set_loop_back(uart_num, true));
TEST_ESP_OK(uart_set_pin(uart_num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART1_CTS_PIN));
//Connect the RTS out_signal to the CTS pin (which is mapped to CTS in_signal)
esp_rom_gpio_connect_out_signal(UART1_CTS_PIN, uart_periph_signal[uart_num].rts_sig, 0, 0);
esp_rom_gpio_connect_out_signal(UART1_CTS_PIN, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RTS_PIN_IDX), 0, 0);
TEST_ESP_OK(uart_wait_tx_done(uart_num, portMAX_DELAY));
vTaskDelay(1 / portTICK_PERIOD_MS); // make sure last byte has flushed from TX FIFO
@ -345,7 +345,7 @@ TEST_CASE("uart tx with ringbuffer test", "[uart]")
TEST_ESP_OK(uart_set_loop_back(uart_num, true));
TEST_ESP_OK(uart_set_pin(uart_num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART1_CTS_PIN));
//Connect the RTS out_signal to the CTS pin (which is mapped to CTS in_signal)
esp_rom_gpio_connect_out_signal(UART1_CTS_PIN, uart_periph_signal[uart_num].rts_sig, 0, 0);
esp_rom_gpio_connect_out_signal(UART1_CTS_PIN, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RTS_PIN_IDX), 0, 0);
for (int i = 0; i < 1024; i++) {
wr_data[i] = i;

View File

@ -587,38 +587,68 @@ esp_err_t uart_isr_free(uart_port_t uart_num)
return ret;
}
static bool uart_try_set_iomux_pin(uart_port_t uart_num, int io_num, uint32_t idx)
{
/* Store a pointer to the default pin, to optimize access to its fields. */
const uart_periph_sig_t* upin = &uart_periph_signal[uart_num].pins[idx];
/* In theory, if default_gpio is -1, iomux_func should also be -1, but
* let's be safe and test both. */
if (upin->iomux_func == -1 || upin->default_gpio == -1 || upin->default_gpio != io_num) {
return false;
}
/* Assign the correct funct to the GPIO. */
assert (upin->iomux_func != -1);
gpio_iomux_out(io_num, upin->iomux_func, false);
/* If the pin is input, we also have to redirect the signal,
* in order to bypasse the GPIO matrix. */
if (upin->input) {
gpio_iomux_in(io_num, upin->signal);
}
return true;
}
//internal signal can be output to multiple GPIO pads
//only one GPIO pad can connect with input signal
esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int rts_io_num, int cts_io_num)
{
ESP_RETURN_ON_FALSE((uart_num >= 0), ESP_FAIL, UART_TAG, "uart_num error");
ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), ESP_FAIL, UART_TAG, "uart_num error");
ESP_RETURN_ON_FALSE((tx_io_num < 0 || (GPIO_IS_VALID_OUTPUT_GPIO(tx_io_num))), ESP_FAIL, UART_TAG, "tx_io_num error");
ESP_RETURN_ON_FALSE((rx_io_num < 0 || (GPIO_IS_VALID_GPIO(rx_io_num))), ESP_FAIL, UART_TAG, "rx_io_num error");
ESP_RETURN_ON_FALSE((rts_io_num < 0 || (GPIO_IS_VALID_OUTPUT_GPIO(rts_io_num))), ESP_FAIL, UART_TAG, "rts_io_num error");
ESP_RETURN_ON_FALSE((cts_io_num < 0 || (GPIO_IS_VALID_GPIO(cts_io_num))), ESP_FAIL, UART_TAG, "cts_io_num error");
if(tx_io_num >= 0) {
/* In the following statements, if the io_num is negative, no need to configure anything. */
if (tx_io_num >= 0 && !uart_try_set_iomux_pin(uart_num, tx_io_num, SOC_UART_TX_PIN_IDX)) {
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[tx_io_num], PIN_FUNC_GPIO);
gpio_set_level(tx_io_num, 1);
esp_rom_gpio_connect_out_signal(tx_io_num, uart_periph_signal[uart_num].tx_sig, 0, 0);
esp_rom_gpio_connect_out_signal(tx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_TX_PIN_IDX), 0, 0);
}
if(rx_io_num >= 0) {
if (rx_io_num >= 0 && !uart_try_set_iomux_pin(uart_num, rx_io_num, SOC_UART_RX_PIN_IDX)) {
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[rx_io_num], PIN_FUNC_GPIO);
gpio_set_pull_mode(rx_io_num, GPIO_PULLUP_ONLY);
gpio_set_direction(rx_io_num, GPIO_MODE_INPUT);
esp_rom_gpio_connect_in_signal(rx_io_num, uart_periph_signal[uart_num].rx_sig, 0);
esp_rom_gpio_connect_in_signal(rx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), 0);
}
if(rts_io_num >= 0) {
if (rts_io_num >= 0 && !uart_try_set_iomux_pin(uart_num, rts_io_num, SOC_UART_RTS_PIN_IDX)) {
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[rts_io_num], PIN_FUNC_GPIO);
gpio_set_direction(rts_io_num, GPIO_MODE_OUTPUT);
esp_rom_gpio_connect_out_signal(rts_io_num, uart_periph_signal[uart_num].rts_sig, 0, 0);
esp_rom_gpio_connect_out_signal(rts_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RTS_PIN_IDX), 0, 0);
}
if(cts_io_num >= 0) {
if (cts_io_num >= 0 && !uart_try_set_iomux_pin(uart_num, cts_io_num, SOC_UART_CTS_PIN_IDX)) {
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[cts_io_num], PIN_FUNC_GPIO);
gpio_set_pull_mode(cts_io_num, GPIO_PULLUP_ONLY);
gpio_set_direction(cts_io_num, GPIO_MODE_INPUT);
esp_rom_gpio_connect_in_signal(cts_io_num, uart_periph_signal[uart_num].cts_sig, 0);
esp_rom_gpio_connect_in_signal(cts_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_CTS_PIN_IDX), 0);
}
return ESP_OK;
}

View File

@ -0,0 +1,53 @@
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include "soc/io_mux_reg.h"
/* Specify the number of pins for UART */
#define SOC_UART_PINS_COUNT (4)
/* Specify the GPIO pin number for each UART signal in the IOMUX */
#define U0TXD_GPIO_NUM (1)
#define U0RXD_GPIO_NUM (3)
#define U0CTS_GPIO_NUM (19)
#define U0RTS_GPIO_NUM (22)
#define U1TXD_GPIO_NUM (10)
#define U1RXD_GPIO_NUM (9)
#define U1CTS_GPIO_NUM (6)
#define U1RTS_GPIO_NUM (11)
#define U2TXD_GPIO_NUM (17)
#define U2RXD_GPIO_NUM (16)
#define U2CTS_GPIO_NUM (8)
#define U2RTS_GPIO_NUM (7)
/* The following defines are necessary for reconfiguring the UART
* to use IOMUX, at runtime. */
#define U0TXD_MUX_FUNC (FUNC_U0TXD_U0TXD)
#define U0RXD_MUX_FUNC (FUNC_U0RXD_U0RXD)
#define U0RTS_MUX_FUNC (FUNC_GPIO22_U0RTS)
#define U0CTS_MUX_FUNC (FUNC_GPIO19_U0CTS)
#define U1TXD_MUX_FUNC (FUNC_SD_DATA3_U1TXD)
#define U1RXD_MUX_FUNC (FUNC_SD_DATA2_U1RXD)
#define U1RTS_MUX_FUNC (FUNC_SD_CMD_U1RTS)
#define U1CTS_MUX_FUNC (FUNC_SD_CLK_U1CTS)
#define U2TXD_MUX_FUNC (FUNC_GPIO17_U2TXD)
#define U2RXD_MUX_FUNC (FUNC_GPIO16_U2RXD)
#define U2RTS_MUX_FUNC (FUNC_SD_DATA0_U2RTS)
#define U2CTS_MUX_FUNC (FUNC_SD_DATA1_U2CTS)

View File

@ -19,27 +19,104 @@
*/
const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = {
{
.tx_sig = U0TXD_OUT_IDX,
.rx_sig = U0RXD_IN_IDX,
.rts_sig = U0RTS_OUT_IDX,
.cts_sig = U0CTS_IN_IDX,
.pins = {
[SOC_UART_TX_PIN_IDX] = {
.default_gpio = U0TXD_GPIO_NUM,
.iomux_func = U0TXD_MUX_FUNC,
.input = 0,
.signal = U0TXD_OUT_IDX,
},
[SOC_UART_RX_PIN_IDX] = {
.default_gpio = U0RXD_GPIO_NUM,
.iomux_func = U0RXD_MUX_FUNC,
.input = 1,
.signal = U0RXD_IN_IDX,
},
[SOC_UART_RTS_PIN_IDX] = {
.default_gpio = U0RTS_GPIO_NUM,
.iomux_func = U0RTS_MUX_FUNC,
.input = 0,
.signal = U0RTS_OUT_IDX,
},
[SOC_UART_CTS_PIN_IDX] = {
.default_gpio = U0CTS_GPIO_NUM,
.iomux_func = U0CTS_MUX_FUNC,
.input = 1,
.signal = U0CTS_IN_IDX,
}
},
.irq = ETS_UART0_INTR_SOURCE,
.module = PERIPH_UART0_MODULE,
},
{
.tx_sig = U1TXD_OUT_IDX,
.rx_sig = U1RXD_IN_IDX,
.rts_sig = U1RTS_OUT_IDX,
.cts_sig = U1CTS_IN_IDX,
.pins = {
[SOC_UART_TX_PIN_IDX] = {
.default_gpio = U1TXD_GPIO_NUM,
.iomux_func = U1TXD_MUX_FUNC,
.input = 0,
.signal = U1TXD_OUT_IDX,
},
[SOC_UART_RX_PIN_IDX] = {
.default_gpio = U1RXD_GPIO_NUM,
.iomux_func = U1RXD_MUX_FUNC,
.input = 1,
.signal = U1RXD_IN_IDX,
},
[SOC_UART_RTS_PIN_IDX] = {
.default_gpio = U1RTS_GPIO_NUM,
.iomux_func = U1RTS_MUX_FUNC,
.input = 0,
.signal = U1RTS_OUT_IDX,
},
[SOC_UART_CTS_PIN_IDX] = {
.default_gpio = U1CTS_GPIO_NUM,
.iomux_func = U1CTS_MUX_FUNC,
.input = 1,
.signal = U1CTS_IN_IDX,
},
},
.irq = ETS_UART1_INTR_SOURCE,
.module = PERIPH_UART1_MODULE,
},
{
.tx_sig = U2TXD_OUT_IDX,
.rx_sig = U2RXD_IN_IDX,
.rts_sig = U2RTS_OUT_IDX,
.cts_sig = U2CTS_IN_IDX,
.pins = {
[SOC_UART_TX_PIN_IDX] = {
.default_gpio = U2TXD_GPIO_NUM,
.iomux_func = U2TXD_MUX_FUNC,
.input = 0,
.signal = U2TXD_OUT_IDX,
},
[SOC_UART_RX_PIN_IDX] = {
.default_gpio = U2RXD_GPIO_NUM,
.iomux_func = U2RXD_MUX_FUNC,
.input = 1,
.signal = U2RXD_IN_IDX,
},
[SOC_UART_RTS_PIN_IDX] = {
.default_gpio = U2RTS_GPIO_NUM,
.iomux_func = U2RTS_MUX_FUNC,
.input = 0,
.signal = U2RTS_OUT_IDX,
},
[SOC_UART_CTS_PIN_IDX] = {
.default_gpio = U2CTS_GPIO_NUM,
.iomux_func = U2CTS_MUX_FUNC,
.input = 1,
.signal = U2CTS_IN_IDX,
}
},
.irq = ETS_UART2_INTR_SOURCE,
.module = PERIPH_UART2_MODULE,
},
}
};

View File

@ -124,9 +124,6 @@
#define GPIO_PAD_PULLDOWN(num) do{PIN_PULLUP_DIS(IOMUX_REG_GPIO##num);PIN_PULLDWN_EN(IOMUX_REG_GPIO##num);}while(0)
#define GPIO_PAD_SET_DRV(num, drv) PIN_SET_DRV(IOMUX_REG_GPIO##num, drv)
#define U0RXD_GPIO_NUM 20
#define U0TXD_GPIO_NUM 21
#define SPI_HD_GPIO_NUM 12
#define SPI_WP_GPIO_NUM 13
#define SPI_CS0_GPIO_NUM 14

View File

@ -240,7 +240,6 @@
/*-------------------------- UART CAPS ---------------------------------------*/
// ESP32-C3 has 2 UARTs
#define SOC_UART_NUM (2)
#define SOC_UART_FIFO_LEN (128) /*!< The UART hardware FIFO length */
#define SOC_UART_BITRATE_MAX (5000000) /*!< Max bit rate supported by UART */

View File

@ -0,0 +1,44 @@
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include "soc/io_mux_reg.h"
/* Specify the number of pins for UART */
#define SOC_UART_PINS_COUNT (4)
/* Specify the GPIO pin number for each UART signal in the IOMUX */
#define U0RXD_GPIO_NUM 20
#define U0TXD_GPIO_NUM 21
#define U0RTS_GPIO_NUM (-1)
#define U0CTS_GPIO_NUM (-1)
#define U1RXD_GPIO_NUM (-1)
#define U1TXD_GPIO_NUM (-1)
#define U1RTS_GPIO_NUM (-1)
#define U1CTS_GPIO_NUM (-1)
/* The following defines are necessary for reconfiguring the UART
* to use IOMUX, at runtime. */
#define U0TXD_MUX_FUNC (FUNC_U0TXD_U0TXD)
#define U0RXD_MUX_FUNC (FUNC_U0RXD_U0RXD)
/* No func for the following pins, they shall not be used */
#define U0RTS_MUX_FUNC (-1)
#define U0CTS_MUX_FUNC (-1)
/* Same goes for UART1 */
#define U1TXD_MUX_FUNC (-1)
#define U1RXD_MUX_FUNC (-1)
#define U1RTS_MUX_FUNC (-1)
#define U1CTS_MUX_FUNC (-1)

View File

@ -18,20 +18,71 @@
Bunch of constants for every UART peripheral: GPIO signals, irqs, hw addr of registers etc
*/
const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = {
{
.tx_sig = U0TXD_OUT_IDX,
.rx_sig = U0RXD_IN_IDX,
.rts_sig = U0RTS_OUT_IDX,
.cts_sig = U0CTS_IN_IDX,
{
.pins = {
[SOC_UART_TX_PIN_IDX] = {
.default_gpio = U0TXD_GPIO_NUM,
.iomux_func = U0TXD_MUX_FUNC,
.input = 0,
.signal = U0TXD_OUT_IDX,
},
[SOC_UART_RX_PIN_IDX] = {
.default_gpio = U0RXD_GPIO_NUM,
.iomux_func = U0RXD_MUX_FUNC,
.input = 1,
.signal = U0RXD_IN_IDX,
},
[SOC_UART_RTS_PIN_IDX] = {
.default_gpio = U0RTS_GPIO_NUM,
.iomux_func = U0RTS_MUX_FUNC,
.input = 0,
.signal = U0RTS_OUT_IDX,
},
[SOC_UART_CTS_PIN_IDX] = {
.default_gpio = U0CTS_GPIO_NUM,
.iomux_func = U0CTS_MUX_FUNC,
.input = 1,
.signal = U0CTS_IN_IDX,
}
},
.irq = ETS_UART0_INTR_SOURCE,
.module = PERIPH_UART0_MODULE,
},
{
.tx_sig = U1TXD_OUT_IDX,
.rx_sig = U1RXD_IN_IDX,
.rts_sig = U1RTS_OUT_IDX,
.cts_sig = U1CTS_IN_IDX,
.pins = {
[SOC_UART_TX_PIN_IDX] = {
.default_gpio = U1TXD_GPIO_NUM,
.iomux_func = U1TXD_MUX_FUNC,
.input = 0,
.signal = U1TXD_OUT_IDX,
},
[SOC_UART_RX_PIN_IDX] = {
.default_gpio = U1RXD_GPIO_NUM,
.iomux_func = U1RXD_MUX_FUNC,
.input = 1,
.signal = U1RXD_IN_IDX,
},
[SOC_UART_RTS_PIN_IDX] = {
.default_gpio = U1RTS_GPIO_NUM,
.iomux_func = U1RTS_MUX_FUNC,
.input = 0,
.signal = U1RTS_OUT_IDX,
},
[SOC_UART_CTS_PIN_IDX] = {
.default_gpio = U1CTS_GPIO_NUM,
.iomux_func = U1CTS_MUX_FUNC,
.input = 1,
.signal = U1CTS_IN_IDX,
},
},
.irq = ETS_UART1_INTR_SOURCE,
.module = PERIPH_UART1_MODULE,
}
},
};

View File

@ -124,9 +124,6 @@
#define GPIO_PAD_PULLDOWN(num) do{PIN_PULLUP_DIS(IOMUX_REG_GPIO##num);PIN_PULLDWN_EN(IOMUX_REG_GPIO##num);}while(0)
#define GPIO_PAD_SET_DRV(num, drv) PIN_SET_DRV(IOMUX_REG_GPIO##num, drv)
#define U0RXD_GPIO_NUM 20
#define U0TXD_GPIO_NUM 21
#define SPI_HD_GPIO_NUM 12
#define SPI_WP_GPIO_NUM 13
#define SPI_CS0_GPIO_NUM 14

View File

@ -235,9 +235,8 @@
#define SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX (32)
/*-------------------------- UART CAPS ---------------------------------------*/
// ESP32-C3 has 2 UARTs
// ESP32-H2 has 2 UARTs
#define SOC_UART_NUM (2)
#define SOC_UART_FIFO_LEN (128) /*!< The UART hardware FIFO length */
#define SOC_UART_BITRATE_MAX (5000000) /*!< Max bit rate supported by UART */

View File

@ -0,0 +1,44 @@
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include "soc/io_mux_reg.h"
/* Specify the number of pins for UART */
#define SOC_UART_PINS_COUNT (4)
/* Specify the GPIO pin number for each UART signal in the IOMUX */
#define U0RXD_GPIO_NUM 20
#define U0TXD_GPIO_NUM 21
#define U0RTS_GPIO_NUM (-1)
#define U0CTS_GPIO_NUM (-1)
#define U1RXD_GPIO_NUM (-1)
#define U1TXD_GPIO_NUM (-1)
#define U1RTS_GPIO_NUM (-1)
#define U1CTS_GPIO_NUM (-1)
/* The following defines are necessary for reconfiguring the UART
* to use IOMUX, at runtime. */
#define U0TXD_MUX_FUNC (FUNC_U0TXD_U0TXD)
#define U0RXD_MUX_FUNC (FUNC_U0RXD_U0RXD)
/* No func for the following pins, they shall not be used */
#define U0RTS_MUX_FUNC (-1)
#define U0CTS_MUX_FUNC (-1)
/* Same goes for UART1 */
#define U1TXD_MUX_FUNC (-1)
#define U1RXD_MUX_FUNC (-1)
#define U1RTS_MUX_FUNC (-1)
#define U1CTS_MUX_FUNC (-1)

View File

@ -18,20 +18,71 @@
Bunch of constants for every UART peripheral: GPIO signals, irqs, hw addr of registers etc
*/
const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = {
{
.tx_sig = U0TXD_OUT_IDX,
.rx_sig = U0RXD_IN_IDX,
.rts_sig = U0RTS_OUT_IDX,
.cts_sig = U0CTS_IN_IDX,
{
.pins = {
[SOC_UART_TX_PIN_IDX] = {
.default_gpio = U0TXD_GPIO_NUM,
.iomux_func = U0TXD_MUX_FUNC,
.input = 0,
.signal = U0TXD_OUT_IDX,
},
[SOC_UART_RX_PIN_IDX] = {
.default_gpio = U0RXD_GPIO_NUM,
.iomux_func = U0RXD_MUX_FUNC,
.input = 1,
.signal = U0RXD_IN_IDX,
},
[SOC_UART_RTS_PIN_IDX] = {
.default_gpio = U0RTS_GPIO_NUM,
.iomux_func = U0RTS_MUX_FUNC,
.input = 0,
.signal = U0RTS_OUT_IDX,
},
[SOC_UART_CTS_PIN_IDX] = {
.default_gpio = U0CTS_GPIO_NUM,
.iomux_func = U0CTS_MUX_FUNC,
.input = 1,
.signal = U0CTS_IN_IDX,
}
},
.irq = ETS_UART0_INTR_SOURCE,
.module = PERIPH_UART0_MODULE,
},
{
.tx_sig = U1TXD_OUT_IDX,
.rx_sig = U1RXD_IN_IDX,
.rts_sig = U1RTS_OUT_IDX,
.cts_sig = U1CTS_IN_IDX,
.pins = {
[SOC_UART_TX_PIN_IDX] = {
.default_gpio = U1TXD_GPIO_NUM,
.iomux_func = U1TXD_MUX_FUNC,
.input = 0,
.signal = U1TXD_OUT_IDX,
},
[SOC_UART_RX_PIN_IDX] = {
.default_gpio = U1RXD_GPIO_NUM,
.iomux_func = U1RXD_MUX_FUNC,
.input = 1,
.signal = U1RXD_IN_IDX,
},
[SOC_UART_RTS_PIN_IDX] = {
.default_gpio = U1RTS_GPIO_NUM,
.iomux_func = U1RTS_MUX_FUNC,
.input = 0,
.signal = U1RTS_OUT_IDX,
},
[SOC_UART_CTS_PIN_IDX] = {
.default_gpio = U1CTS_GPIO_NUM,
.iomux_func = U1CTS_MUX_FUNC,
.input = 1,
.signal = U1CTS_IN_IDX,
},
},
.irq = ETS_UART1_INTR_SOURCE,
.module = PERIPH_UART1_MODULE,
}
},
};

View File

@ -145,11 +145,6 @@
#define GPIO_PAD_PULLUP(num) do{PIN_PULLUP_DIS(IOMUX_REG_GPIO##num);PIN_PULLDWN_EN(IOMUX_REG_GPIO##num);}while(0)
#define GPIO_PAD_SET_DRV(num, drv) PIN_SET_DRV(IOMUX_REG_GPIO##num, drv)
#define U1RXD_GPIO_NUM 18
#define U1TXD_GPIO_NUM 17
#define U0RXD_GPIO_NUM 44
#define U0TXD_GPIO_NUM 43
#define SPI_CS1_GPIO_NUM 26
#define SPI_HD_GPIO_NUM 27
#define SPI_WP_GPIO_NUM 28

View File

@ -242,7 +242,7 @@
#define SOC_TWAI_SUPPORTS_RX_STATUS 1
/*-------------------------- UART CAPS ---------------------------------------*/
// ESP32-S2 have 2 UART.
// ESP32-S2 has 2 UART.
#define SOC_UART_NUM (2)
#define SOC_UART_SUPPORT_REF_TICK (1) /*!< Support REF_TICK as the clock source */
#define SOC_UART_FIFO_LEN (128) /*!< The UART hardware FIFO length */

View File

@ -0,0 +1,43 @@
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include "soc/io_mux_reg.h"
/* Specify the number of pins for UART */
#define SOC_UART_PINS_COUNT (4)
/* Specify the GPIO pin number for each UART signal in the IOMUX */
#define U0RXD_GPIO_NUM (44)
#define U0TXD_GPIO_NUM (43)
#define U0RTS_GPIO_NUM (15)
#define U0CTS_GPIO_NUM (16)
#define U1RXD_GPIO_NUM (18)
#define U1TXD_GPIO_NUM (17)
#define U1RTS_GPIO_NUM (19)
#define U1CTS_GPIO_NUM (20)
/* The following defines are necessary for reconfiguring the UART
* to use IOMUX, at runtime. */
#define U0TXD_MUX_FUNC (FUNC_U0TXD_U0TXD)
#define U0RXD_MUX_FUNC (FUNC_U0RXD_U0RXD)
#define U0RTS_MUX_FUNC (FUNC_XTAL_32K_P_U0RTS)
#define U0CTS_MUX_FUNC (FUNC_XTAL_32K_N_U0CTS)
#define U1TXD_MUX_FUNC (FUNC_DAC_1_U1TXD)
#define U1RXD_MUX_FUNC (FUNC_DAC_2_U1RXD)
#define U1RTS_MUX_FUNC (FUNC_GPIO19_U1RTS)
#define U1CTS_MUX_FUNC (FUNC_GPIO20_U1CTS)

View File

@ -19,18 +19,69 @@
*/
const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = {
{
.tx_sig = U0TXD_OUT_IDX,
.rx_sig = U0RXD_IN_IDX,
.rts_sig = U0RTS_OUT_IDX,
.cts_sig = U0CTS_IN_IDX,
.pins = {
[SOC_UART_TX_PIN_IDX] = {
.default_gpio = U0TXD_GPIO_NUM,
.iomux_func = U0TXD_MUX_FUNC,
.input = 0,
.signal = U0TXD_OUT_IDX,
},
[SOC_UART_RX_PIN_IDX] = {
.default_gpio = U0RXD_GPIO_NUM,
.iomux_func = U0RXD_MUX_FUNC,
.input = 1,
.signal = U0RXD_IN_IDX,
},
[SOC_UART_RTS_PIN_IDX] = {
.default_gpio = U0RTS_GPIO_NUM,
.iomux_func = U0RTS_MUX_FUNC,
.input = 0,
.signal = U0RTS_OUT_IDX,
},
[SOC_UART_CTS_PIN_IDX] = {
.default_gpio = U0CTS_GPIO_NUM,
.iomux_func = U0CTS_MUX_FUNC,
.input = 1,
.signal = U0CTS_IN_IDX,
}
},
.irq = ETS_UART0_INTR_SOURCE,
.module = PERIPH_UART0_MODULE,
},
{
.tx_sig = U1TXD_OUT_IDX,
.rx_sig = U1RXD_IN_IDX,
.rts_sig = U1RTS_OUT_IDX,
.cts_sig = U1CTS_IN_IDX,
.pins = {
[SOC_UART_TX_PIN_IDX] = {
.default_gpio = U1TXD_GPIO_NUM,
.iomux_func = U1TXD_MUX_FUNC,
.input = 0,
.signal = U1TXD_OUT_IDX,
},
[SOC_UART_RX_PIN_IDX] = {
.default_gpio = U1RXD_GPIO_NUM,
.iomux_func = U1RXD_MUX_FUNC,
.input = 1,
.signal = U1RXD_IN_IDX,
},
[SOC_UART_RTS_PIN_IDX] = {
.default_gpio = U1RTS_GPIO_NUM,
.iomux_func = U1RTS_MUX_FUNC,
.input = 0,
.signal = U1RTS_OUT_IDX,
},
[SOC_UART_CTS_PIN_IDX] = {
.default_gpio = U1CTS_GPIO_NUM,
.iomux_func = U1CTS_MUX_FUNC,
.input = 1,
.signal = U1CTS_IN_IDX,
},
},
.irq = ETS_UART1_INTR_SOURCE,
.module = PERIPH_UART1_MODULE,
},

View File

@ -145,11 +145,6 @@
#define GPIO_PAD_PULLUP(num) do{PIN_PULLUP_DIS(IOMUX_REG_GPIO##num);PIN_PULLDWN_EN(IOMUX_REG_GPIO##num);}while(0)
#define GPIO_PAD_SET_DRV(num, drv) PIN_SET_DRV(IOMUX_REG_GPIO##num, drv)
#define U1RXD_GPIO_NUM 18
#define U1TXD_GPIO_NUM 17
#define U0RXD_GPIO_NUM 44
#define U0TXD_GPIO_NUM 43
#define SPI_CS1_GPIO_NUM 26
#define SPI_HD_GPIO_NUM 27
#define SPI_WP_GPIO_NUM 28

View File

@ -0,0 +1,55 @@
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include "soc/io_mux_reg.h"
/* Specify the number of pins for UART */
#define SOC_UART_PINS_COUNT (4)
/* Specify the GPIO pin number for each UART signal in the IOMUX */
#define U0RXD_GPIO_NUM 44
#define U0TXD_GPIO_NUM 43
#define U0CTS_GPIO_NUM 16
#define U0RTS_GPIO_NUM 15
#define U1RXD_GPIO_NUM 18
#define U1TXD_GPIO_NUM 17
#define U1CTS_GPIO_NUM 20
#define U1RTS_GPIO_NUM 19
#define U2RXD_GPIO_NUM (-1)
#define U2TXD_GPIO_NUM (-1)
#define U2CTS_GPIO_NUM (-1)
#define U2RTS_GPIO_NUM (-1)
/* The following defines are necessary for reconfiguring the UART
* to use IOMUX, at runtime. */
#define U0TXD_MUX_FUNC (FUNC_U0TXD_U0TXD)
#define U0RXD_MUX_FUNC (FUNC_U0RXD_U0RXD)
#define U0RTS_MUX_FUNC (FUNC_XTAL_32K_P_U0RTS)
#define U0CTS_MUX_FUNC (FUNC_XTAL_32K_N_U0CTS)
#define U1TXD_MUX_FUNC (FUNC_DAC_1_U1TXD)
#define U1RXD_MUX_FUNC (FUNC_DAC_2_U1RXD)
#define U1RTS_MUX_FUNC (FUNC_GPIO19_U1RTS)
#define U1CTS_MUX_FUNC (FUNC_GPIO20_U1CTS)
/* UART2 cannot be used directly through the IOMUX, these value
* shall not be used. */
#define U2TXD_MUX_FUNC (-1)
#define U2RXD_MUX_FUNC (-1)
#define U2RTS_MUX_FUNC (-1)
#define U2CTS_MUX_FUNC (-1)

View File

@ -19,27 +19,104 @@
*/
const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = {
{
.tx_sig = U0TXD_OUT_IDX,
.rx_sig = U0RXD_IN_IDX,
.rts_sig = U0RTS_OUT_IDX,
.cts_sig = U0CTS_IN_IDX,
.pins = {
[SOC_UART_TX_PIN_IDX] = {
.default_gpio = U0TXD_GPIO_NUM,
.iomux_func = U0TXD_MUX_FUNC,
.input = 0,
.signal = U0TXD_OUT_IDX,
},
[SOC_UART_RX_PIN_IDX] = {
.default_gpio = U0RXD_GPIO_NUM,
.iomux_func = U0RXD_MUX_FUNC,
.input = 1,
.signal = U0RXD_IN_IDX,
},
[SOC_UART_RTS_PIN_IDX] = {
.default_gpio = U0RTS_GPIO_NUM,
.iomux_func = U0RTS_MUX_FUNC,
.input = 0,
.signal = U0RTS_OUT_IDX,
},
[SOC_UART_CTS_PIN_IDX] = {
.default_gpio = U0CTS_GPIO_NUM,
.iomux_func = U0CTS_MUX_FUNC,
.input = 1,
.signal = U0CTS_IN_IDX,
}
},
.irq = ETS_UART0_INTR_SOURCE,
.module = PERIPH_UART0_MODULE,
},
{
.tx_sig = U1TXD_OUT_IDX,
.rx_sig = U1RXD_IN_IDX,
.rts_sig = U1RTS_OUT_IDX,
.cts_sig = U1CTS_IN_IDX,
.pins = {
[SOC_UART_TX_PIN_IDX] = {
.default_gpio = U1TXD_GPIO_NUM,
.iomux_func = U1TXD_MUX_FUNC,
.input = 0,
.signal = U1TXD_OUT_IDX,
},
[SOC_UART_RX_PIN_IDX] = {
.default_gpio = U1RXD_GPIO_NUM,
.iomux_func = U1RXD_MUX_FUNC,
.input = 1,
.signal = U1RXD_IN_IDX,
},
[SOC_UART_RTS_PIN_IDX] = {
.default_gpio = U1RTS_GPIO_NUM,
.iomux_func = U1RTS_MUX_FUNC,
.input = 0,
.signal = U1RTS_OUT_IDX,
},
[SOC_UART_CTS_PIN_IDX] = {
.default_gpio = U1CTS_GPIO_NUM,
.iomux_func = U1CTS_MUX_FUNC,
.input = 1,
.signal = U1CTS_IN_IDX,
},
},
.irq = ETS_UART1_INTR_SOURCE,
.module = PERIPH_UART1_MODULE,
},
{
.tx_sig = U2TXD_OUT_IDX,
.rx_sig = U2RXD_IN_IDX,
.rts_sig = U2RTS_OUT_IDX,
.cts_sig = U2CTS_IN_IDX,
.pins = {
[SOC_UART_TX_PIN_IDX] = {
.default_gpio = U2TXD_GPIO_NUM,
.iomux_func = U2TXD_MUX_FUNC,
.input = 0,
.signal = U2TXD_OUT_IDX,
},
[SOC_UART_RX_PIN_IDX] = {
.default_gpio = U2RXD_GPIO_NUM,
.iomux_func = U2RXD_MUX_FUNC,
.input = 1,
.signal = U2RXD_IN_IDX,
},
[SOC_UART_RTS_PIN_IDX] = {
.default_gpio = U2RTS_GPIO_NUM,
.iomux_func = U2RTS_MUX_FUNC,
.input = 0,
.signal = U2RTS_OUT_IDX,
},
[SOC_UART_CTS_PIN_IDX] = {
.default_gpio = U2CTS_GPIO_NUM,
.iomux_func = U2CTS_MUX_FUNC,
.input = 1,
.signal = U2CTS_IN_IDX,
}
},
.irq = ETS_UART2_INTR_SOURCE,
.module = PERIPH_UART2_MODULE,
},
}
};

View File

@ -18,16 +18,40 @@
#include "soc/uart_struct.h"
#include "soc/periph_defs.h"
#include "soc/gpio_sig_map.h"
#include "soc/io_mux_reg.h"
#include "soc/uart_pins.h"
#ifdef __cplusplus
extern "C" {
#endif
#define SOC_UART_TX_PIN_IDX (0)
#define SOC_UART_RX_PIN_IDX (1)
#define SOC_UART_RTS_PIN_IDX (2)
#define SOC_UART_CTS_PIN_IDX (3)
/**
* @brief Macro that can be used to retrieve the signal of a certain pin for a
* certain UART.
*/
#define UART_PERIPH_SIGNAL(IDX, PIN) (uart_periph_signal[(IDX)].pins[(PIN)].signal)
typedef struct {
const uint8_t tx_sig;
const uint8_t rx_sig;
const uint8_t rts_sig;
const uint8_t cts_sig;
/* Default GPIO number for this UART pin in the IOMUX.
* This value can be -1 if there is no default GPIO for a pin.
* For example, ESP32-C3 doesn't have any default GPIO for
* U0CTS and U0RTS. */
int32_t default_gpio : 15;
/* Func which should be assigned to the GPIO to be used as UART */
int32_t iomux_func : 4;
/* Marks if the current UART pin is input (or not) */
uint32_t input : 1;
/* Signal in the GPIO signal map. */
uint32_t signal : 12;
} uart_periph_sig_t;
typedef struct {
const uart_periph_sig_t pins[SOC_UART_PINS_COUNT];
const uint8_t irq;
const periph_module_t module;
} uart_signal_conn_t;

View File

@ -2,9 +2,9 @@ menu "Echo Example Configuration"
config EXAMPLE_UART_PORT_NUM
int "UART port number"
range 0 2 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S3
range 0 2 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S3
range 0 1 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3
default 2 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S3
default 2 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S3
default 1 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3
help
UART communication port number for the example.

View File

@ -43,11 +43,11 @@ const char test_message[] = "This is an example string, if you can read this, th
*/
static void connect_uarts(void)
{
esp_rom_gpio_connect_out_signal(DEFAULT_UART_RX_PIN, uart_periph_signal[1].tx_sig, false, false);
esp_rom_gpio_connect_in_signal(DEFAULT_UART_RX_PIN, uart_periph_signal[0].rx_sig, false);
esp_rom_gpio_connect_out_signal(DEFAULT_UART_RX_PIN, UART_PERIPH_SIGNAL(1, SOC_UART_TX_PIN_IDX), false, false);
esp_rom_gpio_connect_in_signal(DEFAULT_UART_RX_PIN, UART_PERIPH_SIGNAL(0, SOC_UART_RX_PIN_IDX), false);
esp_rom_gpio_connect_out_signal(DEFAULT_UART_TX_PIN, uart_periph_signal[0].tx_sig, false, false);
esp_rom_gpio_connect_in_signal(DEFAULT_UART_TX_PIN, uart_periph_signal[1].rx_sig, false);
esp_rom_gpio_connect_out_signal(DEFAULT_UART_TX_PIN, UART_PERIPH_SIGNAL(0, SOC_UART_TX_PIN_IDX), false, false);
esp_rom_gpio_connect_in_signal(DEFAULT_UART_TX_PIN, UART_PERIPH_SIGNAL(1, SOC_UART_RX_PIN_IDX), false);
}
/**
@ -58,8 +58,8 @@ static void connect_uarts(void)
*/
static void disconnect_uarts(void)
{
esp_rom_gpio_connect_out_signal(CONSOLE_UART_TX_PIN, uart_periph_signal[1].tx_sig, false, false);
esp_rom_gpio_connect_in_signal(CONSOLE_UART_RX_PIN, uart_periph_signal[1].rx_sig, false);
esp_rom_gpio_connect_out_signal(CONSOLE_UART_TX_PIN, UART_PERIPH_SIGNAL(1, SOC_UART_TX_PIN_IDX), false, false);
esp_rom_gpio_connect_in_signal(CONSOLE_UART_RX_PIN, UART_PERIPH_SIGNAL(1, SOC_UART_RX_PIN_IDX), false);
}
/**