Skip to content

Commit 659cf2a

Browse files
committed
feat(lp_uart): pin setting for lp uart plus esp32p4 fixes
1 parent 8586f1a commit 659cf2a

File tree

1 file changed

+136
-2
lines changed

1 file changed

+136
-2
lines changed

cores/esp32/esp32-hal-uart.c

Lines changed: 136 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@
3333
#include "hal/gpio_hal.h"
3434
#include "esp_rom_gpio.h"
3535

36+
#include "driver/rtc_io.h"
37+
#include "driver/lp_io.h"
38+
#include "soc/uart_periph.h"
39+
#include "esp_private/uart_share_hw_ctrl.h"
40+
3641
static int s_uart_debug_nr = 0; // UART number for debug output
3742
#define REF_TICK_BAUDRATE_LIMIT 250000 // this is maximum UART badrate using REF_TICK as clock
3843

@@ -110,6 +115,94 @@ static uart_t _uart_bus_array[] = {
110115

111116
#endif
112117

118+
#if SOC_UART_LP_NUM >= 1
119+
// LP UART enable pins routine
120+
static bool lp_uart_config_io(int8_t pin, rtc_gpio_mode_t direction, uint32_t idx)
121+
{
122+
/* Skip configuration if the LP_IO is -1 */
123+
if (pin < 0) {
124+
return true;
125+
}
126+
127+
// Initialize LP_IO
128+
if (rtc_gpio_init(pin) != ESP_OK) {
129+
log_e("Failed to initialize LP_IO %d", pin);
130+
return false;
131+
}
132+
133+
// Set LP_IO direction
134+
if (rtc_gpio_set_direction(pin, direction) != ESP_OK) {
135+
log_e("Failed to set LP_IO %d direction", pin);
136+
return false;
137+
}
138+
139+
// Connect pins
140+
const uart_periph_sig_t *upin = &uart_periph_signal[LP_UART_NUM_0].pins[idx];
141+
#if !SOC_LP_GPIO_MATRIX_SUPPORTED // ESP32-C6/C61/C5
142+
// When LP_IO Matrix is not support, LP_IO Mux must be connected to the pins
143+
if (rtc_gpio_iomux_func_sel(pin, upin->iomux_func) != ESP_OK) {
144+
log_e("Failed to set LP_IO pin %d into Mux function", pin);
145+
return false;
146+
}
147+
#else // So far, only ESP32-P4
148+
// If the configured pin is the default LP_IO Mux pin for LP UART, then set the LP_IO MUX function
149+
if (upin->default_gpio == pin) {
150+
if (rtc_gpio_iomux_func_sel(pin, upin->iomux_func) != ESP_OK) {
151+
log_e("Failed to set LP_IO pin %d into Mux function", pin);
152+
return false;
153+
}
154+
} else {
155+
// Otherwise, set the LP_IO Matrix and select FUNC1
156+
if (rtc_gpio_iomux_func_sel(pin, 1) != ESP_OK) {
157+
log_e("Failed to set LP_IO pin %d into Mux function GPIO", pin);
158+
return false;
159+
}
160+
// Connect the LP_IO to the LP UART peripheral signal
161+
esp_err_t ret;
162+
if (direction == RTC_GPIO_MODE_OUTPUT_ONLY) {
163+
ret = lp_gpio_connect_out_signal(pin, UART_PERIPH_SIGNAL(LP_UART_NUM_0, idx), 0, 0);
164+
} else {
165+
ret = lp_gpio_connect_in_signal(pin, UART_PERIPH_SIGNAL(LP_UART_NUM_0, idx), 0);
166+
}
167+
if (ret != ESP_OK) {
168+
log_e("Failed to connect LP_IO pin %d to UART%d signal", pin, LP_UART_NUM_0);
169+
return false;
170+
}
171+
}
172+
#endif // SOC_LP_GPIO_MATRIX_SUPPORTED
173+
174+
return true;
175+
}
176+
177+
// When LP UART needs the RTC IO MUX to set the pin, it will always have fixed pins for RX, TX, CTS and RTS
178+
static bool lpuartCheckPins(int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin, uint8_t uart_nr) {
179+
// check if LP UART is being used and if the pins are valid
180+
#if !SOC_LP_GPIO_MATRIX_SUPPORTED // ESP32-C6/C61/C5
181+
if (uart_nr == LP_UART_NUM_0) {
182+
if (rxPin > 0 && rxPin != LP_U0RXD_GPIO_NUM) {
183+
log_e("UART%d LP UART requires RX pin to be set to %d.", uart_nr, LP_U0RXD_GPIO_NUM);
184+
return false;
185+
}
186+
if (txPin > 0 && txPin != LP_U0TXD_GPIO_NUM) {
187+
log_e("UART%d LP UART requires TX pin to be set to %d.", uart_nr, LP_U0TXD_GPIO_NUM);
188+
return false;
189+
}
190+
if (ctsPin > 0 && ctsPin != LP_U0CTS_GPIO_NUM) {
191+
log_e("UART%d LP UART requires CTS pin to be set to %d.", uart_nr, LP_U0CTS_GPIO_NUM);
192+
return false;
193+
}
194+
if (rtsPin > 0 && rtsPin != LP_U0RTS_GPIO_NUM) {
195+
log_e("UART%d LP UART requires RTS pin to be set to %d.", uart_nr, LP_U0RTS_GPIO_NUM);
196+
return false;
197+
}
198+
}
199+
return true;
200+
#else // ESP32-P4 can set any pin for LP UART
201+
return true;
202+
#endif // SOC_LP_GPIO_MATRIX_SUPPORTED
203+
}
204+
#endif // SOC_UART_LP_NUM >= 1
205+
113206
// Negative Pin Number will keep it unmodified, thus this function can detach individual pins
114207
// This function will also unset the pins in the Peripheral Manager and set the pin to -1 after detaching
115208
static bool _uartDetachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin) {
@@ -219,6 +312,11 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t
219312
}
220313
// connect RX Pad
221314
bool ret = ESP_OK == uart_set_pin(uart->num, UART_PIN_NO_CHANGE, rxPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
315+
#if SOC_UART_LP_NUM >= 1
316+
if (ret && uart_num == LP_UART_NUM_0) {
317+
ret &= lp_uart_config_io(rxPin, RTC_GPIO_MODE_INPUT_ONLY, SOC_UART_RX_PIN_IDX);
318+
}
319+
#endif
222320
if (ret) {
223321
ret &= perimanSetPinBus(rxPin, ESP32_BUS_TYPE_UART_RX, (void *)uart, uart_num, -1);
224322
if (ret) {
@@ -237,6 +335,11 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t
237335
}
238336
// connect TX Pad
239337
bool ret = ESP_OK == uart_set_pin(uart->num, txPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
338+
#if SOC_UART_LP_NUM >= 1
339+
if (ret && uart_num == LP_UART_NUM_0) {
340+
ret &= lp_uart_config_io(txPin, RTC_GPIO_MODE_OUTPUT_ONLY, SOC_UART_TX_PIN_IDX);
341+
}
342+
#endif
240343
if (ret) {
241344
ret &= perimanSetPinBus(txPin, ESP32_BUS_TYPE_UART_TX, (void *)uart, uart_num, -1);
242345
if (ret) {
@@ -255,6 +358,11 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t
255358
}
256359
// connect CTS Pad
257360
bool ret = ESP_OK == uart_set_pin(uart->num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, ctsPin);
361+
#if SOC_UART_LP_NUM >= 1
362+
if (ret && uart_num == LP_UART_NUM_0) {
363+
ret &= lp_uart_config_io(ctsPin, RTC_GPIO_MODE_INPUT_ONLY, SOC_UART_CTS_PIN_IDX);
364+
}
365+
#endif
258366
if (ret) {
259367
ret &= perimanSetPinBus(ctsPin, ESP32_BUS_TYPE_UART_CTS, (void *)uart, uart_num, -1);
260368
if (ret) {
@@ -273,6 +381,11 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t
273381
}
274382
// connect RTS Pad
275383
bool ret = ESP_OK == uart_set_pin(uart->num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, rtsPin, UART_PIN_NO_CHANGE);
384+
#if SOC_UART_LP_NUM >= 1
385+
if (ret && uart_num == LP_UART_NUM_0) {
386+
ret &= lp_uart_config_io(rtsPin, RTC_GPIO_MODE_OUTPUT_ONLY, SOC_UART_RTS_PIN_IDX);
387+
}
388+
#endif
276389
if (ret) {
277390
ret &= perimanSetPinBus(rtsPin, ESP32_BUS_TYPE_UART_RTS, (void *)uart, uart_num, -1);
278391
if (ret) {
@@ -336,6 +449,13 @@ bool uartSetPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t ctsPin, in
336449
// get UART information
337450
uart_t *uart = &_uart_bus_array[uart_num];
338451

452+
#if SOC_UART_LP_NUM >= 1
453+
// check if LP UART is being used and if the pins are valid
454+
if (!lpuartCheckPins(rxPin, txPin, ctsPin, rtsPin, uart_num)) {
455+
return false; // failed to set pins
456+
}
457+
#endif
458+
339459
bool retCode = true;
340460
UART_MUTEX_LOCK();
341461

@@ -427,6 +547,17 @@ uart_t *uartBegin(
427547
}
428548
uart_t *uart = &_uart_bus_array[uart_nr];
429549
log_v("UART%d baud(%ld) Mode(%x) rxPin(%d) txPin(%d)", uart_nr, baudrate, config, rxPin, txPin);
550+
551+
#if SOC_UART_LP_NUM >= 1
552+
// check if LP UART is being used and if the pins are valid
553+
if (!lpuartCheckPins(rxPin, txPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, uart_nr)) {
554+
if (uart_is_driver_installed(uart_nr)) {
555+
return uart; // keep the same installed driver
556+
} else {
557+
return NULL; // no new driver was installed
558+
}
559+
}
560+
#endif
430561

431562
#if !CONFIG_DISABLE_HAL_LOCKS
432563
if (uart->lock == NULL) {
@@ -512,7 +643,7 @@ uart_t *uartBegin(
512643
}
513644
UART_MUTEX_UNLOCK();
514645
if (retCode) {
515-
// UART driver was already working, just return the uart_t structure, syaing that no new driver was installed
646+
// UART driver was already working, just return the uart_t structure, saying that no new driver was installed
516647
return uart;
517648
}
518649
// if we reach this point, it means that we need to restart the UART driver
@@ -532,7 +663,7 @@ uart_t *uartBegin(
532663
log_v("UART%d RX FIFO full threshold set to %d (value requested: %d || FIFO Max = %d)", uart_nr, uart_config.rx_flow_ctrl_thresh, rxfifo_full_thrhd, UART_HW_FIFO_LEN(uart_nr));
533664
rxfifo_full_thrhd = uart_config.rx_flow_ctrl_thresh; // makes sure that it will be set correctly in the struct
534665
uart_config.baud_rate = baudrate;
535-
#if (SOC_UART_LP_NUM >= 1)
666+
#if SOC_UART_LP_NUM >= 1
536667
if (uart_nr == LP_UART_NUM_0) {
537668
uart_config.lp_source_clk = LP_UART_SCLK_DEFAULT; // use default LP clock
538669
log_v("Setting UART%d to use LP clock", uart_nr);
@@ -847,7 +978,10 @@ void uartSetBaudRate(uart_t *uart, uint32_t baud_rate) {
847978
newClkSrc = LP_UART_SCLK_DEFAULT; // use default LP clock
848979
}
849980
#endif
981+
// ESP32-P4 demands an atomic operation for setting the clock source
982+
HP_UART_SRC_CLK_ATOMIC() {
850983
uart_ll_set_sclk(UART_LL_GET_HW(uart->num), newClkSrc);
984+
}
851985
#else // ESP32, ESP32-S2
852986
soc_module_clk_t newClkSrc = baud_rate <= REF_TICK_BAUDRATE_LIMIT ? SOC_MOD_CLK_REF_TICK : SOC_MOD_CLK_APB;
853987
uart_ll_set_sclk(UART_LL_GET_HW(uart->num), newClkSrc);

0 commit comments

Comments
 (0)