@@ -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