Real-Time Operating Systems (Part 8)

RTOS Coding Examples in FreeRTOS

FreeRTOS is a lightweight RTOS widely used in embedded systems. Below are practical coding examples to demonstrate its core features:

1. Task Creation

#include "FreeRTOS.h"
#include "task.h"

void vTask1(void *pvParameters) {
    for (;;) {
        // Task 1 code here
    }
}

void vTask2(void *pvParameters) {
    for (;;) {
        // Task 2 code here
    }
}

int main(void) {
    xTaskCreate(vTask1, "Task 1", 100, NULL, 1, NULL);
    xTaskCreate(vTask2, "Task 2", 100, NULL, 2, NULL);
    vTaskStartScheduler();
    return 0;
}

This example demonstrates creating two tasks with different priorities.

2. Inter-Task Communication (Queues)

#include "FreeRTOS.h"
#include "queue.h"

QueueHandle_t xQueue;

void vSenderTask(void *pvParameters) {
    int valueToSend = 100;
    for (;;) {
        xQueueSend(xQueue, &valueToSend, portMAX_DELAY);
    }
}

void vReceiverTask(void *pvParameters) {
    int receivedValue;
    for (;;) {
        xQueueReceive(xQueue, &receivedValue, portMAX_DELAY);
    }
}

int main(void) {
    xQueue = xQueueCreate(5, sizeof(int));
    xTaskCreate(vSenderTask, "Sender", 100, NULL, 1, NULL);
    xTaskCreate(vReceiverTask, "Receiver", 100, NULL, 2, NULL);
    vTaskStartScheduler();
    return 0;
}

Queues enable efficient communication between tasks, as shown above.

3. Synchronization with Semaphores

#include "FreeRTOS.h"
#include "semphr.h"

SemaphoreHandle_t xSemaphore;

void vTask(void *pvParameters) {
    for (;;) {
        if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) {
            // Critical section code
            xSemaphoreGive(xSemaphore);
        }
    }
}

int main(void) {
    xSemaphore = xSemaphoreCreateBinary();
    xSemaphoreGive(xSemaphore);
    xTaskCreate(vTask, "Task", 100, NULL, 1, NULL);
    vTaskStartScheduler();
    return 0;
}

Semaphores ensure safe access to shared resources in a multitasking environment.

These examples illustrate FreeRTOS’s versatility in managing tasks, communication, and synchronization in embedded systems.

RTOS Coding Examples in Zephyr

Zephyr RTOS is an open-source platform designed for IoT and embedded applications. Here are practical examples showcasing its functionality:

1. Thread Creation

#include 

void thread1(void) {
    while (1) {
        // Thread 1 code here
        k_msleep(1000);
    }
}

void thread2(void) {
    while (1) {
        // Thread 2 code here
        k_msleep(500);
    }
}

K_THREAD_DEFINE(t1, 512, thread1, NULL, NULL, NULL, 1, 0, 0);
K_THREAD_DEFINE(t2, 512, thread2, NULL, NULL, NULL, 2, 0, 0);

This code demonstrates creating two threads with different priorities using Zephyr’s thread management APIs.

2. Message Queue

#include 
#include 

K_MSGQ_DEFINE(my_msgq, sizeof(int), 10, 4);

void sender_thread(void) {
    int data = 42;
    while (1) {
        k_msgq_put(&my_msgq, &data, K_FOREVER);
        k_msleep(1000);
    }
}

void receiver_thread(void) {
    int received_data;
    while (1) {
        k_msgq_get(&my_msgq, &received_data, K_FOREVER);
        printk("Received: %d\n", received_data);
    }
}

K_THREAD_DEFINE(sender, 512, sender_thread, NULL, NULL, NULL, 1, 0, 0);
K_THREAD_DEFINE(receiver, 512, receiver_thread, NULL, NULL, NULL, 2, 0, 0);

Message queues in Zephyr facilitate structured communication between threads, as illustrated here.

3. Synchronization Using Semaphores

#include 
#include 

struct k_sem my_semaphore;

void thread_with_semaphore(void) {
    while (1) {
        k_sem_take(&my_semaphore, K_FOREVER);
        // Critical section code
        printk("Semaphore Acquired\n");
        k_sem_give(&my_semaphore);
        k_msleep(1000);
    }
}

K_THREAD_DEFINE(thread_sem, 512, thread_with_semaphore, NULL, NULL, NULL, 1, 0, 0);

void main(void) {
    k_sem_init(&my_semaphore, 1, 1);
}

This example highlights the use of semaphores for synchronization in Zephyr RTOS.

Zephyr’s APIs offer robust features for managing multitasking, synchronization, and inter-thread communication in embedded systems.

CPU Requirements and Hardware Compatibility

Real-Time Operating Systems (RTOS) are designed to run on a wide range of hardware platforms, from simple microcontrollers to high-end processors. Understanding the CPU requirements is essential for selecting suitable hardware.

1. Minimum CPU Specifications
Most RTOS can run on minimal hardware. For example:

  • FreeRTOS: Requires 2 KB RAM and 8 KB flash, compatible with ARM Cortex-M0+ and AVR processors.
  • Zephyr: Needs around 8 KB RAM and 32 KB flash, supporting ARM, RISC-V, and x86 architectures.

2. Hardware Compatibility
RTOS compatibility varies with processor families. Examples include:

  • VxWorks: Optimized for x86, PowerPC, and ARM architectures, suitable for high-performance applications.
  • QNX: Supports ARM Cortex-A, x86, and MIPS, widely used in automotive systems.

3. Common Misconceptions
Despite popular myths, RTOS does not require high-end hardware. For instance:

  • Low-cost microcontrollers like ESP32 and STM32 can run FreeRTOS efficiently.
  • Zephyr runs seamlessly on Nordic Semiconductor SoCs for IoT applications.

4. Real-Time Performance Metrics
Consider metrics such as interrupt latency, context switch time, and power consumption when evaluating hardware for RTOS. High-end processors may offer better performance but are unnecessary for many use cases.

By matching RTOS requirements with hardware capabilities, developers can optimize performance and cost for their specific applications.