Skip to content

ExoSpaceLabs/hardrt

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

111 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ«€ HardRT [ExoSpaceLabs]

HardRT is the heartbeat of small embedded systems.
A tiny, portable, modular real-time operating system written in C.
Minimal footprint, predictable behavior, and zero hardware dependencies in its core.

Version: 0.4.0


✨ Features

  • Pure C core β€” no dynamic allocation, no HAL dependencies.
  • Portable ports β€” currently: null, posix, cortex-m.
  • Scheduler β€” priority, round-robin, or hybrid.
  • Task control β€” hrt_sleep(), hrt_yield(), hrt_task_delete(), and hrt_now_ms() millisecond helper.
  • Semaphores (binary + counting) β€” blocking take, try_take, ISR-safe give with FIFO wake-up; counting mode via hrt_sem_init_counting.
  • Mutexes β€” owner-tracked, non-recursive, FIFO waiter queue with direct handoff on unlock.
  • Message Queues β€” fixed-size, copy-based FIFO, blocking/non-blocking and ISR support.
  • Static tasks β€” stacks and TCBs supplied by the application.
  • CMake package β€” install and consume via find_package(HardRT).
  • Generated metadata β€” version and port headers at build time.
  • Optional C++17 wrapper β€” header-only interface target when enabled. See C++ Guide.

Please refer to PORTING.md for additional port inclusion.

The POSIX port is for logic verification, not timing accuracy. ucontext is used and supported on Linux/glibc.

β€œOn Cortex-M, the max time from tick to running the next highest priority ready task is bounded by: ISR tail + PendSV latency + context save/restore”

The POSIX port is regularly validated on Ubuntu 22.04, Ubuntu 24.04, and GitHub CI Linux environments. A test-suite failure has been observed on Debian 13 and is currently under investigation.


Architecture

architecture

The Architecture is mainly divided into three layers:

  • Application Layer: Where the tasks are defined. e.g., camera, UART downlink, HK/FDIR, etc.
  • HardRT Core: Where the RTOS lives, manages tasks, and calls the port to switch context when necessary.
    • HardRT Port: Wraps the hardware-specific methods.
  • Hardware Layer: Hardware specific methods, registers, primitives, etc.

β€œEvent-to-task latency in HardRT depends on task priority. When multiple tasks are woken concurrently, the highest-priority task consistently achieves minimal latency, while lower-priority tasks incur bounded additional delay.”

Task State Machine

task_state_machine.png

Where each task is executed in accordance with the policy adopted by the scheduler.

Note: If a task exits, it is automatically deleted (EXIT) and the scheduler won't requeue it.

see also Concepts

πŸ“ Repository Layout

hardrt/
β”œβ”€β”€ inc/                    # Public headers
β”œβ”€β”€ src/                    # Core + port implementations
β”‚   β”œβ”€β”€ core/               # Kernel internals
β”‚   └── port/               # Architecture-specific backends (null, posix, cortex_m)
β”œβ”€β”€ cpp/                    # Optional C++17 interface
β”œβ”€β”€ cmake/                  # additional cmake files and toolchains
β”œβ”€β”€ examples/               # Example applications
β”œβ”€β”€ tests/                  # POSIX test harness
β”œβ”€β”€ scripts/                # scripts to build and test the project
β”œβ”€β”€ docs/                   # Documentation
β”œβ”€β”€ LICENSE
└── README.md

βš™οΈ Build

mkdir -p build && cd build
cmake -DHARDRT_PORT=posix -DHARDRT_BUILD_EXAMPLES=ON ..
cmake --build . -j$(nproc)
./examples/two_tasks/two_tasks

Install package:

cmake --install . --prefix "$PWD/install"

Consume from another CMake project:

find_package(HardRT 0.4.0 REQUIRED)
add_executable(app main.c)
target_link_libraries(app PRIVATE HardRT::hardrt)

For further information and CMake flags, see the Build document.


🧠 Concepts

Tick vs Timeslice

  • Tick: base time unit generated by a timer interrupt (or POSIX signal). HardRT increments a counter each tick and wakes sleepers.
  • Timeslice: number of ticks a task may run before being rotated under RR. In the current implementation, rotation is triggered safely through the scheduler path rather than by direct context switching inside the tick hook.

Policy: Round‑robin within one priority (Sequence at tick times)

policy_RR.png

Caption:

  • Policy: HRT_SCHED_PRIORITY_RR (RR applies within same priority).
  • Two READY tasks with timeslice=1 ms. Handoffs occur exactly at every tick...
  • Self-transitions mark per-tick continuity when no interrupt/context switch occurs.

two_tick_RR.png

Caption:

  • Identical example with timeslice=2 ms is shown above, in essence handoffs occur every two ticks.

each task is executed in order.

Policy: Priority preemption (Sequence at tick times)

preempt.png

Caption:

  • this example shows four tasks with different priorities.
  • D the lowest priority task running continuously.
  • D is interrupted at T6 by Task A lasting one tick and resumes Task D.
  • D is interrupted once again by higher priority task C at T10 lasting three ticks.
  • C as well is interrupted by Task B (an even higher task) at T11 lasting two ticks.
  • B returns to C, which finishes the remaining work (two more ticks); and returns to D.
  • Self-transitions mark per-tick continuity when no interrupt/context switch occurs.

RR with preemption allows the usage of both policies within the same context.


Semaphores (binary + counting)

  • hrt_sem_init, hrt_sem_init_counting, hrt_sem_take, hrt_sem_try_take, hrt_sem_give, hrt_sem_give_from_isr.
  • Use semaphores for event signaling, resource counting, and producer/consumer synchronization.

Mutexes

  • hrt_mutex_init, hrt_mutex_lock, hrt_mutex_try_lock, hrt_mutex_unlock.
  • Owner-tracked, non-recursive, task-context-only mutual exclusion primitive.
  • Unlock performs direct handoff to one waiter when contention exists.
  • Current implementation does not provide priority inheritance or timed lock.

Message Queues

  • hrt_queue_init, hrt_queue_send, hrt_queue_recv, hrt_queue_try_send, hrt_queue_try_recv.
  • Fixed-size items, copy-based FIFO. See QUEUES.md.

Scheduling Flow

scheduling_flow.png

Tick (ISR/signal) -> hrt_tick_from_isr():

  • g_tick++
  • wake any SLEEP tasks whose wake_tick ⇐ now
  • hrt__pend_context_switch() (set resched flag)

Scheduler loop (port):

  • if resched flag:
    • next = hrt__pick_next_ready()
    • swapcontext/PendSV to next task

Task-level yield/sleep:

  • mark state (READYβ†’queue or SLEEP)
  • hrt__pend_context_switch()
  • hrt_port_yield_to_scheduler() (safe handoff from task ctx)

Statistics

See STATISTICS.md for detailed information on timing and tests collected for HardRT v0.4.0.

These results provide a solid baseline for further optimization and for documenting real-time behavior guarantees. Fundamental deterministic behavior remains identical to previous versions.


πŸ“œ License

Apache License 2.0 β€” see LICENSE.