OS Abstraction Layer (OSAL)ΒΆ

OverviewΒΆ

OSAL provides a portable interface for RTOS primitives. Applications can switch between different RTOS backends (FreeRTOS, RT-Thread, Zephyr) or run bare-metal without code changes.

Key features:

  • Unified API across multiple RTOS backends

  • Bare-metal support for resource-constrained systems

  • Task, mutex, semaphore, queue, and timer primitives

  • Critical section and interrupt management

  • Memory allocation abstraction

Supported BackendsΒΆ

Backend

Status

Notes

Bare-metal

βœ… Ready

Cooperative

FreeRTOS

βœ… Ready

Full support

RT-Thread

🚧 Planned

Zephyr

🚧 Planned

Getting StartedΒΆ

Include the header:

#include "osal/osal.h"

Initialize OSAL:

osal_init();

Task ManagementΒΆ

Create a task:

void my_task(void* arg)
{
    while (1) {
        /* Task code */
        osal_task_delay(100);
    }
}

osal_task_config_t cfg = {
    .name       = "my_task",
    .func       = my_task,
    .arg        = NULL,
    .stack_size = 1024,
    .priority   = OSAL_PRIORITY_NORMAL,
};

osal_task_handle_t handle;
osal_status_t status = osal_task_create(&cfg, &handle);

Task control:

/* Delay current task */
osal_task_delay(100);  /* 100 ms */

/* Suspend task */
osal_task_suspend(handle);

/* Resume task */
osal_task_resume(handle);

/* Delete task */
osal_task_delete(handle);

/* Get current task handle */
osal_task_handle_t current = osal_task_get_current();

MutexΒΆ

Create and use mutex:

osal_mutex_handle_t mutex;
osal_mutex_create(&mutex);

/* Lock with timeout */
if (osal_mutex_lock(mutex, 1000) == OSAL_OK) {
    /* Critical section */
    /* ... */

    /* Unlock */
    osal_mutex_unlock(mutex);
}

/* Lock forever */
osal_mutex_lock(mutex, OSAL_WAIT_FOREVER);

/* Try lock (non-blocking) */
if (osal_mutex_lock(mutex, 0) == OSAL_OK) {
    /* Got the lock */
}

/* Delete when done */
osal_mutex_delete(mutex);

SemaphoreΒΆ

Binary semaphore:

osal_sem_handle_t sem;
osal_sem_create_binary(0, &sem);  /* Initial count = 0 */

/* Wait (take) */
osal_sem_take(sem, OSAL_WAIT_FOREVER);

/* Signal (give) */
osal_sem_give(sem);

/* Delete */
osal_sem_delete(sem);

Counting semaphore:

osal_sem_handle_t sem;
osal_sem_create_counting(10, 0, &sem);  /* max=10, initial=0 */

/* Take multiple */
osal_sem_take(sem, 1000);

/* Give multiple */
osal_sem_give(sem);

/* Get current count */
uint32_t count = osal_sem_get_count(sem);

Message QueueΒΆ

Create and use queue:

typedef struct {
    uint32_t id;
    uint32_t data;
} message_t;

osal_queue_handle_t queue;
osal_queue_create(sizeof(message_t), 10, &queue);

/* Send message */
message_t msg = { .id = 1, .data = 42 };
osal_queue_send(queue, &msg, OSAL_WAIT_FOREVER);

/* Send to front (high priority) */
osal_queue_send_front(queue, &msg, 1000);

/* Receive message */
message_t received;
osal_queue_receive(queue, &received, OSAL_WAIT_FOREVER);

/* Check available messages */
uint32_t count = osal_queue_get_count(queue);

/* Delete */
osal_queue_delete(queue);

Software TimerΒΆ

Create and use timer:

void timer_callback(void* arg)
{
    /* Timer expired */
}

osal_timer_handle_t timer;
osal_timer_create("my_timer", timer_callback, NULL,
                  1000,  /* Period: 1000 ms */
                  true,  /* Auto-reload */
                  &timer);

/* Start timer */
osal_timer_start(timer);

/* Stop timer */
osal_timer_stop(timer);

/* Change period */
osal_timer_set_period(timer, 500);

/* Delete */
osal_timer_delete(timer);

Critical SectionsΒΆ

Disable/enable interrupts:

osal_enter_critical();
/* Interrupts disabled - keep this section short! */
/* ... */
osal_exit_critical();

Nested critical sections:

uint32_t state = osal_interrupt_disable();
/* Interrupts disabled */
/* ... */
osal_interrupt_restore(state);

Memory ManagementΒΆ

Dynamic allocation:

void* ptr = osal_malloc(1024);
if (ptr) {
    /* Use memory */
    osal_free(ptr);
}

/* Aligned allocation */
void* aligned = osal_malloc_aligned(1024, 32);
osal_free_aligned(aligned);

Time FunctionsΒΆ

Get system time:

/* Get tick count */
uint32_t ticks = osal_get_tick_count();

/* Get milliseconds */
uint32_t ms = osal_get_time_ms();

/* Delay */
osal_delay_ms(100);

Error HandlingΒΆ

All OSAL functions return osal_status_t:

osal_status_t status = osal_mutex_create(&mutex);
if (status != OSAL_OK) {
    /* Handle error */
}

Common status codes:

  • OSAL_OK - Success

  • OSAL_ERR_PARAM - Invalid parameter

  • OSAL_ERR_TIMEOUT - Operation timeout

  • OSAL_ERR_NO_MEM - Out of memory

  • OSAL_ERR_ISR - Called from ISR context

Bare-metal ConsiderationsΒΆ

When using the bare-metal backend:

  • Tasks run cooperatively (no preemption)

  • osal_task_delay() uses busy-wait

  • Mutexes use simple flags (no priority inheritance)

  • Queues use ring buffers

  • Call osal_scheduler_run() in main loop

int main(void)
{
    osal_init();

    /* Create tasks */
    osal_task_create(&task1_cfg, &task1);
    osal_task_create(&task2_cfg, &task2);

    /* Run scheduler (bare-metal) */
    osal_scheduler_run();

    return 0;
}

API ReferenceΒΆ

See OSAL API Reference for complete API documentation.