universalisos/MICROKERNEL_IMPLEMENTATION_PLAN.md
Fábio Coutada 059f96c948 docs: add safety-critical evaluation and implementation plans
- HARD_REALTIME_EVALUATION.md: full HRT audit
- MICROKERNEL_*.md: complete architecture targets and implementation plan
- PIKEOS_3LAYER_REPLICATION_PLAN.md: 3-layer replication strategy
- PIKEOS_POSIX_AUDIT.md: POSIX compliance audit
- RTOS_AUDIT.md: RTOS comparison
- XTENSA_AUDIT.md: Xtensa ISA audit
- BIBLIOGRAPHY_SAFETY_CRITICAL_HYPERVISOR.md: references
2026-07-15 15:32:05 +01:00

22 KiB

UniversalisOS Microkernel — Implementation Plan

Date: 2026-07-14 Status: ACTIVE — Implementation Plan Scope: Universal microkernel for ALL architectures, from AVR to Xeon


Executive Summary

UniversalisOS microkernel is a single codebase that compiles for every architecture from 8-bit AVR to 64-bit x86_64 with VT-x. It uses compile-time tier selection to scale from a 2KB cooperative task switcher (Cortex-M0, no MPU) to a full type-1 hypervisor with hardware virtualization (x86_64 VT-x).

Core design: uos_* naming throughout. Agnostic API shell. Personality wrappers for FreeRTOS, ThreadX, Zephyr, POSIX, CMSIS-RTOS v2.

Primary references: f9-kernel (MPU isolation), ThreadX (port breadth), ChibiOS (port contract), NuttX (no-MMU strategy), RTEMS (context switch HAL).


Architecture: The Tier System

Tier 0: Bare Metal (no MPU, no MMU)
  Targets: Cortex-M0/M0+, AVR, basic RISC-V (RV32I), 8051
  RAM: 4-16KB
  Kernel: ~2KB
  Features: Cooperative scheduling, static alloc, no isolation
  Context switch: Direct register save/restore (PendSV/manual)

Tier 1: MPU-Based (Memory Protection Unit)
  Targets: Cortex-M3/M4/M7/M23/M33/M55, Cortex-R4/R5/R7, ESP32
  RAM: 64-512KB
  Kernel: ~8KB
  Features: Preemptive, MPU isolation, stack canary, priority scheduling
  Context switch: PendSV (Cortex-M) / ECALL (RISC-V) / Syscall (Xtensa)

Tier 2: MMU-Based (Full Virtual Memory)
  Targets: Cortex-A5/A7/A8/A9/A53/A72/A76, RISC-V Sv39+, x86 protected
  RAM: 1MB-4GB
  Kernel: ~32KB
  Features: Full type-1 hypervisor, partition isolation, guest OS boot
  Context switch: SVC/HVC (ARM) / ECALL (RISC-V) / INT (x86)

Tier 3: Hardware Virtualization
  Targets: Cortex-A with VE, RISC-V H-extension, x86 VT-x/AMD-V
  RAM: 4GB+
  Kernel: ~64KB
  Features: Hardware-assisted, nested page tables, device passthrough
  Context switch: VM entry/exit (hardware-managed)

Compile-Time Selection

// kernel/include/uos_config.h
#if defined(__ARM_ARCH_6M__)     // Cortex-M0/M0+
  #define UOS_TIER 0
  #define UOS_HAS_MPU 0
  #define UOS_HAS_MMU 0
  #define UOS_MAX_TASKS 8
  #define UOS_TICK_RATE_HZ 100
#elif defined(__ARM_ARCH_7M__)   // Cortex-M3/M4/M7
  #define UOS_TIER 1
  #define UOS_HAS_MPU 1
  #define UOS_HAS_MMU 0
  #define UOS_MAX_TASKS 32
  #define UOS_MPU_REGIONS 8
#elif defined(__ARM_ARCH_7A__)   // Cortex-A
  #define UOS_TIER 2
  #define UOS_HAS_MPU 0
  #define UOS_HAS_MMU 1
  #define UOS_MAX_TASKS 128
#elif defined(__riscv)
  #if __riscv_xlen == 32
    #define UOS_TIER 1  // PMP-based
    #define UOS_HAS_PMP 1
  #else
    #define UOS_TIER 2  // Sv39
    #define UOS_HAS_MMU 1
  #endif
#elif defined(__x86_64__)
  #define UOS_TIER 3
  #define UOS_HAS_VT_X 1
  #define UOS_HAS_MMU 1
