RA3 RTOS Logo RA3 RTOS

RA3 RTOS

Built by Ali Yasser, Powered by You

Dive into the code, make your mark, and be part of an evolving open-source project tailored for embedded systems. Let's innovate together!

Overview

RA3 RTOS is an open-source real-time operating system designed for embedded systems, providing a robust foundation for developing applications across various processor architectures. Currently, RA3 RTOS supports the ARM Cortex-M3 processor, making it an ideal choice for developers looking to create efficient and responsive applications in this environment.

The kernel of RA3 RTOS employs a preemptive priority round-robin scheduling algorithm, ensuring that tasks are managed effectively to meet real-time requirements. This approach allows for smooth task switching and high responsiveness, which are critical in embedded systems.

As part of our commitment to continuous improvement and community involvement, we invite developers to join us in enhancing RA3 RTOS. Future plans include:

Whether you are a seasoned developer or new to embedded systems, RA3 RTOS provides the tools and flexibility to bring your projects to life. Join us in shaping the future of this Egyptian RTOS and contribute to its growth and success.

Note

This project is open for contributions! We welcome feedback, feature requests, and any form of collaboration. Feel free to reach out to improve RA3 RTOS.

Meet the Team

Right now, the RA3 RTOS team consists solely of me, Ali Yasser Ali Abdallah. I am a passionate computer engineering student driven to contribute to the embedded systems industry by developing RA3 RTOS as an open-source, community-driven project. Through RA3, I aim to provide accessible, efficient solutions for embedded applications and offer a platform where developers can learn, innovate, and build together.

This team is open for expansion! If you share a vision for advancing embedded systems through open-source contributions, we welcome you to join and help enhance RA3 RTOS.

Ali Yasser Ali Abdallah

Founder & Lead Developer

Getting Started

Installation Instructions

1. Download the Latest Version: Visit the Releases page to download the latest release of RA3 RTOS as a ZIP file.
2. Unzip the File: Extract the contents of the downloaded ZIP file into your project directory.
3. Add to Project: Link the RA3 RTOS files into your project setup.

Setting up the Development Environment

Compiler Requirements: RA3 RTOS is currently built to support ARM Cortex-M3 processors. Use a compatible compiler (e.g., GCC for ARM).
Required Tools: Ensure your development environment includes debugging tools, a JTAG or SWD interface, and any additional peripherals needed for your specific application.

Quick Start Guide

1. Initialize the OS: Call OS_Init() to initialize RA3 RTOS before creating tasks or semaphores.
2. Create Tasks: Use OS_CreateTask() to define and initialize tasks, setting each task's function, priority, and stack size.
3. Start the OS: Call OS_StartOS() to start the scheduler and allow tasks to begin running.

For full documentation, refer to the RA3 RTOS Guide.

Core Concepts

Understanding the foundational concepts of RA3 RTOS is essential for effectively utilizing its features and developing applications. This section outlines the key components and mechanisms that drive the operating system.

1. Task Management

At the heart of RA3 RTOS is its task management system, which allows for the creation, scheduling, and control of tasks. The Task Control Block (TCB) is a crucial data structure that defines each task within the system. It contains essential information, including:

Tasks can exist in various states, including Ready, Running, and Suspended, which are managed by the scheduler to ensure efficient execution.

2. Memory Management

RA3 RTOS employs a flexible memory management strategy to allocate stacks for tasks dynamically. This approach allows for efficient use of memory resources, accommodating varying stack sizes based on the needs of different tasks. Key components include:

Efficient memory management is crucial for embedded systems, where resources are often limited.

3. Inter-task Communication

Effective communication between tasks is vital for synchronizing operations and sharing resources. RA3 RTOS provides several mechanisms for inter-task communication, including:

These mechanisms facilitate coordinated interactions between tasks, enhancing the overall functionality of applications.

4. Scheduling

RA3 RTOS employs a preemptive priority round-robin scheduling algorithm, which dynamically allocates CPU time based on task priorities. The scheduler continually evaluates task states and prioritizes execution based on their assigned priority levels. This approach allows high-priority tasks to preempt lower-priority tasks, ensuring timely execution of critical operations.

As part of our future roadmap, we aim to introduce additional scheduling algorithms and an OSEK-compliant version to broaden the applicability of RA3 RTOS across various domains.

API Reference

This section provides a detailed reference for the API functions available in RA3 RTOS. Each function is described with its purpose, parameters, return values, and an example of usage.

1. Task Management APIs

API Function: OS_CreateTask

Header File: Tasks.h

OS_ErrorStatus OS_CreateTask(OS_TCB* Task);

Creates a new task and adds it to the list of tasks that are ready to run. Each task requires RAM that is used to hold the task state and is utilized by the task as its stack. The task's stack size and function are specified in the OS_TCB structure.

Parameters:

Returns:

Example Usage:


    // Task function to be created.
    void MyTask(void) {
        for(;;) {
            // Task code goes here.
        }
    }

    void CreateMyTask(void) {
        OS_TCB myTask;
        myTask.Priority = 1;               // Task priority
        strncpy((char*)myTask.TaskName, "MyTask", sizeof(myTask.TaskName)); // Task name
        myTask.StackSize = 100;            // Stack size in words
        myTask.func = MyTask;              // Task function

        OS_ErrorStatus status = OS_CreateTask(&myTask); // Create the task
        if (status == OS_OK) {
            // Task was created successfully
        }
    }
        

API Function: OS_ActivateTask

Header File: Tasks.h

OS_ErrorStatus OS_ActivateTask(OS_TCB* Task);

Activates a previously created task and makes it ready to run. The task's state is changed to ready, allowing it to be scheduled by the RTOS.

Parameters:

Returns:

Example Usage:


    void ActivateMyTask(void) {
        OS_ErrorStatus status = OS_ActivateTask(&myTask); // Activate the task
        if (status == OS_OK) {
            // Task was activated successfully
        }
    }
        

API Function: OS_TerminateTask

Header File: Tasks.h

OS_ErrorStatus OS_TerminateTask(OS_TCB* Task);

Terminates a running task and removes it from the task scheduler. The task cannot be activated again after termination.

Parameters:

Returns:

Example Usage:


    void TerminateMyTask(void) {
        OS_ErrorStatus status = OS_TerminateTask(&myTask); // Terminate the task
        if (status == OS_OK) {
            // Task was terminated successfully
        }
    }
        

API Function: OS_DelayTask

Header File: Tasks.h

OS_ErrorStatus OS_DelayTask(OS_TCB* Task, uint32_t NoOfTicks);

Delays the execution of the specified task for a given number of ticks.

Parameters:

Returns:

Example Usage:


    void DelayMyTask(void) {
        OS_ErrorStatus status = OS_DelayTask(&myTask, 10); // Delay the task for 10 ticks
        if (status == OS_OK) {
            // Task was delayed successfully
        }
    }
        

2. Initialization and OS Control APIs

API Function: OS_Init

Header File: Tasks.h

OS_ErrorStatus OS_Init(void);

Initializes the RA3 RTOS kernel by setting up essential data structures, initializing resources, and preparing the system for task scheduling and synchronization. This function should be called before any other RTOS functions to ensure that the RTOS kernel is correctly initialized and ready for operation.

Parameters: None

Returns:

Example Usage:


    void main(void) {
        OS_ErrorStatus status = OS_Init();  // Initialize the RTOS
        if (status == OS_OK) {
            // Initialization succeeded, proceed with task creation and scheduling
            OS_StartScheduler();  // Start task scheduling
        } else {
            // Handle initialization error
        }
    }
        

API Function: OS_StartOS

Header File: Tasks.h

OS_ErrorStatus OS_StartOS();

Starts the operating system scheduler. This function must be called after creating and activating all tasks.

Returns:

Example Usage:


    void StartMyRTOS(void) {
        OS_ErrorStatus status = OS_StartOS(); // Start the RTOS scheduler
        if (status == OS_OK) {
            // RTOS started successfully
        }
    }
        

3. Hook APIs

API Function: OS_RegisterSysTickHook

Header File: Tasks.h

void OS_RegisterSysTickHook(OS_SysTickHook callback);

Sets a custom callback function to be executed at each SysTick interrupt. This function allows the user to define specific actions or behaviors that should occur periodically with every SysTick event.

Parameters:

Returns: None

Example Usage:


    void MySysTickHandler(void) {
        // Custom code to execute on each SysTick
    }

void SetMySysTickHook(void) {
    OS_RegisterSysTickHook(MySysTickHandler); // Set the SysTick hook to the custom handler
}
        

API Function: OS_RegisterIdleTaskHook

Header File: Tasks.h

void OS_RegisterIdleTaskHook(OS_IdleTaskHook callback);

Sets a custom callback function to be executed when the OS enters the idle state. This allows the user to define behavior for when no tasks are ready to run.

Parameters:

Returns: None

Example Usage:


    void MyIdleTaskHandler(void) {
        // Custom code to execute when the OS is idle
    }

void SetMyIdleTaskHook(void) {
    OS_RegisterIdleTaskHook(MyIdleTaskHandler); // Set the idle task hook to the custom handler
}
        

4. Semaphore APIs

API Function: OS_InitSemaphore

Header File: semaphore.h

OS_SemaphoreState OS_InitSemaphore(OS_Semaphore* semaphore, uint8_t initialCount);

Initializes a semaphore with a specified initial count. This count represents the number of available resources that the semaphore can manage.

Parameters:

Returns:

Example Usage:


    void InitMySemaphore(void) {
        OS_Semaphore mySemaphore;
        OS_SemaphoreState state = OS_InitSemaphore(&mySemaphore, 1); // Initialize semaphore with 1 resource
        if (state == OS_SEMAPHORE_INIT_OK) {
            // Semaphore initialized successfully
        }
    }
        

API Function: OS_AcquireSemaphore

Header File: semaphore.h

OS_SemaphoreState OS_AcquireSemaphore(OS_Semaphore* semaphore, OS_TCB* task);

Attempts to acquire the specified semaphore. If the semaphore is available, the task becomes the owner, and the semaphore count is decremented. If it is busy, the task is added to the waiting queue.

Parameters:

Returns:

Example Usage:


    void AcquireMySemaphore(OS_TCB* myTask) {
        OS_SemaphoreState state = OS_AcquireSemaphore(&mySemaphore, myTask); // Attempt to acquire the semaphore
        if (state == OS_SEMAPHORE_AVAILABLE) {
            // Semaphore acquired successfully
        } else if (state == OS_SEMAPHORE_BUSY) {
            // Semaphore is busy; task is now waiting
        }
    }
        

API Function: OS_ReleaseSemaphore

Header File: semaphore.h

OS_SemaphoreState OS_ReleaseSemaphore(OS_Semaphore* semaphore);

Releases the semaphore, making it available for other tasks. If there are tasks waiting for the semaphore, one is woken up and allowed to acquire the semaphore.

Parameters:

Returns:

Example Usage:


    void ReleaseMySemaphore(void) {
        OS_SemaphoreState state = OS_ReleaseSemaphore(&mySemaphore); // Release the semaphore
        if (state == OS_SEMAPHORE_AVAILABLE) {
            // Semaphore released successfully
        }
    }
        

5. Mutex APIs

API Function: OS_InitMutex

Header File: Mutex.h

OS_MutexState OS_InitMutex(OS_Mutex* mutex);

Initializes a mutex, setting its initial state to unlocked. This function prepares the mutex for use by a task.

Parameters:

Returns:

Example Usage:


    void InitMyMutex(void) {
        OS_Mutex myMutex;
        OS_MutexState state = OS_InitMutex(&myMutex); // Initialize the mutex
        if (state == OS_MUTEX_INIT_OK) {
            // Mutex initialized successfully
        }
    }
        

API Function: OS_AcquireMutex

Header File: Mutex.h

OS_MutexState OS_AcquireMutex(OS_Mutex* mutex, OS_TCB* task);

Attempts to acquire the specified mutex for the given task. If the mutex is already locked and owned by another task, the calling task will be blocked and added to the waiting queue.

Parameters:

Returns:

Example Usage:


    void AcquireMyMutex(OS_TCB* myTask) {
        OS_MutexState state = OS_AcquireMutex(&myMutex, myTask); // Attempt to acquire the mutex
        if (state == OS_MUTEX_AVAILABLE) {
            // Mutex acquired successfully
        } else if (state == OS_MUTEX_BUSY) {
            // Mutex is busy; task is now waiting
        }
    }
        

API Function: OS_ReleaseMutex

Header File: Mutex.h

OS_MutexState OS_ReleaseMutex(OS_Mutex* mutex);

Releases the mutex from the current owner, making it available for other tasks. If there are tasks waiting for the mutex, one of them is woken up and allowed to acquire the mutex.

Parameters:

Returns:

Example Usage:


    void ReleaseMyMutex(void) {
        OS_MutexState state = OS_ReleaseMutex(&myMutex); // Release the mutex
        if (state == OS_MUTEX_AVAILABLE) {
            // Mutex released successfully
        }
    }
        

6. Event Group APIs

API Function: OS_InitEventGroup

Header File: event_group.h

OS_EventGroupState OS_InitEventGroup(OS_EventGroup* eventGroup);

Initializes an event group. This function prepares the event group for use by tasks that require synchronization.

Parameters:

Returns:

Example Usage:


    void InitMyEventGroup(void) {
        OS_EventGroup myEventGroup;
        OS_EventGroupState state = OS_InitEventGroup(&myEventGroup); // Initialize the event group
        if (state == OS_EVENT_GROUP_INIT_OK) {
            // Event group initialized successfully
        }
    }
        

API Function: OS_SetEvent

Header File: event_group.h

OS_EventGroupState OS_SetEvent(OS_EventGroup* eventGroup, uint32_t eventMask);

Sets the specified bits in the event group, allowing tasks waiting for those events to be notified.

Parameters:

Returns:

Example Usage:


    void SetMyEvent(void) {
        OS_EventGroupState state = OS_SetEvent(&myEventGroup, 0x01); // Set event with bitmask 0x01
        if (state == OS_EVENT_SET_OK) {
            // Event set successfully
        }
    }
        

API Function: OS_ClearEvent

Header File: event_group.h

OS_EventGroupState OS_ClearEvent(OS_EventGroup* eventGroup, uint32_t eventMask);

Clears the specified bits in the event group, indicating that those events are no longer valid.

Parameters:

Returns:

Example Usage:


    void ClearMyEvent(void) {
        OS_EventGroupState state = OS_ClearEvent(&myEventGroup, 0x01); // Clear event with bitmask 0x01
        if (state == OS_EVENT_CLEAR_OK) {
            // Event cleared successfully
        }
    }
        

Configuration for RA3 RTOS

Header File: config.h

The config.h configuration file provides essential options to tailor RA3 RTOS to meet specific system requirements. By adjusting these parameters, you can define core settings such as stack size, timing, priority levels, CPU frequency, and other key aspects that influence the RTOS's performance in embedded applications. Below, the default parameter values are provided to guide initial configurations for RA3 RTOS in your project.


            // Define macro for OS preemption control
#define OS_PREEMPTION_ENABLED         1  // Set to 1 to enable, 0 to disable preemption
            
// Size of the main stack in bytes
#define OS_MAIN_STACK_SIZE            3072
            
// Default stack size for tasks in bytes
#define OS_DEFAULT_TASK_STACK_SIZE    1024
            
// Time duration of each tick in milliseconds
#define OS_TICK_TIME_IN_MS            1
            
// CPU clock frequency in hertz
#define OS_CPU_CLOCK_FREQ_IN_HZ       72000000  
            
// Lowest priority level for tasks
#define OS_LOWEST_PRIORITY            255
            
// Highest priority level for tasks
#define OS_HIGHEST_PRIORITY           0
            
// Enable/disable the tick task hook
#define OS_TICK_HOOK_ENABLED          1
            
// Enable/disable the idle task hook
#define OS_IDLE_TASK_HOOK_ENABLED     1
        

Configuration Parameters in config.h

PREEMPTION
#define OS_PREEMPTION_ENABLED 1
Description: Enables or disables OS preemption. If set to 1, preemption is enabled, allowing the OS to switch tasks based on priority. If set to 0, the PendSV trigger for task switching will be removed, disabling preemption.

MAIN_STACK_SIZE
#define OS_MAIN_STACK_SIZE 3072
Description: Sets the size of the main stack used by the RTOS in bytes. Adjust this according to your system’s memory requirements, especially if the main stack handles intensive or recursive tasks.

DEFAULT_TASK_STACK_SIZE
#define OS_DEFAULT_TASK_STACK_SIZE 1024
Description: Specifies the default stack size for tasks. Increase this value if tasks require more stack space (e.g., tasks involving deep function calls or large local variables).

TICK_TIME_IN_MS
#define OS_TICK_TIME_IN_MS 1
Description: Sets the duration of each OS tick. This tick frequency controls the RTOS's task switching and timing functions. A lower tick duration means more frequent task switching but higher CPU load.

CPU_CLOCK_FREQ_IN_HZ
#define OS_CPU_CLOCK_FREQ_IN_HZ 7200000
Description: Defines the CPU clock frequency in Hz. Accurate setting is essential for precise timing in the RTOS scheduler. Ensure this matches your processor’s actual frequency for optimal performance.

OS_LOWEST_PRIORITY
#define OS_LOWEST_PRIORITY 255
Description: Specifies the lowest priority level available for tasks, where higher numbers represent lower priorities. Setting this higher allows for a more granular priority system.

OS_HIGHEST_PRIORITY
#define OS_HIGHEST_PRIORITY 0
Description: Sets the highest priority level for tasks. Lower numbers represent higher priorities in RA3 RTOS. Set this to define the top priority available for critical tasks.

IDLE_TASK_HOOK_ENABLED
#define OS_IDLE_TASK_HOOK_ENABLED 1
Description: Enables or disables the idle task hook. If enabled (1), the RTOS will execute a user-defined callback whenever the idle task runs, allowing low-priority background operations.

TICK_HOOK_ENABLED
#define OS_TICK_HOOK_ENABLED 1
Description: Enables or disables the tick hook. If enabled (1), the RTOS will execute a user-defined callback function at each tick, useful for periodic background tasks.

Note

Note: Ensure you review and adjust these parameters based on the specific needs of your embedded system for optimal performance. Misconfiguration can lead to unexpected behavior in task timing, scheduling, and memory utilization.

Contributing to RA3 RTOS

Contributions from the community are essential to the growth and improvement of RA3 RTOS! By contributing, you’re helping to enhance the RTOS's functionality and reliability for embedded systems worldwide. Follow the guidelines and steps below to make your contributions count!

1. Review Contribution Guidelines

Before starting, please refer to the RA3 RTOS Documentation to understand the coding standards, structure, and best practices that maintain the project’s consistency and quality. Ensure you follow these guidelines to keep the codebase organized and efficient.

2. Follow These Steps to Contribute

  1. Fork the Repository: Start by forking the RA3 RTOS repository to your GitHub account to create your own workspace for experimentation and improvements.
  2. Clone Your Fork: Bring the repository to your local machine for easy editing.
    git clone https://github.com/ENGaliyasser/RA3-RTOS.git
    cd RA3-RTOS
                    
  3. Create a New Branch: Organize your changes by creating a new branch for your feature or bug fix, keeping your work clean and isolated.
    git checkout -b feature/my-new-feature
                    
  4. Implement Your Changes: Dive in! Add your new feature, squash that bug, or enhance the existing codebase while following the project’s coding guidelines. Your improvements help RA3 RTOS serve the embedded systems community better!
  5. Test Your Changes: Validate your updates by testing thoroughly. Quality is key, so make sure everything runs smoothly and reliably.
  6. Commit Your Changes: Commit your work with a meaningful, descriptive message that explains what you’ve added.
    git add .
    git commit -m "Add my new feature"
                    
  7. Push Your Changes: Share your work by pushing the new branch to your forked repository.
    git push origin feature/my-new-feature
                    
  8. Create a Pull Request: Head back to the original RA3 RTOS repository and submit a pull request, sharing your contribution with the maintainers. Include a clear title and description to help others understand the value you’re adding.
  9. Address Feedback: Engage with maintainers, refine your work, and address any comments or suggestions. This collaboration helps bring out the best in your contribution!
  10. 🎉 Celebrate Your Contribution! 🎉: When your pull request is merged, congratulations are in order! You’ve officially contributed to RA3 RTOS and made an impact in the embedded systems world. Thank you for your valuable contribution, and welcome to the RA3 RTOS community!