2018-11-14 01:02 PM
Hi,
I am working with the Nucleo-F401RE board and I am trying to implement the printf function to work with UART2. I can load and run the example project, but implementing the same code does not work in a separate project.
I have had zero luck getting this work after having read and implementing everything that I can find.
I have the following code in the main function taken from the example.
I am missing something crucial here and could use some insight.
Thanks,
D
/* USER CODE END PFP */
#ifdef __GNUC__
/* With GCC, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
/* USER CODE BEGIN 0 */
PUTCHAR_PROTOTYPE
{
/* Place your implementation of fputc here */
/* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
Solved! Go to Solution.
2018-11-15 09:49 AM
Newlib library definitely calls _write() for standard output. So it has to be implemented somewhere. It seems that the original example had a file syscalls.c like this one:
https://github.com/joeferner/stm32-utils/blob/master/syscalls.c
It has function _write() implemented and calls __io_putchar() from there. You have to implement _write() in Your code.
Although my previous post is still valid, it is not complete. Output gets flushed on reaching newline character or calling fflush(stdout) function. Additionally there is an option to disable buffering entirely by calling setbuf(stdout, NULL). Examples rely on newline, but... For example, I'm looking at examples for STM32F7 and there they use "\n\r". There is no platform using that sequence, the correct one is "\r\n". Examples are not examples of high quality...
2018-11-14 01:25 PM
add syscalls.c to your project. copying the one from your other project should work just fine.
i tend to put the putchar prototype in user code 4, but thats just me.
2018-11-14 01:38 PM
Thank you for the quick reply. I have put the syscalls.c in my src folder and the putchar prototype after main( ) and still does not work.
If I put a break point in _write( ) it never gets there. Seems the printf call is not linked to the syscalls functions.
It is mind boggling why it won't work.
Seems like a setting or something fundamental not setup correctly. I am using STM32 Workbench.
2018-11-14 03:08 PM
Make sure you initialize the USART somewhere, it's clocks, pins, and settings, etc.
Clocks and pins might be hiding in MSP or BSP files.
2018-11-14 03:13 PM
To ensure that all data gets written out (_write() called) before internal buffers reach some threshold, after a sequence of output operations You have to call:
fflush(stdout);
2018-11-14 03:28 PM
Thank you Clive and Piranha.
Clive: I can get output using HAL_UART_TRANSMIT with no problem. So I am confident everything is setup correctly. I am also using the STMCubeMX tool which automates much of this.
Piranha: The example code does not do a flush. It simple adds the prototype for io_putchar and uses the HAL_UART_TRANSMIT to send out the individual characters.
I have done everything that the example does from a code perspective. Everyone else seems to have no problem getting this to work.
I've just written my own printf statement instead and now up and running with no issues, but it is not as elegant as this solution. Really frustrating cause I am not an expert but no slouch either.
Oh well kludge and move forward...
2018-11-15 09:49 AM
Newlib library definitely calls _write() for standard output. So it has to be implemented somewhere. It seems that the original example had a file syscalls.c like this one:
https://github.com/joeferner/stm32-utils/blob/master/syscalls.c
It has function _write() implemented and calls __io_putchar() from there. You have to implement _write() in Your code.
Although my previous post is still valid, it is not complete. Output gets flushed on reaching newline character or calling fflush(stdout) function. Additionally there is an option to disable buffering entirely by calling setbuf(stdout, NULL). Examples rely on newline, but... For example, I'm looking at examples for STM32F7 and there they use "\n\r". There is no platform using that sequence, the correct one is "\r\n". Examples are not examples of high quality...
2018-11-15 03:08 PM
You nailed it sir!!! OK. So now I understand that they have provided a handy capped version of printf as an example (SHAME).
I added the escape characters and WHA LA!
Luckily my new implementation does not have these limitations and behaves just like we'd expect from a printf statement.
THANKS! Now I can breath.
2018-11-16 12:44 AM
Newlib is not made by ST. And _write() function is actually a performance improvement, because writing chunks of data is more effective than writing single characters. You can disable buffering and then it writes out everything immediately. :)
2021-11-06 02:38 AM
Here you can take ITM example
https://community.st.com/s/question/0D53W00000oVtxzSAC/swv-not-working-with-stm32f469idisco