All Projects
Embedded OSIndustrial

APEX-RTOS: Real-Time Operating System for Industrial Edge Controllers

Validated on ARM-based industrial edge controllers with deterministic interrupt latency under 50 microseconds under full load. Smaller memory footprint than commercial alternatives without sacrificing reliability.

APEX-RTOS on ARM Cortex-M hardware showing real-time task scheduling for industrial controllers

APEX-RTOS on ARM Cortex-M: preemptive scheduler handling concurrent industrial sensor and actuator tasks

// The Challenge

Industrial automation controllers require deterministic, sub-millisecond interrupt response that general-purpose operating systems cannot guarantee. Commercial RTOS options restrict hardware targets and offer no recourse when scheduling guarantees fall short of specific latency requirements. Building a custom RTOS provides full control over every scheduling and interrupt-handling decision, and eliminates licensing constraints on hardware target selection.

// Our Approach

Built a custom RTOS from scratch: preemptive priority-based scheduler with hard real-time guarantees, a hardware abstraction layer targeting ARM Cortex-M, minimal memory footprint, lightweight IPC primitives, and a peripheral driver framework for common industrial sensors and actuators. All components are designed for deterministic behaviour with no dynamic allocation in interrupt context and no unbounded execution paths in the scheduler.

// System Modules
3 of 3
// SCHEDULER

Preemptive priority scheduler

256 priority levels with hard real-time interrupt latency guarantees

The scheduler implements fixed-priority preemptive scheduling with 256 priority levels. Higher-priority tasks preempt lower-priority tasks immediately at any safe preemption point. The scheduler uses a bitmask-based ready queue that resolves the highest-priority runnable task in O(1) time regardless of the number of tasks in the system. Interrupt latency is bounded and verified under full task load.

READY QUEUET1 priority 7Highest — selectedT2 priority 4PreemptedT3 priority 2WaitingO(1) selectEXECUTION TIMELINET1 runsT1 blocksT2 runsT1 preemptsT2 ← priorityT1 resumest=0t→Scheduler selects highest runnable priority in O(1) — no iteration over task list
Preemptive scheduling: T1 (highest priority) preempts T2 mid-execution when it becomes runnable, with O(1) task selection at every context switch

Key Capabilities

  • 256 priority levels with deterministic highest-priority selection
  • O(1) ready queue lookup via hardware-assisted bit scan
  • Priority inheritance on mutex acquisition to prevent inversion
  • Tick-less idle: no unnecessary wake-ups when no task is runnable
  • Context switch time measured and documented per target device
  • Interrupt latency under 50 microseconds under full load validated
// HARDWARE ABSTRACTION

Hardware abstraction layer

Portable peripheral API across ARM Cortex-M3, M4, and M7 targets

The HAL provides a uniform API for GPIO, UART, SPI, I2C, timers, and ADC peripherals that is identical across all supported ARM Cortex-M variants. Application tasks call the HAL API without any knowledge of vendor-specific register layouts. Adding support for a new microcontroller variant requires only a new HAL backend file, without modifying application or RTOS core code.

Application TasksGPIO_Write() · UART_Send() · SPI_Transfer() · I2C_Read() — uniform API callsAPEX HAL LayerVendor-independent peripheral abstraction — identical API on all targetsCortex-M3 BackendSTM32F1 registersCortex-M4 BackendSTM32F4 registersCortex-M7 BackendSTM32H7 registers
HAL architecture: application tasks call identical peripheral APIs on all targets. Only the HAL backend changes when targeting a new Cortex-M variant.

Key Capabilities

  • GPIO, UART, SPI, I2C, Timer, ADC covered in unified API
  • Cortex-M3, M4, M7 backends implemented and tested
  • Register-level peripheral initialisation in HAL backend only
  • DMA-backed UART and SPI transfers for high-throughput peripherals
  • Interrupt-driven peripheral events wired to RTOS task notification
  • New target: only HAL backend required, zero changes to RTOS core
// IPC PRIMITIVES

IPC and synchronisation primitives

Safe inter-task communication with priority inheritance

Tasks communicate through a set of lightweight IPC primitives: binary semaphores, counting semaphores, mutexes with priority inheritance, message queues, and event flag groups. All primitives are implemented with bounded execution time and no dynamic allocation. Priority inheritance on mutexes prevents priority inversion, a common cause of missed deadlines in systems where high and low priority tasks share a resource.

APEX-RTOS running on ARM Cortex-M development board: real-time task scheduling demonstrated under concurrent interrupt load from industrial sensor peripherals
APEX-RTOS running on ARM Cortex-M development board: real-time task scheduling demonstrated under concurrent interrupt load from industrial sensor peripherals

Key Capabilities

  • Binary and counting semaphores for interrupt-to-task signalling
  • Mutex with priority inheritance: inversion prevented by protocol
  • Message queues: fixed-size message passing with configurable depth
  • Event flag groups: wait on arbitrary bitwise combination of flags
  • All primitives: bounded execution time, no dynamic allocation
  • Timeout support on all blocking operations with return code
// Technical Complexity
  • Hard real-time correctness under concurrent interrupt load requires that every code path in the scheduler and IPC layer has a provable upper bound on execution time, which means no loops with data-dependent iteration counts and no dynamic memory allocation anywhere in the kernel execution path.
  • Priority inheritance on mutexes requires the scheduler to temporarily elevate a low-priority task's effective priority and restore it correctly when the mutex is released, including the case where multiple tasks are waiting on the same mutex at different priorities simultaneously.
  • Deterministic boot sequence for autonomous field deployment means the system must reach a defined ready state from cold power-on without any external trigger or human intervention, requiring careful sequencing of clock setup, peripheral initialisation, and task creation before the scheduler is started.
  • Context switch implementation on ARM Cortex-M targets uses the PendSV exception for task switching, which interacts with the SysTick interrupt and any application interrupts. The relative priorities of these exceptions must be configured correctly to prevent the scheduler from being inadvertently masked by application interrupt handlers.
// Stack & Methods
RTOSARM Cortex-MCCMSISGCC ARM ToolchainOpenOCDJTAGReal-Time Systems