Skip to content

HardwareSerial: No way to wait for data in queue. #5472

Closed
@dibalavs

Description

@dibalavs

Hardware:

Board: ESP32
Core Installation version: framework-arduinoespressif32 3.10006.210326 (1.0.6)
IDE name: Platform.io
Flash Frequency: 40Mhz
PSRAM enabled: no
Upload Speed: 115200
Computer OS: Windows 10

Description:

I have worker task, which should sleep while no incoming data on uart and wake on data and process it.
I found that HardwareSerial::available() and HardwareSerial::read()
are non-blocking. So i have busyloop in task which is not good for CPU resource optimization.

Sketch:

#include <Arduino.h>
#include <HardwareSerial.h>

void *uart_task(void *arg)
{
	size_t read;
	for (;;) {
		wait_for_data(&Serial2); // <- How to do this????

		if (!Serial2.available()) // This is non-blocking.
			continue;

		read = Serial2.read(buff, sizeof(buff)); // Also non-blocking.
		process_data(buff, read);
	}
}

Activity

dibalavs

dibalavs commented on Jul 28, 2021

@dibalavs
Author

Some additionals:

I mean sleep on some sync primitive like mutex or semaphore.
I know that Stream has timedRead() function:

int Stream::timedRead()
{
    int c;
    _startMillis = millis();
    do {
        c = read();
        if(c >= 0) {
            return c;
        }
    } while(millis() - _startMillis < _timeout);
    return -1;     // -1 indicates timeout
}

But it is not I want.

bertmelis

bertmelis commented on Jul 28, 2021

@bertmelis
Contributor

Why don't you do

size_t readBlocking(HardwareSerial* serial) {
  while (!serial->available()) {
    delay();
  }
  return serial->available();
}

delay() uses vTaskDelay under the hood so during the wait your task is using minimal resources. In the Arduino framework there is no other way besides polling.

dibalavs

dibalavs commented on Jul 29, 2021

@dibalavs
Author

@bertmelis , actually this is not solution. This is dirty hack.

If delay() will very short, It will just usual busy loop.
if delay() will long, it will have slow response to available data in uart buffer, so you can lost data on overflow while is sleeping on delay()

just curious, esp32-hal-uart.c which is used as back-end for HardwareSerial is using xQueueReceive() for reading from uart buffer, which CAN sleep while no data, but this queue is used in non-blocking mode.

I think it couldn't be a problem to do sleeping on no-data.

bertmelis

bertmelis commented on Jul 29, 2021

@bertmelis
Contributor

Yes it will be a problem because it will be a MAJOR breaking change.

It might not be a problem for you but it will for numerous other users, including me.

If the suggested solution doesn't work for you, you might want to switch to ESP-IDF or a completely different platform.

Besides, what do you think the processor is doing when there is nothing specific to be done?
Do you actually have a problem with timing or are you chasing nonexisting problems?

SuGlider

SuGlider commented on Aug 17, 2021

@SuGlider
Collaborator

Would the Arduino serialEvent be a solution?
https://www.arduino.cc/reference/en/language/functions/communication/serial/serialevent/

It's not blocking, but it is called only when there is some data to be read on Serial Port. It could trigger some action or task.
It checks for data right after executing loop(). Thus if loop() takes too long, serialEvent won't be frequently verified.

serialEvent is implemented in the PR #5549

self-assigned this
on Aug 25, 2021
VojtechBartoska

VojtechBartoska commented on Nov 18, 2021

@VojtechBartoska
Contributor

@dibalavs Any updates or can I consider this as solved?

SuGlider

SuGlider commented on Jan 12, 2022

@SuGlider
Collaborator

A potential solution is being implemented.
It's the Serial.onReceive(function)

As soon as any data arrives UART RX, function() will called.

3 remaining items

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

    HardwareSerial: No way to wait for data in queue. · Issue #5472 · espressif/arduino-esp32