Scuola Politecnica e delle Scienze di Base Corso di Laurea in Ingegneria Informatica Elaborato finale in Sistemi real-time Analisi del sistema operativo ChibiOS per applicazioni real time Anno Accademico 2014/2015 Candidato: Francesco Montella matr. n46001243 Dedico questo traguardo a mio padre , mia madre , mio fratello e mia sorella che hanno sempre creduto in me e mi hanno sempre sostenuto. Un pensiero va a mio nonno che oggi sarebbe stato fiero di me ”La vita è come una stoffa ricamata della quale ciascuno nella propria metà dell’esistenza può osservare il diritto, nella seconda invece il rovescio: quest’ultimo non è cosı̀ bello, ma più istruttivo, perché ci fa vedere l’intreccio dei fili.” 1 1 Arthur Schopenhauer Indice Introduzione vi 1 Architettura Generale 1.1 1 Componenti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.1.1 Platform Layer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.1.2 Dipendenze . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 2 Architettura Kernel 4 2.1 Base Kernel Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 2.2 Sincronizzazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2.3 Memory Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 3 Architettura HAL 3.1 OSAL 3.2 HAL Device Drivers 10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 Threading 10 12 13 4.0.1 Delays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 4.0.2 Threads di default . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 4.0.3 Thread Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 4.0.4 Priority Management 14 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 Scheduling 17 5.1 Introduzione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 5.2 Scheduling in chibi/os . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 iii Indice 5.2.1 Ready list . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 5.2.2 Idle thread . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 6 Interrupts 6.0.1 20 Interrupt handlers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 7 Conclusioni e sviluppi futuri 22 Ringraziamenti 25 Bibliografia 26 iv Elenco delle figure 1.1 Dependencies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2.1 Base Kernel Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2.2 Synchronization services diagram . . . . . . . . . . . . . . . . . . . . . . . . . . 7 2.3 Memory Management diagram . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 3.1 Livelli e struttura del chibiOS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 3.2 Hal diagram . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 4.1 Esempio codice parte 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 4.2 Esempio codice parte 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 5.1 Esempio: Cooperative Round Robin . . . . . . . . . . . . . . . . . . . . . . . . . 18 5.2 Diagramma della ready list . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 v Introduzione L’efficienza e correttezza di un sistema operativo real-time (RTOS) non dipendono univocamente dalla validità dei risultati ottenuti ma esse sono strettamente correlate al significato e al ruolo del concetto di “tempo”. Sono sempre più numerosi i settori applicativi che necessitano di attività di calcolo real-time, tra essi vi sono: • la regolazione di impianti chimici e nucleari; • il controllo di processi produttivi complessi; • i sistemi di controllo di volo su aerei e simulatori; • i sistemi di controllo del traffico (aereo, ferroviario e marittimo ); • i sistemi di regolazione delle automobili; • i sistemi di sorveglianza e di monitoraggio ambientale; • l’automazione industriale e la robotica; • i sistemi militari di difesa; • le missioni spaziali; • i sistemi multimediali e la realtà virtuale; • i sistemi di telecomunicazioni. Un’elaborazione in tempo reale si distingue dagli altri tipi di elaborazioni grazie al concetto di “tempo”. La dicitura di “tempo reale” racchiude due concetti fondamentali che fanno da padrone all’interno di un RTOS: vi Introduzione • la parola “tempo” indica che la validità dei risultati prodotti da un processo di elaborazione dipende dal tempo impiegato ad ottenere tali risultati e non solo dalla correttezza degli stessi; • la parola “reale” indica che la risposta del sistema agli eventi esterni deve avvenire durante l’evolversi degli eventi stessi. Di conseguenza il tempo di sistema e quello dell’ambiente devono scorrere con la stessa velocità. Un processo real time deve terminare entro una scadenza temporale prefissata, che prende il nome di DEADLINE, e ciò rappresenta la principale differenza con un sistema non real-time. Con il termine “deadline” si intende il tempo massimo entro cui il processo deve terminare la propria esecuzione, poichè un risultato prodotto oltre la propria deadline è dannoso (oltre che in ritardo) . I processi real-time vengono distinti in tre tipi in base alle conseguenze dovute alla violazione della propria deadline: • se si ha un effetto catastrofico sul sistema, un processo si dice di tipo Hard real-time; • se non vi sono effetti catastrofici ma l’utilità dei risultati è inversamente proporzionale al ritardo, un processo si dice Firm real-time; • se si ha un degrado delle prestazioni ma il corretto funzionamento del sistema non è compromesso, un processo si dice Soft real-time. Un sistema operativo in grado di gestire dei processi real-time di tipo hard è detto sistema hard real-time e comprende sia attività di tipo hard che di tipo soft. Un sistema operativo in grado di gestire dei processi real-time di tipo soft viene detto sistema soft real time. Limiti : I kernel, su cui si basano molti RTOS, sono sviluppati a partire da versioni di tipo timesharing, di conseguenza ereditano inevitabilmente alcuni meccanismi di base per la gestione di processi, che non sono adatti a supportare applicazioni in tempi reale. Caratteristiche desiderabili nei sistemi real-time: Presupposti sui cui dovrebbe basarsi un sistema operativo real-time: • Timeliness: I risultati devono essere corretti nel dominio del tempo oltre che nei valori; vii Introduzione • Prevedibilità: Il sistema deve essere in grado di valutare la fattibilità della schedulazione (in funzione delle proprietà temporali dei vari processi) e di prevedere le conseguenze derivanti dalle decisioni dello scheduling; • Tolleranza ai sovraccarichi : in caso di sovraccarico il sistema non deve collassare; • Monitorabilità: Il sistema deve poter segnalare eventuali eccezioni dovute alla violazione dei vincoli temporali ed intraprendere azioni di recupero, di conseguenza lo stato di esecuzione dei processi deve poter essere monitorato dal sistema; • Flessibilità: il sistema deve essere realizzato secondo una struttura modulare e facilmente modificabile al fine di adattare i meccanismi di nucleo alle esigenze dell’applicazione. Tra i numerosi sistemi real-time andremo ad approfondire le caratteristiche del sistema operativo ChibiOS/RT che è un sistema operativo real-time molto compatto ed efficiente progettato per applicazioni embedded . Il sistema supporta diverse architetture ed è rilasciato sotto la licenza GPL3. Il Kernel supporta una varietà di meccanismi come: multithreading, timer software, semafarori, mutex, variabili condizionali, messaggi, sorgenti di eventi, code, I/O sincrono o asincrono con possibilità di timeout. Il kernel non ha tabelle interne, non c’è nulla che deve essere configurato in fase di compilazione o che possa andare in overflow in fase di esecuzione, le strutture interne sono tutte dinamiche anche se tutti gli oggetti sono allocati staticamente. ChibiOS è quindi, completamente statico: cioè non c’è memoria allocata o rilasciata. Le API del sistema non hanno condizioni di errore: hanno sempre successo se vengono passati parametri corretti (eccezione a questa regola sono le API dinamiche), inoltre le API non sono rallentate dai controlli dei parametri. Il focus è sulla velocità e l’efficienza di esecuzione e quindi sulle dimensioni del codice. Questo non significa che il sistema operativo è grande, la dimensione del kernel con tutti i sottosistemi attivati pesa circa 5.5 KiB . 2 Sarebbe possibile fare qualcosa di ancora più piccolo, ma: • Non avrebbe senso, è già molto piccolo; • Non è conveniente cambiare efficienza o funzionalità per risparmiare pochi byte. In seguito approfondiremo i vari aspetti caratteristici e significativi di ChibiOS/RT. 2 1 KiB = 1 kibibyte=1024 B = 210 byte viii Capitolo 1 Architettura Generale In questo capitolo è descritta l’architettura generale del ChibiOS / RT, introducendo anche la terminologia e concetti utilizzati nei successivi capitoli. 1.1 Componenti Chibios / rt è diviso internamente in diversi importanti componenti indipendenti. I componenti stessi sono divisi in più sottosistemi: • Kernel: insieme con il suo Port Layer, è un sistema stand alone e può lavorare anche senza l’HAL o qualsiasi altro componente; • Port Layer: questo componente è responsabile dell’avvio del sistema, interrompe l’astrazione, le primitive di blocco / sblocco. Esso contiene, di solito, poco codice perché la maggior parte del sistema operativo è molto portatile ma la qualità dell’attuazione ti tale componente possono influenzare pesantemente le prestazioni del sistema operativo. Questo è probabilmente la parte più critica dell’intero sistema operativo; • Hardware Abstraction Layer: questo componente contiene una serie di driver astratti che offrono una comune I/O API per l’applicazione su tutte le piattaforme di supporto. Il codice di HAL è completamente portatile attraverso le varie architetture e compilatori. I driver si classificano in diverse classi: 1 Capitolo 1. Architettura Generale – Normal Driver: Questa classe di driver è composto da un astratto driver portatile di alto livello (HLD) e un driver a basso livello specifico per piattaforma (LLD). Driver normali sono sufficientemente generici per essere utilizzati su diverse piattaforme semplicemente scrivendo una LLD specifica; – Driver Complex: Questa classe di driver è completamente portatile e non ha dipendenze hardware, questa classe si basa su altri driver per le sue esigenze di I/O. Sottosistemi complessi, come un file system, possono essere visti come driver complessi nell’architettura generale; – Platform Driver: Questa classe di driver è specifico di una piattaforma e non è portatile. Codice condiviso tra più drivers, di solito, è implementato come un driver di piattaforma. 1.1.1 Platform Layer Questo livello contiene una serie di implementazioni di drivers per devices. Implementazioni di driver di periferica sono solitamente dedicati a un’intera famiglia di prodotti piuttosto che ad un modello MCU specifico. 1.1.2 Dipendenze Il diagramma seguente mostra le relazioni tra i vari componenti che compongono il sistema: 2 Capitolo 1. Architettura Generale Figura 1.1: Dependencies 3 Capitolo 2 Architettura Kernel Il kernel RT è vagamente ispirata a Posix, in ChibiOs è presente la maggior parte dei meccanismi di threading Posix e API. Il kernel è stato progettato sulla base dei seguenti concetti: • Deve essere veloce, l’efficienza di esecuzione è il requisito principale; • Il codice deve essere ottimizzato per le dimensioni senza andare in contrasto con il punto precedente; • Il kernel deve offrire un set completo delle caratteristiche di un RTOS ; • Deve essere sicuro. La regola è quello di guidare l’utente a scegliere un approccio sicuro, se possibile; • La base di codice deve essere elegante, coerente, leggibile. Il kernel è composto da vari sottosistemi definiti, la maggior parte dei sottosistemi sono opzionali. E’ importante mantenere i sottosistemi ben isolati in modo da poter abilitare o disabilitare ogni sottosistema dal file di configurazione. La disattivazione dei sottosistemi non utilizzati consente forti risparmi nel codice e/o di spazio dati. 2.1 Base Kernel Services Questa categoria contiene i sottosistemi obbligatori del kernel: • Gestione di Sistema: inizializzazione, lock, power management, gestione di interruzioni e anomalie; 4 Capitolo 2. Architettura Kernel • Timers: timer virtuali e le time API; • Scheduler, API scheduler: il più alto livello meccanismo di sincronizzazione viene implementato attraverso questo sottosistema ed è molto flessibile; • Threads: un thread è un’astrazione di un flusso indipendente di istruzioni. In Chibios / rt un thread possiede un contesto del processore, informazioni di stato e un’area stack dedicata. Mentre le variabili statiche sono condivise tra tutti i threads, le variabili automatiche sono locali al thread. Operazioni definite per i threads: – Create: si crea un thread in base alla funzione del thread specificato (l’operazione è sia statica che dinamica); – Exit: un thread termina, può invocare una API specifica e può restituire un valore recuperabile da altri threads; – Wait: un thread attende la terminazione di un altro thread e recupera il suo valore di ritorno; – Resume: un thread, creato in stato di sospensione, viene avviato; – Sleep: l’esecuzione di un thread viene sospesa per il periodo di tempo specificato; – SetPriority: un thread cambia il proprio livello di priorità; – Yield: un thread rinuncia volontariamente al suo time slot. Figura 2.1: Base Kernel Services 2.2 Sincronizzazione Questa categoria contiene i sottosistemi di sincronizzazione: • Semafori a conteggio: le operazioni definite sono: 5 Capitolo 2. Architettura Kernel – Signal: il contatore del semaforo aumenta e se il risultato è negativo allora un thread in attesa viene rimosso dalla coda del semaforo e reso pronto per l’esecuzione; – Wait: il contatore del semaforo viene decrementato e se il risultato diventa negativo il thread viene accodata nel semaforo e sospeso; – Reset: il contatore del semaforo viene resettato ad un valore non negativo e tutti i threads nella coda vengono rilasciati. I semafori possono essere utilizzati per garantire la mutua esclusione. • Semafori binari: la differenza tra i semafori a conteggio e i semafori binari è che il contatore dei semafori binari non può assumere valori oltre il valore 1. L’operazione signal, se ripetuta, viene ignorata. Un semaforo binario può quindi avere solo due stati definiti: – Taken: quando il suo contatore ha valore zero o minore. Un numero negativo rappresenta il numero di threads in coda sul semaforo binario; – Not taken: quando il suo contatore ha valore 1. • Mutex: è un oggetto di sincronizzazione dei thread può essere in due stati distinti: – Not owned (sbloccato); – Owned by a thread (bloccato); Operazioni definite per i mutex: – Lock: il mutex è verificato, se il mutex non è di proprietà di qualche altro thread, allora è associato al thread di blocco, altrimenti il thread è in coda nel mutex in una lista ordinata per priorità; – Unlock: il mutex viene rilasciato dal proprietario e il thread a priorità più alta in coda, se presente, viene ripreso e reso proprietario del mutex. • Condition Variables: questo modulo implementa il meccanismo delle variabili Condition, che sono un estensione del sottosistema Mutex e non possono lavorare da sole. La variabile condizione è un oggetto di sincronizzazione pensato per essere utilizzato all’interno di una zona protetta da un Mutex. Mutex e variabili Condition insieme sono in grado di implementare un costrutto Monitor; 6 Capitolo 2. Architettura Kernel • Eventi: fonti di eventi e event flags con un supporto flessibile per e / o condizioni e scambio automatico di funzioni del gestore; • Messaggi: messaggi sincroni sono un meccanismo di comunicazione veloce e facile da usare. I threads possono agire come server di messaggi e/o client dei messaggi, in modo tale che i dati possono essere trasportati in entrambe le direzioni. Si noti che i messaggi non vengono copiati tra il client e il thread del server, ma è passato solo un puntatore cosı̀ lo scambio è molto efficiente in termini temporali. I messaggi sono tipi di dati scalari di tipo msg t ; • Mailbox: una mailbox è un meccanismo di comunicazione asincrona. Un messaggio è una variabile di tipo msg t. Operazioni definite: – Post: invia un messaggio sulla segreteria in ordine FIFO; – Post Ahead: invia un messaggio sulla mailbox con priorità urgente; – Fetch: un messaggio viene prelevato dalla cassetta mailbox e rimosso dalla coda; – Reset: la mailbox viene svuotata e tutti i messaggi memorizzati vengono persi. Possiamo riassumere i sottoinsiemi di sincronizzazione con un diagramma: Figura 2.2: Synchronization services diagram 2.3 Memory Management Diagramma del Memory Management: 7 Capitolo 2. Architettura Kernel Figura 2.3: Memory Management diagram • Core allocator: è un allocatore semplificato che consente solo di allocare blocchi di memoria senza la possibilità di liberarli. Questo allocatore è inteso come un fornitore di blocchi di memoria per gli altri allocatori , quali: – C-Runtime allocator; – Memory pools allocator; – Heap Allocator. Avendo un fornitore di memoria centralizzata, i vari allocatori possono coesistere e condividere la memoria principale. Questo allocatore, da solo, è anche utile per applicazioni molto semplici che richiedono solo un modo semplice per ottenere blocchi di memoria; • Memory heaps: utilizzando una strategia First Fit, permette anche la creazione di più heaps al fine di gestire le aree di memoria non uniformi; • Memory pool: allocatore veloce di oggetti a dimensione fissa; 8 Capitolo 2. Architettura Kernel • Threads dinamici: solitamente i threads sono statici in ChibiOS/RT ma c’è l’opzione per la gestione dinamica dei threads. 9 Capitolo 3 Architettura HAL HAL (Hardware Abstraction Layer) è un set di driver per le periferiche che comunemente si trovano in micro-controllori, è l’interfaccia tra l’applicazione e hardware Chibios / rt. L’HAL è suddiviso in diversi strati: • HAL API Layer: questo livello contiene una serie di drivers portatili di periferiche ; • HAL Port Layer: si tratta di implementazioni di driver di periferica per un micro-controller specifico o una famiglia di micro-controllori; • HAL Board Layer: contiene tutti i dettagli di una specifica scheda di montaggio del microcontrollore; • HAL OSAL Layer: questo è l’Operating System Abstraction Layer. L’HAL deve accedere a determinati servizi RTOS, al fine di attuare la sua funzionalità. L’accesso ai servizi RTOS avviene attraverso questo strato di astrazione. E’ chiaro che RT non ha bisogno di HAL e può essere utilizzato da solo se HAL non è necessario. 3.1 OSAL OSAL è la specifica di un sottoinsieme di una API RTOS sufficiente a sostenere l’HAL. Questa API può essere, in linea di principio, attuata nel corso di qualsiasi RTOS, ma è stata 10 Capitolo 3. Architettura HAL Figura 3.1: Livelli e struttura del chibiOS progettata per essere utilizzabile anche senza un vero RTOS. Caratteristiche: • Lightweight abstraction su un RTOS: la maggior parte delle funzioni possono essere implementate come macro o funzioni inline, overhead minimo; • I servizi OSAL possono essere convenientemente utilizzati dall’applicazione se un RTOS non è disponibile; • Abstracted RTOS services: zone critiche, la gestione ISR, sincronizzazione ISR-task, I/O timeout, mutua esclusione ed eventi. • OSAL può anche essere usato da solo, senza HAL; • OSAL templates available : l’implementazione di un OSAL significa solo caricare i templates. 11 Capitolo 3. Architettura HAL 3.2 HAL Device Drivers Un driver di periferica è di solito diviso in due strati: • High Level Device Driver (HLD): contiene le definizioni del driver delle API e la parte indipendente della piattaforma del driver. Un HLD è composto da due file: driver.c, il file di implementazione HLD e deve essere incluso nel Makefile per usare il driver. Il file di intestazione HLD è driver.h ed è implicitamente incluso dal file di intestazione HAL hal.h. • Low Level Device Driver (LLD): contiene la parte dipendente della piattaforma del driver. Un LLD è composto da due file: driver.c, il file di implementazione LLD e deve essere incluso nel Makefile per usare il driver. Il file di intestazione LLD è driver.h ed è implicitamente incluso dal file di intestazione HLD. LLD potrebbe non essere presente in quei driver che non accedono direttamente ma attraverso altri driver di periferica hardware. Figura 3.2: Hal diagram 12 Capitolo 4 Threading Il threading module è responsabile per le operazioni relative ai threads. I servizi di tale modulo sono: dichiarazione, ciclo di vita, delays, threads suspension, threads queues, thread time, gestione di priorità, Round Robin. 4.0.1 Delays Un problema comune è quello di inserire ritardi nell’esecuzione dei threads. Chibios/rt offre diverse soluzioni a questo problema. Threads Delays sono caratterizzati da: • una risoluzione ottenibile dipende dal system tick frequency, se la frequenza è 1000Hz allora la risoluzione dei ritardi è 1mS; • Il tempo di un ritardo viene utilizzato per eseguire altri thread. 4.0.2 Threads di default Dopo aver inizializzato Chibios/rt con chSysInit () sono automaticamente generati due threads: • Idle Thread: thread a priorità più bassa; • Main Thread: questo thread esegue la funzione main() in fase di avvio. Il main thread viene creato a livello NORMALPRIO ma può cambiare la propria priorità se necessario. E’ dal main thread che sono generalmente creati gli altri threads. 13 Capitolo 4. Threading 4.0.3 Thread Classes Ci sono due classi di threads in Chibios / rt: • Static Threads: sono staticamente allocati in memoria in fase di compilazione. Al fine di creare un thread statico deve essere dichiarata un’area di lavoro usando THD WORKING AREA: static THD WORKING AREA(myThreadWorkingArea, 128). Questa macro riserva 128 byte di stack per il thread e spazio per tutte le relative strutture richieste dal thread. Un thread statico può essere avviato con chThdCreateStatic (): thread t * tp = chThdCreateStatic (myThreadWorkingArea, sizeof(myThreadWorkingArea), NORMALPRIO /*priorità iniziale*/, MyThread /* Thread Fuction*/, NULL /*Thread Parameter*/ ); • Dynamic Threads: sono creati mediante allocazione di memoria in fase di runtime in una memory heap o una memory pool. Creazione di un thread dinamico in una memory heap: thread t *tp = chThdCreateFromHeap(NULL, /* NULL = Default heap. */ THD WORKING AREA SIZE(128), /* Stack. */ NORMALPRIO, /* Priorità iniziale. */ myThread, /* Thread function. */ NULL); /* Thread parameter. */ La memoria viene allocata nella heap specificata e il thread viene avviato. Si noti che la memoria non viene liberata quando il thread termina, ma viene liberata quando l’ultimo riferimento al thread viene rilasciato mentre il thread è nel suo stato finale. 4.0.4 Priority Management In Chibios/rt è possibile per un thread cambiare la propria priorità anche se non è normalmente richiesto. chThdGetPriorityX () restituisce la priorità del thread corrente, mentre chThdSetPriority () cambia il livello di priorità del thread restituendo la vecchia priorità. 14 Capitolo 4. Threading Figura 4.1: Esempio codice parte 1 15 Capitolo 4. Threading Figura 4.2: Esempio codice parte 2 16 Capitolo 5 Scheduling 5.1 Introduzione Definiamo prima cos’è una schedulazione. Dato un insieme di tasck = { j1 ,...,jn } una schedulazione è un assegnamento dei task al processore. Formalmente una schedulazione è una funzione σ : R+ → N tale che ∀ t ∈ R+ , ∃ t1 , t2 tali che t ∈ [ t1 , t2 ) e ∀ t0 ∈ [ t1 , t2 ) , si ha σ (t) = σ (t0 ). Quindi la funzione σ (t) è una funzione intera e costante a tratti. 5.2 Scheduling in chibi/os A differenza di molti altri RTOS, ChibiOS/RT supporta più threads allo stesso livello di priorità e li schedula utilizzando una strategia di Round Robin. Lo scheduler è influenzato dal seguente global setting: CH CFG TIME QUANTUM: Time slice, in system ticks, dell’intervallo di Round Robin. Una rotazione Round Robin può accadere a causa dei seguenti eventi: • Il thread attualmente eseguito invoca volontariamente chThdYield () per consentire l’esecuzione di un altro thread allo stesso livello di priorità, se esiste; • Il thread attualmente eseguito va volontariamente in uno stato di sleep, quando il thread è risvegliato si accoda a qualsiasi altro thread pronto allo stesso livello di priorità; • Se la costante di configurazione CH CFG TIME QUANTUM è impostata a un valore maggiore di zero, se il quantum tempo specificato è scaduto e se un thread con uguale 17 Capitolo 5. Scheduling priorità è pronto allora il thread attualmente in esecuzione è sospeso e viene reinserito nella coda Pronto dietro qualsiasi altro thread con lo stesso livello di priorità. Ponendo CH CFG TIME QUANTUM a zero nel file di configurazione, si rende il kernel molto più veloce e più piccolo e non vieta l’uso di più threads allo stesso livello di priorità. Lo scheduling Round Robin può lavorare, quindi, in due diverse modalità: • Preemptive Round Robin: viene attivata impostando CH CFG TIME QUANTUM ad un valore maggiore di zero; • Cooperative Round Robin: questa modalità viene attivata impostando CH CFG TIME QUANTUM a zero. Lo scambio tra threads allo stesso livello di priorità è sempre cooperativo. Figura 5.1: Esempio: Cooperative Round Robin 18 Capitolo 5. Scheduling 5.2.1 Ready list La ready list è probabilmente la struttura dati più importante in ChibiOS/rt. Si tratta di una lista chiusa, ordinata e bidirezionale di threads che rappresentano i thread idonei per l’esecuzione. Il thread corrente non appartiene alla ready list ma è indicato da un puntatore globale. : Figura 5.2: Diagramma della ready list 5.2.2 Idle thread ll sistema esegue sempre un thread chiamato ”idle thread”. Questo thread ha il livello di priorità più basso e rimane in esecuzione (fino a quando qualche altro thread diventa pronto), eseguendo un ciclo senza fine oppure una funzione di servizio di bassa priorità che non deve mai essere bloccante per un altro thread. Un dettaglio importante è che l’idle thread può essere solo negli stati READY o corrente. 19 Capitolo 6 Interrupts In Chibios/rt ci sono tre classi logiche di interrupts: • Normal Interrupts: sono in grado di richiamare le API del sistema operativo dall’interno dei loro gestori. I gestori di interrupts appartenenti a questa classe devono essere scritti seguendo alcune regole; • Fast Interrupts: hanno una latenza inferiore e sono meno soggetti a jitter. I Fast Interrupts non sono autorizzati a ricorrere ad ogni API del sistema operativo dall’interno dei loro gestori; • Non Maskable Interrupts: sono totalmente fuori dal controllo del sistema operativo ed hanno la più bassa latenza. Tali fonti non sono supportate su tutte le architetture. 6.0.1 Interrupt handlers Chibios/rt offre un metodo multi-piattaforma per la scrittura di gestori di interrupts. Un Regular Interrupt handler è un ISR da cui è possibile invocare le API di sistema, esso deve essere scritto con la seguente forma generale: CH IRQ HANDLER (myIRQ) { CH IRQ PROLOGUE (); /* Codice di gestione IRQ, preemptable se l’architettura supporta. */ 20 Capitolo 6. Interrupts chSysLockFromISR (); /* Invocazione di alcune API di sistema I-Class, mai preemptable. */ chSysUnlockFromISR (); / *Codice di gestione IRQ, di nuovo preemptable. * / CH IRQ EPILOGUE (); } Le Fast interrupts hanno una priorità hardware superiore al kernel in modo che non è possibile richiamare le API del sistema da lı̀. I Fast Interrupt handlers devono essere scritti utilizzando la seguente forma generale: CH FAST IRQ HANDLER (myIRQ) { /* Codice di gestione Fast IRQ, preemptable se l’architettura supporta.*/ } 21 Capitolo 7 Conclusioni e sviluppi futuri In questo elaborato abbiamo affrontato una panoramica generale sulla struttura e sulle caratteristiche del sistema operativo ChibiOs/rt per applicazioni real time. Inizialmente sono stati illustrati i principali componenti in particolar modo il kernel, proseguendo con multithreading e scheduling, cercando di presentare un discorso fluido e per lo più completo riguardante l’argomento assegnato. In sintesi è possibile dire che Chibios è un RTOS compatto e veloce che supporta diverse architetture. Parlando di SO non si devono immaginare finestre e widgets ma, in embedded, un sistema operativo è solamente un gestore di risorse hardware, in effetti si usa un Rtos come un set di protocolli e tools chiamato PI. ChibiOS può essere classificato in diversi blocchi indipendenti, il principale è il kernel che è il cuore del RTOS e gestisce lo scheduling e le priorità e comunicazione dei threads ed eventi. Inoltre offre dei tools per la protezione e accesso alla memoria come mutex e semafori. Vi sono due tipi di kernel: RT e NIL, ma in questo elaborato è stato trattato solo il primo dei due. Un’altra parte di Chibos è un set di device drivers chiamato HAL, che supporta un gran numero di periferiche; ogni driver, eccetto PAL (gestisce le porte di I/O), deve essere avviato prima dell’utilizzo. ChibiOS permette il multithreading: questo significa che il kernel può gestire indipendentemente più di una sequenza di istruzioni. Un thread può essere visto come una semplice funzione a cui è assegnata una priorità e una Working Area. Il kernel esegue i threads indipendentemente (apparentemente in parallelo) anche se c’è un singolo core, questo spiega i concetti di scheduling e priorità. L’avanzato kernel è stato progettato per rendere ChibiOs un RTOS ad hoc per le applicazioni embedded. Le linee guida di progettazione sono state: 22 Capitolo 7. Conclusioni e sviluppi futuri • Nessun compromesso in termini di prestazioni: deve essere il più veloce RTOS disponibile; • Tutte le caratteristiche comuni ai vari RTOS devono essere supportate; • Architettura Completamente statica; • Prevedibile e deterministico; • Piccole dimensioni; • Pienamente compatibile con HAL OSAL; Oltre alle comuni caratteristiche di un RTOS, sono implementate delle caratteristiche uniche che lo rendono uno tra i più avanzati RTOS disponibili. CHIBIOS/RT CARATTERISTICHE: • Progettato per le applicazioni in tempo reale; • Facilmente portatile; • Preemptive scheduling; • 128 livelli di priorità. Sono ammessi più threads allo stesso livello di priorità; • Schedulazione Round Robin per i threads allo stesso livello di priorità; • Offre threads, virtual timers, semafori, mutexes, variabili Condition, event flags, messaggi, mailboxes, code I/O; • Nessuna configurazione statica in fase di compilazione; • Timer, i canali di I / O e le altre risorse HW sono simulate in un processo di un sistema operativo guest e il codice applicativo non ha bisogno di essere a conoscenza di esso; • Tutte le strutture del kernel sono statiche; • Opzionale, thread-safe, sottosistema Heap Allocator; • Opzionale, thread-safe, sottosistema Memory Pools Allocator; • Blocco e non blocco di canali I/O con timeout e capacità di generare eventi; 23 Capitolo 7. Conclusioni e sviluppi futuri • Requisiti minimi di sistema: circa 6 KiB ROM con tutte le opzioni abilitate e ottimizzazioni di velocità. La dimensione può ridursi sotto 2 KiB disattivando i sottosistemi non utilizzati e l’ottimizzazione per le dimensioni; • Quasi totalmente scritto in C con poco codice ASM necessaria per le porte; • Hardware Abstraction Layer opzionale (HAL) con supporto per molti modelli di device driver e implementazioni di device drivers. Spero che questo elaborato possa essere, in futuro, una base su cui partire per approfondire lo studio del sistema operativo ChibiOS. 24 Ringraziamenti Desidero ringraziare tutti coloro che hanno contribuito per la stesura di questa tesi. Ringrazio il prof. Marcello Cinque per la sua disponibilità e per i preziosi consigli riguardanti la stesura di questo elaborato. Ringrazio mio padre che nel periodo di raccolta delle nocciole/noci mi ha risparmiato la faticaccia di seguirlo in campagna, permettendomi di avere intere giornate per studiare. Ringrazio mia mamma che ha avuto in ogni occasione una parola di conforto. Ringrazio mio fratello Nello che in questi anni si è comportato da ”tassista” percorrendo svariate volte il tragitto casa-stazione , stazione-casa. Ringrazio mia sorella Mariangela per avermi assillato con le sue canzoni e urla durante le ore di studio. Ringrazio Mario amico e collega universitario che per tutto il percorso universitario mi ha consigliato ed accompagnato in ogni mia scelta. Infine un ringraziamento speciale va a Claudia, amica, collega, compagna che mi ha sostenuto e appoggiato nei momenti più difficili di questo percorso che abbiamo affrontato insieme 25 Bibliografia [1] Sistemi in Tempo Reale terza edizione Giorgio C.Buttazzo [2] http://www.chibios.org [3] http://www.chibios.org/dokuwiki/doku.php [4] http://wiki.chibios.org/dokuwiki/doku.php?id=chibios:documents:architecture [5] http://chibios.sourceforge.net/html/index.html [6] http://chibios-book.readthedocs.org [7] http://it.emcelettronica.com 26