libretiny icon indicating copy to clipboard operation
libretiny copied to clipboard

Arduino Ring Buffer is not suitable for serial interface

Open hn opened this issue 2 years ago • 3 comments

Libretiny uses the Arduino Ring Buffer for serial port i/o. However, the implementation is not interrupt-safe and there are no plans to change this.

This causes hard to debug problems with serial i/o. One pain point is that the Arduino Ring buffer is very error prone when used in such a situation (it uses a redundant way to store its state). And if it breaks, it will never be good again (no self-healing). You have to (in most cases) reboot the device or restart the component in question.

As far as I can (quickly) see the ESP8266 and ESP32 serial port components do not use the Arduino Ring Buffer, but implement some own 'magic' for the buffer.

I suggest replacing the Arduino Ring Buffer within the serial component with a better option (at least it should not break permanently).

hn avatar Aug 11 '23 09:08 hn

Please consider the work of @KurtE for a possible solution: https://github.com/hn/ginlong-solis/issues/4#issuecomment-1673194618 and https://github.com/hn/ginlong-solis/issues/4#issuecomment-1674801822

I'm using https://github.com/hn/ginlong-solis/commit/76d81ce4d0418884d14362b2f8980c9652d40ebd as a temporary workaround.

hn avatar Aug 12 '23 11:08 hn

It seems that using the SafeRingBuffer would be a viable option, since it's only a small wrapper around the RingBuffer from Arduino API. On that note, it's pretty disappointing that the API is so much different from most actual official Arduino cores (even things like Serial.printf(), which makes Arduino devs very angry when mentioned).

If the wrapper adds too much overhead by using the synchronized blocks, it could be rewritten to use FreeRTOS' mutexes or semaphores instead.

kuba2k2 avatar Aug 12 '23 18:08 kuba2k2

If I understand correctly, ESP32 uses this:

#define UART_MUTEX_LOCK()    do {} while (xSemaphoreTake(uart->lock, portMAX_DELAY) != pdPASS)
#define UART_MUTEX_UNLOCK()  xSemaphoreGive(uart->lock)

hn avatar Aug 20 '23 10:08 hn

Hi,

Any update on this issue? I'm dealing with a ESPHome component relying on UART for RTL8710BN and fails occur very frequently... Increasing buffer size or patching ArduinoCoreAPI using @hn forks didn't solve the issue.

I read ModBus issue which is marked solved but I didn't find any solution there.

clsergent avatar Jul 14 '25 15:07 clsergent

@clsergent Well, at the time I wrote the patches it definitely fixed the problem (for me).

By coincidence, I upgraded my Solis S3 stick last week and I encountered a serial error two days ago (just one time, can't say if it is a real problem or just a glitch in the matrix).

Maybe you try the RingBufferSelfHeal branch of the ArduinoCore-API, which uses a slightly different approach.

hn avatar Jul 14 '25 21:07 hn

Hello @hn, Thank you for replying so quickly. I tried a new firmware with your RingBufferFix and an increased buffer size (1024, seems huge but it seemed a desperate case at the moment). I found in the meanwhile that the RTL8710 may have OTA instability issues, so I'm not so sure that my issues were caused by UART only... Anyway, 15 hours later and no crash, so I may be good.

My initial question still remain for the maintainers of this repository: a fix is it planned for the ring buffer issue?

Edit: I also reduced time devoted to uart operations in my scheduler, maybe it helped avoiding overflows.

clsergent avatar Jul 15 '25 16:07 clsergent