RIOT is an IoT OS for microcontrollers.

This is a description of one facet of my attempts to find a way to do 'smarter' things with an Arduino than the traditional 'sketch' paradigm seems to support ( or at least, to make easy ). My feeling was that I needed a 'proper' embedded OS. One key thing I was looking for was thread/task support. Another key thing was out-of-the-box support for the Arduino DUE that I wanted to use.

On the face of it, RIOT more than meets my needs. It's targeted at IoT devices rather than generic embedded systems, so there's an emphasis on comms capabilities that you may or may not need, and which a DUE certainly doesn't support by default, ditto with sensors.

When you use RIOT, the thing that you transfer from your development environment to the target board is a compiled and linked binary image which contains your application and RIOT. This is pretty normal for small embedded systems, and is entirely similar to, for example, normal Arduino development where the Arduino IDE builds a binary image containing your sketch and the Arduino runtime, which is a wrapper around the C standard library. So you don't 'install' RIOT, in the same sense as you would install Linux or Windows.

Whether the Arduino runtime qualifies as 'an OS' is, for most purposes, a semantic quibble. What is certainly true is that RIOT, as with other similiar embedded OS's, provides a more feature rich environment than the Arduino runtime.

Somewhat confusingly, RIOT provides an implementation of the Arduino API ( using it's 'module' concept ) - so an Arduino sketch stands a chance of running, and there's an example given of this. Why you would want to use RIOT to run an Arduino sketch isn't clear to me - if you're using RIOT, by definition you want to do things that are tricky or impossible via the Arduino API, but maybe you're starting off from an existing app.

The RIOT development environment

Where Arduino provides an IDE for creating Arduino applications, RIOT does not currently provide an IDE or any integration with IDE's.

To build a RIOT application, you can hack code using whatever tool you like, but you must create a Makefile ( using targets and configuration metadata specified by RIOT ) to drive the building and flashing process. Work is under way for RIOT to support the PlatformIO plugin for VS Code, and when this is done there will, in effect, be an IDE for RIOT. Don't hold your breath - mapping RIOT's make system and configuration model onto PlatformIO's doesn't look like a trivial exercise.

Regarding development environments and toolchains, RIOT provides at least one Docker instance that removes the need for a certain amount of messing around with toolchains ( see 'Use Docker to build RIOT' ). For my application ( Arduino DUE, using the recommended ARM cross development toolchain ), it was as easy to grab RIOT and install the ARM toolchain locally as it would have been to get involved with Docker.

The Make system

The RIOT make system is a work of art 🙂. It has to be, to deal with the huge range of potential configurations and environments that RIOT is supporting. I don't pretend to understand the finer details, but fortunately that's not necessary - I'm not attempting to add a new board, or support additional hardware, or add new build targets. What the problem boils down to is setting correct values for a relatively small number of make system variables, which are at least documented.

If you are coming from an Arduino IDE background, what may not be clear from the above is that you will, at least once, need to compile RIOT itself. In fact, you'll need to do it for any target you want to use ( RIOT supports many, not just Arduinos ). In most Arduino scenarios, progamming via the Arduino IDE, the Arduino runtime ( a.k.a Arduino core ) is precompiled.

Note that you do not have to do this compilation explicitly - the make system will do it for you if it needs to be done. This is what make is for, and is just a side effect of having a thorough specification of dependencies. But RIOT is particularly aggressive about this - a lot of effort has been devoted to ensure that the make system will do everything necessary to satisfy your make command, even to the extent of downloading and building tools, all you have to do ( see below ) is provide an appropriately configured makefile for your target and application ( i.e. the code you actually write ). However, this is the reason why you need the RIOT sources.

The RIOT sources

There are three different approaches to using the RIOT sources, and which you choose depends on the nature and ambition of the work you'll be doing. This is a general pattern with OSS projects.

  1. Copy the files ( get a zip from gitHub )

If you have no need or intention to actually make any change or contribution to RIOT, you're just going to use it, this is probably what you should do. This is a bit like installing a traditional SDK - after you've compiled everything you need for your board, RIOT is in effect a read-only resource. Of course, you could clone the repo using git and just never change any of the sources in it - same effect but a little pointless.

  1. Clone the repo

If you are working with device drivers, protocols, or anything new that you want to integrate into the RIOT platform, or you need to hack parts of RIOT, then you will almost certainly need to contribute code to RIOT. You may be forced to do this by licencing considerations, or you may just be a nice person 🙂 Or maybe you just want to track the bleeding edge of RIOT development. In this case you'll have no choice but to work with the RIOT repo via git.

  1. Fork the project

In effect, this means taking a copy of RIOT and putting it in a new repo somewhere. If you have an ambitious vision for a different flavour of RIOT, you could do this. It's almost certainly not a good idea, absolutely not required for 99.99% of use cases, and may cause your hair to fall out. But if you're doing it, you know this already 🙂.

First step

The 'quickest start' instructions are for what is, in effect, a sanity check on your instance of RIOT. It builds and fires up a RIOT application on your host. A couple of points to note. It assumes you are cloning the repo, and you need to pick which release you want - these releases correspond to particular git branches, and you need go to gitHub to see what they're called.

Secondly, the behaviour of this example when you fire it up is not particularly useful - it starts to dump packets that it sees on the tap interfaces. This is actually intended behaviour and does not indicate any error. The RIOT build/application that you've started is running a task called 'pktdump' in addition to the shell, and this is what pktdump does. You can still interact with the terminal/shell and use the commands provided, but pktdump will throw whatever packets it sees at you regardless.

PKTDUMP: data received:
~~ SNIP  0 - size:  56 byte, type: NETTYPE_UNDEF (0)
00000000  60  00  00  00  00  10  3A  FF  FE  80  00  00  00  00  00  00
00000010  08  8A  EB  FF  FE  B4  55  CA  FF  02  00  00  00  00  00  00
00000020  00  00  00  00  00  00  00  02  85  00  E7  1B  00  00  00  00
00000030  01  01  0A  8A  EB  B4  55  CA
~~ SNIP  1 - size:  20 byte, type: NETTYPE_NETIF (-1)
if_pid: 4  rssi: 0  lqi: 0
flags: 0x0
src_l2addr: 0A:8A:EB:B4:55:CA
dst_l2addr: 33:33:00:00:00:02
~~ PKT    -  2 snips, total size:  76 byte
help
help
Command              Description
---------------------------------------
reboot               Reboot the node
version              Prints current RIOT_VERSION
pm                   interact with layered PM subsystem
ps                   Prints information about running threads.
rtc                  control RTC peripheral interface
ifconfig             Configure network interfaces
txtsnd               Sends a custom string as is over the link layer
saul                 interact with sensors and actuators using SAUL
> version
version
2020.10

An application !

Unless you are developing new modules, examples, or boards that you intend to contribute to RIOT ( you may need to, but I don't ), you will want to do development outside of RIOT itself. The make system has the variable 'RIOTBASE', which gives you a way to point the build at the RIOT sources and tools. There aren't many essential variables, and the documentation describes what a basic makefile should look like.

But some more digging in the documentation turns up the existence of the riotgen tool. riotgen is a python3 tool, and you can install it with pip3. The documentation talks about riotgen as if it were only for use within the RIOT repo, but this is not the case. You can fire up riotgen in your development directory, and it will prompt you through a series of questions and deliver a skeleton main.c, makefile, and README.md. Simple but effective, particularly if you're only looking for a 'Hello world' to test out your board.

It's a bit annoying that it forces you to add a licence, and that you don't get the choice of public domain, but these options would very likely be wrong choices if you were working 'in RIOT'. This is what it gave me :

/*
 * MIT License
 *
 * Copyright (C) 2021 Mark de Roussier
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:

 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

/**
 * @{
 *
 * @file
 * @brief       First stab at a DUE app
 *
 * @author      Mark de Roussier <zzz@zzz.zzz>
 *
 * @}
 */

#include <stdio.h>

int main(void)
{
    puts("Generated RIOT application: 'DUEHelloWorld'");
    return 0;
}

And this makefile :

# name of the application
APPLICATION = DUEHelloWorld

# If no BOARD is found in the environment, use this default:
BOARD ?= arduino-due

# This has to be the absolute path to the RIOT base directory:
RIOTBASE ?= /home/mark/Projects/RIOT

# Comment this out to disable code in RIOT that does safety checking
# which is not needed in a production environment but helps in the
# development process:
DEVELHELP ?= 1

# Change this to 0 show compiler invocation lines by default:
QUIET ?= 1

include $(RIOTBASE)/Makefile.include

The key problem to note is that this makefile doesn't specify a port to use for flashing, so I can't just run 'make flash' - or at least, I can't if my board is on a non default port. But see below for a discussion of flashing.

What I could do is use this makefile and specify the necessary port as a parameter. The ability to supply non default values for things is the purpose of the '?=' operator, and this is a common pattern in the RIOT make system. Things are given a default value via '?=', but you're able ( and expected to ) override these when you invoke make.

Flashing a DUE

Everything up until now has been straightforward. A bit of RTFM required, but nothing terribly annoying. This will change.

The bootloader

Firstly, it's important to understand the bootloader situation. Normally, for AVR based devices, a bootloader resides in flash. When you upload a sketch to your board, the Arduino IDE activates this bootloader code and feeds it with your compiled binary. The bootloader arranges to store this binary in flash. When the board is reset, the bootloader starts your code.

Because the bootloader is in flash, you can, if you so wish, replace it with something else ( or fix it, if it gets corrupted ). RIOT supplies a bootloader, which you could use if you felt like it on an AVR device. It's not necessary to do so, but you could. The tool used for all this stuff, at least on Linux, is avrdude.

The DUE is not an AVR device, it's an ARM SOC, namely an SAM3X8E. This has a bootloader burned into ROM which uses the SAM-BA protocol [[ link to bootloader description ]]. You can't change it, and avrdude won't talk to it. The ARM and Arduino folk have done all sorts of smart shit to make sure that you can access a communication channel that will deliver data to the bootloader via numerous routes, but the question is, what software can actually talk to it ?

Flash dancing

A lot of material on line will point you in the direction of SAM-BA tools from vendors such as Microchip and Atmel. All of these appear to be useless if you are using Linux. Atmel appears to offer a tool on Github that you can build, but you can't because it depends on a commercial library ( J-Link ) that isn't supplied. Microchip offer Linux tools, but don't list the Atmel device as a supported option.

However, the Arduino IDE can certainly arrange to program a DUE, and after a certain amount of googling the solution emerges from the mist - there is a tool called BOSSA that can do it. Although it doesn't promise to do it for the SAM3X8E.

So downloading and building BOSSA gets you a tool. Well, it does after you've worked out which unlisted dependencies you need to install to get the build working - you need the libwxbase and libwxgtk dev packages if you want the GUI version. You also get a command line version called bossac.

BOSSA is, to an extent, documented here : https://www.shumatech.com/web/products/bossa. This is all you have to go on, apart from the sources themselves. It's not a flashing tutorial but it's enough to get a good idea.

To check the operation of BOSSA, you can just use the -i parameter to get info from your board without erasing anything. But there's a twist in the case of the DUE. If you just plug your DUE in, you'll get a serial port in /dev - probably /dev/ttyACM0, or some higher number if you've got other USB serial things connected too as I tend to have. But to make that serial connection talk to the bootloader, it must ( first ) operate at 1200 baud. On Linux you can set this using stty :

stty -F /dev/ttyACM1 1200

If you don't do this, you'll get complaints about 'No device found' when BOSSA is run. Here is the output from bossac for my DUE :

$ bossac -i -p /dev/ttyACM1
Device       : ATSAM3X8
Version      : v1.1 Dec 15 2010 19:25:04
Address      : 0x80000
Pages        : 2048
Page Size    : 256 bytes
Total Size   : 512KB
Planes       : 2
Lock Regions : 32
Locked       : none
Security     : false
Boot Flash   : false

Note that I'm connected to the 'programming' port of the DUE whilst doing this.

RIOT and BOSSA

The RIOT make system supports a make target which aims to flash the code you have built to your target device. However, the design and configuration of this part of the system is not explained in the documentation.

In fact, RIOT will attempt to download and build any necessary tools to enable flashing the target device. In the case of the DUE, it will attempt to download and build bossac. For reasons that aren't entirely clear, RIOT thinks it should use version 1.8 of BOSSA for DUE, not the current 1.9, so it builds that if necessary.

A full description of all the BOSSA related parts of the RIOT make system would be painful, and is unnecessary. Examination of [[ dist/tools/bossa-1.9/bossa.inc.mk ]] shows some of the logic, and reveals the variables involved to make BOSSA work, the key one being $(PROG_DEV). You need to set $(PROG_DEV) in your makefile before the

include $(RIOTBASE)/Makefile.include

( or supply it as a command line definition ) to point at the device corresponding to your board. My makefile contains

 # What device corresponds to the attached board ?
PROG_DEV = /dev/ttyACM1

Running 'make flash' will now, provided your board is connected, do anything necessary to send your app to your board, the final part being the use of BOSSA :

[INFO] bossac 1.8 binary successfully built!
/home/mark/Projects/RIOT/dist/tools/bossa-1.8/bossac -p /dev/ttyACM1  -e -i -w -v -b -R /home/mark/Projects/RIOTApps/DUEHelloWorld/bin/arduino-due/DUEHelloWorld.bin
Device       : ATSAM3X8
Chip ID      : 285e0a60
Version      : v1.1 Dec 15 2010 19:25:04
Address      : 524288
Pages        : 2048
Page Size    : 256 bytes
Total Size   : 512KB
Planes       : 2
Lock Regions : 32
Locked       : none
Security     : false
Boot Flash   : false
Erase flash

Done in 0.049 seconds
Write 7980 bytes to flash (32 pages)
[==============================] 100% (32/32 pages)
Done in 1.557 seconds
Verify 7980 bytes of flash
[==============================] 100% (32/32 pages)
Verify successful
Done in 1.446 seconds
Set boot flash true
CPU reset.

Bingo.

Or JTAG ?

One of the nice things about the DUE is that it exposes a JTAG interface. But that may be a seperate blogpost.

UP | NEXT | HOME

© Mark de Roussier 2021, all rights reserved.