RIOT OS - "stdout" for embedded platforms

1.5k Views Asked by At

I'm trying out RIOT OS for the first time. After downloading source, I can build applications pretty easily, including targets that need the ARM toolchain.

The hello-world application runs fine on my Linux build machine (built using BOARD=native) and prints in the terminal.

When I switch to an embedded platform (Nucleo F411 e.g. ARM Cortex M4) where can I expect any puts() or printf() calls to appear? Further, how can I setup printf() to go to UART1 if that's not where it's going already?

Apologies if this is too specific for SO. I'm not familiar with the RIOT OS mailing lists but I'll try there as well.

EDIT: The hello-world example is really bare bones, as follows:

#include <stdio.h>

int main(void)
{
    puts("Hello World!");

    printf("You are running RIOT on a(n) %s board.\n", RIOT_BOARD);
    printf("This board features a(n) %s MCU.\n", RIOT_MCU);

    return 0;
}

I am compiling with the ARM GNU toolchain, gcc-arm-none-eabi-7-2017-q4, after following install instructions here: link. I figure I am going to need some extra compiler flags, or editing the board init functions outside the application code above. But, at this stage, I don't know where to start. My end goal is to observe "Hello World!" and "You are running..." on pin TX/D1 of my dev kit after configuring it to go there.

4

There are 4 best solutions below

0
On BEST ANSWER

In RIOT OS, by default the stdio is mapped to UART0. This can be seen here: https://github.com/RIOT-OS/RIOT/blob/master/sys/include/stdio_uart.h#L38

By redefining STDIO_UART_DEV you can map the stdio to a different UART. If you want to know which UART is mapped to which pins, have a look in the periph_conf.h of your board, which in case of the Nucleo F411 is here: https://github.com/RIOT-OS/RIOT/blob/master/boards/nucleo-f411re/include/periph_conf.h#L56

2
On

The toolchain you are using uses the Newlib C library (rather than GNU's libc which has POSIX dependencies). To port newlib to your target, some standard functions require re-implementation of at least some of the syscalls stub.

Specifically for stdout to work, you need to implement at least _write_r(). If the UART is the only device you will ever support, you can ignore the file descriptor - for stdout it will always be 1 (0 = stdin, 2 = stderr).

As an aside if you want malloc() et al to work, you need ot implement _sbrk_r().

Bill Gatliff's article on embedded.com provides examples for Newlib porting for uC/OS - the principles are probably similar for RIOT OS, but equally you could make it simpler if your library I/O needs do not need to be that sophisticated.

1
On

On embedded systems the user has to implement the function putchar(char chr) to output a single char. This function can use UART for example.

The function should look something like:

int fputc(int ch, FILE *f)
{
    /* Place your implementation of fputc here */
    /* e.g. write a character to the USART */
    HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 100);

    return ch;
}

Here you find a more complex example for an STM32F0

https://github.com/bjornfor/stm32-test/blob/master/STM32F0xx_StdPeriph_Lib_V1.0.0/Project/STM32F0xx_StdPeriph_Examples/USART/Printf/main.c

2
On

Embedded microcontroller system compilers fall into a category called freestanding implementations. This means that they don't have to provide libraries like stdio.h and you can't expect printf to be available.

There is however a probability that there's a compiler library implementing stdio.h through UART transmission. You will have to check if your compiler implements this or not.

Just for simple tests and "hello world"-like applications, it is far easier just to use GPIO pins. The embedded systems equivalent of "hello world" is to flash a LED.