Description
Describe the bug
I'm using Sparkfun's SARA-R5 library - an LTE modem using UART connection.
The init sequence includes autobaud selection - it cycles through different UART baudrates and reinitiailizes the UART like this (original code here):
void SARA_R5::beginSerial(unsigned long baud)
{
delay(100);
if (_hardSerial != nullptr)
{
_hardSerial->end();
_hardSerial->begin(baud);
}
...
delay(100);
}
Then it sends ATE0
and waits for OK
response on selected baudrate - classic stuff.
The problem comes up when HardwareSerial
has hw flow control enabled and there's no device attached (i.e. CTS not asserted). The end()
function gets stuck forever because of flush()
waiting for the ringbuffer to become empty (line 499).
Arduino_Core_STM32/cores/arduino/HardwareSerial.cpp
Lines 490 to 504 in 0c69f37
But because hw flow control enabled and CTS not asserted (i.e. SARA-R5 not connected) the bytes pending in the ringbuffer never get transmitted (remember it tries to send ATE0
) so the whole while loop just hangs forever.
I've made a "dirty" fix that removes the problem in this specific case - if CTS is enabled and no CTS asserted (UART CTS flag is not set) then simply reset ringbuffer:
void HardwareSerial::flush()
{
// If we have never written a byte, no need to flush. This special
// case is needed since there is no way to force the TXC (transmit
// complete) bit to 1 during initialization
if (!_written) {
return;
}
// If we have CTS flow control enabled and CTS is not asserted, no need to flush - just reset tx buffer.
if (_serial.pin_cts != NC && !__HAL_UART_GET_FLAG(&_serial.handle, UART_FLAG_CTS)) {
_serial.tx_head = 0;
_serial.tx_tail = 0;
return;
}
while ((_serial.tx_head != _serial.tx_tail)) {
// nop, the interrupt handler will free up space for us
}
// If we get here, nothing is queued anymore (DRIE is disabled) and
// the hardware finished transmission (TXC is set).
}
But this generally opens a broader issue some of HardwareSerial
code has infinite loops relying purely on interrupts and no timeout exit: flush()
and write()
. Kinda similar to what #1834 brings up
Desktop (please complete the following information):
- OS: Windows 10 x64
- Arduino IDE version: 2.2.1
- STM32 core version: 2.6.0
- Tools menu settings if not the default: -g3, -Os, newlib nano + printf, USB CDC (supersede U(S)ART). USART Enabled (generic 'Serial), own board variant
- Upload method: SWD
Board (please complete the following information):
Custom PCB using STM32L496RGT6 MCU connected via UART with CTS\RTS to a u-blox SARA-R5 modem
Metadata
Metadata
Assignees
Labels
Type
Projects
Status