33
33
#include "hal/gpio_hal.h"
34
34
#include "esp_rom_gpio.h"
35
35
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
+
36
41
static int s_uart_debug_nr = 0 ; // UART number for debug output
37
42
#define REF_TICK_BAUDRATE_LIMIT 250000 // this is maximum UART badrate using REF_TICK as clock
38
43
@@ -110,6 +115,94 @@ static uart_t _uart_bus_array[] = {
110
115
111
116
#endif
112
117
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
+
113
206
// Negative Pin Number will keep it unmodified, thus this function can detach individual pins
114
207
// This function will also unset the pins in the Peripheral Manager and set the pin to -1 after detaching
115
208
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
219
312
}
220
313
// connect RX Pad
221
314
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
222
320
if (ret ) {
223
321
ret &= perimanSetPinBus (rxPin , ESP32_BUS_TYPE_UART_RX , (void * )uart , uart_num , -1 );
224
322
if (ret ) {
@@ -237,6 +335,11 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t
237
335
}
238
336
// connect TX Pad
239
337
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
240
343
if (ret ) {
241
344
ret &= perimanSetPinBus (txPin , ESP32_BUS_TYPE_UART_TX , (void * )uart , uart_num , -1 );
242
345
if (ret ) {
@@ -255,6 +358,11 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t
255
358
}
256
359
// connect CTS Pad
257
360
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
258
366
if (ret ) {
259
367
ret &= perimanSetPinBus (ctsPin , ESP32_BUS_TYPE_UART_CTS , (void * )uart , uart_num , -1 );
260
368
if (ret ) {
@@ -273,6 +381,11 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t
273
381
}
274
382
// connect RTS Pad
275
383
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
276
389
if (ret ) {
277
390
ret &= perimanSetPinBus (rtsPin , ESP32_BUS_TYPE_UART_RTS , (void * )uart , uart_num , -1 );
278
391
if (ret ) {
@@ -336,6 +449,13 @@ bool uartSetPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t ctsPin, in
336
449
// get UART information
337
450
uart_t * uart = & _uart_bus_array [uart_num ];
338
451
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
+
339
459
bool retCode = true;
340
460
UART_MUTEX_LOCK ();
341
461
@@ -427,6 +547,17 @@ uart_t *uartBegin(
427
547
}
428
548
uart_t * uart = & _uart_bus_array [uart_nr ];
429
549
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
430
561
431
562
#if !CONFIG_DISABLE_HAL_LOCKS
432
563
if (uart -> lock == NULL ) {
@@ -512,7 +643,7 @@ uart_t *uartBegin(
512
643
}
513
644
UART_MUTEX_UNLOCK ();
514
645
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
516
647
return uart ;
517
648
}
518
649
// if we reach this point, it means that we need to restart the UART driver
@@ -532,7 +663,7 @@ uart_t *uartBegin(
532
663
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 ));
533
664
rxfifo_full_thrhd = uart_config .rx_flow_ctrl_thresh ; // makes sure that it will be set correctly in the struct
534
665
uart_config .baud_rate = baudrate ;
535
- #if ( SOC_UART_LP_NUM >= 1 )
666
+ #if SOC_UART_LP_NUM >= 1
536
667
if (uart_nr == LP_UART_NUM_0 ) {
537
668
uart_config .lp_source_clk = LP_UART_SCLK_DEFAULT ; // use default LP clock
538
669
log_v ("Setting UART%d to use LP clock" , uart_nr );
@@ -847,7 +978,10 @@ void uartSetBaudRate(uart_t *uart, uint32_t baud_rate) {
847
978
newClkSrc = LP_UART_SCLK_DEFAULT ; // use default LP clock
848
979
}
849
980
#endif
981
+ // ESP32-P4 demands an atomic operation for setting the clock source
982
+ HP_UART_SRC_CLK_ATOMIC () {
850
983
uart_ll_set_sclk (UART_LL_GET_HW (uart -> num ), newClkSrc );
984
+ }
851
985
#else // ESP32, ESP32-S2
852
986
soc_module_clk_t newClkSrc = baud_rate <= REF_TICK_BAUDRATE_LIMIT ? SOC_MOD_CLK_REF_TICK : SOC_MOD_CLK_APB ;
853
987
uart_ll_set_sclk (UART_LL_GET_HW (uart -> num ), newClkSrc );
0 commit comments