Table of Contents

A simple ARM Operating System for the Raspberry Pi, supporting Aarch32 and Aarch64 architectures. It supports both Raspberry Pi Zero / Zero W and Raspberry Pi 4.

This project was made for the Embedded Systems course at NTUA 2020-2021.

Quick Links:

There is presentation in Greek that was made to showcase the Project. You can find it here or hosted in the repository.

About

This simple Operating System (kernel) is inspired and based on the Linux kernel, especially the ARM specific architecture parts. The features of the kernel are presented in detail in a later section. The main focus of this project, was to dive deep into core OS related concepts (such as the scheduler, drivers, handling processes/memory) and get to know the hardware and low level features of ARM embedded devices such as the Raspberry Pi.

The other focus of this project, was to explore both the Aarch32 and Aarch64 ARM states developing the OS using the ARMv6/ARMv7-a and the ARMv8-a architecture respectively. The 32-bit version is the older and more widespreed architecture in embedded devices, but the 64-bit version is a more powerfull, modern and secure architecture with lots of differences from the old one.

  • The Aarch32 version was tested on the Raspberry Pi Zero W, but it should work with minor changes to the Raspberry Pi 2 and the original Pi.
  • Then Aarch64 version was tested on the Raspberry Pi 4, but it should work with minor changes to the Raspberry Pi 3.

Technologies

The main technologies used for this project (language, tools, hardware):

C logo gcc logo make logo bash logo aarch64 pi logo raspberry pi logo travic ci logo github logo doxygen logo

For a detailed list of all technologies used check the technologies used section.

Documentation

There is proper documentation available for the project in two different formats:

Doxygen Documentation

There is detailed documentation of all the source code, generated by Doxygen, describing all the structures and functions of the project.

NOTE: The documentation is generated either for the Rasperry Pi 4 or the Raspberry Pi Zero / Zero W. They have some differences mainly regarding the register addresses, but they are mostly identical.

Wiki Documentation

There are specific details about the implementation of most major parts of the OS, and guides for installing the dependencies and running the OS on a Pi.

Project Structure

The project structure for the source code is the following:

├── arch
│   ├── armv6
│   ├── armv7-a
│   └── armv8-a
├── armstub
│   └── src
├── include
│   ├── armv6
│   ├── armv8-a
│   ├── common
│   ├── kernel
│   └── peripherals
└── src
    ├── common
    └── kernel

The include/ directory contains definitions of structures and functions:

  • kernel/: For the core features of the kernel.
  • armv6/ and armv8-a/: For architecture specific routines implemented in ARM assembly code.
  • common/: For common libraries such as string.h and stdlib.h needed for the kernel.
  • peripherals/: For the register’s addresses for the peripherals of the devices, in order to provide basic drivers for them.

The src/ directory contains the implementations of the functions defined in the include/ directory.

The arch/ directory contains the implementations of the architecture specific routines implemented in ARM assembly code, separated based on the ARM architecture.

The armstub/ directory contains a simple bootloader for the ARMv-8 architecture, in order to boot the kernel in the proper Exception Level.

Features

The current features of the kernel are the following:

  • Drivers for basic peripherals of the Pi boards:
    • mini UART
    • System Timers
    • GPIO Pins
    • LED
  • Implementation of basic library functions:
    • string.h
    • stdlib.h
    • stdbool.h
    • printk()
  • Exception Level handling for the ARMv-8 architecture:
    • Setting kernel at EL 1.
  • Handling Interrupts - Exceptions:
    • Initialize vector table.
    • Handles Timer and UART IRQs.
  • Scheduler and processes:
    • Creates and kills processes.
    • Schedules them in order to run multiple processes concurrently.
    • Performs Context Switching for the execution of different processes.
  • Implementation of basic serial console:
    • Communication with users through serial input and output.
    • Available commands to execute.

Features to be implemented in the near feature:

  • System Calls
  • Proper Virtual memory management
  • Video drivers

Demo of kernel

A screenshot of the kernel in action, after booting up:

                  _____ _____
 ___ ___ _____   |     |   __|
| . |  _|     |  |  |  |__   |
|__,|_| |_|_|_|  |_____|_____|

armOS initializing...

        Board: Raspberry Pi 4
        Arch: aarch64


----- Exception level: EL1 -----
Initializing IRQs...Done
Enabling IRQ controllers...Done
Enabling IRQs...Done
Initializing LED...Done

This is a minimal console, type 'help' to see the available commands. (Maximum Input Length: 80)
root@pi-4#

A screencast where, we create 3 processes, run them and kill them: armOS asciicast example

Available Commands

Showing the available commands of the console, using the help command:

root@pi-4# help
Available commands:
    help:
        Prints available commands to the console.
    help_led:
        Prints available LED commands to the console.
    create_procs:
        Creates proc_num kernel processes.
    run_procs:
        Runs the created kernel processes concurrently.
    kill_procs:
        Kills all created kernel processes.
    halt:
        Halts the system.

Requirements

In order to run this kernel in a Raspberry Pi you need the following:

Boards

A Rasberry Pi board. One of the following:

  • Raspberry Pi 4
  • Raspberry Pi Zero or Zero W

Tools

  • A USB to TTL serial cable.
  • An a SD Card.

Software

  • The Pi Imager program.
  • A Linux/Unix development environment to build the project.
  • A Serial Console emulator (suggested: screen).

Toolchain

An ARM Cross-Compiler Toolchain:

Instructions

Install Toolchain

For detailed instructions, see the Install Toolchain wiki page.

Serial Connection with Raspberry PI

For detailed instructions, see the Serial Connection wiki page.

Running on Raspberry Pi

For detailed instructions, see the Installation wiki page.

Basic overview of the steps:

  • Format the SD card, with the Raspberry Pi Imager.
  • Set cross-compiler path on the Makefile.
  • Clone the project.
  • Build project using Makefile.
  • Transfer .img, config.txt to SD Card.
  • Unmount SD card.
  • Put SD card on Pi.
  • Connect USB-to-TTL serial cable to the Pi and Linux host.
  • Open screen.
  • Power on the Pi.

Generating Documentation

In order to generate the Doxygen documentation locally, see the Generate Docs wiki page.

Implementation Details

For information about the source code, see on Wiki, the Implementation section.

For detailed documentation of all the source code, generated by Doxygen, describing all the structures and functions of the project, see the GitHub Pages hosted site.

Technologies Used

A complete list of all the technologies used in this project:

Technology Selection
Editor Visual Studio Code
Host OS Ubuntu 20.04
Cross-Compiler arm-none-eabi-gcc, aarch64-none-elf-gcc
Binutils objdump, objcopy, size, nm
Building Make
Scripts Bash
Documentation Doxygen
CI Travis CI
Static Hosting GitHub Pages
Version Control Git, GitHub
Console Emulator screen
Boards Raspberry Pi 4, Raspberry Pi Zero W
Hardware SD card, USB-to-TTL Serial cable

Resources

Manuals

Wikis

Repositories

Book