Skip to content

andrenepomuceno/CriticalTaskScheduler

Repository files navigation

CriticalTaskScheduler

Arduino Library Manager PlatformIO Registry License: MIT

Read this in other languages: English · Português · Español · 中文

Lightweight cooperative task scheduler for Arduino and ESP32.

  • Two execution modesbackground (cooperative, runs the earliest-due task per loop() call) and critical (runs all due tasks; pair with the optional FreeRTOS runner on ESP32).
  • Portable core — no String, no std::vector, no std::function; works on AVR, SAMD, RP2040, ESP8266, ESP32, etc.
  • Per-task stats — runs, last/avg/max execution time, total time, next-run time.
  • Pluggable time source — inject a fake clock for unit tests; default is millis().
  • Optional FreeRTOS critical thread — auto-enabled on ESP32, RP2040, and nRF52 (FreeRTOS bundled in core). STM32 and Teensy 4.x require manual opt-in (-D CRITICALTASKSCHEDULER_HAS_FREERTOS=1 + adding a FreeRTOS library to lib_deps). Any other FreeRTOS platform can opt in the same way.

Battle-tested on a real ESP32-S3 robot in production.

Install

Arduino IDE

  1. Open Tools → Manage Libraries…
  2. Search for CriticalTaskScheduler and click Install.

PlatformIO

Add to your platformio.ini:

lib_deps = andrenepomuceno/CriticalTaskScheduler@^1.0.0

Manual

Clone or download into your libraries/ folder:

git clone https://github.com/andrenepomuceno/CriticalTaskScheduler.git CriticalTaskScheduler

Architecture

graph TD
    USER["Your sketch"]

    subgraph SCHED["Scheduler"]
        BG["Background bucket\nTask* [MAX_TASKS]"]
        CR["Critical bucket\nTask* [MAX_TASKS]"]
    end

    subgraph TASK["Task"]
        CB["TaskCallback\nvoid (*)()" ]
        STATS["Stats\nruns · last · avg · max · total"]
        NRT["nextRunTime"]
    end

    subgraph ESP32["ESP32 only"]
        FRT["FreeRTOSCriticalRunner\nvTaskDelayUntil @ tickMs"]
    end

    USER -- "addTask()" --> BG
    USER -- "addTask() + critical=true" --> CR
    USER -- "execute()\nin loop()" --> BG
    FRT -- "executeCritical()\nhigh-priority thread" --> CR
    BG -- "runs earliest-due\none per call" --> TASK
    CR -- "runs all due\nper call" --> TASK
    TASK --> CB
    TASK --> STATS
    TASK --> NRT
Loading
#include <CriticalTaskScheduler.h>

TSScheduler sched;

void blink()  { digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); }
void status() { Serial.println("alive"); }

TSTask blinkTask("blink", 500,  blink);
TSTask statusTask("status", 1000, status);

void setup() {
    Serial.begin(115200);
    pinMode(LED_BUILTIN, OUTPUT);

    sched.addTask(&blinkTask);
    sched.addTask(&statusTask);
    sched.enableAll();
}

void loop() {
    sched.execute(); // runs the earliest-due background task; never delay()
}

See examples/ for more — including critical-vs-background timing, delayed start, and stats.

Why another scheduler?

Feature This library arkhipenko/TaskScheduler
Critical (FreeRTOS-thread) tasks Built-in (ESP32) No
Earliest-due single-shot in execute() Yes (anti-starvation) No (runs all due)
Per-task runs/avg/max/total stats Built-in Optional
Portable AVR↔ESP32 core Yes Yes
Static allocation only Yes (no heap) Optional

Documentation

License

MIT — see LICENSE.

About

Lightweight cooperative task scheduler for Arduino and ESP32.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors