Skip to main content
Explorer II
June 21, 2025
Solved

Trouble with printf and sprintf with float in STM32Cube + VS Code (CMake)

  • June 21, 2025
  • 4 replies
  • 1208 views

Hi everyone,

I'm working on an STM32 (Nucleo-F446RE to be spesific) project using the STM32Cube extension for VS Code, not CubeIDE. I'm using CMake for building the project.

I encountered a few issues:

  1. printf doesn't print anything to the serial monitor, so I switched to using HAL_UART_Transmit.

  2. When I try to print a float using sprintf(msg, "value: %f\n", var);, it doesn’t work. The output just skips the float value (e.g., "value: \n").

  3. After some research, I found out I need to add "-u _printf_float" to the linker flags to enable float formatting support with printf and sprintf.
    However, I'm new to CMake and I couldn’t figure out which CMake file I need to modify in the project folder to add this flag.

I'd really appreciate it if someone could guide me:

  • Where exactly should I add the "-u _printf_float" flag?

  • Is there anything else I should do to make printf work properly over UART?

Thanks in advance for your help.

Best answer by manolo_embedded

@umut373 wrote:
  • Where exactly should I add the "-u _printf_float" flag?


As a beginner, I faced the same problem.

I also use CMake, but I generate the project with STM32CubeMX, so I don't know what your configuration is. I use a NUCLEO-F439ZI board, so things might also be different on that side.

On my end, I have a toolchain configuration file ./cmake/gcc-arm-none-eabi.cmake and I added the following line to be able to use snprintf with floats (however, i'm not sure if it's the best way to do it) :

set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -u _printf_float")

 


@umut373 wrote
  • Is there anything else I should do to make printf work properly over UART?

For printf, I chose not to use it and instead created a custom function that resembles it and uses UART as you did.

void print_to_uart(UART_HandleTypeDef huart, const char *format, ...)
{
 char buffer[256];
 int cx;

 va_list args;
 va_start(args, format);
 cx = vsnprintf(buffer, sizeof(buffer), format, args);
 va_end(args); 

 if (cx >= 0 && cx < static_cast<int>(sizeof(buffer)))
 {
 HAL_UART_Transmit(&huart, (uint8_t*) buffer, cx, 1000);
 }
}

And I use it like this :

print_to_uart(huart3 ,"This is PI value : %f \n", 3.141592);



4 replies

Andrew Neil
Super User
June 25, 2025

@umut373 wrote:
  1. printf doesn't print anything to the serial monitor


Have you followed the instructions:

https://community.st.com/t5/stm32-mcus/how-to-redirect-the-printf-function-to-a-uart-for-debug-messages/ta-p/49865

 

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
manolo_embeddedBest answer
Visitor II
September 22, 2025

@umut373 wrote:
  • Where exactly should I add the "-u _printf_float" flag?


As a beginner, I faced the same problem.

I also use CMake, but I generate the project with STM32CubeMX, so I don't know what your configuration is. I use a NUCLEO-F439ZI board, so things might also be different on that side.

On my end, I have a toolchain configuration file ./cmake/gcc-arm-none-eabi.cmake and I added the following line to be able to use snprintf with floats (however, i'm not sure if it's the best way to do it) :

set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -u _printf_float")

 


@umut373 wrote
  • Is there anything else I should do to make printf work properly over UART?

For printf, I chose not to use it and instead created a custom function that resembles it and uses UART as you did.

void print_to_uart(UART_HandleTypeDef huart, const char *format, ...)
{
 char buffer[256];
 int cx;

 va_list args;
 va_start(args, format);
 cx = vsnprintf(buffer, sizeof(buffer), format, args);
 va_end(args); 

 if (cx >= 0 && cx < static_cast<int>(sizeof(buffer)))
 {
 HAL_UART_Transmit(&huart, (uint8_t*) buffer, cx, 1000);
 }
}

And I use it like this :

print_to_uart(huart3 ,"This is PI value : %f \n", 3.141592);



Pavel A.
Super User
September 23, 2025

Instead of adding options to the linker command line (can be tricky with cmake) you can do this in your linker script (.ld file): add

EXTERN(_printf_float);

 

/* or even reference _printf_float in your C source file, but make sure it won't be discarded as unreferenced */

 

ST Employee
September 30, 2025

Be aware latest update is promoting some semihosting feature !
Let's have a try enriching your launch.json relying on serverSemihosting parameter.

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.