Skip to content

Repository files navigation

SyntropicOS Banner

SyntropicOS

High-Performance Bare-Metal Application Framework & Cooperative OS

License C99 Build & Test

SyntropicOS is a zero-overhead, production-grade C99 framework designed for deeply embedded microcontrollers (STM32, RP2040, ESP32, AVR, RISC-V). It combines stackless coroutines, non-blocking hardware drivers, industrial fieldbuses, fixed-point DSP, and display graphics into a single cooperative ecosystem.


Why SyntropicOS? (Design Rationale & Philosophy)

Deeply embedded systems present a fundamental architectural choice:

  1. Bare-Metal Super-Loops (while(1)): Simple to start and zero memory overhead. However, managing timers, state machines, protocol decoders, and non-blocking I/O in a single main loop quickly results in unmaintainable code. Any blocking call halts the entire microcontroller.
  2. Preemptive RTOS (FreeRTOS, Zephyr): Multi-tasking where every task requires an allocated stack (512 B to 4 KB RAM per task). On microcontrollers with 2 KB to 16 KB total RAM, allocating thread stacks severely constrains memory. Preemptive switches also introduce race conditions, mutex contention, context-switch overhead, and potential stack overflows.
  3. The SyntropicOS Approach: A cooperative OS built around stackless coroutines (protothreads syn_pt). Tasks execute sequentially on a single system stack while syntax macros handle yielding and resumption. Continuation state costs 2 bytes of RAM per thread (uint16_t lc). Memory allocation is 100% static (zero malloc()), preventing runtime heap fragmentation.

SyntropicOS is not the first system to use stackless coroutines — Contiki OS (created by Adam Dunkels, who invented protothreads) popularized them for microcontrollers. The difference is that every SyntropicOS module is built from the ground up with the cooperative model in mind. All 70+ drivers, protocol stacks, and subsystems expose non-blocking _poll(), _update(), or _process() APIs that yield cooperatively. There are no blocking wrappers around third-party libraries or hidden busy-waits inside module code.


Architecture & Framework Comparison

Feature Bare-Metal Super-Loop Preemptive RTOS (FreeRTOS / Zephyr) SyntropicOS
RAM per Thread 0 B 512 B – 4 KB per task (stack pointer) 2 B per thread (uint16_t lc)
Concurrency Model Manual state machines in main loop Preemptive multi-threading Cooperative protothreads (syn_pt)
Memory Allocation Static Dynamic heap or static pool allocation 100% Zero-Heap / Static
Context Switch Cost Zero CPU register push/pop & stack frame swap Zero (C99 switch continuation jump)
Race Conditions None (single thread execution) High (requires mutexes, semaphores, spinlocks) None across yield points
Execution Safety Low (blocking functions freeze system) Stack overflow risk High (no thread stack overflow risk)
Target Hardware 8-bit to 32-bit MCUs 32-bit MCUs (typically >32 KB RAM) 8-bit to 32-bit MCUs (2 KB+ RAM)

Core Concepts Explained

1. Stackless Protothreads (syn_pt)

Protothreads provide sequential, non-blocking flow control inside standard C functions without requiring separate stacks.

  • Continuation via Duff's Device: PT_BEGIN() expands to a switch(pt->lc) statement. When yielding (PT_WAIT_UNTIL or PT_TASK_DELAY_MS), pt->lc records __LINE__ and returns PT_WAITING. Upon re-invocation, the switch jumps directly to the saved line.
  • RAM Footprint: Stores only a uint16_t continuation variable (2 bytes RAM).
  • Variable Lifetime: Local variables inside a protothread function do not persist across yields. Persistent state must be stored in static variables, global contexts, or a struct passed via user_data.

2. Cooperative Task Scheduler (syn_sched)

The scheduler runs an array of SYN_Task descriptors. On each tick, it executes the highest-priority ready task (priority 0 highest). Equal-priority tasks execute round-robin.

  • Zero Dynamic Allocation: The application owns and allocates the SYN_Task array statically.
  • Tickless Idle: Includes low-power sleep support (syn_sched_run_tickless()) when no tasks are ready.

3. Ground-Up Non-Blocking Module Ecosystem

Every driver and protocol module in SyntropicOS is written from scratch as a cooperative, non-blocking state machine. Modules expose _poll(), _update(), or _process() entry points (e.g. syn_modbus_poll(), syn_button_update(), syn_ble_gatt_process_att_pdu()) that do a bounded unit of work and return immediately. No module internally blocks, busy-waits, or calls delay().


Technical Specifications At-a-Glance

