2025-09-21 11:21 PM
Hi everyone,
I’m working on an STM32 firmware project (HAL + CubeIDE). I’m trying to output debug messages to Tera Term via UART using printf and puts.
Here’s the situation:
Debug build: Both printf and puts work perfectly.
Release build: Calling printf or puts causes the MCU to reset immediately. Maybe due to watchdog reset and these function call cause the MCU freezing.
I also retarget the printf function by implemented the following:
int __io_putchar(int ch) {
while (!(huart1.Instance->ISR & USART_ISR_TXE));
huart1.Instance->TDR = (uint16_t)ch;
return ch;
}
int _write(int file, char *ptr, int len) {
for (int i = 0; i < len; i++) {
__io_putchar(ptr[i]);
}
return len;
}
My questions:
Why do printf and puts crash/reset in Release but work in Debug?
Are there known issues with _write or __io_putchar in Release builds?
Any recommended approach to safely use printf/puts in Release firmware for UART output?
Thanks in advance!
2025-09-21 11:59 PM
Compare the build settings for debug and release.
Normally you have semihosting enabled for debug, which includes additional code and these outputs are routed via JTAG/SWD or an UART line.
Relase build setting do usually not.
This is why you have debug and release builds in the first place - you don't do debug printf()s in release versions.
I'm not using CubeIDE, so I don't know why it crashes.
With my toolchain, the _write and __io_putchar calls are empty functions in the release version, and thus printf()s in the release build amount to nothing.
2025-09-22 1:25 AM
The thing is my application support CLI function, accept commands from console like tera term and response accordingly.
2025-09-22 1:47 AM
Then don't use the semihosting interface for that, but a separate UART.
Or extend the release build settings accordingly.
2025-09-22 5:45 AM
You can still run the Release version in the debugger to see what's happening.
@chai2145 wrote:
Maybe due to watchdog reset and these function call cause the MCU freezing
Maybe instrument your code so that you can see if that actually is the case ...
As @Ozone said, check what's different between the builds - Optimisation level is another common one.
When increasing the optimisation level breaks your code, that usually indicates flaws in the code.
eg, failure to use 'volatile' where required...