#endif

Universal Kernel API (uos_*)

Every function, every type, every constant uses the uos_ prefix. This is the identity.

// kernel/include/uos_api.h — THE universal API

/* === Types === */
typedef uint32_t        uos_tick_t;
typedef uint8_t         uos_prio_t;
typedef int32_t         uos_status_t;
typedef uint32_t        uos_flags_t;
typedef uint32_t        uos_size_t;
typedef uint32_t        uos_count_t;

/* Opaque kernel objects (Tier 1+: heap-allocated; Tier 0: static) */
typedef struct uos_task  uos_task_t;
typedef struct uos_sem   uos_sem_t;
typedef struct uos_mutex uos_mutex_t;
typedef struct uos_queue uos_queue_t;
typedef struct uos_event uos_event_t;
typedef struct uos_timer uos_timer_t;

/* Status codes */
#define UOS_OK              0
#define UOS_ERR_TIMEOUT    -1
#define UOS_ERR_NOMEM      -2
#define UOS_ERR_PARAM      -3
#define UOS_ERR_STATE      -4
#define UOS_ERR_WOULDBLOCK -5
#define UOS_ERR_ISR        -6

/* Special timeout values */
#define UOS_WAIT_FOREVER   0xFFFFFFFF
#define UOS_NO_WAIT        0

/* === Task Management === */
uos_task_t*   uos_task_create(const char* name, uos_prio_t prio,
                              void (*entry)(void*), void* arg,
                              void* stack, uos_size_t stack_size);
uos_status_t  uos_task_delete(uos_task_t* task);
uos_status_t  uos_task_yield(void);
uos_status_t  uos_task_suspend(uos_task_t* task);
uos_status_t  uos_task_resume(uos_task_t* task);
uos_task_t*   uos_task_self(void);
uos_prio_t    uos_task_get_priority(uos_task_t* task);
uos_status_t  uos_task_set_priority(uos_task_t* task, uos_prio_t prio);

/* === Scheduling === */
uos_status_t  uos_sched_start(void);  /* never returns */
uos_status_t  uos_sched_stop(void);

/* === Semaphores === */
uos_status_t  uos_sem_init(uos_sem_t* sem, uos_count_t count);
uos_status_t  uos_sem_destroy(uos_sem_t* sem);
uos_status_t  uos_sem_wait(uos_sem_t* sem, uos_tick_t timeout);
uos_status_t  uos_sem_post(uos_sem_t* sem);
uos_status_t  uos_sem_post_from_isr(uos_sem_t* sem);

/* === Mutexes === */
uos_status_t  uos_mutex_init(uos_mutex_t* mutex, bool recursive);
uos_status_t  uos_mutex_destroy(uos_mutex_t* mutex);
uos_status_t  uos_mutex_lock(uos_mutex_t* mutex, uos_tick_t timeout);
uos_status_t  uos_mutex_unlock(uos_mutex_t* mutex);

/* === Message Queues === */
uos_queue_t*  uos_queue_create(uos_size_t msg_size, uos_count_t max_msgs);
uos_status_t  uos_queue_delete(uos_queue_t* queue);
uos_status_t  uos_queue_send(uos_queue_t* queue, const void* msg, uos_tick_t timeout);
uos_status_t  uos_queue_receive(uos_queue_t* queue, void* msg, uos_tick_t timeout);
uos_status_t  uos_queue_send_from_isr(uos_queue_t* queue, const void* msg);

/* === Event Flags === */
uos_status_t  uos_event_init(uos_event_t* event);
uos_status_t  uos_event_set(uos_event_t* event, uos_flags_t flags);
uos_status_t  uos_event_clear(uos_event_t* event, uos_flags_t flags);
uos_status_t  uos_event_wait(uos_event_t* event, uos_flags_t flags,
                             uos_flags_t* actual, uos_tick_t timeout);

/* === Timers === */
uos_timer_t*  uos_timer_create(const char* name, uos_tick_t period,
                               void (*callback)(void*), void* arg, bool periodic);
uos_status_t  uos_timer_start(uos_timer_t* timer);
uos_status_t  uos_timer_stop(uos_timer_t* timer);
uos_status_t  uos_timer_delete(uos_timer_t* timer);

/* === Memory (Tier 1+ only; Tier 0 uses static alloc) === */
void*         uos_mem_alloc(uos_size_t size);
void*         uos_mem_aligned_alloc(uos_size_t align, uos_size_t size);
void          uos_mem_free(void* ptr);

/* === Time === */
uos_tick_t    uos_tick_get(void);
uos_status_t  uos_tick_delay(uos_tick_t ticks);
uos_status_t  uos_tick_delay_until(uos_tick_t* prev, uos_tick_t increment);
uos_tick_t    uos_ms_to_ticks(uint32_t ms);
uos_tick_t    uos_us_to_ticks(uint32_t us);

/* === Interrupt Management (Tier 1+ === */
typedef void (*uos_isr_t)(void* arg);
uos_status_t  uos_irq_attach(uint32_t irq, uos_isr_t handler, void* arg);
uos_status_t  uos_irq_enable(uint32_t irq);
uos_status_t  uos_irq_disable(uint32_t irq);

Port Layer (4 files per architecture)

Inspired by ThreadX (70+ ports) + ChibiOS (chcore.h contract).

Port Directory Structure

kernel/ports/
├── armv6m/                    ← Cortex-M0/M0+ (Tier 0)
│   ├── uos_port.h             ← Port defines, critical section macros
│   ├── uos_port_init.c        ← NVIC setup, SysTick config
│   ├── uos_port_context.S     ← PendSV handler: save/restore R4-R11
│   └── uos_port_dispatch.S    ← First task launch: load SP, restore context
│
├── armv7m/                    ← Cortex-M3/M4/M7 (Tier 1)
│   ├── uos_port.h             ← MPU register access, CLZ instruction
│   ├── uos_port_init.c        ← NVIC priority config, MPU setup
│   ├── uos_port_context.S     ← PendSV with lazy FPU stacking
│   └── uos_port_dispatch.S    ← First task with MPU region setup
│
├── armv8m/                    ← Cortex-M23/M33/M55 (Tier 1, TrustZone)
│   ├── uos_port.h             ← TrustZone SAU/IDAU defines
│   ├── uos_port_init.c        ← Secure/Non-secure partition setup
│   ├── uos_port_context.S     ← Secure context save (8 additional regs)
│   └── uos_port_dispatch.S    ← Non-secure task launch via SG instruction
│
├── armv7a/                    ← Cortex-A (Tier 2)
│   ├── uos_port.h             ← CP15 register access, cache ops
│   ├── uos_port_init.c        ← MMU setup, GIC init, page table config
│   ├── uos_port_context.S     ← SVC/IRQ handlers: save full register set
│   └── uos_port_dispatch.S    ← First task with MMU context switch
│
├── armv8a/                    ← Cortex-A53/A72 (Tier 2/3)
│   ├── uos_port.h             ← EL2/EL1 system register access
│   ├── uos_port_init.c        ← VBAR_EL2, HCR_EL2, VTTBR setup
│   ├── uos_port_context.S     ← EL2 exception vectors, context save
│   └── uos_port_dispatch.S    ← ERET into first guest task
│
├── riscv32/                   ← RV32IMC (Tier 1, PMP)
│   ├── uos_port.h             ← CSR access macros, PMP defines
│   ├── uos_port_init.c        ← PMP configuration, CLINT timer setup
│   ├── uos_port_context.S     ← ECALL/trap handler: save caller-saved regs
│   └── uos_port_dispatch.S    ← MRET into first task
│
├── riscv64/                   ← RV64GC (Tier 2, Sv39)
│   ├── uos_port.h             ← Sv39 page table defines
│   ├── uos_port_init.c        ← SATP setup, PLIC init
│   ├── uos_port_context.S     ← Trap handler with full context save
│   └── uos_port_dispatch.S    ← SRET into first task
│
├── x86/                       ← 32-bit protected mode (Tier 2)
│   ├── uos_port.h             ← GDT/TSS/IDT defines
│   ├── uos_port_init.c        ← GDT setup, IDT init, PIT timer
│   ├── uos_port_context.S     ← INT handler: pusha/popa context save
│   └── uos_port_dispatch.S    ← IRET to first task
│
├── x86_64/                    ← 64-bit long mode (Tier 3)
│   ├── uos_port.h             ← VMX/EPT defines, MSR access
│   ├── uos_port_init.c        ← GDT/IDT, VMX init, HPET timer
│   ├── uos_port_context.S     ← SYSCALL handler: swapgs, full save
│   └── uos_port_dispatch.S    ← SYSRET/IRETQ to first task
│
├── xtensa/                    ← ESP32/ESP32-S3 (Tier 1)
│   ├── uos_port.h             ← Windowed register defines, EXCSAVE
│   ├── uos_port_init.c        ← Interrupt matrix, timer config
│   ├── uos_port_context.S     ← Level-1 interrupt handler context save
│   └── uos_port_dispatch.S    ← First task via RFI
│
└── mips32/                    ← PIC32 (Tier 1)
    ├── uos_port.h             ← CP0 register access
    ├── uos_port_init.c        ← EBASE setup, timer config
    ├── uos_port_context.S     ← General exception handler
    └── uos_port_dispatch.S    ← ERET to first task

