TockOS Enablement on i.MX RT 1052

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

TockOS Enablement on i.MX RT 1052

ioana_maria_cul
Contributor I
0 0 1,706

This project was implemented by Ioana CULIC (ioana_maria.culic@upb.ro), PhD candidate at the Politehnica University of Bucharest, and Alexandru VOCHESCU (alexandru.vochescu@stud.acs.upb.ro) as part of his bachelor thesis at the Politehnica University of Bucharest. All the contributions are open source and are part of the Tock project, available on github.

 

1. Context

 

When it comes to embedded devices applications, Real Time Operating Systems are widely used as support for running multiple concurrent applications on resource-constrained devices. However, most of the RTOSes available emphasise the efficient resource usage, while  lackin in default security mechanisms such as fault isolation.

 

In this context, Tock OS comes as the first operating system for embedded devices that is developed with security in mind. Tock is described as “an embedded operating system designed for running multiple concurrent, mutually distrustful applications on low-memory and low-power microcontrollers”. Tock OS implements memory isolation through the MPU (Memory Protection Unit) already existent in the ARM Cortex-M devices. It is an open-source project developed by researchers at universities such as UC Berkeley, Stanford or MIT which is written in Rust, a secure-oriented programming language which relies on compile-time memory checking. Rust supports unsafe code snippets, where the compiler does not enforce memory safety.

 

Architecturally speaking, Tock OS is structured on three main layers (Figure 1):

  • Core Kernel - It is written in Rust, has a small size, and its main purpose is to expose the hardware features to the Capsules. This part of the OS is considered fully trusted, so it can contain unsafe code which can dereference raw memory (extremely important in accessing the registers of the peripherals).
  • Capsules - These are written in Rust, can be of larger dimension, mostly equivalent to the linux kernel drivers. They must not contain unsafe code.
  • Processes - They can be written in any programming language (for now only C, C++ and Rust are supported). They rely heavily on the MPU.

 

113830988_287408362355735_6794883327032545373_n.png

