Skip to content

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

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

Closed
dibalavs opened this issue Jul 28, 2021 · 7 comments · Fixed by #6134
Closed

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

dibalavs opened this issue Jul 28, 2021 · 7 comments · Fixed by #6134
Assignees

Comments

@dibalavs
Copy link

dibalavs commented Jul 28, 2021

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);
	}
}
@dibalavs
Copy link
Author

dibalavs commented Jul 28, 2021

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
Copy link
Contributor

bertmelis commented Jul 28, 2021

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
Copy link
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
Copy link
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
Copy link
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

@SuGlider SuGlider self-assigned this Aug 25, 2021
@VojtechBartoska VojtechBartoska added the Resolution: Awaiting response Waiting for response of author label Nov 18, 2021
@VojtechBartoska
Copy link
Contributor

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

@VojtechBartoska VojtechBartoska added Resolution: Expired More info wasn't provided and removed Resolution: Awaiting response Waiting for response of author labels Dec 14, 2021
@SuGlider
Copy link
Collaborator

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

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

@SuGlider SuGlider reopened this Jan 12, 2022
@SuGlider SuGlider added Status: In Progress ⚠️ Issue is in progress and removed Resolution: Expired More info wasn't provided labels Jan 12, 2022
@VojtechBartoska VojtechBartoska removed the Status: In Progress ⚠️ Issue is in progress label Jan 24, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants