Skip to content

MoeSimpleRealtimeOS is a lightweight, portable embedded real-time operating system (RTOS) designed specifically for the Arduino platform and similar microcontroller environments.

License

Notifications You must be signed in to change notification settings

OmniX-Space/MoeSimpleRealtimeOS

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MoeSimpleRealtimeOS

MoeSimpleRealtimeOS is a lightweight, portable embedded real-time operating system (RTOS) designed specifically for the Arduino platform and similar microcontroller environments.

It provides fundamental task scheduling, priority management, and inter-task communication mechanisms, aiming to help developers organize complex embedded applications in a clearer and more modular way.

Features

Task Management and Scheduling

  • Preemptive Scheduling: Supports priority-based preemptive scheduling. A higher-priority task can immediately preempt a currently running lower-priority task when it transitions to the "Ready" state.
  • Time-Slice Round Robin: Tasks with the same priority execute in rotation using a fixed time slice (default 10ms), preventing any single task from monopolizing the CPU for extended periods.
  • Multi-Task State Management: Supports five task states:
    • RUNNING: The task currently being executed.
    • READY: Ready to run, waiting for the scheduler to assign CPU time.
    • BLOCKED: Blocked due to calling vTaskDelay() or waiting for a resource.
    • PAUSED: Explicitly paused and will not participate in scheduling.
    • DEAD: Terminated or unassigned task.
  • Dynamic Task Creation and Destruction: Supports dynamically creating, starting, pausing, and terminating tasks at runtime.

Inter-Task Communication

  • Message Queue
    • Provides a type-safe, thread-safe message passing mechanism suitable for data exchange and event notification between tasks.
    • Implemented using a circular buffer, supporting arbitrary data types (via templates).
    • Supports blocking dequeue operations with timeout, facilitating the implementation of synchronization logic.
    • Uses interrupt protection to ensure data consistency in multi-tasking/interrupt environments.
  • Resource Exclusive Control (Planned)
    • Safe access to shared resources (e.g., serial port, I2C bus) can be achieved through external mutual exclusion mechanisms (e.g., semaphores, critical sections).
    • Currently, it is recommended to use noInterrupts()/interrupts() or FreeRTOS (on ESP32 platforms) to implement resource protection.

Usage

1. Task Management Usage

(1) Initialization and Scheduler Execution

Create an instance of MoeTask and configure tasks within setup(); continuously call runScheduler() in loop() to initiate the scheduling loop.

#include "MoeTask.h"

MoeTask os; // Create an OS instance

void setup() {
    Serial.begin(115200);
    while (!Serial); // Wait for serial monitor connection (for development only)

    // Create tasks
    int t1 = os.vTaskCreate(task1, 1); // Priority 1
    int t2 = os.vTaskCreate(task2, 2); // Priority 2 (higher)

    // Start tasks
    os.vTaskStart(t1);
    os.vTaskStart(t2);
}

void loop() {
    os.runScheduler(); // Must be called continuously in loop
}

(2) Defining Task Functions

Task functions are of type void() with no parameters or return value. Implement business logic within these functions, and use vTaskDelay() to achieve non-blocking delays.

void task1() {
    Serial.println("Task 1 is running");
    os.vTaskDelay(1000); // Delay 1 second (non-blocking)
}

void task2() {
    Serial.println("  Task 2 is running");
    os.vTaskDelay(500);  // Delay 500ms
}

(3) Task Control API

Function Description
int vTaskCreate(void (*taskFunc)(void), int priority = 0) Creates a task, returns task ID; priority range 0~9 (9 is highest)
void vTaskStart(int taskId) Sets task state to READY, adding it to scheduling
void vTaskPause(int taskId) Pauses task (enters PAUSED state)
void vTaskKill(int taskId) Terminates task (enters DEAD state)
int vTaskId(void (*taskFunc)(void)) Looks up task ID by function pointer
void vTaskDelay(uint32_t ms) Delays current task by specified milliseconds (enters BLOCKED state)