Port Contract (what each port MUST export)

// kernel/ports/<arch>/uos_port.h — REQUIRED exports

/* Critical section */
uos_status_t  uos_port_critical_enter(void);   /* return previous state */
void          uos_port_critical_exit(uos_status_t prev);

/* Context switch trigger */
void          uos_port_yield(void);             /* PendSV/ECALL/SVC/syscall */

/* First task dispatch (never returns) */
void          uos_port_dispatch_first(void) __attribute__((noreturn));

/* Tick timer */
void          uos_port_tick_init(uint32_t freq_hz);
uint32_t      uos_port_tick_get(void);

/* MPU/MMU (Tier 1+) */
#if UOS_HAS_MPU
void          uos_port_mpu_set_region(uint32_t idx, uint32_t base, uint32_t size, uint32_t attrs);
void          uos_port_mpu_enable(void);
void          uos_port_mpu_disable(void);
#endif

#if UOS_HAS_MMU
void          uos_port_mmu_set_table(uint32_t table_phys);
void          uos_port_mmu_invalidate_tlb(void);
#endif

/* Architecture-specific constants */
#define UOS_PORT_STACK_ALIGN    8    /* or 4 for Cortex-M0, 16 for AArch64 */
#define UOS_PORT_MIN_STACK_SIZE 256  /* or 128 for Tier 0 */

Personality Shell Architecture

kernel/personality/
├── freertos/                  ← FreeRTOS API → uos_* wrapper
│   ├── FreeRTOS.h             ← Redirects to uos_* internals
│   ├── task.h                 ← xTaskCreate → uos_task_create
│   ├── semphr.h               ← xSemaphoreCreateCounting → uos_sem_init
│   ├── queue.h                ← xQueueCreate → uos_queue_create
│   ├── timers.h               ← xTimerCreate → uos_timer_create
│   └── portable/              ← FreeRTOS port layer (maps to uos_port_*)
│
├── threadx/                   ← ThreadX API → uos_* wrapper
│   ├── tx_api.h               ← tx_thread_create → uos_task_create
│   ├── tx_thread.h            ← ThreadX thread types → uos_task_t
│   └── tx_port.h              ← Maps ThreadX port macros to uos_port_*
│
├── zephyr/                    ← Zephyr API → uos_* wrapper
│   ├── kernel.h               ← k_thread_create → uos_task_create
│   └── zephyr/                ← Zephyr kernel object mapping
│
├── posix/                     ← POSIX PSE51 → uos_* wrapper
│   ├── pthread.h              ← pthread_create → uos_task_create
│   ├── semaphore.h            ← sem_init → uos_sem_init
│   ├── mqueue.h               ← mq_open → uos_queue_create
│   └── signal.h               ← signal handling (Tier 2+)
│
├── cmsis_rtos2/               ← CMSIS-RTOS v2 → uos_* wrapper
│   ├── cmsis_os2.h            ← osThreadNew → uos_task_create
│   └── cmsis_os.h             ← osThreadCreate (v1 compat)
│
└── arduino/                   ← Arduino API → uos_* wrapper
    └── Arduino.h              ← setup()/loop() → uos_task

How a Personality Shell Works

// Example: FreeRTOS personality
// kernel/personality/freertos/task.h

#include "uos_api.h"

#define xTaskCreate(entry, name, stack, arg, prio, handle) \
    uos_task_create(name, (uos_prio_t)(prio), (void(*)(void*))(entry), \
                    (void*)(arg), NULL, (uos_size_t)(stack))

#define vTaskDelete(task)       uos_task_delete((uos_task_t*)(task))
#define vTaskDelay(ticks)       uos_tick_delay((uos_tick_t)(ticks))
#define xTaskGetCurrentTaskHandle() ((TaskHandle_t)uos_task_self())

Kernel Object System (inspired by RT-Thread)

// kernel/include/uos_object.h — Base kernel object

