-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Changes UART ISR to only trigger on RX FIFO Full and timeout #6930
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
Conversation
@SuGlider Do you have any sketch to easily demonstrate the PR? :) |
Added an example in PR text. Thanks. |
@gonzabrusco - Please note the observation above, in the PR description. |
Thanks for the heads up @SuGlider After reviewing the changes I see that not much has changed in the way everything works. The main changes are:
If I use onReceive(callbackFunc, true) I will be called only on Timeout and with a timeout of 2 characters. As it was on 2.0.4 right? It seems this change allows a user to change the fifo full interrupt threshold and have a better reception control, particularly if the expected byte quantity is known (eg. you except always a fixed message of 30 bytes from another device). If not (like my use case with modbus) the timeout is still needed and the fifo full interrupt is not relevant because you can't predict the sizes of the messages on the RS485 bus. But nevertheless I like the change because it offers more control which is always nice to have 😀 I will try it and let you know if everything is working |
Yes, IDF default is 120 bytes.
Yes, exactly. You can still change the timeout using
That's the target. To improve user control over UART. |
@gonzabrusco - some more new changes... talking to my colleague @P-R-O-C-H-Y, he tested the second sketch I posted, sending 2049 bytes, using the Serial Monitor and he asked me why the callback was never called and he had the impression that the Serial port was frozen as well, because it was not working anymore. In this case, this happens because the Serial port gets its Buffer FULL and then later, FIFO Full as well. User callback is never called, but instead it calls the It made me think that for most users, it is important that the regular User Call back with Data is also called in order to "consume" the incoming data, even when there is an error. The Error Callback gets called first, letting the Application to signal the error to the User Callback or even treat the data there. This was done in my last commit. Please let me know your thought about it. |
LGTM @SuGlider @P-R-O-C-H-Y In my current project I treat the data on the error callback so I won't be called again. But I think it's a nice addition for most users. |
cores/esp32/HardwareSerial.h
Outdated
@@ -61,7 +61,8 @@ typedef enum { | |||
UART_BUFFER_FULL_ERROR, | |||
UART_FIFO_OVF_ERROR, | |||
UART_FRAME_ERROR, | |||
UART_PARITY_ERROR | |||
UART_PARITY_ERROR, | |||
UART_NO_ERROR |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that having UART_NO_ERROR
be the first item in the enum makes most sense. It will equal to 0, which conforms to most/all error uses in C/C++ (and ESP-IDF)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
LGTM apart from one small comment :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, tested on ESP32
Set NO_ERROR as first error code, same as ESP_OK = 0
Description of Change
This PR tries to make Arduino HardwareSerial be configurable the way the application needs it to work by fine tunning its RX Interrupt parameters.
It also forces UART RX ISR to only trigger on RX Timout and FIFO Full, ignoring errors such as BREAK, Parity or Overflow.If the user wants each single arriving byte to be immediately inserted in the RxBuffer and made available right away, the sketch can use
void setRxFIFOFull(uint8_t fifoBytes)
setting it to 1 byte. It will consume more CPU time, but it wil trigger the transfer from RX FIFO to Arduino Buffer on a single byte level.Receiving a single byte will depend on the Serial port baud rate. It is easier to see that using slower baud rates, such as 9600.
Another importante change is that by default
onReceive()
callback will be called when FIFO is full (by default on receiving 120 bytes or when Rx Timeout on about 2 symbols in the current baudrate).In order to only get called when all data is received at the end of a transmission, it is necessary to explicity use
true
inonReceive(cbFunc, bool)
and set an adequate buffer size in order to get all data at once, usingsetRxBufferSize()
beforebegin()
.Tests scenarios
It was tested using ESP32 with this sketch:
This sketch forces Arduino Serial to make data available every 5 bytes received
This sketch demonstrates how to set a call back only whenever all data is received by Serial
Related links