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

poll() cannot be used to check if data can be written without blocking to a UART file descriptor (IDFGH-9640) #10986

Closed
3 tasks done
AguileraG opened this issue Mar 14, 2023 · 2 comments
Assignees
Labels
Resolution: NA Issue resolution is unavailable Status: Done Issue is done internally Type: Bug bugs in IDF

Comments

@AguileraG
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.0

Operating System used.

Linux

How did you build your project?

Command line with CMake

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

None

Development Kit.

ESP32-S3-DevKitC-1 v1.0

Power Supply used.

USB

What is the expected behavior?

The function poll() is used to check if read/write file operations can be performed without blocking. The virtual filesystem component allows accessing the UART port though file operations, therefore poll() should be able to tell if writing to stdout (or any other file descriptor that points to a UART) would block.

What is the actual behavior?

The function poll() does not work properly with UART file descriptors, as it is not able to check if an UART file is writeable using the event POLLOUT. This issue affects both the standard file descriptors (stdout, stderr) as well as other files opened with the standard function open().

Steps to reproduce.

  1. Call the functions uart_driver_install() and uart_param_config() to configure the UART 0, then call esp_vfs_dev_uart_use_driver() to register this driver.
  2. Get the stdout file descriptor using fileno().
  3. Call poll() with the stdout file descriptor and the event POLLOUT to check if data can be written without blocking.

This behaviour can be reproduced with the following example:

#include <stdio.h>
#include "driver/uart.h"
#include "esp_vfs_dev.h"
#include "esp_log.h"
#include <errno.h>
#include <sys/poll.h>

static const int uart_port = 0;
static const char tag[] = "example";

void app_main(void)
{
    int res = uart_driver_install(uart_port, 8 * SOC_UART_FIFO_LEN,
                                  8 * SOC_UART_FIFO_LEN, 0, NULL, 0);
    ESP_LOGI(tag, "uart_driver_install: %d", res);

    esp_vfs_dev_uart_use_driver(uart_port);

    const uart_config_t config = {
        .baud_rate = 115200,
        .data_bits = UART_DATA_8_BITS,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .parity = UART_PARITY_DISABLE,
        .rx_flow_ctrl_thresh = 0.75 * SOC_UART_FIFO_LEN,
        .source_clk = UART_SCLK_APB,
        .stop_bits = UART_STOP_BITS_1,
    };

    res = uart_param_config(uart_port, &config);
    ESP_LOGI(tag, "uart_param_config: %d", res);

    const int fid = fileno(stdout);
    ESP_LOGI(tag, "stdout fid: %d", fid);

    struct pollfd poll_fd = {
        .fd = fid,
        .events = POLLOUT,
        .revents = 0,
    };

    res = poll(&poll_fd, 1, 1000);

    if ((res > 0) && ((poll_fd.revents & POLLOUT) == POLLOUT))
    {
        ESP_LOGI(tag, "stdout is writeable");
    }
    else if (res < 0)
    {
        ESP_LOGI(tag, "poll error: %d, %d", res, errno);
    }
    else
    {
        ESP_LOGI(tag, "stdout is not writeable: %d", res);
    }
}

Debug Logs.

ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce3810,len:0x165c
load:0x403c9700,len:0xbe0
load:0x403cc700,len:0x2ef8
entry 0x403c9900
I (25) boot: ESP-IDF v5.0.1-320-ge14c47ee44-dirty 2nd stage bootloader
I (25) boot: compile time 16:35:14
I (25) boot: chip revision: v0.1
I (28) boot.esp32s3: Boot SPI Speed : 80MHz
I (33) boot.esp32s3: SPI Mode       : DIO
I (38) boot.esp32s3: SPI Flash Size : 2MB
I (43) boot: Enabling RNG early entropy source...
I (48) boot: Partition Table:
I (52) boot: ## Label            Usage          Type ST Offset   Length
I (59) boot:  0 nvs              WiFi data        01 02 00009000 00006000
I (66) boot:  1 phy_init         RF data          01 01 0000f000 00001000
I (74) boot:  2 factory          factory app      00 00 00010000 00100000
I (81) boot: End of partition table
I (86) esp_image: segment 0: paddr=00010020 vaddr=3c020020 size=09a2ch ( 39468) map
I (101) esp_image: segment 1: paddr=00019a54 vaddr=3fc92000 size=02328h (  9000) load
I (104) esp_image: segment 2: paddr=0001bd84 vaddr=40374000 size=04294h ( 17044) load
I (115) esp_image: segment 3: paddr=00020020 vaddr=42000020 size=1bbe4h (113636) map
I (140) esp_image: segment 4: paddr=0003bc0c vaddr=40378294 size=09cf4h ( 40180) load
I (155) boot: Loaded app from partition at offset 0x10000
I (155) boot: Disabling RNG early entropy source...
I (166) cpu_start: Pro cpu up.
I (166) cpu_start: Starting app cpu, entry point is 0x40375260
I (0) cpu_start: App cpu up.
I (181) cpu_start: Pro cpu start user code
I (181) cpu_start: cpu freq: 160000000 Hz
I (181) cpu_start: Application information:
I (184) cpu_start: Project name:     main
I (189) cpu_start: App version:      v5.0.1-320-ge14c47ee44-dirty
I (195) cpu_start: Compile time:     Mar 14 2023 16:34:52
I (201) cpu_start: ELF file SHA256:  7f0b744445053d38...
I (207) cpu_start: ESP-IDF:          v5.0.1-320-ge14c47ee44-dirty
I (214) cpu_start: Min chip rev:     v0.0
I (219) cpu_start: Max chip rev:     v0.99 
I (224) cpu_start: Chip rev:         v0.1
I (228) heap_init: Initializing. RAM available for dynamic allocation:
I (236) heap_init: At 3FC94D58 len 000549B8 (338 KiB): DRAM
I (242) heap_init: At 3FCE9710 len 00005724 (21 KiB): STACK/DRAM
I (249) heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM
I (255) heap_init: At 600FE010 len 00001FF0 (7 KiB): RTCRAM
I (262) spi_flash: detected chip: generic
I (266) spi_flash: flash io: dio
W (270) spi_flash: Detected size(8192k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
I (283) cpu_start: Starting scheduler on�%�I (304) example: uart_param_config: 0
I (304) example: stdout fid: 1
I (1314) example: stdout is not writeable: 0

More Information.

No response

@AguileraG AguileraG added the Type: Bug bugs in IDF label Mar 14, 2023
@espressif-bot espressif-bot added the Status: Opened Issue is new label Mar 14, 2023
@github-actions github-actions bot changed the title poll() cannot be used to check if data can be written without blocking to a UART file descriptor poll() cannot be used to check if data can be written without blocking to a UART file descriptor (IDFGH-9640) Mar 14, 2023
@chipweinberger
Copy link
Contributor

chipweinberger commented Mar 14, 2023

another poll issue: #9964

@4e4o
Copy link

4e4o commented Apr 18, 2023

Also select() should return when data can be written to uart. I am using asio, async_read works fine, but async_write hangs forever.

@espressif-bot espressif-bot added Status: Selected for Development Issue is selected for development Status: In Progress Work is in progress and removed Status: Opened Issue is new Status: Selected for Development Issue is selected for development labels May 16, 2023
@espressif-bot espressif-bot added Status: Reviewing Issue is being reviewed and removed Status: In Progress Work is in progress labels Jun 12, 2023
@espressif-bot espressif-bot added Status: Done Issue is done internally Resolution: NA Issue resolution is unavailable and removed Status: Reviewing Issue is being reviewed labels Jul 13, 2023
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

5 participants