@@ -295,6 +295,125 @@ static bool _uartDetachBus_RTS(void *busptr) {
295
295
return _uartDetachPins (bus -> num , UART_PIN_NO_CHANGE , UART_PIN_NO_CHANGE , UART_PIN_NO_CHANGE , bus -> _rtsPin );
296
296
}
297
297
298
+ static bool _uartTrySetIomuxPin (uart_port_t uart_num , int io_num , uint32_t idx ) {
299
+ // Store a pointer to the default pin, to optimize access to its fields.
300
+ const uart_periph_sig_t * upin = & uart_periph_signal [uart_num ].pins [idx ];
301
+
302
+ // In theory, if default_gpio is -1, iomux_func should also be -1, but let's be safe and test both.
303
+ if (upin -> iomux_func == -1 || upin -> default_gpio == -1 || upin -> default_gpio != io_num ) {
304
+ return false;
305
+ }
306
+
307
+ // Assign the correct function to the GPIO.
308
+ assert (upin -> iomux_func != -1 );
309
+ if (uart_num < SOC_UART_HP_NUM ) {
310
+ gpio_iomux_out (io_num , upin -> iomux_func , false);
311
+ // If the pin is input, we also have to redirect the signal, in order to bypass the GPIO matrix.
312
+ if (upin -> input ) {
313
+ gpio_iomux_in (io_num , upin -> signal );
314
+ }
315
+ }
316
+ #if (SOC_UART_LP_NUM >= 1 ) && (SOC_RTCIO_PIN_COUNT >= 1 )
317
+ else {
318
+ if (upin -> input ) {
319
+ rtc_gpio_set_direction (io_num , RTC_GPIO_MODE_INPUT_ONLY );
320
+ } else {
321
+ rtc_gpio_set_direction (io_num , RTC_GPIO_MODE_OUTPUT_ONLY );
322
+ }
323
+ rtc_gpio_init (io_num );
324
+ rtc_gpio_iomux_func_sel (io_num , upin -> iomux_func );
325
+ }
326
+ #endif
327
+ return true;
328
+ }
329
+
330
+ static esp_err_t _uartInternalSetPin (uart_port_t uart_num , int tx_io_num , int rx_io_num , int rts_io_num , int cts_io_num ) {
331
+ // Since an IO cannot route peripheral signals via IOMUX and GPIO matrix at the same time,
332
+ // if tx and rx share the same IO, both signals need to be routed to IOs through GPIO matrix
333
+ bool tx_rx_same_io = (tx_io_num == rx_io_num );
334
+
335
+ // In the following statements, if the io_num is negative, no need to configure anything.
336
+ if (tx_io_num >= 0 ) {
337
+ #if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND || CONFIG_PM_SLP_DISABLE_GPIO
338
+ // In such case, IOs are going to switch to sleep configuration (isolate) when entering sleep for power saving reason
339
+ // But TX IO in isolate state could write garbled data to the other end
340
+ // Therefore, we should disable the switch of the TX pin to sleep configuration
341
+ gpio_sleep_sel_dis (tx_io_num );
342
+ #endif
343
+ if (tx_rx_same_io || !_uartTrySetIomuxPin (uart_num , tx_io_num , SOC_UART_TX_PIN_IDX )) {
344
+ if (uart_num < SOC_UART_HP_NUM ) {
345
+ gpio_func_sel (tx_io_num , PIN_FUNC_GPIO );
346
+ esp_rom_gpio_connect_out_signal (tx_io_num , UART_PERIPH_SIGNAL (uart_num , SOC_UART_TX_PIN_IDX ), 0 , 0 );
347
+ // output enable is set inside esp_rom_gpio_connect_out_signal func after the signal is connected
348
+ // (output enabled too early may cause unnecessary level change at the pad)
349
+ }
350
+ #if SOC_LP_GPIO_MATRIX_SUPPORTED
351
+ else {
352
+ rtc_gpio_init (tx_io_num ); // set as a LP_GPIO pin
353
+ lp_gpio_connect_out_signal (tx_io_num , UART_PERIPH_SIGNAL (uart_num , SOC_UART_TX_PIN_IDX ), 0 , 0 );
354
+ // output enable is set inside lp_gpio_connect_out_signal func after the signal is connected
355
+ }
356
+ #endif
357
+ }
358
+ }
359
+
360
+ if (rx_io_num >= 0 ) {
361
+ #if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND || CONFIG_PM_SLP_DISABLE_GPIO
362
+ // In such case, IOs are going to switch to sleep configuration (isolate) when entering sleep for power saving reason
363
+ // But RX IO in isolate state could receive garbled data into FIFO, which is not desired
364
+ // Therefore, we should disable the switch of the RX pin to sleep configuration
365
+ gpio_sleep_sel_dis (rx_io_num );
366
+ #endif
367
+ if (tx_rx_same_io || !_uartTrySetIomuxPin (uart_num , rx_io_num , SOC_UART_RX_PIN_IDX )) {
368
+ if (uart_num < SOC_UART_HP_NUM ) {
369
+ gpio_input_enable (rx_io_num );
370
+ esp_rom_gpio_connect_in_signal (rx_io_num , UART_PERIPH_SIGNAL (uart_num , SOC_UART_RX_PIN_IDX ), 0 );
371
+ }
372
+ #if SOC_LP_GPIO_MATRIX_SUPPORTED
373
+ else {
374
+ rtc_gpio_mode_t mode = (tx_rx_same_io ? RTC_GPIO_MODE_INPUT_OUTPUT : RTC_GPIO_MODE_INPUT_ONLY );
375
+ rtc_gpio_set_direction (rx_io_num , mode );
376
+ if (!tx_rx_same_io ) { // set the same pin again as a LP_GPIO will overwrite connected out_signal, not desired, so skip
377
+ rtc_gpio_init (rx_io_num ); // set as a LP_GPIO pin
378
+ }
379
+ lp_gpio_connect_in_signal (rx_io_num , UART_PERIPH_SIGNAL (uart_num , SOC_UART_RX_PIN_IDX ), 0 );
380
+ }
381
+ #endif
382
+ }
383
+ }
384
+
385
+ if (rts_io_num >= 0 && !_uartTrySetIomuxPin (uart_num , rts_io_num , SOC_UART_RTS_PIN_IDX )) {
386
+ if (uart_num < SOC_UART_HP_NUM ) {
387
+ gpio_func_sel (rts_io_num , PIN_FUNC_GPIO );
388
+ esp_rom_gpio_connect_out_signal (rts_io_num , UART_PERIPH_SIGNAL (uart_num , SOC_UART_RTS_PIN_IDX ), 0 , 0 );
389
+ // output enable is set inside esp_rom_gpio_connect_out_signal func after the signal is connected
390
+ }
391
+ #if SOC_LP_GPIO_MATRIX_SUPPORTED
392
+ else {
393
+ rtc_gpio_init (rts_io_num ); // set as a LP_GPIO pin
394
+ lp_gpio_connect_out_signal (rts_io_num , UART_PERIPH_SIGNAL (uart_num , SOC_UART_RTS_PIN_IDX ), 0 , 0 );
395
+ // output enable is set inside lp_gpio_connect_out_signal func after the signal is connected
396
+ }
397
+ #endif
398
+ }
399
+
400
+ if (cts_io_num >= 0 && !_uartTrySetIomuxPin (uart_num , cts_io_num , SOC_UART_CTS_PIN_IDX )) {
401
+ if (uart_num < SOC_UART_HP_NUM ) {
402
+ gpio_pullup_en (cts_io_num );
403
+ gpio_input_enable (cts_io_num );
404
+ esp_rom_gpio_connect_in_signal (cts_io_num , UART_PERIPH_SIGNAL (uart_num , SOC_UART_CTS_PIN_IDX ), 0 );
405
+ }
406
+ #if SOC_LP_GPIO_MATRIX_SUPPORTED
407
+ else {
408
+ rtc_gpio_set_direction (cts_io_num , RTC_GPIO_MODE_INPUT_ONLY );
409
+ rtc_gpio_init (cts_io_num ); // set as a LP_GPIO pin
410
+ lp_gpio_connect_in_signal (cts_io_num , UART_PERIPH_SIGNAL (uart_num , SOC_UART_CTS_PIN_IDX ), 0 );
411
+ }
412
+ #endif
413
+ }
414
+ return ESP_OK ;
415
+ }
416
+
298
417
// Attach function for UART
299
418
// connects the IO Pad, set Paripheral Manager and internal UART structure data
300
419
static bool _uartAttachPins (uint8_t uart_num , int8_t rxPin , int8_t txPin , int8_t ctsPin , int8_t rtsPin ) {
@@ -307,7 +426,7 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t
307
426
//log_v("attaching UART%d pins: prev,new RX(%d,%d) TX(%d,%d) CTS(%d,%d) RTS(%d,%d)", uart_num,
308
427
// uart->_rxPin, rxPin, uart->_txPin, txPin, uart->_ctsPin, ctsPin, uart->_rtsPin, rtsPin); vTaskDelay(10);
309
428
310
- // IDF uart_set_pin () checks if the pin is used within LP UART and if it is a valid RTC IO pin
429
+ // IDF _uartInternalSetPin () checks if the pin is used within LP UART and if it is a valid RTC IO pin
311
430
// No need for Arduino Layer to check it again
312
431
bool retCode = true;
313
432
if (rxPin >= 0 ) {
@@ -316,7 +435,7 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t
316
435
perimanClearPinBus (rxPin );
317
436
}
318
437
// connect RX Pad
319
- bool ret = ESP_OK == uart_set_pin (uart -> num , UART_PIN_NO_CHANGE , rxPin , UART_PIN_NO_CHANGE , UART_PIN_NO_CHANGE );
438
+ bool ret = ESP_OK == _uartInternalSetPin (uart -> num , UART_PIN_NO_CHANGE , rxPin , UART_PIN_NO_CHANGE , UART_PIN_NO_CHANGE );
320
439
#if SOC_UART_LP_NUM >= 1
321
440
if (ret && uart_num >= SOC_UART_HP_NUM ) { // it is a LP UART NUM
322
441
ret &= lp_uart_config_io (uart -> num , rxPin , RTC_GPIO_MODE_INPUT_ONLY , SOC_UART_RX_PIN_IDX );
@@ -339,7 +458,7 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t
339
458
perimanClearPinBus (txPin );
340
459
}
341
460
// connect TX Pad
342
- bool ret = ESP_OK == uart_set_pin (uart -> num , txPin , UART_PIN_NO_CHANGE , UART_PIN_NO_CHANGE , UART_PIN_NO_CHANGE );
461
+ bool ret = ESP_OK == _uartInternalSetPin (uart -> num , txPin , UART_PIN_NO_CHANGE , UART_PIN_NO_CHANGE , UART_PIN_NO_CHANGE );
343
462
#if SOC_UART_LP_NUM >= 1
344
463
if (ret && uart_num >= SOC_UART_HP_NUM ) { // it is a LP UART NUM
345
464
ret &= lp_uart_config_io (uart -> num , txPin , RTC_GPIO_MODE_OUTPUT_ONLY , SOC_UART_TX_PIN_IDX );
@@ -362,7 +481,7 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t
362
481
perimanClearPinBus (ctsPin );
363
482
}
364
483
// connect CTS Pad
365
- bool ret = ESP_OK == uart_set_pin (uart -> num , UART_PIN_NO_CHANGE , UART_PIN_NO_CHANGE , UART_PIN_NO_CHANGE , ctsPin );
484
+ bool ret = ESP_OK == _uartInternalSetPin (uart -> num , UART_PIN_NO_CHANGE , UART_PIN_NO_CHANGE , UART_PIN_NO_CHANGE , ctsPin );
366
485
#if SOC_UART_LP_NUM >= 1
367
486
if (ret && uart_num >= SOC_UART_HP_NUM ) { // it is a LP UART NUM
368
487
ret &= lp_uart_config_io (uart -> num , ctsPin , RTC_GPIO_MODE_INPUT_ONLY , SOC_UART_CTS_PIN_IDX );
@@ -385,7 +504,7 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t
385
504
perimanClearPinBus (rtsPin );
386
505
}
387
506
// connect RTS Pad
388
- bool ret = ESP_OK == uart_set_pin (uart -> num , UART_PIN_NO_CHANGE , UART_PIN_NO_CHANGE , rtsPin , UART_PIN_NO_CHANGE );
507
+ bool ret = ESP_OK == _uartInternalSetPin (uart -> num , UART_PIN_NO_CHANGE , UART_PIN_NO_CHANGE , rtsPin , UART_PIN_NO_CHANGE );
389
508
#if SOC_UART_LP_NUM >= 1
390
509
if (ret && uart_num >= SOC_UART_HP_NUM ) { // it is a LP UART NUM
391
510
ret &= lp_uart_config_io (uart -> num , rtsPin , RTC_GPIO_MODE_OUTPUT_ONLY , SOC_UART_RTS_PIN_IDX );
@@ -1398,11 +1517,13 @@ void uart_internal_loopback(uint8_t uartNum, int8_t rxPin) {
1398
1517
log_e ("UART%d is not supported for loopback or RX pin %d is invalid." , uartNum , rxPin );
1399
1518
return ;
1400
1519
}
1520
+ #if 0 // leave this code here for future reference and need
1401
1521
// forces rxPin to use GPIO Matrix and setup the pin to receive UART TX Signal - IDF 5.4.1 Change with uart_release_pin()
1402
1522
gpio_func_sel ((gpio_num_t )rxPin , PIN_FUNC_GPIO );
1403
1523
gpio_pullup_en ((gpio_num_t )rxPin );
1404
1524
gpio_input_enable ((gpio_num_t )rxPin );
1405
1525
esp_rom_gpio_connect_in_signal (rxPin , uart_periph_signal [uartNum ].pins [SOC_UART_RX_PIN_IDX ].signal , false);
1526
+ #endif
1406
1527
esp_rom_gpio_connect_out_signal (rxPin , uart_periph_signal [uartNum ].pins [SOC_UART_TX_PIN_IDX ].signal , false, false);
1407
1528
}
1408
1529
0 commit comments