typedef enum {
    UOS_OBJ_TASK   = 0x01,
    UOS_OBJ_SEM    = 0x02,
    UOS_OBJ_MUTEX  = 0x03,
    UOS_OBJ_QUEUE  = 0x04,
    UOS_OBJ_EVENT  = 0x05,
    UOS_OBJ_TIMER  = 0x06,
} uos_obj_type_t;

typedef struct uos_object {
    uos_obj_type_t  type;
    const char*     name;
    uint8_t         flags;       /* static/dynamic, allocated/free */
#if UOS_TIER >= 1
    struct uos_object* next;     /* linked list for object registry */
#endif
} uos_object_t;

/* All kernel objects embed uos_object_t as first member */
struct uos_task {
    uos_object_t    obj;         /* must be first */
    uos_prio_t      priority;
    uint8_t         state;
    void*           stack_ptr;
    uos_size_t      stack_size;
    /* ... arch-specific context at end ... */
};

Context Switch: Cortex-M Example (Tier 0/1)

@ kernel/ports/armv7m/uos_port_context.S
@ PendSV handler  the heart of Cortex-M context switching

.global PendSV_Handler
.type PendSV_Handler, %function
PendSV_Handler:
    @ Save context of current task
    mrs     r0, psp                 @ Get process stack pointer
    tst     lr, #0x10               @ Check if FPU context needs saving
    it      eq
    vstmdbeq r0!, {s16-s31}        @ Save FPU regs if used
    stmdb   r0!, {r4-r11, lr}      @ Save core regs + EXC_RETURN

    @ Load uos_task_current pointer
    ldr     r1, =uos_task_current
    ldr     r2, [r1]
    str     r0, [r2]                @ Save SP to current task's TCB

    @ Load next task
    ldr     r2, =uos_task_next
    ldr     r2, [r2]
    str     r2, [r1]                @ Update current = next
    ldr     r0, [r2]                @ Load next task's SP

    @ Restore context of next task
    ldmia   r0!, {r4-r11, lr}      @ Restore core regs + EXC_RETURN
    tst     lr, #0x10
    it      eq
    vldmiaeq r0!, {s16-s31}        @ Restore FPU regs if needed
    msr     psp, r0                 @ Set process stack pointer
    bx      lr                      @ Return to next task (hardware restores R0-R3, PC, LR, xPSR)

Implementation Phases

Phase 1: Core Microkernel (Tier 0 — Cortex-M0) — Weeks 1-4

  • uos_task_t with static allocation (8 tasks max)
  • Cooperative round-robin scheduler
  • PendSV context switch (Cortex-M0: save R4-R11, no FPU)
  • uos_tick_delay() via SysTick
  • uos_sem_init/wait/post (counting semaphore)
  • uos_sched_start() — launch first task
  • Test: STM32F0 (real hardware) + QEMU cortex-m0

Phase 2: Preemptive + MPU (Tier 1 — Cortex-M4) — Weeks 5-8

  • Preemptive priority scheduler (32 levels, bitmap)
  • MPU region management (8 regions per task)
  • uos_mutex_init/lock/unlock with priority inheritance
  • uos_queue_create/send/receive (message passing)
  • uos_event_init/set/wait (event flags)
  • uos_timer_create/start/stop (periodic + one-shot)
  • Tickless idle for power efficiency
  • Test: STM32F4 (real hardware) + QEMU cortex-m3

Phase 3: Additional Ports — Weeks 9-12

  • armv8m/ — Cortex-M33 with TrustZone (Secure/Non-secure)
  • riscv32/ — RV32IMC with PMP (f9-kernel pattern)
  • xtensa/ — ESP32 (windowed registers, level-1 interrupt)
  • armv7a/ — Cortex-A with MMU (Tier 2)
  • Test: nRF5340, ESP32, HiFive1, QEMU arm-virt

Phase 4: Personality Shells — Weeks 13-16

  • FreeRTOS personality: xTaskCreate, xSemaphoreCreate, xQueueCreate
  • ThreadX personality: tx_thread_create, tx_mutex_get, tx_queue_send
  • POSIX personality: pthread_create, sem_wait, mq_send
  • CMSIS-RTOS v2: osThreadNew, osSemaphoreAcquire
  • Test: Run existing FreeRTOS/ThreadX apps unchanged on UniversalisOS

Phase 5: Hypervisor Extensions (Tier 2/3) — Weeks 17-24

  • armv8a/ — AArch64 EL2 with vGIC, Stage-2 translation
  • riscv64/ — Sv39 with H-extension (G-stage page tables)
  • x86_64/ — VT-x with EPT, VMCS management
  • Guest OS boot (Linux, FreeRTOS, bare-metal)
  • Device passthrough (PCI, UART, timer)
  • Test: QEMU aarch64-virt, QEMU riscv64-virt, QEMU x86_64

