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: preemptive scheduler handling concurrent industrial sensor and actuator tasks
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.
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.
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.
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 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.
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 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.

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
- 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.