Property Design Specification
Concurrency Cooperative stackless coroutines (syn_pt). Continuation state costs 2 bytes RAM per thread.
Scheduler Cooperative task runner (syn_sched). Task descriptors cost ~16–28 bytes RAM per task.
Memory Allocation 100% Zero-Heap / Static Allocation. No malloc() or dynamic pool fragmentation over long runtimes.
Execution Model All 70+ drivers & protocol stacks are written as non-blocking state machines.
Compatibility Standard C99. Compiles with GCC, Clang, IAR, Keil, STM32CubeIDE, and Arduino IDE.

System Architecture

Note

If the Mermaid architecture diagram below fails to render on first load, please refresh your browser (GitHub's client-side Mermaid renderer occasionally takes a coffee break).

flowchart TD
    App["Application Logic & Callbacks"] --> Modules["SyntropicOS Non-Blocking State Machine Modules"]
    
    subgraph Modules
        IO["Input/Output (Buttons, Encoders, LEDs)"]
        Comm["Communication (COBS, Router, Modbus, DALI, BACnet, M-Bus)"]
        Storage["Storage (Settings, LittleFS, VFS)"]
        Display["Display (Canvas 1bpp/16bpp, IMGUI)"]
        DSP["DSP & Control (PID, Biquad, FFT, FOC, TinyML)"]

    end
    
    Modules --> Kernel["Cooperative Kernel (syn_pt + syn_sched)"]
    Kernel --> HAL["Hardware Port Layer (syn_port_*)"]
    HAL --> Hardware["Microcontroller Hardware (STM32, RP2040, ESP32, AVR)"]
Loading

Quick Navigation & Documentation Index

Module Guides

  • ⚡ Core & Multitasking — Protothreads, Task Scheduler, Active Objects, Workqueues.
  • 🎛️ Input / Output — Debounced Buttons, Tap Gestures, Combos, Rotary Encoders, LEDs, Soft PWM.
  • 📡 Communication Protocols — COBS Framing, Addressed Router, Modbus RTU/TCP, DALI, BACnet MS/TP, M-Bus, ISO-TP, J1939, NMEA 2000, CCP v2.1, ASAM XCP v1.x, UDS (ISO 14229), ODVA DeviceNet.
  • 💾 Storage & Filesystems — Persistent Settings Manager, Wear-Leveled Flash, LittleFS, FAT.
  • 🖥️ Display & Embedded UI — Framebuffer Canvas, 2D Graphics, Zero-Heap IMGUI.
  • 🔬 Diagnostics & Debug — Lightweight Event Tracer (syn_trace), Task CPU Profiler (syn_profiler), Serial CLI.

Minimal Example

#include "syntropic/syntropic.h"

#define LED_PIN 13

static SYN_PT_Status blink_task(SYN_PT *pt, SYN_Task *task) {
    PT_BEGIN(pt);
    for (;;) {
        syn_gpio_toggle(LED_PIN);
        PT_TASK_DELAY_MS(pt, task, 500); // Non-blocking 500ms delay
    }
    PT_END(pt);
}

int main(void) {
    syn_gpio_init(LED_PIN, SYN_GPIO_OUTPUT);
    
    static SYN_Task tasks[1];
    static SYN_Sched sched;
    
    syn_task_create(&tasks[0], "blink", blink_task, 0, NULL);
    syn_sched_init(&sched, tasks, 1);
    syn_sched_run_forever(&sched);
}

Example Projects Directory (examples/)

SyntropicOS includes over 50 complete hardware and SDK examples across bare-metal C, STM32 HAL, PlatformIO, and Arduino. See examples/README.md for the full categorized directory.

Featured Example Highlights

👉 Explore all 50+ example projects in the Examples Directory.


Containerized Verification Workflow

make test         # Run Unity unit test suite (2000+ unit tests passing)
make san          # Execute AddressSanitizer & UBSan memory safety audit
make qemu         # Bare-metal ARM Cortex-M4 boot emulation
make fuzz         # Run LLVM libFuzzer protocol targets (COBS, Modbus, MQTT, HTTP)
make cov          # Generates LCOV HTML code coverage reports
make static       # Run Cppcheck and Clang scan-build static analysis
make dox          # Build Doxygen API documentation (0 warnings tolerance)
make integration  # Run E2E tests against 8 genuine production container daemons

About

Modular cooperative RTOS for MCUs — protothread scheduler, industrial fieldbus (Modbus, EtherCAT, CANopen, LIN, PMBus), DSP/NN, motor control, IoT & 60+ drivers. Zero-dependency C99 for ARM Cortex-M, RISC-V, ESP32, RP2040, AVR. Bare-metal & Arduino.

Topics

Resources

Stars

6 stars

Watchers

1 watching

Forks

Releases

Contributors

Languages