RTOS per sistemi embedded

Definizione di Sistema Embedded

Il termine “embedded” (integrato) si applica a computer/microcontrollori (incapsulati in dispositivi pilotati) che eseguono un’applicazione per il controllo.
Sistemi real-time sono progettati per controllare e monitorare il loro ambiente. Molti di questi sistemi utilizzano sensori per raccogliere informazioni sullo stato dell’ambiente, ed usare degli esecutori per cambiare qualcosa.

Esistono due tipi di sistemi real-time: “hard real-time” e “soft real-time”. Il primo tipo deve completare un’operazione in tempo, senza eccezioni. I ritardi sono critici e possono rendere il sistema poco affidabile.

Struttura RTOS

RTOS Overview

Il cuore di ogni sistema operativo real-time (RTOS) è il Kernel. All’interno del Kernel c’è lo scheduler. Fondamentalmente si tratta di un set di algoritmi con i quali gestire l’ordine dei task in esecuzione. La definizione di multitasking deriva dall’abilità del Kernel di controllare task multipli che devono essere eseguiti insieme senza ritardi. Il multitasking da la sensazione che thread multipli vengano eseguiti contemporaneamente: in realtà il processore esegue task dopo task, seguendo l’ordine dello scheduler.

Programmare con RTOS

Semafori

Semaphores

Un sistema multitasking richiede un’interconnessione tra i processi. La comunicazione dipende dalla sincronizzazione, effettuata da semafori. In base all’applicazione, ci sono tre tipi di semafori:
Binario – È il più utilizzato
Esclusione Reciproca (Mutex) – È simile al binario, ma è molto utile per gestire le priorità su inheritance, rimozione o ricorsione.
Conteggio – È usato quando molti processi accedono allo stesso semaforo.

Programmazione dei semafori su Linux RTAI:

#include "rtai.h"                    /* Configurazione degli switch RTAI */
#include "rtai_sched.h"              /* scheduling RTAI */
#include "rtai_sem.h"                /* Semafori RTAI */

/* Variabili Globali */
#define CNTR 10
static RT_TASK t1;
static RT_TASK t2;
/* Prototipi di funzione */
void taskOne(long arg);
void taskTwo(long arg);
int objects = 0;
void tasks(void)
{
int retval;
    /* Inizializzazione dei task */
    retval = rt_task_init( &t1, task1, 0, 512, 0, 0, 0);
    retval = rt_task_init( &t2, task2, 0, 512, 0, 0, 0);
    /* Avviamento dei task */
    retval = rt_task_resume( &t1);
    retval = rt_task_resume( &t2);
}

void task1(long arg)
{
int i;
    for (i=0; i< CNTR; i++)
    {
        rt_printk(" task1: objects = %d \n", ++ objects);
    }
}

void task2(long arg)
{
int i;
    for (i=0; i < CNTR; i++)
    {
        rt_printk(" task2: objects = %d \n", -- objects);
    }
}

int init_module(void)
{
    printk(" start module\n");
    rt_set_oneshot_mode();                /* Settaggio della modalità oneshot per il timer. */
    start_rt_timer(1);                    /* Avvia il timer con periodo 1*/
    tasks();
    printk("end module\n");
    return 0;
}

void cleanup_module(void)
{
    /* fine dei task per default */
    return;
}

Code dei messaggi

Message Queues

Due task possono comunicare usando una coda. Il risultato è che il task A invia un messaggio al task B direttamente, ma in realtà sono condivisi in un’area di memoria, e un terzo processo (il sistema operativo) prende l’incarico di trasferire i dati da un task ad un altro. Usando una sola coda la comunicazione può avere una solo direzione (nell’esempio, Task A-> Task B). Quando è necessaria una comunicazione bi-direazionale (ad esempio Task A <-> Task B) vengono utilizzate due code.

Mailbox è come sempre un tipo di buffer gestito dal sistema operativo. Può essere usato da task multipli ed è simile ad una struttura FIFO.

Uso di Comunicazione Mailbox su Linux RTAI:

#include "rtai.h"
#include "rtai_sched.h"
#include "rtai_mbx.h"
static RT_TASK t1;
static RT_TASK t2;
/* Funzioni Prototipi */
void task1(long arg);
void task2(long arg);
/* definizioni */
#define MAX_NO_MESS     10
#define MAX_MESS_LENGTH 100
/* Variabili globali */
static MBX mailboxId;
/* Crea la coda di messaggio e 2 Task */
void message(void)
{
int retval;
    /* Crea mailbox FIFO */
    retval = rt_typed_mbx_init( &mailboxId, MAX_NO_MESS, FIFO_Q);
    if (0 != retval)
    {
        printk("Space mailbox not allocated.");
    }
    /* Crea e inizializza 2 task */
    retval = rt_task_init( &t1, task1, 0, 512, 0, 0, 0);
    retval = rt_task_init( &t2, task2, 0, 512, 0, 0, 0);
    /* Avvia i due task */
    retval = rt_task_resume( &t1);
    retval = rt_task_resume( &t2);
}

/* Task1 scrive nella mailbox */
void task1(long arg)
{
int retval;
    char mess[] = "Received message from task1";
    /* Invia messaggio */
    retval = rt_mbx_send( &mailboxId, mess, sizeof(mess));
    if (0 != retval)
    {
        rt_printk(" mailbox not invalid \n");
    } else {
        rt_printk(" task1: message sent to mailbox \n");}
    }
}
    /* Task2 legge dalla mailbox */
void task2(long arg)
{
int retval;
    char msgBuff[MAX_MESS_LENGTH];
    /* Ricezione messaggio */
    retval = rt_mbx_receive_wp( &mailboxId, msgBuff, 50);
    if (-EINVAL == retval) 
    { /* il task non fa riferimento ad un task valido */
        rt_printk(" mailbox not invalid\n");
    } else {
        rt_printk(" task2: receive message %s from mailbox \n", msgBuff);
    }
    /* cancella mailbox */
    rt_mbx_delete( &mailboxId);
}
int init_module(void)
{
    printk(" start module \n");
    rt_set_oneshot_mode();
    start_rt_timer(1);
    message();
    printk(" end module\n");
    return 0;
}
void cleanup_module(void)
{
    stop_rt_timer();       /* Ferma il timer */
    rt_task_delete( &t1);
    rt_task_delete( &t2);
    return;
}

Scheduling dei task

Task Scheduling

Il task scheduler stabilisce degli slot a tempo per i task. L’ampiezza e l’attivazione degli slot a tempo dipendono dalle risorse disponibili e dalle priorità.

Metodo Round Robin
Questo metodo gestisce i task con la stessa priorità, usando il concetto del “time slice” (porzione di tempo).Ogni task è abilitato all’esecuzione per un tempo prefissato, al termine del quale si interrompe. Il sistema operativo in seguito attiva il successivo task pronto.

Segnali
Un task può ricevere notifiche quando un evento è disponibile da un ambiente esterno, con linee di interrupt ( notifica hardware), o da un altro task con dei segnali (notifica software). Un task che è stato già generato può avere due stati: recapitato o sospeso: dipende dalla destinazione.

Altri argomenti di studio
Il settore del real-time è ampio ed ha molti strumenti per risolvere un problema. Altri aspetti che andrebbero studiati approfonditamente sono:

    • Prenotazione
    • Inversione di priorità
    • Eccezioni ed interrupt
    • Servizi a tempo
    • I Pipe
    • Gestione della memoria
Scarica subito una copia gratis
Tags:

Una risposta

  1. Avatar photo slovati 18 Marzo 2009

Scrivi un commento

Seguici anche sul tuo Social Network preferito!

Send this to a friend