Skip to content

Commit 60f5828

Browse files
committed
feat(uart): add pin release process to uart driver
1 parent 606ba21 commit 60f5828

File tree

2 files changed

+120
-33
lines changed

2 files changed

+120
-33
lines changed

components/esp_driver_i2c/i2c_common.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -32,6 +32,9 @@
3232
#include "driver/rtc_io.h"
3333
#include "soc/rtc_io_channel.h"
3434
#include "driver/lp_io.h"
35+
#if SOC_LP_GPIO_MATRIX_SUPPORTED
36+
#include "soc/lp_gpio_pins.h"
37+
#endif
3538
#endif
3639
#if I2C_USE_RETENTION_LINK
3740
#include "esp_private/sleep_retention.h"
@@ -427,8 +430,8 @@ esp_err_t i2c_common_deinit_pins(i2c_bus_handle_t handle)
427430
ESP_RETURN_ON_ERROR(rtc_gpio_deinit(handle->sda_num), TAG, "deinit rtc gpio failed");
428431
ESP_RETURN_ON_ERROR(rtc_gpio_deinit(handle->scl_num), TAG, "deinit rtc gpio failed");
429432
#if SOC_LP_GPIO_MATRIX_SUPPORTED
430-
lp_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, i2c_periph_signal[port_id].scl_in_sig, 0);
431-
lp_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, i2c_periph_signal[port_id].sda_in_sig, 0);
433+
lp_gpio_connect_in_signal(LP_GPIO_MATRIX_CONST_ZERO_INPUT, i2c_periph_signal[port_id].scl_in_sig, 0);
434+
lp_gpio_connect_in_signal(LP_GPIO_MATRIX_CONST_ZERO_INPUT, i2c_periph_signal[port_id].sda_in_sig, 0);
432435
#endif
433436
}
434437
#endif

components/esp_driver_uart/src/uart.c

Lines changed: 114 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@
3636
#include "driver/rtc_io.h"
3737
#include "hal/rtc_io_ll.h"
3838
#include "driver/lp_io.h"
39+
#if SOC_LP_GPIO_MATRIX_SUPPORTED
40+
#include "soc/lp_gpio_pins.h"
41+
#endif
3942
#endif
4043
#include "clk_ctrl_os.h"
4144
#include "esp_pm.h"
@@ -109,6 +112,11 @@ static const char *UART_TAG = "uart";
109112
.hal.dev = UART_LL_GET_HW(uart_num), \
110113
INIT_CRIT_SECTION_LOCK_IN_STRUCT(spinlock) \
111114
.hw_enabled = false, \
115+
.tx_io_num = -1, \
116+
.rx_io_num = -1, \
117+
.rts_io_num = -1, \
118+
.cts_io_num = -1, \
119+
.io_reserved_mask = 0, \
112120
}
113121

114122
typedef struct {
@@ -170,6 +178,11 @@ typedef struct {
170178
uart_hal_context_t hal; /*!< UART hal context*/
171179
DECLARE_CRIT_SECTION_LOCK_IN_STRUCT(spinlock)
172180
bool hw_enabled;
181+
int tx_io_num;
182+
int rx_io_num;
183+
int rts_io_num;
184+
int cts_io_num;
185+
uint64_t io_reserved_mask;
173186
} uart_context_t;
174187

175188
static uart_obj_t *p_uart_obj[UART_NUM_MAX] = {0};
@@ -707,8 +720,66 @@ static bool uart_try_set_iomux_pin(uart_port_t uart_num, int io_num, uint32_t id
707720
return true;
708721
}
709722

710-
//internal signal can be output to multiple GPIO pads
711-
//only one GPIO pad can connect with input signal
723+
static void uart_release_pin(uart_port_t uart_num)
724+
{
725+
if (uart_num >= UART_NUM_MAX) {
726+
return;
727+
}
728+
if (uart_context[uart_num].tx_io_num >= 0) {
729+
gpio_output_disable(uart_context[uart_num].tx_io_num);
730+
#if (SOC_UART_LP_NUM >= 1)
731+
if (!(uart_num < SOC_UART_HP_NUM)) {
732+
rtc_gpio_deinit(uart_context[uart_num].tx_io_num);
733+
}
734+
#endif
735+
}
736+
737+
if (uart_context[uart_num].rx_io_num >= 0) {
738+
if (uart_num < SOC_UART_HP_NUM) {
739+
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), false);
740+
}
741+
#if (SOC_UART_LP_NUM >= 1)
742+
else {
743+
#if SOC_LP_GPIO_MATRIX_SUPPORTED
744+
lp_gpio_connect_in_signal(LP_GPIO_MATRIX_CONST_ONE_INPUT, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), false);
745+
#endif
746+
rtc_gpio_deinit(uart_context[uart_num].rx_io_num);
747+
}
748+
#endif
749+
}
750+
751+
if (uart_context[uart_num].rts_io_num >= 0) {
752+
gpio_output_disable(uart_context[uart_num].rts_io_num);
753+
#if (SOC_UART_LP_NUM >= 1)
754+
if (!(uart_num < SOC_UART_HP_NUM)) {
755+
rtc_gpio_deinit(uart_context[uart_num].rts_io_num);
756+
}
757+
#endif
758+
}
759+
760+
if (uart_context[uart_num].cts_io_num >= 0) {
761+
if (uart_num < SOC_UART_HP_NUM) {
762+
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, UART_PERIPH_SIGNAL(uart_num, SOC_UART_CTS_PIN_IDX), false);
763+
}
764+
#if (SOC_UART_LP_NUM >= 1)
765+
else {
766+
#if SOC_LP_GPIO_MATRIX_SUPPORTED
767+
lp_gpio_connect_in_signal(LP_GPIO_MATRIX_CONST_ZERO_INPUT, UART_PERIPH_SIGNAL(uart_num, SOC_UART_CTS_PIN_IDX), false);
768+
#endif
769+
rtc_gpio_deinit(uart_context[uart_num].cts_io_num);
770+
}
771+
#endif
772+
}
773+
774+
esp_gpio_revoke(uart_context[uart_num].io_reserved_mask);
775+
776+
uart_context[uart_num].tx_io_num = -1;
777+
uart_context[uart_num].rx_io_num = -1;
778+
uart_context[uart_num].rts_io_num = -1;
779+
uart_context[uart_num].cts_io_num = -1;
780+
uart_context[uart_num].io_reserved_mask = 0;
781+
}
782+
712783
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)
713784
{
714785
ESP_RETURN_ON_FALSE((uart_num >= 0), ESP_FAIL, UART_TAG, "uart_num error");
@@ -740,6 +811,9 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r
740811
}
741812
#endif
742813

814+
// First, release previously configured IOs if there is
815+
uart_release_pin(uart_num);
816+
743817
// Potential IO reserved mask
744818
uint64_t io_reserve_mask = 0;
745819
io_reserve_mask |= (tx_io_num > 0 ? BIT64(tx_io_num) : 0);
@@ -752,42 +826,48 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r
752826
bool tx_rx_same_io = (tx_io_num == rx_io_num);
753827

754828
/* In the following statements, if the io_num is negative, no need to configure anything. */
755-
if (tx_io_num >= 0 && (tx_rx_same_io || !uart_try_set_iomux_pin(uart_num, tx_io_num, SOC_UART_TX_PIN_IDX))) {
756-
if (uart_num < SOC_UART_HP_NUM) {
757-
gpio_func_sel(tx_io_num, PIN_FUNC_GPIO);
758-
esp_rom_gpio_connect_out_signal(tx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_TX_PIN_IDX), 0, 0);
759-
// output enable is set inside esp_rom_gpio_connect_out_signal func after the signal is connected
760-
// (output enabled too early may cause unnecessary level change at the pad)
761-
}
829+
if (tx_io_num >= 0) {
830+
uart_context[uart_num].tx_io_num = tx_io_num;
831+
if (tx_rx_same_io || !uart_try_set_iomux_pin(uart_num, tx_io_num, SOC_UART_TX_PIN_IDX)) {
832+
if (uart_num < SOC_UART_HP_NUM) {
833+
gpio_func_sel(tx_io_num, PIN_FUNC_GPIO);
834+
esp_rom_gpio_connect_out_signal(tx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_TX_PIN_IDX), 0, 0);
835+
// output enable is set inside esp_rom_gpio_connect_out_signal func after the signal is connected
836+
// (output enabled too early may cause unnecessary level change at the pad)
837+
}
762838
#if SOC_LP_GPIO_MATRIX_SUPPORTED
763-
else {
764-
rtc_gpio_init(tx_io_num); // set as a LP_GPIO pin
765-
lp_gpio_connect_out_signal(tx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_TX_PIN_IDX), 0, 0);
766-
// output enable is set inside lp_gpio_connect_out_signal func after the signal is connected
767-
}
839+
else {
840+
rtc_gpio_init(tx_io_num); // set as a LP_GPIO pin
841+
lp_gpio_connect_out_signal(tx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_TX_PIN_IDX), 0, 0);
842+
// output enable is set inside lp_gpio_connect_out_signal func after the signal is connected
843+
}
768844
#endif
845+
}
769846
}
770847

