STM32Cube Output to Serial

Hello,

I am sure this question has already been answered, and I am just not able to find it within the community threads.

I am looking to output text to the serial monitor using the STM32Cube framework on a Nucleo F446RE development board. I am just not sure where to start, and would appreciate any and all help!!

See STM32CubeF4/Projects/STM32446E-Nucleo/Examples/UART/UART_Printf at master · STMicroelectronics/STM32CubeF4 · GitHub

Thank you @maxgerhardt for the link! I was able to clone and set up the example as a project using the PlatformIO CLI, compile, and upload the program to the Nucleo F446RE. I then ran the pio device monitor command to see if the message would output to the terminal…no luck.

I’m wondering if there is an example from a project created within PlatformIO? Are there dependencies/packages I am missing and need to install?

Thank you so much for your time!

Sure I can put it in a PlatformIO project.

However,

looks suspucious to me, since I don’t know if that “small printf” linker option is used in PlatformIO. Can you replace the code block

with just

#include <errno.h>
#include <sys/unistd.h> // STDOUT_FILENO, STDERR_FILENO
int _write(int file, char *data, int len) {
  if ((file != STDOUT_FILENO) && (file != STDERR_FILENO)) {
      errno = EBADF;
      return -1;
  }
  HAL_UART_Transmit(&UartHandle, (uint8_t *)data, (uint16_t) len, 0xFFFF); 
  return len;
}

and retry?

Ah, my above modification might not be necessary if you added their STM32CubeF4/syscalls.c at master · STMicroelectronics/STM32CubeF4 · GitHub to the src/ folder of the project. Did you do that?

I had not moved syscalls.c to the src/ directory until just now. Still no output to the terminal.

I don’t see syscalls.c being included in any of the other files. Not sure if that affects anything? This is where my lack of knowledge/understanding of the project structure starts to show.

Do you recommend I make the above suggested modifications?

I’m wondering if my taking the sample project and turning it into a project using the PlatformIO CLI might’ve jumbled things up as well?

It doesn’t need to be #included by other files, the function it implements tell GCC what do to when printf() etc is called, i.e. to call the _write function that eventually calls into the function (__io_putchar) that does the HAL_UART_Transmit() – that one’s crucial, otherwise there’s no output.

Then I’ll setup the project myself and quickly double-check.

1 Like

Thanks @maxgerhardt! I apologize for making things harder than expected!

Can you test GitHub - maxgerhardt/pio-nucleo-f446-test?

I allowed myself to make a small addition in the while(1) loop of main.c and in the Systick handler so that HAL_Delay works and stuff can be contiously printed on the serial monitor – otherwise the very first printf() happens very fast and probably won’t be cought be the PlatformIO serial monitor because it opens too late. You would have to press the reset button on the board to see that message.

1 Like

Perfect! I am seeing output within the serial monitor now! You were correct about the first printf() message not displaying unless I pressed the Reset button.

The only “issue” on my end is that some of the text characters within the string display as question marks (see image). I imagine that can be solved via some text encode settings?

Well that shouldn’t happen, it should print a nice ASCII readable

I think that’s because the reference example chooses a weird UART setting with ODD parity

So either change that to UART_PARITY_NONE (the PlatformIO serial monitor standard) or add

monitor_parity = O

in the platformio.ini (docs).

Works like a charm now!! Thank you for all of your hardwork and bearing with me on this!

I am now wondering though, is there a library or package that can be installed that comes with all of the specific files needed for UART transfer? Are those already included within the STM32Cube framework?

The STM32Cube has the whole HAL (hardware abstraction layer) already in it that the firmware is just using, specifically the stm32f4xx_hal_uart.c for UART. The firmware just has to call it with HAL_UART_Init(), HAL_UART_Transmit() etc.

If you want a very simplified way to “just” use UART, I’d actually just recommend to use the Arduino core with it. Under the hood it still uses STM32Cube, but it does all the heavy lifting for you, like interrupt-based, buffered sending and receiving procedures et cetera, so that you just have to do Serial.begin(9600); and Serial.println("Test test");. See arduino-blink for the baseline.

Gotcha. Initially I wanted to try out the stm32cube framework and figured there would be a lot more steps/preparation involved with things that are much simpler in the arduino framework.

The main thing I will need to remember is the setup process.


 UartHandle.Instance          = USARTx;
  
 UartHandle.Init.BaudRate     = 9600;
 UartHandle.Init.WordLength   = UART_WORDLENGTH_8B;
 UartHandle.Init.StopBits     = UART_STOPBITS_1;
 UartHandle.Init.Parity       = UART_PARITY_NONE;
 UartHandle.Init.HwFlowCtl    = UART_HWCONTROL_NONE;
 UartHandle.Init.Mode         = UART_MODE_TX_RX;
 UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;

Thank you again @maxgerhardt for all your work and help on this! Very much appreciated!