Target Hardware Matrix (Priority Order)

| P0 | STM32F4 (Cortex-M4), QEMU all arches, x86_64 (existing) | | P1 | nRF52/53 (Cortex-M4/M33), ESP32 (Xtensa), STM32H7 (M7) | | P2 | i.MX RT1060 (M7), HiFive1 (RISC-V), PIC32 (MIPS32) | | P3 | STM32MP1 (A7+M4), i.MX 8M (A53), RISC-V boards |


File Structure (Target)

kernel/
├── include/
│   ├── uos_api.h              ← Universal kernel API
│   ├── uos_object.h           ← Kernel object base type
│   ├── uos_config.h           ← Tier/arch detection
│   ├── uos_types.h            ← uos_tick_t, uos_prio_t, uos_status_t
│   └── uos_compiler.h         ← Compiler abstraction (__attribute__, etc.)
├── src/
│   ├── core/
│   │   ├── uos_task.c         ← Task management (universal)
│   │   ├── uos_sched.c        ← Scheduler (universal, tier-scaled)
│   │   ├── uos_sem.c          ← Semaphore (universal)
│   │   ├── uos_mutex.c        ← Mutex with priority inheritance
│   │   ├── uos_queue.c        ← Message queue
│   │   ├── uos_event.c        ← Event flags
│   │   ├── uos_timer.c        ← Software timers
│   │   ├── uos_mem.c          ← Memory allocator (tier-scaled)
│   │   ├── uos_tick.c         ← Tick management
│   │   ├── uos_irq.c          ← Interrupt dispatch
│   │   └── uos_idle.c         ← Idle task (WFI/WFE/HALT)
│   ├── port/                  ← 11 architecture ports (4 files each)
│   └── personality/           ← 6 RTOS personality shells
├── platform/                  ← Board-specific BSP (pinmux, clock, UART)
└── test/                      ← Kernel test suite

Key Design Decisions

  1. Static allocation for Tier 0: No malloc, no heap. All kernel objects statically allocated at compile time via UOS_STATIC_TASK() macro.

  2. PendSV for all Cortex-M: Hardware saves R0-R3, LR, PC, xPSR on exception entry. Software saves R4-R11 (and optionally S16-S31). This is the most efficient context switch for Cortex-M.

  3. Bitmap priority scheduler: O(1) using CLZ instruction (available on all ARM Cortex). 32 priority levels. Round-robin within same priority.

  4. f9-kernel MPU pattern for Tier 1: Flexible pages (power-of-2, aligned) mapped to MPU regions. LRU eviction when 8 regions insufficient.

  5. Object registry for Tier 1+: All kernel objects linked in a list for debug/monitoring. Tier 0 skips this (no spare RAM).

  6. Personality shells are compile-time: #define UOS_PERSONALITY_FREERTOS selects the FreeRTOS wrapper. Multiple personalities can coexist (each gets its own namespace).

  7. Port contract is 4 files: Every architecture port provides exactly uos_port.h, uos_port_init.c, uos_port_context.S, uos_port_dispatch.S. No exceptions.


Success Criteria

Phase 1 (Week 4)

  • Cooperative scheduling on Cortex-M0 (QEMU + STM32F0)
  • 8 tasks running with semaphores and delays
  • Context switch < 5μs on 48MHz Cortex-M0
  • Kernel binary < 2KB

Phase 2 (Week 8)

  • Preemptive scheduling on Cortex-M4 (QEMU + STM32F4)
  • MPU isolation: task A cannot access task B's memory
  • Mutex with priority inheritance
  • Message queues, event flags, software timers
  • Context switch < 2μs on 168MHz Cortex-M4

Phase 3 (Week 12)

  • ESP32 port boots and runs tasks
  • RISC-V PMP port boots on HiFive1
  • TrustZone Secure/Non-secure split on Cortex-M33

Phase 4 (Week 16)

  • FreeRTOS app compiles and runs unchanged on UniversalisOS
  • ThreadX app compiles and runs unchanged on UniversalisOS
  • POSIX pthread app compiles and runs on UniversalisOS

Phase 5 (Week 24)

  • Linux boots as guest on AArch64 Tier 3
  • FreeRTOS runs as guest inside UniversalisOS hypervisor on x86_64
  • Same kernel binary runs on Cortex-M0 AND Cortex-A72 (different tiers)