armOS - Building a simple ARM Operating System for the Raspberry Pi
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:
- GitHub repository: https://github.com/thanoskoutr/armOS
- Wiki Documentation: https://github.com/thanoskoutr/armOS/wiki
- Doxygen Documentation: https://thanoskoutr.github.io/armOS/
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):
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:
- In the GitHub Pages of the project’s GitHub repository.
- In the Wiki section of the project’s GitHub repository.
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/
andarmv8-a/
: For architecture specific routines implemented in ARM assembly code.common/
: For common libraries such asstring.h
andstdlib.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:
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:
- For building the 32-bit kernel:
arm-none-eabi-gcc
: Download from ARM website - For Linux x86_64 Hosts - For building the 64-bit kernel:
aarch64-none-elf-gcc
Download from ARM website - For Linux x86_64 Hosts
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
- Linux Kernel - /arch/arm/
- Learning operating system development using Linux kernel and Raspberry Pi
- Building an Operating System for the Raspberry Pi
- Raspberry Pi ARM based bare metal examples
- Bare metal Raspberry Pi 3 tutorials
- Writing a “bare metal” operating system for Raspberry Pi 4