Skip to main content
AAnth.1
Senior
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,

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

Peter BENSCH
Peter BENSCHBest answer
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

In order 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.
AAnth.1
AAnth.1Author
Senior
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.1
AAnth.1Author
Senior
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,

Qye
Associate II
October 5, 2023

Started working when I added fflush(stdout);

CCend.2
Associate 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.

Pavel A.
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.