-
Notifications
You must be signed in to change notification settings - Fork 2k
Introduction
RIOT is an operating system designed for the particular requirements of Internet of Things (IoT) scenarios. These requirements comprise a low memory footprint, high energy efficiency, real-time capabilities, a modular and configurable communication stack, and support for a wide range of low-power devices. RIOT provides a microkernel, utilities like cryptographic libraries, data structures (bloom filters, hash tables, priority queues), a shell, various network stacks, and support for various microcontrollers, radio drivers, sensors, and configurations for entire platforms, e.g. TelosB or STM32 Discovery Boards.
The microkernel itself comprises thread management, a priority-based scheduler, a powerful API for inter-process communication (IPC), a system timer, and mutexes.
In order to build an application or library with RIOT, you need first to
download the source code (Getting the source
code). This contains - besides the
before mentioned features - also some example applications (located in the
examples
subdirectory) and a sample Makefile you may use for your own
application. This Makefile template shows you how to compile and link your application
against RIOT (Compiling RIOT).
If you want to use RIOT directly with your embedded platform, you need to install the corresponding toolchain for the deployed microcontroller (microcontroller examples include ARM based platforms, TI MSP430 based platforms).
As a special platform, you will find a CPU and board called native
in the
repository. This target allows you to run RIOT as a process on Linux on most
supported hardware platforms. Just set BOARD to native
in your
application's Makefile, call make
, and execute the resulting elf-file. Further
documentation about the native port can be found in cpu/native/README
.
The RIOT repository contains the following ten subdirectories:
- boards
- core
- cpu
- dist
- doc
- drivers
- examples
- pkg
- sys
- tests
The boards
directory provides the configurations and initialization code for
supported IoT platforms. In core
you can find the kernel, while cpu
comprises microcontroller specific implementations like startup and exception
handling code. The folder dist
contains a template for an application's Makefile
and external utilities like the terminal program pyterm
or a script to build
your own toolchain for ARM microcontrollers. Not very surprisingly you will find
the (doxygen) documentation in doc
and peripheral driver code in drivers
.
The examples
folder provides some exemplary applications, pkg
includes
Makefiles to integrate external libraries into RIOT, and sys
system libraries
as well as the implementation of the network stacks which are located in
sys/net
. Finally, the subdirectory tests
contains test applications,
including also a few expect scripts to automatically validate some of them.
You can obtain the latest RIOT code from our Github account either by downloading the latest tarball or by cloning the git repository.
In order to clone the RIOT repository, you need the Git revision control system and run the following command:
git clone git://github.com/RIOT-OS/RIOT.git
The repository contains the kernel, support for different CPUs and platforms, device drivers, system libraries, and network stack implementations. In addition it comprises various example applications to demonstrate the usage of some important features.
It also provides you with useful tools like a terminal program and scripts to setup a toolchain.
Depending on the hardware you want to use, you need to first install a corresponding toolchain.
see: ARM
Download and install GCC toolchain for MSP430 according to the information provided on the website.
see: native
RIOT uses GNU Make as build system. The simplest way to compile and link an application with RIOT, is to set up a Makefile providing at least the following variables:
- APPLICATION
- BOARD
- RIOTBASE
and an instruction to include the Makefile.include
, located in RIOT's root
folder. APPLICATION
should contain the (unique) name of your application, BOARD
specifies the platform the application should be built for by default, and
RIOTBASE
specifies the path to your copy of the RIOT repository (note, that
you may want to use $(CURDIR)
here, to give a relative path). You can use Make's
?=
operator in order to allow overwriting variables from the command line. For
example, you can easily specify the target platform, using the sample Makefile,
by invoking make like this:
make BOARD=telosb
Besides typical targets like clean
, all
, or doc
, RIOT provides the special
targets flash
and term
to invoke the configured flashing and terminal tools
for the specified platform. These targets use the variable PORT
for the serial
communication to the device. For the native port, PORT
has a special meaning,
it is used to identify the tap interface if the nativenet module is used.
The target debug
can be used to invoke a debugger on some platforms.
For the native port the additional targets all-valgrind
and valgrind
exist.
The all-valgrind
target can be used instead of all
to build the application
for later use with the valgrind memory analyzer. This can be done with the
valgrind
target.
Some RIOT folders contain special Makefiles like Makefile.base
,
Makefile.include
or Makefile.dep
. The first one can be included into other
Makefiles to define some standard targets. The files called Makefile.include
are used in boards
and cpu
to append target specific information to
variables like INCLUDES
, setting the include paths. Makefile.dep
serves to
define dependencies.
By default a RIOT build comprises only the application code, the kernel, and platform specific code. In order to use additional modules, such as a particular device driver or a system library, you have to append the modules' names to the USEMODULE variable. For example, to build an application using the SHT11 temperature sensor and 6LoWPAN network stack, your Makefile needs to contain these lines:
USEMODULE += sht11
USEMODULE += sixlowpan
To contribute a new module to RIOT, your module's Makefile needs to set the
variable MODULE
to a unique name. If the module depends on other modules, this
information needs to be added to RIOT's Makefile.dep
.
After the board is initialized, RIOT starts two threads: the idle thread and the main thread. The idle thread has the lowest priority and will run, whenever no other thread is ready to run. It will automatically use the lowest possible power mode for the device. The main thread - configured with a default priority that is right in the middle between the lowest and the highest available priority - is the first thread that runs and calls the main function. This function needs to be defined by the application.
Choosing the right stack size for a new thread is not an easy, but a very crucial task. Since memory is usually a scarce resource in IoT scenarios, one must be careful not to assign too much stack to a single thread. However, if you allocate too little memory for a stack, your application will probably crash. The minimum stack size depends also on some RIOT internal structs and is hardware dependent. In order to help developers finding the right stack size, RIOT defines some typical stack sizes in cpu-conf.
(which should be provided by the implementation for all supported MCUs). The constants for these stack sizes are
KERNEL_CONF_STACKSIZE_IDLE
KERNEL_CONF_STACKSIZE_DEFAULT
KERNEL_CONF_STACKSIZE_PRINTF
KERNEL_CONF_STACKSIZE_MAIN
and can be used by including kernel.h
. ARM based platforms additionally define KERNEL_CONF_STACKSIZE_PRINTF_FLOAT
, because newlibs printf implementation uses more memory for printing floating point numbers.
KERNEL_CONF_STACKSIZE_IDLE
is the stack size for the idle thread and probably the smallest sensible stack size. KERNEL_CONF_STACKSIZE_DEFAULT
is a default size for any typical thread, not using printf. KERNEL_CONF_STACKSIZE_PRINTF
defines additional stack space needed if the thread needs to call printf (which requires additional memory when using newlib. KERNEL_CONF_STACKSIZE_MAIN
is the stack size for the main thread and probably a good size for your application. (Note, that on most non-newlib dependent platforms this will probably equal KERNEL_CONF_STACKSIZE_DEFAULT
.)
Like any microkernel system, RIOT has an IPC API that enables data exchange between modules or a single module and the kernel. This API is documented in the doxygen documentation. The IPC can be used in several ways, such as synchronous or asynchronous, blocking or non-blocking, with or without a message queue. In the default case, a thread does not have a message queue. Hence, messages sent in a non-blocking manner are lost, when the target thread is not in receive mode. A thread may set up a message queue using the corresponding function, but has to provide the memory for this queue itself.
The transceiver module is an abstraction layer and multiplexer between the
network stack and the radio driver. It runs in a single thread with the PID
transceiver_pid
. It provides an IPC interface that enables to configure and
use available radio drivers, e.g. setting the radio channel or sending a packet.
A thread may also register at the transceiver module, in order to get notified
whenever a packet for a particular radio transceiver is received. The
notification message contains a pointer to the packet struct. After processing
the packet, the registered thread needs to decrease this struct's member
processing
which acts as a semaphore for the packet's memory buffer.
Once you have set up the toolchain, you can create your own application. Apart from
the C file(s) containing your source code you need a Makefile. A template
Makefile is available in the dist
folder of the RIOT
repository.
Within your application's Makefile, you can define the target hardware as well as the modules you want to use.
Unless specified otherwise, make will create an elf-file as well as an Intel
hex file in the bin
folder of your application directory.