0

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.

Citrullin
  • 2,269
  • 14
  • 29
bjornruffians
  • 671
  • 5
  • 16
  • 1
    It is not too specific for SO but in order to get a better answer, you need to state exactly which tool chain that is used. – Lundin Jan 31 '18 at 15:57
  • Could you solve your problem? If not, first of all try using [Docker](https://github.com/RIOT-OS/RIOT/wiki/Use-Docker-to-build-RIOT) to build the hello world example. Afterwards invoking `make BOARD=nucleo-f411re flash-only term` should burn the image, open the termnial and show the hello world messages. – yegorich Apr 24 '19 at 09:51
  • I did not end up solving this. A project I was working on went a different direction (different platform and OS). This was at the evaluation stage of the project. Had RIOT been super easy to use, I would have recommended it but the MCU vendor had examples with freeRTOS that worked "out-of-the-box". (My opinion) – bjornruffians Apr 24 '19 at 14:55

4 Answers4

5

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

Toon
  • 66
  • 1
  • 2
2

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.

Clifford
  • 88,407
  • 13
  • 85
  • 165
  • This is not particularly useful for the described case, as RIOT-OS already implements those, and it stands to reason that bornruffians will keep using it on the embedded device. Then, redefining them would only cause build issues. – chrysn Aug 01 '19 at 17:11
  • @chrysn : Point noted. It seems that Toons answer makes that clear - a clear case of RTFM it seems. – Clifford Aug 01 '19 at 18:33
1

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

Jonny Schubert
  • 1,393
  • 2
  • 18
  • 39
  • I implemented a fputc() function, but it doesn't seem to change behavior (no observable activity on the UART pins). I also added a call to uart_init() from the file uart.c – bjornruffians Jan 31 '18 at 21:40
0

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.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • I guess I'm not sure how to do a simple GPIO either in the "RIOT OS" environment. I assume there is some standard way, versus platform specific function calls? – bjornruffians Jan 31 '18 at 17:14
  • @bornruffians Perfect time to learn then. No there's no standard way, it is MCU dependant. You'll have to read the friendly manual. – Lundin Feb 01 '18 at 08:06