Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 

README.md

Malbolge RTOS (STM32U585 / Arduino UNO Q)

A from-scratch cooperative real-time kernel whose tasks are Malbolge VMs. It runs on the host (LED matrix rendered as terminal ASCII) and bare-metal on the Arduino UNO Q's STM32U585, where it scrolls "Hello World from Malbolge VM" forever on the on-board 13×8 charlieplexed LED matrix.

Build & run

make run     # host simulation (gcc): scheduler + matrix scroll as ASCII
make arm     # STM32U585 firmware -> build/arm/firmware.bin

make arm needs arm-none-eabi-gcc. Output: ~3.8 KB flash, ~125 KB SRAM (one 59049-word Malbolge memory). The U585's 786 KB SRAM fits up to ~6 VMs.

How it works

Each task is one mb_vm_t (registers + a 59049-word memory). The interpreter is a step machine, so kern_schedule_pass() advances each task by a quantum of Malbolge cycles and moves on — no per-task stacks, no asm context switch. A task blocks when it reads input that isn't ready (/) and resumes when it arrives; it finishes when its program halts.

src/malbolge_vm.{h,c}  freestanding VM: mb_load(), mb_step(budget, io), blocks on input
src/kernel.{h,c}       task control blocks + round-robin scheduler
src/display.{h,c}      13×8 framebuffer + 5×7 text scroller (loops forever)
src/font5x7.h          generated 5×7 font
src/charlieplex_map.h  104 LED pin-pairs (PF0..PF10) + 180° mount mapping
src/programs.h         embedded Malbolge programs (the scroll message, a cat)
host/main_host.c       host entry: renders the matrix as ASCII
port/main.c            firmware entry
port/board.c           clock/FPU + GPIOF charlieplex driver + SysTick scan/scroll
port/startup_stm32u585.c, port/stm32u585.ld   bare-metal startup + linker script
port/cmsis/            vendored CMSIS headers (ST/Arm) for a self-contained build

Display

The UNO Q's matrix is 104 LEDs charlieplexed across PF0..PF10, mounted 180°. Each pixel is a {high, low} pin pair (drive high HIGH, low LOW, all others Hi-Z). A SysTick ISR (20 kHz) multiplexes one pixel per tick (~192 Hz full frame) and paces the scroll. The pin-pair table matches the upstream Zephyr board device tree for the UNO Q. A Malbolge task's output bytes feed the scroller; the text loops forever even after the program halts.

Clock

Runs on the default MSIS 4 MHz system clock — no PLL setup, nothing to mis-configure. (USART1 on PB6/PB7 is the board console if you wire one up.)

Flashing

Flash build/arm/firmware.bin to 0x08000000. On the UNO Q the STM32U585 is reached over SWD; a BOOT0-low hold across write+verify+reset is required, or the MCU comes up in the system ROM bootloader instead of your image. The on-board LED matrix scrolling the message is the visible proof it's running.