In my STM32 application I have the following code in main:
printf("\nRunning Smoke Tests...\n");
The problem is that the whole string is not sent via UART. With some testing I found out that the leading \n
is the cause. If i remove the leading \n
the string is sent without issues via UART.
This is the implementation of _write
which is used by printf:
int _write(int file, char* ptr, uint16_t len)
{
UNUSED(file);
// Calculate minimum transmission time in milliseconds with a safety margin of 10
static constexpr uint32_t BAUD_RATE = 115200; // Baud rate in bits per second - see MX_USART2_UART_Init()
static constexpr uint32_t BITS_PER_CHARACTER = 10; // 1 start bit, 8 data bits, 1 stop bit, no parity - see MX_USART2_UART_Init()
auto const timeout_ms =
static_cast<uint32_t>((static_cast<double>(len * BITS_PER_CHARACTER) * 1000.0 / BAUD_RATE) * 10);
auto aux_result = HAL_UART_Transmit(&huart2, reinterpret_cast<const uint8_t*>(ptr), len, timeout_ms);
if (aux_result == 0) {
return len; // transmit succeeded, return length of transmitted data
} else {
return -1; // transmit failed, return error
}
}
The debugger gives some insight:
This is the Stacktrace:
stm32-template-project.elf
Thread #1 (Suspended : Breakpoint)
_write() at stm32_system.cpp:180 0x80096aa
_write_r() at 0x800c1ac
__sflush_r() at 0x800b7cc
_fflush_r() at 0x800b81e
__sfvwrite_r() at 0x800ba28
_puts_r() at 0x800bcf0
smokeTests() at main.cpp:17 0x8001554
main() at main.cpp:37 0x80015a8
With the debugger I see that len=1
is passed when _write
is called.
If I remove the leading \n
in the string len
is correctly passed with 23.
My toolchain:
There is a subtle bug in _write
implementation. The timeout_ms
value for a single-character string turns out to be 0. HAL_UART_Transmit
with 0 timeout fails with HAL_TIMEOUT
immediately after initiating a transmission; that error gets promoted upwards into libc which flags stdout
as erred. Therefore, libc wouldn't even try to write anything anymore until that error is manually cleared, thus the rest of the string never gets sent.