Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

uart_set_pin() with the same pin for both RX and TX doesn't work! (IDFGH-13954) #14787

Closed
3 tasks done
arduino12 opened this issue Oct 25, 2024 · 1 comment
Closed
3 tasks done
Assignees
Labels
Resolution: NA Issue resolution is unavailable Status: Done Issue is done internally Type: Bug bugs in IDF

Comments

@arduino12
Copy link

Answers checklist.

  • I have read the documentation ESP-IDF Programming Guide and the issue is not addressed there.
  • I have updated my IDF branch (master or release) to the latest version and checked that the issue is present there.
  • I have searched the issue tracker for a similar issue and not found a similar issue.

IDF version.

v5.3.0

Espressif SoC revision.

ESP32-C3 (revision v0.4)

Operating System used.

Windows

How did you build your project?

VS Code IDE

If you are using Windows, please specify command line type.

PowerShell

Development Kit.

ESP32 C3 Super Mini

Power Supply used.

USB

What is the expected behavior?

Full code demo:

#include "freertos/FreeRTOS.h"
#include "driver/uart.h"
#include "soc/uart_periph.h"
#include "driver/gpio.h"
#include "esp_log.h"


#define BYPASS              (0) // don't use `uart_set_pin`
#define WORKAROUND          (1) // add workaround after calling `uart_set_pin`
#define UART_TX_RX_PIN      (0) // GPIO used for both TX and RX lines - can hook to logic analyzer / USB-UART
#define UART_PORT_NUM       (1)
#define UART_BAUD_RATE      (1000000)
#define UART_BUF_SIZE       (1024)

static const char *TAG = "UART TEST";

void app_main()
{
    uart_config_t uart_config = {
        .baud_rate = UART_BAUD_RATE,
        .data_bits = UART_DATA_8_BITS,
        .parity    = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_DEFAULT,
    };

    ESP_ERROR_CHECK(uart_driver_install(UART_PORT_NUM, UART_BUF_SIZE, 0, 0, NULL, 0));
    ESP_ERROR_CHECK(uart_param_config(UART_PORT_NUM, &uart_config));

#if BYPASS
    ESP_ERROR_CHECK(gpio_set_pull_mode(UART_TX_RX_PIN, GPIO_PULLUP_ONLY));
    ESP_ERROR_CHECK(gpio_set_direction(UART_TX_RX_PIN, GPIO_MODE_INPUT_OUTPUT_OD));
    esp_rom_gpio_connect_out_signal(UART_TX_RX_PIN, UART_PERIPH_SIGNAL(UART_PORT_NUM, SOC_UART_TX_PIN_IDX), 0, 0);
    esp_rom_gpio_connect_in_signal(UART_TX_RX_PIN, UART_PERIPH_SIGNAL(UART_PORT_NUM, SOC_UART_RX_PIN_IDX), 0);
#else
    ESP_ERROR_CHECK(uart_set_pin(UART_PORT_NUM, UART_TX_RX_PIN, UART_TX_RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
#if WORKAROUND
    esp_rom_gpio_connect_out_signal(UART_TX_RX_PIN, UART_PERIPH_SIGNAL(UART_PORT_NUM, SOC_UART_TX_PIN_IDX), 0, 0);
#endif
#endif

    const char *TX_BUFF = "Test";
    char *rx_buff = (char *)malloc(UART_BUF_SIZE);

    while (1) {
        uart_write_bytes(UART_PORT_NUM, TX_BUFF, sizeof(TX_BUFF));
        int len = uart_read_bytes(UART_PORT_NUM, rx_buff, (UART_BUF_SIZE - 1), 20 / portTICK_PERIOD_MS);
        if (len) {
            rx_buff[len] = '\0';
            ESP_LOGI(TAG, "Echo: %s", rx_buff);
        }
        else {
            ESP_LOGW(TAG, "No echo");
        }
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

I expected:

uart_set_pin(UART_PORT_NUM, UART_TX_RX_PIN, UART_TX_RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE)

to work- but is seems to overwrite the TX output configuration and only the RX pin is configured correctly.

My workaround is to re-write the TX output configuration after the uart_set_pin(..) :

esp_rom_gpio_connect_out_signal(UART_TX_RX_PIN, UART_PERIPH_SIGNAL(UART_PORT_NUM, SOC_UART_TX_PIN_IDX), 0, 0);

I think the uart_set_pin(..) needs to support this case of a single pin for both TX and RX-
(maybe test if rx_pin == tx_pin and if so- apply my workaround?)
I use it to control some single line smart servo motors with open-drain UART bus...

The ESP32 support this common UART configuration (like RS485),
it also support echo-cancellation (may also be nice to have this functionality..)

What is the actual behavior?

When:

#define BYPASS              (0) // don't use `uart_set_pin`
#define WORKAROUND          (0) // add workaround after calling `uart_set_pin`

I get:
W UART TEST: No echo - Bad!

When:

#define BYPASS              (0) // don't use `uart_set_pin`
#define WORKAROUND          (1) // add workaround after calling `uart_set_pin`

or

#define BYPASS              (1) // don't use `uart_set_pin`

I get:
I UART TEST: Echo: Test - Good!

Steps to reproduce.

Compile and run the demo code I made with and without the WORKAROUND..

Debug Logs.

No response

More Information.

No response

@arduino12 arduino12 added the Type: Bug bugs in IDF label Oct 25, 2024
@arduino12
Copy link
Author

I encountered this bug with MicroPython and opened an issue:
micropython/micropython#16079
(Tested on ESP32-S2, S3, C3)

I finally got here realizing the bug is in uart_set_pin(..)

@github-actions github-actions bot changed the title uart_set_pin() with the same pin for both RX and TX doesn't work! uart_set_pin() with the same pin for both RX and TX doesn't work! (IDFGH-13954) Oct 25, 2024
@espressif-bot espressif-bot added the Status: Opened Issue is new label Oct 25, 2024
@espressif-bot espressif-bot added Status: In Progress Work is in progress and removed Status: Opened Issue is new labels Nov 6, 2024
@espressif-bot espressif-bot added Status: Done Issue is done internally Resolution: NA Issue resolution is unavailable and removed Status: In Progress Work is in progress labels Nov 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Resolution: NA Issue resolution is unavailable Status: Done Issue is done internally Type: Bug bugs in IDF
Projects
None yet
Development

No branches or pull requests

3 participants