3. User Space
The SO3 user space is a small, self-contained set of applications built against
the MUSL C library. Everything lives under usr/.
3.1. The MUSL C library
SO3 uses MUSL as its libc for user applications — a small, clean and
static-friendly implementation well suited to embedded systems. Not every libc
function is enabled; functions are pulled in as the need arises. More complex
facilities (for example full pthreads) are intentionally kept minimal.
Applications are linked statically against MUSL, so each executable is self-contained.
3.2. Build system (CMake)
The user space is built with CMake and the MUSL cross toolchain. The build
is driven by usr/build.sh, which:
reads
PLATFORMfrom../build.confand selects the matching toolchain file —usr/aarch64-linux-musl.cmakefor 64-bit platforms (virt64, rpi4_64),usr/arm-linux-musl.cmakefor 32-bit ones;configures and builds the tree under
usr/build/;separates debug information (a stripped
*.elfplus a*.elf.debug) and collects the deployable binaries inusr/build/deploy/.
cd usr
./build.sh
Adding an application means dropping a C file in usr/src/ and referencing it
from the relevant CMakeLists.txt.
3.3. Applications
The standard applications in usr/src/ include:
Program |
Role |
|---|---|
|
the init process: reads |
|
the interactive shell (the |
|
basic file utilities |
|
ICMP ping (exercises the lwIP stack) |
|
simple timing utility |
|
minimal example |
|
API and subsystem demonstrations |
|
LVGL graphical demos (framebuffer builds — see LVGL — Light and Versatile Embedded Graphics Library) |
MicroPython |
the MicroPython interpreter (ARM64 — see MicroPython) |
User-space libraries used by the applications live in usr/lib/ (the LVGL
graphics library, logging helpers, and so on).
3.4. Init and the shell
When the kernel hands over to user space, the root process execve()s
init.elf. Init reads a small commands.ini script and runs it line by
line; a typical script prints a banner and starts the shell:
echo SO3 Init Program :)
shell
The shell then presents the so3% prompt and runs commands by forking and
execve()-ing the corresponding .elf from the root filesystem.
Note
The shell does not implement cd: all executables and data files live in
the root directory of the filesystem (except the device nodes under
dev/).
3.5. Root filesystem
The applications are delivered through a root filesystem. In the default
(ramfs) configuration this is a FAT image, rootfs/rootfs.fat, created by:
cd rootfs
./create_ramfs.sh
deploy.sh -u copies the freshly built user binaries from
usr/build/deploy/ into this image, which is then packed into the FIT image
and written to the SD-card (User Guide). The same FAT image can be
inspected on the host by mounting its partition — useful when debugging what
actually ended up on the target.