cancel
Showing results for 
Search instead for 
Did you mean: 

How to use printf() function with stm32cubeMX + sw4stm32

gae089
Associate II
Posted on September 01, 2015 at 19:13

Hi to every one,

It's the first time that I use the STM32CubeMX + SWSTM32 to program a stm32f401RE board. I have done already some example project but I can't use the printf() function to communicate  with a terminal ( Tera Term) on the PC. Somebody can explain me how I can do it?

Thank you in advance!!
21 REPLIES 21
Posted on February 21, 2017 at 18:28

Hello Nesrine,

I'd like to use UART to retarget the C library printf and I followed your comment but I'm stuck when I opened the folder STM32Cube_FW_F4_V1.8.0\Projects\STM32F401RENucleo\Examples\UART\UART_Printf\SW4STM32. Here is what it showes:

-Dir: STM32F4xx-Nucleo

-startup_stm32f411xe.s

-syscalls.c

I don't know what to do next. Please help.

Thanks

Posted on February 21, 2017 at 22:18

Hello,

you need to look in the \Src subdirectory, not the \SW4STM32 one - that only contains some files specific to the toolchain, but not the actual source code.

tommi
Associate II
Posted on July 13, 2017 at 19:38

Just to clarify the issue for future users. I know its repetition but having the full solution in one post is very helpful.

Enable the Uart port and pins needed for the application in Cube or manually. Test the port that it works:

HAL_UART_Transmit(&huart1, 'Hello\n', 6, 0xFFFF);

If it works then continue with printf.

First add this to the bottom of your usart.c file generated by Cube. Change &huart1 as required for the UART port that you are using.

/**

  * @brief  Retargets the C library printf function to the USART.

  * @param  None

  * @retval None

  */

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(&huart1, (uint8_t *)&ch, 1, 0xFFFF);

  return ch;

}

Next add this to the top of the usart.c file:

#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__ */

Finally, syscalls.c file needs to be copied to your project, this can be placed in the src folder. The file can be copied as is from:

STM32Cube_FW_F4_V1.8.0\Projects\STM32F401RENucleo\Examples\UART\UART_Printf\SW4STM32

Now printf should be working. For making float number print refer to the other posts in this thread.

Tested with F0 discovery.

mile milestone
Associate
Posted on October 18, 2017 at 13:05

PLEASE ALLOW ME TO ADD DETAILS OF WHAT I'VE DONE, TESTED ON NUCLEO F401RET

1. Using CUBEMX, I configures USART 2 as my serial communication (set as Asynchronous) and let it (cubemx) generate all initilial files and folders

   CUBEMX USART2 SETUP:

   - Asynchronous

   -Parameter Setting by Default, except  Baud Rate is 115200 

   -NVIC Setting, uncheck the UART global interrupt

   -Did not touch the rest

   - Finally, hit the Generate Code Icon !!

2. Opening the project with AC6 Workbench we should see something like this

0690X00000608fQQAQ.png

3. NOW LET'S DO THE ADDITIONAL CODES AND SOME STEPS

Step 1 Let's add the following two function in our main.c - you can place them above the main() function 

in my case i paste it on /* USER CODE BEGIN PV */ see highlighted

#ifdef __GNUC__

#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)

#else

#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)

#endif /* __GNUC__ */

PUTCHAR_PROTOTYPE

{

HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 0xFFFF);

return ch;

}

see pic below

0690X00000608fzQAA.png

Step 2 : Modify the linker flag in the project properties.

2.1 Go to Menu: Project\Properties\

2.2 Expand  C\C++ Build on left pane, select Settings

2.3 On middel expand MCU GCC Linker drop down menu, and select Miscellaneous

2.4 Now on the rightside you can see the the ''Linker Flag'' text box.

2.5 Replace/update  the text to 

      -specs=nosys.specs -specs=nano.specs -u _printf_float

Hit Ok

0690X00000608crQAA.png

Step 3: Locate the file ''

syscalls.c

'' and place it on startup folder i.e. together with 

startup_stm32f401xe.s

 

It should appear in the ''project explorer'' under ''startup'' folder

I found  syscall.c in the repository of example folder of CubeMX . i.e. C:\Users\My\STM32Cube\Repository\STM32Cube_FW_F4_V1.16.0

STEP 4: I did check on STM32F401RETx_FLASH.ld  file (on file exporer, its the file on the last - see picture) as suggest in the comment above and it is 

0x20018000 by default so i leave it as is.

/* Highest address of the user mode stack */

_estack = 0x20018000; /* end of RAM */0690X00000608gJQAQ.png

FINAL STEP. Finally I tried and run inside loop 

printf

(

''%f\t  %i\n''

, 0.1250f, 12345); It woks.

Hope will be useful for future user. I wish printf() would be a straightforward feature of the IDE so we don't have to work around.

If there is better approach, please share.

I Thank you for all the inputs mentioned in this forum.

Posted on November 20, 2017 at 05:08

Good job, mile! 

🙂

Just a quick reminder.

The core of this retargeting is using HAL_UART_Transmit(), 

which works in blocking mode and strings are sent 

character

by character.

If your application needs to do some heavy task without much resource for debug print, you may consider use DMA.

.Zt

Posted on November 20, 2017 at 05:29

Buffering to a FIFO and using an IRQ are also extremely effective. Where that is not practical a very high baud rate can help.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on November 20, 2017 at 05:37

Sure thing! 

I also use FIFO + IRQ when DMA channels run out for UART TX.
Posted on November 20, 2017 at 05:53

I think that's awesome, any link that can demonstrate would be helpful. My next task is to send serial on other USART which printf doesnt work, F401 comunicate well on its default USART2 but not on the other say USART1 OR USART 6.

Posted on November 20, 2017 at 22:53

The USARTs should work fine, USART1 and 6 are on APB2, you'd want to check the clock, GPIO configuration and AF mux selection

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..