Figure 1. The TockOS stack. (Source: https://github.com/tock/tock/blob/master/doc/tock-stack.png)

 

In order to extend the usage of this Operating System, we created support for a new board: the i.MX RT 1052 EVKB, which features an ARM Cortex-M7 processor with a 600 MHz frequency and up to 512 kB Tightly Coupled Memory.

 

2. Process overview - adding a new board to Tock OS

 

When we are talking about the code, the Tock OS project is structured in the following folders, which contain modules (that in Rust are called crates

 

  • arch/ -  It contains the code specific to the MCU architecture such as the context switch from kernel to userspace or the interaction with the MPU.
  • boards/ - It contains the initialization and start-up code for each board that is supported by Tock. This code is used for initializing the peripherals used by the board such as UART (Universal Asynchronous Receiver-Transmitter) and the capsules exposed by the board, and in starting the kernel loop.
  • chips/ -  It contains the code that implements the hardware features in a generic way in order to be used by the capsules without depending on the board or MCU that Tock OS runs on (in Rust this feature is called implementing traits). This part of the project contains the low-level interaction with registers for peripherals such as GPIO, UART, or I2C.
  • kernel/ - It contains microcontroller-independent code. Here we can find the implementations for the process scheduler, memory management, and the structure and functions of a process. Moreover, in this part of the project we find the generic functions that need to be exported by the code for each peripheral in the chips/ folder.
  • tools/ - It contains tools used mostly for code formatting, but also tools which can be helpful in the development process.
  •  

In order to add support for a new board in Tock OS, we first have to make sure that the MCU architecture is supported by the OS by checking the arch component of the project. Otherwise, we need to port it first by creating a crate for the new architecture in the arch/ folder. After that, we need to create a new chip crate if the MCU is not supported yet (which was also the case for i.MX RT 1050 MCU). As the final step, we need to create a board crate which instantiates the modules implemented in the correspondent MCU crate. This component will also set the clock frequency for the peripherals used, load the applications from flash, and finally start the kernel loop (essentially starting the Operating System).

 

Last step in the process is to make the code available to use for other users, by creating a Pull Request on Tock OS github.

 

3. The porting process 

 

The porting process takes place only in the Core Kernel part of the Operating System so the code can contain unsafe sections since it is fully trusted. However, the aim is to keep the unsafe snippets to minimum.

 

The first thing we had to do in the porting process, since Tock OS did not support the ARM Cortex-M7 architecture was to include it as a new module. However, since the ARM Cortex-M4 was already supported, we have created the ARM Cortex-M7 crate based on it, the only major difference being that M7 supports 16 MPU regions instead of 8 (which is the case for M4).

 

The next step is related to the chips/ component of the project, where the MCU-specific implementations are contained. Therefore, we started implementing a few of the core features of the board as different modules in the i.MX RT 1050 MCU crate such as:

  • CCM (Clocks Controller Module), which is used for activating the clock used for the peripherals implemented by us in the porting process;
  • Iomuxc (Input Output Multiplexer Controller), used for configuring different electronical aspects of the pins exposed by the board, but also for configuring alternative functions for different hardware protocols such as I2C, UART or SPI;
  • GPIO (General Purpose Input Output), used for the interaction with the pins;
  • GPT (General Purpose Timer), used for delay functions (the function in the userspace library which uses this module is called delay_ms);
  • LPUART (Low-Power Universal Asynchronous Receiver-Transmitter), used for communication through the serial line with the PC from which the board is programmed;
  • I2C (Inter-integrated Circuit) - hardware protocol used for communicating with other devices; it can be used for testing the accelerometer/magnetometer sensor (Fxos8700) present in the i.MX RT 1052 EVKB board;
  • NVIC (Nested-Vector Interrupt Controller), a module for assigning handlers to be called by the Instruction Service Routine in the kernel when an interrupt signal appears.

 

The final stage of the process was to create a new crate in the boards/ folder where we instantiated the features implemented in the  i.MX RT 1050 MCU crate. This crate functions as a start-up configuration file for the Tock Operating System.

 

4. The result

Through this process, we managed to create a working Tock OS instance on the i.MX RT 1052 EVKB board and created a pull request on Tock OS github in order to make the code be available for everyone to use. The functionalities implemented were tested using a simple C application in userspace, with which we interact through the serial line (using the Lpuart module) and through which we can turn the User LED on or off using the GPIO module (Figure 2), or print information from the accelerometer sensor (through the I2C module).

 

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <timer.h>

#include <led.h>

#include <ninedof.h>

#include <console.h>

 

static bool ninedof = false;

 

int main(void) {

  char c = 0;

  char str[10];

  int i = 0;

  printf("What is your name?\r\n");

  c = getch();

  while (c != 13) {

    str[i++] = c;

    c = getch();

  }

 

  printf("Welcome %s!\r\n"

    "Type \"o\" to turn led on, or \"f\" to turn led off!\r\n"

    "Type \"s\" to print accelerometer data!\r\n"

    "Press \"e\" to exit!\r\n", str);

  while (1)

  {

    c = getch();

    printf("You typed: %c!\r\n", c);

    if (c == 'o')

      led_on(0);

    else if (c == 'f')

      led_off(0);

    else if (c == 's') {

      ninedof     = driver_exists(DRIVER_NUM_NINEDOF);

 

      int ninedof_x = 0, ninedof_y = 0, ninedof_z = 0;

      if (ninedof) {

          ninedof_read_acceleration_sync(&ninedof_x, &ninedof_y, &ninedof_z);

          printf("FXOS8700CQ: X:               %d\r\n", ninedof_x);

          printf("FXOS8700CQ: Y:               %d\r\n", ninedof_y);

          printf("FXOS8700CQ: Z:               %d\r\n", ninedof_z);

        }

    }

    else if (c == 'e')

      break;

  }

  printf("Good\r\n");

  delay_ms(1000);

 

  printf("Bye!\r\n");

  delay_ms(2000);

  return 0;

}

115804790_287117685833095_1815255548123268287_n.jpgFigure 2. LED on example.

 

In order to create a project using Tock OS for the i.MX RT 1052 EVKB, we need to clone the repositories for tock and libtock-c from GitHub. Afterwards, we compile an application for the userspace from the examples in libtock-c by going into the examples directory and running make in the folder of a project such as c_hello/. For the next step, we have to modify the APP variable in boards/imxrt1050-evkb/Makefile to point to the binary generated in the previous step.

 

Example:

APP=../../../libtock-c/examples/c_hello/build/cortex-m7/cortex-m7.tbf

After that, we run make program in the board’s folder.

 

In order to flash the application on the board, we need to use the MCUXpresso IDE and the SDK for the IMXRT1050 board. We import an SDK example such as Hello World in order to generate the hierarchy for the project. Next, we copy the app image from target/thumbv7em-none-eabi/debug/imxrt1050-evkb-app.axf to the Debug folder in MCU Expresso via drag and drop (Figure 3).

 

115805741_290649905701963_4743804123734922978_n.png

Figure 3. Importing the app image.

 

Afterwards, we modify the LinkServer in order to point to the Tock OS binary instead of pointing towards the hello_world example as depicted in figure 4.

 

112453659_755184065287053_569680544364068795_n.png

Figure 4. Edit LinkServer.

 

Finally, we simply press debug in order to flash the application on the board and enjoy!

 

5. Future work

For the moment, we are working on the created pull request in order for it to be accepted and afterwards, we will work on exposing all the other functionalities such as SPI or Ethernet and we will enable cache for instructions and data. Furthermore, we are looking into porting the other boards in the i.MX RT family such as the i.MX RT 1060 EVKB.

 

When the Pull Request will be accepted, the board will appear as an experimental board supported by Tock OS, since not all features are implemented and the project is not thoroughly tested.