vsOS – Very Simple OS

vsOS is a Very Simple Operating System for the STM32-P405 board, it can also be build for the lm3s6965evb board running under the QEMU emulator.

It is a small unix-like operating system for ARM Cortex-M3/M4 processors and written to demonstrate some features of operating system design, it has the following features:

  • Preemptive task switching
  • Fault handling to identify task responsible for fault
  • System calls
  • GPIO control
  • Serial I/O
  • VSFS – A minimal read only file system (to provide /dev/tty etc.)
  • Character and block device layer
  • Minimal implementation of stdio and unistd functions (read()/write()/printf() etc.)
  • MiniSH A small shell implemention for built in command (ls, cat etc.)
  • Scripts to allow Jenkins or other CI integration tools to build and test
  • Built in support for unit tests
  • Kernel API is portable between board types
  • Runs in less than 8KB of memory (excluding flash file system)
  • Build time is measured in seconds


The git repo can be found on bitbucket and can be cloned from BitBucket as follows:

git clone https://bitbucket.org/akeane_chx/vsos.git

There are two targets which can be built, qemu-lm3s6965evb and stm32p405, the default is qemu-lm3s6965evb but can be changed by setting the environment variable BOARD, for example to build the default do the following:

git clone https://bitbucket.org/akeane_chx/vsos.git
cd vsos

To build the for the stm32p405 target do the following:

git clone https://bitbucket.org/akeane_chx/vsos.git
cd vsos
BOARD=stm32p405 make

You can also edit the Makefile to set the default board.

Always do a make clean after changing code as the build system doesn’t allow for dependancies to be correctly specified, however a fresh build only takes a few seconds.

For the qemu-lm3s6965evb target, open another window, change to the vsos directory and do the following:

make qemu

<output not shown>

qemu-system-arm -machine lm3s6965evb -S -gdb tcp::1234 -nographic -kernel vsos.elf -chardev tty,id=any,path=/dev/pts/0

In the original window do the following:

make debug

<output not shown>

arm-none-eabi-gdb -x gdbinit
GNU gdb (7.10-1ubuntu3+9) 7.10
Copyright (C) 2015 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-linux-gnu --target=arm-none-eabi".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
Find the GDB manual and other documentation resources online at:
For help, type "help".
Type "apropos word" to search for commands related to "word".
0x00000040 in ?? ()
Loading section .text, size 0x1cec lma 0x0
Loading section .rodata, size 0x286 lma 0x1cec
Loading section .data, size 0xcc lma 0x1f72
Loading section .rootfs, size 0x800 lma 0x4000
Start address 0x0, load size 10302
Transfer rate: 10060 KB/sec, 1287 bytes/write.
Breakpoint 1 at 0x11ea: file init.c, line 50.

Breakpoint 1, init () at init.c:50
50 {

This starts the gdb debugger and connects to the QEMU instance, type cont and press return in gdb as follows:

Breakpoint 1, init () at init.c:50
50 {
(gdb) cont

Now go back to the QEMU window and the following is displayed:

VSOS 0.1

Board: lm3s6965evb
 Serial baudrate: 115200
 Clock rate : 12000000
 Filesystem: vsfs: 0x00003342 registered
 Block device: flash : 0 registered
 Opening flash
 Character device: 'null' : 0 registered
 Character device: 'zero' : 1 registered
 Character device: 'serial' : 2 registered

You can enter anything for the username, and just press enter for the password:

username: armE

armE@hostname ~/ $

Now you can type commands such as ls and cat:

armE@hostname ~/ $ ls
drwxrwxr-- . --> 1
drwxrwxr-- .. --> 1
drwxrwxr-- dev --> 2
-rw-rw-r-- file --> 3
armE@hostname ~/ $ cat file
This is some file data
armE@hostname ~/ $ ls dev
drwxrwxr-- . --> 2
drwxrwxr-- .. --> 1
crw-rw-r-- null
crw-rw-r-- ttyS0
crw-rw-r-- zero

For the stm32p405 target open a new window and type:

sudo minicom -D /dev/ttyUSB0 115200 # Or wherever your serial port is located

In the original window run:

sudo ./scripts/stm32p405_boot.sh

Type cont at the gdb prompt as above, go back to the minicom window and you will get the login prompt as shown above, you will also see the user LED flashing as a seperate task is running to do this and demonstrate multiple tasks running.