2015-09-01 10:13 AM
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!!2017-02-21 10:28 AM
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
2017-02-21 02:18 PM
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.
2017-07-13 10:38 AM
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.
2017-10-18 04:05 AM
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
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
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
Step 3: Locate the file ''
syscalls.c
'' and place it on startup folder i.e. together withstartup_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 */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.
2017-11-19 09:08 PM
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
2017-11-19 09:29 PM
Buffering to a FIFO and using an IRQ are also extremely effective. Where that is not practical a very high baud rate can help.
2017-11-19 09:37 PM
Sure thing!
I also use FIFO + IRQ when DMA channels run out for UART TX.2017-11-19 09:53 PM
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.
2017-11-20 02:53 PM
The USARTs should work fine, USART1 and 6 are on APB2, you'd want to check the clock, GPIO configuration and AF mux selection
2018-01-26 06:13 PM
Hi,
look this examples:
http://www.emcu.eu/how-to-implement-printf-for-send-message-via-usb-on-stm32-nucleo-boards/