Skip to main content
Visitor II
February 24, 2022
Solved

STM32G0 redirect printf() to _write() and use UART - How to?

  • February 24, 2022
  • 4 replies
  • 19129 views

Hi,

I know the question has been asked before, and there is some information (to some extent) on the internet, though I cannot seem to make it happen. My question is:

How can I use print() for debugging purpose? I have an UART peripheral up and running fine. I have a syscalls.c file that has a _write() function defined:

__attribute__((weak)) int _write(int file, char *ptr, int len)
{
	int DataIdx;
 
	for (DataIdx = 0; DataIdx < len; DataIdx++)
	{
		__io_putchar(*ptr++);
	}
	return len;
}

So to my understanding, I should have the UART transmit implementation inside my _write function. So the modified _write function would look like this:

__attribute__((weak)) int _write(int file, char *ptr, int len)
{
	int DataIdx;
 
	for (DataIdx = 0; DataIdx < len; DataIdx++)
	{
		// __io_putchar(*ptr++);
		while (!LL_USART_IsActiveFlag_TXE(USART2)) {}
 LL_USART_TransmitData8(USART2, ptr[DataIdx]);
	}
	return len;
}

So when using

printf("Hello, world");

somewhere in my code, I would expect my _write function to be called.

However, doing step-by-step debugging, I can see that my printf() never calls the _write function.

Please find below my linker arguments:

-mcpu=$(MACH) -mthumb -mfloat-abi=soft --specs=nano.specs --specs=nosys.specs -TSTM32G031K8TX_FLASH.ld -Wl,-Map=$(OUTPUT)/$(BIN).map -Wl,--gc-sections -static

Can anyone guide me on what I am doing wrong?

Thank you,

    This topic has been closed for replies.
    Best answer by Peter BENSCH

    Depending on the compiler, printf uses the function __io_putchar() or fputc.

    If you use e.g. STM32CubeIDE (based on GNU GCC), you would have to adapt the function __io_putchar.

    Please note that __io_putchar has the attribute weak, so you should define the new __io_putchar in your main.c for example.

    Good luck!

    Regards

    /Peter

    4 replies

    Technical Moderator
    February 24, 2022

    Depending on the compiler, printf uses the function __io_putchar() or fputc.

    If you use e.g. STM32CubeIDE (based on GNU GCC), you would have to adapt the function __io_putchar.

    Please note that __io_putchar has the attribute weak, so you should define the new __io_putchar in your main.c for example.

    Good luck!

    Regards

    /Peter

    AAnth.1Author
    Visitor II
    February 24, 2022

    Thank you, Peter. It somewhat works, but not entirely. I have posted my full minimalistic code below, where I also show my modification of __io_putchar(). I am using arm-none-eabi-gcc as you mentioned

    AAnth.1Author
    Visitor II
    February 24, 2022

    Managed to got it work. Following __io_putchar(int ch) implementation does the job:

    int __io_putchar(int ch)
     
    {
     
     while (!LL_USART_IsActiveFlag_TXE(USART2)) {}
     
     LL_USART_TransmitData8(USART2, ch);
     
     return ch;
     
    }

     Thank you,

    Graduate
    October 5, 2023

    Started working when I added fflush(stdout);

    Explorer II
    June 18, 2024

    Thank you! I was pulling my hair out trying to override __io_putchar() and _write() and fputc() and not seeing any of those functions getting called by printf(). Adding fflush(stdout) made it work.

    Super User
    June 18, 2024

    > Adding fflush(stdout) made it work.

    Just disable buffering stdout.

    setbuf(stdin, NULL);
    setbuf(stdout, NULL);

     Also, the GNU library has function dprintf. It is like printf but prints to a file descriptor instead of FILE, without any buffering.