Implementation of printf that works in threads.

nb3m wrote on Thursday, October 17, 2019:

Hello,
I am using stm32wb board and freertos cmsis 2.0. I have implemented printf so it does print data into uart. In main function printf works fine, however if I try to print something from thread it hangs. Can nyone explain me why it happens and how can I fix it? This is only for debugging reason however it makes life easier. Hal_uart_transmit works fine from threads. Please take a look at my code below:

int __io_putchar(int ch)
{
 uint8_t c[1];
 c[0] = ch & 0x00FF;
 HAL_UART_Transmit(&huart1, &*c, 1, 10);
 return ch;
}

int _write(int file,char *ptr, int len)
{
 int DataIdx;
 for(DataIdx= 0; DataIdx< len; DataIdx++)
 {
 __io_putchar(*ptr++);
 }
return len;
}
const osThreadAttr_t main_attributes = {
    .name = "main",
    .priority = (osPriority_t) osPriorityNormal,
    .stack_size = 1024
  };
  mainHandle = osThreadNew(mainFunction, NULL, &main_attributes);
  
  void mainFunction(void *argument)
{
    uint8_t message[40] = "Hello World! This is mine.\n\r";
     for(;;)
  {
	  printf("Hello this is printf!\n\r");
	//HAL_UART_Transmit(&huart1,message,sizeof(message),10);
        vTaskDelay(200/portTICK_RATE_MS);
  }
}

rtel wrote on Thursday, October 17, 2019:

Whenever you access any IO port, be that a console or a UART or anything else, you are going to have to serialise the access. There are a few ways you can do that, for example use a mutex, but the mutex would have to be around the entire string write not just the individual characters. Another method would be to use something like a stream buffer - anything that wants to write to the output writes the message to the stream buffer, and then you have a task that drains the stream buffer and writes anything it obtains from the buffer to the output. Note stream buffers only expect one writer though, so then the mutex has to be around the stream buffer (so maybe that doesn’t gain anything?).

nb3m wrote on Saturday, October 19, 2019:

Hi Richard,

I am using sucessfully printf outside of the thread. There are no other threads than main with printf function. I don’t get why data serialization in this case might be a problem?

Lukasz

rtel wrote on Saturday, October 19, 2019:

You mention it is handing, can you give more detail? For example, if
you break on the debugger, what is the code executing? Could it be
printf() is overflowing the stack and you are hanging in the stack
overflow hook function, or hitting an assert, or something similar?

nb3m wrote on Saturday, October 19, 2019:

I think printf got stuck on functions: __sfputs_r(), __vprintf_r(). I have to dig a little bit more.

heinbali01 wrote on Sunday, October 20, 2019:

Here you find an alternative for [v][s][n]printf() functions that is thread- and interrupt- safe:

https://sourceforge.net/p/freertos/discussion/382005/thread/8fbac97d/?limit=250#45ce

It does not implement printing floating point numbers ( %f, %g ).

When you define SPRINTF_LONG_LONG as 1, it will also print 64-bit numbers.

EDIT As developers still find this post, I update the location of ‘printf-stdarg.c’.

nb3m wrote on Monday, October 21, 2019:

Thanks Hein for your feedback! After spending several hours reading and getting into that solution I finally managed to get it working! Really helpful was this link http://www.nadler.com/embedded/newlibAndFreeRTOS.html

Thank you all for your replays! Cheers!

heinbali01 wrote on Monday, October 21, 2019:

Thank you Lukasz for this URL.