Added RioT OS support to PolyMCU by Olivier on 11/12/2015 00:42

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:

RIOT-OS logo

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

Run RioT-OS Hello World

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.

Integrate RioT-OS in PolyMCU

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!

RioT-OS and LLVM support

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!

RioT-OS and CMSIS RTOS API support

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:

Notes

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.

No comment yet

Login to comment Comment as anonymous