771-
if (rx_io_num >= 0 && (tx_rx_same_io || !uart_try_set_iomux_pin(uart_num, rx_io_num, SOC_UART_RX_PIN_IDX))) {
772-
io_reserve_mask &= ~BIT64(rx_io_num); // input IO via GPIO matrix does not need to be reserved
773-
if (uart_num < SOC_UART_HP_NUM) {
774-
gpio_input_enable(rx_io_num);
775-
esp_rom_gpio_connect_in_signal(rx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), 0);
776-
}
777-
#if SOC_LP_GPIO_MATRIX_SUPPORTED
778-
else {
779-
rtc_gpio_mode_t mode = (tx_rx_same_io ? RTC_GPIO_MODE_INPUT_OUTPUT : RTC_GPIO_MODE_INPUT_ONLY);
780-
rtc_gpio_set_direction(rx_io_num, mode);
781-
if (!tx_rx_same_io) { // set the same pin again as a LP_GPIO will overwrite connected out_signal, not desired, so skip
782-
rtc_gpio_init(rx_io_num); // set as a LP_GPIO pin
848+
if (rx_io_num >= 0) {
849+
uart_context[uart_num].rx_io_num = rx_io_num;
850+
if (tx_rx_same_io || !uart_try_set_iomux_pin(uart_num, rx_io_num, SOC_UART_RX_PIN_IDX)) {
851+
io_reserve_mask &= ~BIT64(rx_io_num); // input IO via GPIO matrix does not need to be reserved
852+
if (uart_num < SOC_UART_HP_NUM) {
853+
gpio_input_enable(rx_io_num);
854+
esp_rom_gpio_connect_in_signal(rx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), 0);
783855
}
856+
#if SOC_LP_GPIO_MATRIX_SUPPORTED
857+
else {
858+
rtc_gpio_mode_t mode = (tx_rx_same_io ? RTC_GPIO_MODE_INPUT_OUTPUT : RTC_GPIO_MODE_INPUT_ONLY);
859+
rtc_gpio_set_direction(rx_io_num, mode);
860+
if (!tx_rx_same_io) { // set the same pin again as a LP_GPIO will overwrite connected out_signal, not desired, so skip
861+
rtc_gpio_init(rx_io_num); // set as a LP_GPIO pin
862+
}
784863

785-
lp_gpio_connect_in_signal(rx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), 0);
786-
}
864+
lp_gpio_connect_in_signal(rx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), 0);
865+
}
787866
#endif
867+
}
788868
}
789869

790-
if (rts_io_num >= 0 && !uart_try_set_iomux_pin(uart_num, rts_io_num, SOC_UART_RTS_PIN_IDX)) {
870+
if (rts_io_num >= 0 && (uart_context[uart_num].rts_io_num = rts_io_num, !uart_try_set_iomux_pin(uart_num, rts_io_num, SOC_UART_RTS_PIN_IDX))) {
791871
if (uart_num < SOC_UART_HP_NUM) {
792872
gpio_func_sel(rts_io_num, PIN_FUNC_GPIO);
793873
esp_rom_gpio_connect_out_signal(rts_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RTS_PIN_IDX), 0, 0);
@@ -802,7 +882,7 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r
802882
#endif
803883
}
804884

805-
if (cts_io_num >= 0 && !uart_try_set_iomux_pin(uart_num, cts_io_num, SOC_UART_CTS_PIN_IDX)) {
885+
if (cts_io_num >= 0 && (uart_context[uart_num].cts_io_num = cts_io_num, !uart_try_set_iomux_pin(uart_num, cts_io_num, SOC_UART_CTS_PIN_IDX))) {
806886
io_reserve_mask &= ~BIT64(cts_io_num); // input IO via GPIO matrix does not need to be reserved
807887
if (uart_num < SOC_UART_HP_NUM) {
808888
gpio_pullup_en(cts_io_num);
@@ -819,6 +899,7 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r
819899
}
820900

821901
// IO reserve
902+
uart_context[uart_num].io_reserved_mask = io_reserve_mask;
822903
uint64_t old_busy_mask = esp_gpio_reserve(io_reserve_mask);
823904
uint64_t conflict_mask = old_busy_mask & io_reserve_mask;
824905
while (conflict_mask > 0) {
@@ -1801,6 +1882,9 @@ esp_err_t uart_driver_delete(uart_port_t uart_num)
18011882
ESP_LOGI(UART_TAG, "ALREADY NULL");
18021883
return ESP_OK;
18031884
}
1885+
1886+
uart_release_pin(uart_num);
1887+
18041888
esp_intr_free(p_uart_obj[uart_num]->intr_handle);
18051889
uart_disable_rx_intr(uart_num);
18061890
uart_disable_tx_intr(uart_num);

0 commit comments

Comments
 (0)