A sophisticated bare-metal operating system designed to run on Raspberry Pi 4 and 5, develo4. Build release version:
cargo build --release --target aarch64-unknown-none
-
Extract raw kernel binary:
# IMPORTANT: Extract only the .text section containing executable code # (The ELF places rodata first, but Pi firmware expects code at 0x80000) rust-objcopy -j .text -O binary target/aarch64-unknown-none/release/tiny_os kernel8.img
-
Copy kernel to SD card:
cp kernel8.img /path/to/sdcard/ ```st. TinyOS features comprehensive memory management, interrupt handling, and an interactive shell interface.
- ✅ Bare-metal ARM64 kernel with custom boot process
- ✅ Interactive shell with real-time command processing (UART only)
- ✅ Comprehensive memory management with bitmap allocation
- ✅ Interrupt management system with ARM GIC simulation
- ✅ Exception vector table with ARM64 exception handling
- ✅ Hardware drivers for UART, GPIO, and System Timer
- ✅ Diagnostic and testing suite with health checks
- ✅ QEMU development environment with real hardware deployment ready
- ✅ Memory protection with corruption detection and canary values
- ✅ Defragmentation support and real-time memory analysis
- ✅ Performance benchmarks and comprehensive test suites
- ✅ Cross-platform development with automated testing
- 🔧 Serial-based interface - No HDMI/video output (by design)
- Rust: Install from rustup.rs
- QEMU: For testing and development
Install QEMU:
# macOS
brew install qemu
# Ubuntu/Debian
sudo apt install qemu-system-arm
# Arch Linux
sudo pacman -S qemu-arch-extra
Setup Rust Toolchain:
# Add the AArch64 target for cross-compilation
rustup target add aarch64-unknown-none-softfloat
Development (QEMU):
# Easy way - use the run script
./run.sh
# Manual way
cargo build
qemu-system-aarch64 -M raspi4b -kernel target/aarch64-unknown-none/debug/tiny_os -serial stdio -display none
Note: Press Ctrl+A
then X
to exit QEMU.
Run all tests:
./test_tinyos.sh
Quick validation:
./test_tinyos.sh validate
Test specific components:
./test_tinyos.sh boot # Boot and system validation tests
./test_tinyos.sh unit # Rust unit tests
./test_tinyos.sh memory # Memory management tests (automated)
./test_tinyos.sh interrupts # Interrupt handling tests (automated)
./test_tinyos.sh hardware # Hardware/driver tests (automated)
Advanced options:
./test_tinyos.sh --verbose # Show detailed output
./test_tinyos.sh --interactive # Use interactive test suites (requires expect)
./test_tinyos.sh --help # Show all available options
Note: Automated tests are the default and require no external dependencies. Interactive test suites (for manual testing) require the expect
tool and the --interactive
flag.
-
Format SD card with FAT32 partition
CRITICAL: Proper SD card formatting is essential for Pi 5 boot!
Option A: Using Raspberry Pi Imager (Recommended):
# Download and use Raspberry Pi Imager # 1. Select "CHOOSE OS" → "Erase (Format as FAT32)" # 2. Select your SD card # 3. Write (this creates proper partition table)
Option B: Manual formatting (Linux/macOS):
# DANGER: Replace /dev/sdX with your actual SD card device! # Check with: lsblk or df -h # Unmount the SD card first sudo umount /dev/sdX* # Create new partition table and FAT32 partition sudo fdisk /dev/sdX # In fdisk: o (new partition table) → n (new partition) → p (primary) # → 1 (partition number) → Enter → Enter → t (change type) → c (FAT32) → w (write) # Format as FAT32 sudo mkfs.vfat -F 32 /dev/sdX1
Option C: Using diskutil (macOS):
# Find your SD card diskutil list # Unmount and format (replace diskX with your SD card) diskutil unmountDisk /dev/diskX sudo diskutil eraseDisk FAT32 BOOT MBR /dev/diskX
-
Download Raspberry Pi firmware files from rpi-firmware:
For Pi 4:
start4.elf
,start4cd.elf
,start4db.elf
,start4x.elf
fixup4.dat
,fixup4cd.dat
,fixup4db.dat
,fixup4x.dat
bootcode.bin
(Pi 4 only)
For Pi 5:
start_cd.elf
(debug),start.elf
(standard),start_x.elf
(extended)fixup_cd.dat
,fixup.dat
,fixup_x.dat
bcm2712-rpi-5-b.dtb
(device tree blob - this is in the same boot directory!)
Quick download for Pi 5:
# Download Pi 5 firmware files wget https://github.com/raspberrypi/firmware/raw/master/boot/start_cd.elf wget https://github.com/raspberrypi/firmware/raw/master/boot/fixup_cd.dat wget https://github.com/raspberrypi/firmware/raw/master/boot/bcm2712-rpi-5-b.dtb
-
Copy firmware files to SD card root
-
What is the Device Tree Blob (DTB)?
The
bcm2712-rpi-5-b.dtb
file is the Device Tree Blob for Raspberry Pi 5. It describes the hardware layout to the firmware and kernel:- Required for Pi 5: Pi 5 has different hardware than older models
- Hardware description: Tells the system about GPIO pins, peripherals, memory layout
- Firmware dependency: The Pi firmware uses this to initialize hardware correctly
Without the DTB file, Pi 5 will not boot properly!
-
Create config.txt (required for proper boot):
# Enable 64-bit mode arm_64bit=1 # Use appropriate start file based on memory split start_file=start_cd.elf fixup_file=fixup_cd.dat # Set GPU memory split (16MB minimum) gpu_mem=16 # Enable UART for debugging enable_uart=1 # Disable rainbow splash screen disable_splash=1 # For Pi 5: specify device tree device_tree=bcm2712-rpi-5-b.dtb # Kernel loading address (important!) kernel_address=0x80000
-
Build release version:
cargo build --release --target aarch64-unknown-none
-
Extract raw kernel binary: (this is already part of build.sh)
# IMPORTANT: Extract only the .text section containing executable code # (The ELF places rodata first, but Pi firmware expects code at 0x80000) rust-objcopy -j .text -O binary target/aarch64-unknown-none/release/tiny_os kernel8.img
-
Copy kernel to SD card:
cp kernel8.img /path/to/sdcard/
Check boot files on SD card:
# Your SD card should contain these files:
ls /path/to/sdcard/
# Expected: config.txt, kernel8.img, start_cd.elf, fixup_cd.dat, bcm2712-rpi-5-b.dtb (Pi 5)
Enable UART debugging:
Pi 5 boots but no output visible? This is likely a UART configuration issue.
-
Connect USB-to-TTL serial adapter to Pi GPIO pins:
- Pin 8 (GPIO 14, TXD) → Adapter RX
- Pin 10 (GPIO 15, RXD) → Adapter TX
- Pin 6 (Ground) → Adapter Ground
-
Open serial terminal BEFORE powering on Pi:
# Linux/macOS screen /dev/ttyUSB0 115200 # Or use: minicom -D /dev/ttyUSB0 -b 115200 # Or use: picocom /dev/ttyUSB0 -b 115200 # Windows # Use PuTTY, TeraTerm, or similar with COM port at 115200 baud
-
Expected output when TinyOS boots:
TinyOS v0.1.0 - Raspberry Pi Kernel Kernel started successfully! Running on QEMU Raspberry Pi 4 emulation Initializing System Timer... System Timer initialized! Initializing GPIO... GPIO initialized! Initializing Memory Manager... Memory Manager initialized! Initializing Interrupt Controller... Interrupt Controller initialized! TinyOS Interactive Shell Type 'h' for help, 'x' to exit >
-
If you see no output at all:
- Check UART adapter connections
- Verify config.txt has
enable_uart=1
- Try different baud rates: 9600, 38400, 115200
- Check if adapter needs drivers installed
-
If you see garbled output:
- Wrong baud rate (should be 115200)
- Check TX/RX aren't swapped
- Verify 3.3V adapter (NOT 5V!)
-
Alternative: Check HDMI output
IMPORTANT: TinyOS has NO HDMI/display output!
TinyOS is a UART-only operating system designed for embedded/bare-metal development:
- No video output: HDMI monitor will remain blank (this is normal!)
- Serial communication only: All input/output is via UART
- Embedded design: Like most bare-metal kernels, it uses serial for debugging/interaction
Your HDMI monitor staying blank is expected behavior - not an error!
Check kernel build target:
# Verify correct target was used
file target/aarch64-unknown-none/release/tiny_os
# Should show: "ELF 64-bit LSB executable, ARM aarch64"
# CRITICAL: Extract only .text section for Pi firmware
rust-objcopy -j .text -O binary target/aarch64-unknown-none/release/tiny_os kernel8.img
# Verify raw binary was created and starts with boot code
file kernel8.img
# Should show: "data"
hexdump -C kernel8.img | head -2
# Should show ARM assembly instructions, starting with something like:
# 00000000 a1 00 38 d5 21 04 40 92 61 00 00 b4 5f 20 03 d5
Common issues:
- Missing device tree blob (Pi 5 requirement)
- Wrong start/fixup files (Pi 5 uses different names)
- Missing config.txt or incorrect kernel_address
- Wrong build target (must be aarch64-unknown-none)
- Incorrect firmware versions (use latest from official repo)
- Wrong binary extraction: Must use
-j .text
to extract only executable code, not entire ELF - SD card filesystem issues: "Unable to read partition as FAT" - see SD card troubleshooting below
Error: "Unable to read partition as FAT type: 32 lba: 0"
This means the Pi firmware cannot read your SD card's filesystem. This is NOT a kernel issue:
-
Check SD card compatibility:
# Use high-quality SD card (Class 10, 32GB or less recommended) # Avoid cheap/counterfeit cards
-
Verify partition table:
# Linux/macOS - check partition structure sudo fdisk -l /dev/sdX # Replace sdX with your SD card # Should show: # Device Boot Start End Sectors Size Id Type # /dev/sdX1 * 1 ... ... ... c W95 FAT32 (LBA)
-
Re-format SD card completely:
# SAFEST: Use Raspberry Pi Imager to format # Download from: https://www.raspberrypi.org/software/ # Choose "Erase (Format as FAT32)" option
-
Test SD card on another device:
# Mount on your computer and verify you can read/write files # If this fails, the SD card may be corrupted
-
Check file copy integrity:
# After copying files, verify they exist and have correct sizes ls -la /path/to/sdcard/ # Should show: # config.txt (your config) # kernel8.img (88 bytes - your kernel) # start_cd.elf (~2.8MB) # fixup_cd.dat (~7KB) # bcm2712-rpi-5-b.dtb (~50KB)
Step-by-step debugging for Pi 5:
-
Verify SD card contents:
# Your SD card root should contain: config.txt # Boot configuration kernel8.img # Your TinyOS kernel (119KB) start_cd.elf # Pi firmware starter fixup_cd.dat # Memory split configuration bcm2712-rpi-5-b.dtb # Device tree blob for Pi 5
-
Test with minimal config.txt:
arm_64bit=1 kernel=kernel8.img uart_2ndstage=1 enable_uart=1 device_tree=bcm2712-rpi-5-b.dtb
-
Troubleshoot "boots but no output":
If the Pi 5 boots (no more FAT errors) but you see no output:
Check UART setup:
# Verify UART is enabled in config.txt grep enable_uart /path/to/sdcard/config.txt # Should show: enable_uart=1 # Try alternative UART settings in config.txt: enable_uart=1 uart_2ndstage=1 dtparam=uart0=on
Test serial connection:
# Before powering Pi, test your serial adapter: # Connect TX to RX on the adapter (loopback test) # Type in terminal - you should see characters echoed back
-
Alternative debugging - LED blink test: TinyOS has LED control. If it's running, the activity LED should be controllable through the shell (commands
1
and0
). If you can't see output but suspect it's running, the LED may still respond to input. -
Check kernel loading address:
# Verify kernel is linked for correct address readelf -h target/aarch64-unknown-none/release/tiny_os | grep "Entry point" # Should show: Entry point address: 0x80000
-
Enable maximum debug output in config.txt:
arm_64bit=1 kernel=kernel8.img uart_2ndstage=1 enable_uart=1 boot_delay=3 disable_splash=1
-
Alternative kernel names to try:
- Copy kernel as
kernel8.img
(standard) - Try
kernel.img
(fallback) - Try
kernel7l.img
(32-bit fallback)
- Copy kernel as
If still not working, try this debug sequence:
-
SD Card Basic Test:
# Test if SD card works with official Raspberry Pi OS first # Download Raspberry Pi OS Lite and flash it # If this doesn't boot, your SD card/reader has issues
-
Test with a known-working kernel:
# Download a simple "hello world" Pi kernel to test firmware wget https://github.com/bztsrc/raspi3-tutorial/raw/master/01_bareminimum/kernel8.img # Copy to SD card and test - this verifies firmware setup
-
Check TinyOS boot code:
# Verify _start symbol exists nm target/aarch64-unknown-none/release/tiny_os | grep _start
-
Serial debugging setup:
- Use 3.3V USB-to-TTL adapter (NOT 5V!)
- Pi 5 GPIO: Pin 8=TX, Pin 10=RX, Pin 6=GND
- 115200 baud, 8N1
- Connect before powering on Pi
# Alternative config.txt for troubleshooting
arm_64bit=1
kernel=kernel8.img
gpu_mem=16
enable_uart=1
uart_2ndstage=1
disable_splash=1
# For Pi 5 - explicit device tree
device_tree=bcm2712-rpi-5-b.dtb
# Debug options
boot_delay=1
disable_overscan=1
├── src/
│ ├── main.rs # Main kernel and interactive shell
│ ├── boot.s # Assembly boot code and initialization
│ ├── uart.rs # PL011 UART driver
│ ├── gpio.rs # GPIO and LED control driver
│ ├── timer.rs # BCM2835 System Timer driver
│ ├── memory.rs # Bitmap-based memory manager
│ ├── interrupts.rs # ARM GIC interrupt controller
│ └── tests/ # Rust unit tests
├── tests/ # Test suite
│ ├── test_*_automated.sh # Automated test scripts (no dependencies)
│ ├── test_*_suite.sh # Interactive test suites (require expect)
│ ├── test_qemu_boot.sh # Boot validation
│ └── validate_tinyos.sh # System validation
├── .cargo/
│ └── config.toml # Cargo configuration for cross-compilation
├── linker.ld # Custom linker script for memory layout
├── aarch64-raspi.json # Custom target specification
├── test_tinyos.sh # Unified test runner (at project root)
├── build.sh # Build script
├── run.sh # QEMU execution script
└── DOCS.md # Technical documentation
Testing:
./test_tinyos.sh
- Run all available tests./test_tinyos.sh --help
- Show test options./test_tinyos.sh boot
- Test boot and validation./test_tinyos.sh unit
- Test Rust unit tests only./test_tinyos.sh validate
- Quick validation check
Building:
./build.sh
- Build kernelcargo build
- Standard Rust buildcargo build --release
- Release build for hardware
Running:
./run.sh
- Run in QEMU./test_tinyos.sh validate
- Quick health check
Once TinyOS is running, use these commands in the interactive shell:
h
- Help menu with all commandsc
- System health checkm
- Memory statisticsi
- Interrupt statusv
- Exception statisticsw
- Test exception handlings
- System informationt
- Current time1/0
- LED on/offx
- Memory testj
- Interrupt test
- Exception vectors implementation
- Real hardware validation on Pi 4/5
- Enhanced GPIO control capabilities
- Device driver framework
- Power management
- Watchdog timer support
- Virtual memory management (MMU)
- Page table management
- Memory protection improvements
- Dynamic memory allocation optimizations
- Memory compression
- Multi-tasking support
- Process isolation
- Context switching optimization
- Thread support
- Process scheduler improvements
- SD card driver
- FAT32 file system support
- File I/O operations
- Directory management
- Boot from file system
- Ethernet driver
- Basic TCP/IP stack
- UDP support
- Network interface management
- DHCP client
- Multi-core support (SMP)
- Kernel/user mode separation
- System call interface
- Dynamic loading
- Implement basic HDMI video support (framebuffer graphics)
- USB support
- Automated hardware testing
- Performance benchmarking suite
- Code coverage analysis
- Continuous integration
- Documentation automation
- Fork the repository
- Create a feature branch
- Make changes with tests
- Run
./test_tinyos.sh
to verify - Submit a pull request
For detailed technical documentation, architecture details, and API references, see DOCS.md.
This project is open source. See LICENSE file for details.