⚠️ Note: vTaskDelay() can only be called by the task itself, not within interrupts or other non-task contexts.

2. Message Queue Usage

(1) Define Message Structure and Queue

Use the template MoeQueue<T, Size> to define a queue, supporting any copyable type.

#include "MoeQueue.h"

struct SensorData {
    float temperature;
    float humidity;
    uint32_t timestamp;
};

// Create a queue capable of holding up to 8 SensorData messages
MoeQueue<SensorData, 8> sensorQueue;

(2) Producer-Consumer Pattern Example

void loop() {
    // Producer: Generate one data point every 2 seconds
    static uint32_t lastSend = 0;
    if (millis() - lastSend > 2000) {
        SensorData data = {25.5f, 60.0f, millis()};
        if (sensorQueue.push(data)) {
            Serial.println("Data pushed to queue");
        } else {
            Serial.println("Queue full!");
        }
        lastSend = millis();
    }

    // Consumer: Attempt to retrieve data (wait up to 100ms)
    SensorData received;
    if (sensorQueue.pop(received, 100)) {
        Serial.printf("Received: Temp=%.1f°C, Humi=%.1f%%, Time=%u\n",
                      received.temperature, received.humidity, received.timestamp);
    }

    delay(10); // Prevent loop from consuming CPU too quickly
}

(3) Message Queue API

Function Description
bool push(const T& msg) Enqueues a message; returns true on success, false if queue is full
bool pop(T& msg) Dequeues a message non-blockingly; returns false if queue is empty
bool pop(T& msg, uint32_t timeoutMs) Dequeues a message with timeout (0 means non-blocking)
bool empty() const Checks if the queue is empty
bool full() const Checks if the queue is full
size_t size() const Gets the current number of messages in the queue
void clear() Clears the queue

Thread Safety: All operations achieve atomicity by disabling interrupts, ensuring safe usage in multi-tasking or interrupt environments.

Configuration Options

System behavior can be adjusted at compile-time via predefined macros:

Macro Definition Default Value Description
MAX_TASKS 10 Maximum number of concurrent tasks; adjustable based on memory
TASK_TIMESLICE_MS 10 Time-slice length (in milliseconds) for tasks of the same priority

Example: Defining #define MAX_TASKS 5 before compilation reduces memory usage.

Platform Support and Multi-Core (ESP32)

  • General Platforms (e.g., Arduino Uno, ESP8266):
    • Uses runScheduler() in loop() for polling-based scheduling.
    • Runs on a single core, relying on millis() for time management.
  • ESP32 Multi-Core Support (Experimental):
    • Automatically enables FreeRTOS integration when ARDUINO_ARCH_ESP32 is detected.
    • Supports running the scheduler on dual cores via xTaskCreatePinnedToCore (currently not supported; defaults to single-core polling).
    • True multi-core parallel scheduling may be implemented in future versions.

Design Philosophy and Use Cases

Design Philosophy:

  • Minimalist kernel with clear code, easy to understand and customize.
  • Zero dependencies (aside from Arduino core libraries), facilitating portability.
  • Suitable for education, prototyping, and small-to-medium projects.

Use Cases:

  • Multi-sensor data acquisition and processing
  • Separation of user interface and background tasks
  • Timed control and event-driven systems
  • Educational tool for learning RTOS fundamentals

Version Updates

Refer to CHANGELOG.md for version update history.

📌 Note: This system is currently a lightweight implementation that does not support advanced features such as memory protection or task stack isolation. It is suitable for resource-constrained embedded scenarios requiring basic multitasking capabilities.

Author

Acknowledgements

  • Thanks to all contributors

License

This project is open-source under the LGPLv2.1 license.

About

MoeSimpleRealtimeOS is a lightweight, portable embedded real-time operating system (RTOS) designed specifically for the Arduino platform and similar microcontroller environments.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages