Yesterday, I was asked about how to integrate RioT-OS in PolyMCU. Hmm, I do not think I heard of RioT OS before receiving this email. From the RioT-OS website:
In term of resource consumption, it looks quite similar to ARM RTX and FreeRTOS.
The first step to integrate RioT-OS is to create its new root directory into PolyMCU. The RTOS will live into RTOS/RioTOS
cd RTOS
mkdir RioTOS && cd RioTOS
git clone https://github.com/RIOT-OS/RIOT.git src
Get the latest stable branch
cd src
git checkout 2015.09
Let's try to build and deploy RioT-OS hello_world
example on the NXP LPC1768 mbed board after adding the Embedded GCC Toolchain to my PATH
export PATH=~/Toolchains/gcc-arm-none-eabi-4_9-2015q3/bin:$PATH
cd examples/hello-world
make BOARD=mbed_lpc1768 flash
Building application "hello-world" for "mbed_lpc1768" with MCU "lpc1768".
"make" -C /home/olivier/labapart/polymcu/RTOS/RioTOS/boards/mbed_lpc1768
"make" -C /home/olivier/labapart/polymcu/RTOS/RioTOS/core
"make" -C /home/olivier/labapart/polymcu/RTOS/RioTOS/cpu/lpc1768
"make" -C /home/olivier/labapart/polymcu/RTOS/RioTOS/cpu/cortexm_common
"make" -C /home/olivier/labapart/polymcu/RTOS/RioTOS/cpu/lpc1768/periph
"make" -C /home/olivier/labapart/polymcu/RTOS/RioTOS/drivers
"make" -C /home/olivier/labapart/polymcu/RTOS/RioTOS/sys
"make" -C /home/olivier/labapart/polymcu/RTOS/RioTOS/sys/auto_init
"make" -C /home/olivier/labapart/polymcu/RTOS/RioTOS/sys/newlib
"make" -C /home/olivier/labapart/polymcu/RTOS/RioTOS/sys/tsrb
"make" -C /home/olivier/labapart/polymcu/RTOS/RioTOS/sys/uart_stdio
text data bss dec hex filename
7464 128 2632 10224 27f0 /home/olivier/labapart/polymcu/RTOS/RioTOS/examples/hello-world/bin/mbed_lpc1768/hello-world.elf
/home/olivier/labapart/polymcu/RTOS/RioTOS/boards/mbed_lpc1768/dist/flash.sh
UPLOAD SUCCESFUL
Let's see if the RioT-OS application runs on the LPC1768 board:
main(): This is RIOT! (Version: 2015.09-olivier-laptop-HEAD)
Hello World!
You are running RIOT on a(n) mbed_lpc1768 board.
This board features a(n) lpc1768 MCU.
I noticed the existing board and CPU supports in RioT-OS repository. We want RioT-OS to use the board and device support of PolyMCU and not to duplicate the hardware support in both projects. Using both supports could lead to conflict.
Note: I will add a link to the github commits to help you to see the changes I have done while porting RioT-OS to PolyMCU.
We will try to integrate examples/ipc_pingpong
into PolyMCU framework. We will start bycopying examples/ipc_pingpong
into Application/Examples
as RioTOS
. Github: RTOS: Added RioT-OS
We can remove the application's Makefile
to replace it by Application.cmake
and CMakeLists.txt
files we copied from the ones from Application/Examples/CMSIS_RTOS
. Github: RTOS/RioTOS: Added initial PolyMCU support
And we try to build it...
mkdir Build && cd Build
export CROSS_COMPILE=~/Toolchains/gcc-arm-none-eabi-4_9-2015q3/bin/arm-none-eabi-
cmake -DBOARD=NXP/LPC1768mbed -DAPPLICATION=Examples/RioTOS ..
make
Linking C static library libboard_nxp.a
[ 58%] Built target board_nxp
Scanning dependencies of target riot_rtos
[ 61%] Building C object RTOS/RioTOS/CMakeFiles/riot_rtos.dir/src/core/atomic.c.o
In file included from /home/olivier/labapart/polymcu/RTOS/RioTOS/src/core/atomic.c:26:0:
/home/olivier/labapart/polymcu/RTOS/RioTOS/src/cpu/cortexm_common/include/cpu.h:35:22: fatal error: cpu_conf.h: No such file or directory
#include "cpu_conf.h"
First error! If we look for cpu_conf.h
in RIOT-OS repository, we can find this file in the MCU ports. As said earlier we do not want to add board specific support from RIOT-OS. So we will create a file RTOS/RioTOS/include/cpu_conf.h
that will invoke PolyMCU board's board.h
defined by the different boards. Github: RTOS/RioTOS: Added 'cpu_conf.h'
After various tweaks...
(...)
[ 92%] Building C object RTOS/RioTOS/CMakeFiles/riot_rtos.dir/src/cpu/cortexm_common/panic.c.o
[ 95%] Building C object RTOS/RioTOS/CMakeFiles/riot_rtos.dir/src/cpu/cortexm_common/reboot_arch.c.o
[ 97%] Building C object RTOS/RioTOS/CMakeFiles/riot_rtos.dir/src/cpu/cortexm_common/thread_arch.c.o
Linking C static library libriot_rtos.a
[ 97%] Built target riot_rtos
Scanning dependencies of target Firmware
[100%] Building C object Application/Examples/RioTOS/CMakeFiles/Firmware.dir/main.c.o
Linking C executable RIOT_RTOS_Example.elf
text data bss dec hex filename
11648 100 1872 13620 3534 /home/olivier/labapart/polymcu/Build/Application/Examples/RioTOS/RIOT_RTOS_Example.elf
succesfully updated crc to: efff5bde
[100%] Built target Firmware
Would it run? I noticed earlier in the source code that the entrypoint of RioT OS kernel is kernel_init
. Let's check if this function is present in the firmware:
$ ${CROSS_COMPILE}nm Application/Examples/RioTOS/RIOT_RTOS_Example.elf | grep kernel_init
$
Ouch, the RioT-OS entrypoint is not present!
PolyMCU is based on Newlib. Newlib invokes the software hook software_init_hook()
before main()
is started. Github: RTOS/RioTOS: Added softwareinithook()
We will use this hook to start RioT-OS kernel such as we did for FreeRTOS. New try...
(...)
[ 93%] Building C object RTOS/RioTOS/CMakeFiles/riot_rtos.dir/src/cpu/cortexm_common/panic.c.o
[ 95%] Building C object RTOS/RioTOS/CMakeFiles/riot_rtos.dir/src/cpu/cortexm_common/reboot_arch.c.o
[ 97%] Building C object RTOS/RioTOS/CMakeFiles/riot_rtos.dir/src/cpu/cortexm_common/thread_arch.c.o
Linking C static library libriot_rtos.a
[ 97%] Built target riot_rtos
Scanning dependencies of target Firmware
[100%] Building C object Application/Examples/RioTOS/CMakeFiles/Firmware.dir/main.c.o
Linking C executable RIOT_RTOS_Example.elf
../../../RTOS/RioTOS/libriot_rtos.a(kernel_init.c.o): In function `idle_thread':
/home/olivier/labapart/polymcu/RTOS/RioTOS/src/core/kernel_init.c:74: undefined reference to `lpm_arch_set'
/home/olivier/labapart/polymcu/RTOS/RioTOS/src/core/kernel_init.c:77: undefined reference to `lpm_arch_set'
collect2: error: ld returned 1 exit status
make[2]: *** [Application/Examples/RioTOS/RIOT_RTOS_Example.elf] Error 1
make[1]: *** [Application/Examples/RioTOS/CMakeFiles/Firmware.dir/all] Error 2
make: *** [all] Error 2
lpm_arch_set()
is the RioT OS power management function. We will provide a __attribute__((weak))
implementation to allow boards to provide a more optimal implementation. Github: RTOS/RioTOS: Added generic lpmarchset()
$ make install
[ 6%] Built target polymcu
[ 27%] Built target device_nxp
[ 46%] Built target tool_lpcrc
[ 48%] Built target board_nxp
Scanning dependencies of target riot_rtos
[ 51%] Building C object RTOS/RioTOS/CMakeFiles/riot_rtos.dir/riotos.c.o
Linking C static library libriot_rtos.a
[ 97%] Built target riot_rtos
Linking C executable RIOT_RTOS_Example.elf
text data bss dec hex filename
12392 108 3812 16312 3fb8 /home/olivier/labapart/polymcu/Build/Application/Examples/RioTOS/RIOT_RTOS_Example.elf
succesfully updated crc to: efff5af6
[100%] Built target Firmware
Install the project...
-- Install configuration: "Debug"
INFO:root:new board id detected: 101030cf6fd400ae795d2bba5413a147da5d
INFO:root:board allows 10 concurrent packets
INFO:root:DAP SWD MODE initialised
INFO:root:IDCODE: 0x2BA01477
INFO:root:6 hardware breakpoints, 4 literal comparators
INFO:root:CPU core is Cortex-M3
INFO:root:4 hardware watchpoints
[====================] 100%
Would it work this time? Let's boot it... No output on the UART :-(
I will have to connect the GDB debugger to see where the board is stuck.
$ ${CROSS_COMPILE}gdb Application/Examples/RioTOS/RIOT_RTOS_Example.elf
Reading symbols from Application/Examples/RioTOS/RIOT_RTOS_Example.elf...done.
(gdb) target remote localhost:3333
Remote debugging using localhost:3333
SVC_Handler () at /home/olivier/labapart/polymcu/Device/NXP/lpc_chip_175x_6x/src/cr_startup_lpc175x_6x.c:344
344 { while(1) {}
(gdb) where
#0 SVC_Handler () at /home/olivier/labapart/polymcu/Device/NXP/lpc_chip_175x_6x/src/cr_startup_lpc175x_6x.c:344
#1 <signal handler called>
#2 0x00001bee in thread_arch_start_threading () at /home/olivier/labapart/polymcu/RTOS/RioTOS/src/cpu/cortexm_common/thread_arch.c:257
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
(gdb)
We can notice SVC_Handler()
is still pointing to the default implementation provided by cr_startup_lpc175x_6x.c
.
RioT-OS actually uses isr_svc()
instead. After calling isr_svc()
in SVC_Handler()
... Github: RTOS/RioTOS: Added SVCHandler() and PendSVHandler()
Got msg main(): This is RIOT! (Version: 2015.09)
Starting IPC Ping-pong example...
1st thread started, pid: 2
2nd thread started, pid: 3
2nd: Got msg from 2
1st: Got msg with content 2
2nd: Got msg from 2
1st: Got msg with content 3
2nd: Got msg from 2
1st: Got msg with content 4
2nd: Got msg from 2
1st: Got msg with content 5
2nd: Got msg from 2
(...)
Success!
Let's try to build RIOT-OS with LLVM:
$ rm -Rf * && CC=clang-3.6 cmake -DBOARD=NXP/LPC1768mbed -DAPPLICATION=Examples/RiotOS .. && make
(...)
[ 93%] Building C object RTOS/RioTOS/CMakeFiles/riot_rtos.dir/src/cpu/cortexm_common/panic.c.o
[ 95%] Building C object RTOS/RioTOS/CMakeFiles/riot_rtos.dir/src/cpu/cortexm_common/reboot_arch.c.o
[ 97%] Building C object RTOS/RioTOS/CMakeFiles/riot_rtos.dir/src/cpu/cortexm_common/thread_arch.c.o
Linking C static library libriot_rtos.a
[ 97%] Built target riot_rtos
Scanning dependencies of target Firmware
[100%] Building C object Application/Examples/RioTOS/CMakeFiles/Firmware.dir/main.c.o
Linking C executable RIOT_RTOS_Example.elf
text data bss dec hex filename
14084 108 3812 18004 4654 /home/olivier/labapart/polymcu/Build/Application/Examples/RioTOS/RIOT_RTOS_Example.elf
succesfully updated crc to: efff558a
[100%] Built target Firmware
... and it even runs fine on the board!
You want to go further? What about CMSIS RTOS support in RioT-OS?
CMSIS RTOS API allows to switch RTOS (such as RTX, FreeRTOS) without having to change the code of your application.
Examples/CMSIS_RTOS
is a simple example that creates two tasks and invokes some delay.
rm -Rf * && cmake -DBOARD=NXP/LPC1768mbed -DAPPLICATION=Examples/CMSIS_RTOS -DSUPPORT_RTOS=RioTOS .. && make
I added some initial CMSIS RTOS support to help people to start. But it is not completed yet... Github: RTOS/RioTOS: Added some initial CMSIS RTOS API support
Once this example works, if you want to go even further, you can try to pass the CMSIS RTOS API Conformance test we wrote: https://github.com/labapart/polymcu/tree/master/Application/LabAPart/CMSISRTOSConformance
To build the CMSIS RTOS conformance test for RioT-OS:
rm -Rf * && cmake -DBOARD=NXP/LPC1768mbed -DAPPLICATION=LabAPart/CMSIS_RTOS_Conformance -DSUPPORT_RTOS=RiotOS .. && make
The minimal set of CMSIS RTOS API functions that must be supported by the RTOS to pass the test:
I have been really surprise to see that RioT-OS design choices have been really similar to the ones we choose for PolyMCU.
The source code is divided into the same modules that exist in PolyMCU: board
(PolyMCU's Board
), cpu
& drivers
(PolyMCU's Devices
), examples
(PolyMCU's Applications
).
Also the board initialization is done before main()
starts.