Sommario
Ringraziamenti...................................................................................................................3
Introduzione.......................................................................................................................4
1 Sistemi operativi Realtime..............................................................................................6
1.1 Concetto di Realtime...............................................................................................6
1.2 RealTime OS – Hard vs Soft Realtime...................................................................8
1.3 Panoramica sui Sistemi operativi RealTime...........................................................8
1.4 Content Switch, Stack, Task Control Block, Preemption e Timeslices................10
1.5 Concorrenza..........................................................................................................14
1.6 Interrupt.................................................................................................................15
1.7 Scheduler...............................................................................................................16
2 Caratteristiche di eCos..................................................................................................17
2.1 Dove è cominciato tutto – Cygnus Solutions........................................................17
2.2 L'origine di eCos...................................................................................................18
2.2.1 Configurabilità e configurazione...................................................................18
2.2.2 I componenti chiave di eCos.........................................................................20
2.2.3 Supporto a processori e piattaforme di valutazione......................................21
2.2.4 Supporto tecnico ad eCos..............................................................................22
2.3 Visione d'insieme del sistema eCos......................................................................23
2.4 Terminologia di eCos............................................................................................23
2.4.1 Il component framework...............................................................................24
2.4.2 Component Repository..................................................................................25
2.4.3 Opzioni di Configurazione............................................................................27
2.4.4 Pacchetti e componenti..................................................................................28
2.4.5 Target............................................................................................................29
2.4.6 Template........................................................................................................29
3 Caratteristiche di eCos..................................................................................................31
3.1 Portabilità..............................................................................................................31
3.2 Caratteristiche di base di HAL..............................................................................31
3.2.1 Funzionalità di HAL.....................................................................................33
3.2.2 Configurazione di HAL.................................................................................34
3.2.2.1 Componenti di configurazione comuni.................................................34
3.2.2.2 Componenti di configurazione specifici dell'architettura......................35
3.2.3 Inizializzazione di HAL................................................................................36
3.3 Il kernel di eCos....................................................................................................39
3.4 Meccanismi di gestione del tempo in eCos...........................................................40
3.5 Scheduler nativi in eCos.......................................................................................40
3.5.1 Bitmap Scheduling........................................................................................40
3.5.2 MLQ scheduler..............................................................................................42
3.6 Sincronizzazione dei thread con eCos..................................................................43
4 Esempio di applicazione usando eCos..........................................................................44
4.1 Processo di build di eCos......................................................................................44
4.2 Un'occhiata più da vicino......................................................................................44
4.3 Setup dell'hardware di sviluppo............................................................................48
4.4 Tool di configurazione di eCos.............................................................................49
4.5 Redboot.................................................................................................................49
4.5.1 Installazione di RedBoot...............................................................................51
4.5.2 Boot di RedBoot............................................................................................51
1
4.6 Processo di build di eCos......................................................................................52
4.7 Applicazioni..........................................................................................................53
Considerazioni finali e Conclusioni................................................................................55
Riferimenti Bibliografici.................................................................................................59
2
Ringraziamenti
Ringrazio la Prof. Leonardi e il Prof. Valenti per la pazienza e la disponibilità che hanno
avuto nei miei confronti durante il periodo di stesura dell'elaborato.
Ringrazio immensamente Alfonso e Patrizia, i miei genitori, per la fiducia dimostrata in
questi anni e per la sopportazione delle mie frequenti crisi universitarie; senza di loro
non sarei mai arrivato fino a questo punto e quindi a loro va tutto il mio rispetto, la mia
riconoscenza e la mia stima. Ringrazio Alex, mio fratello, anche lui ha mi sopportato
parecchio, soprattutto nelle mie richieste di aiuto notturne pre-esame e Cristiana, sua
moglie, che più di una volta si è data da fare per darmi aiuto con gli esami. Ringrazio
poi mia nonna, i miei zii e i miei cugini che si sono sempre interessanti di come stesse
procedendo l'università. Ringrazio tutti i miei amici, in particolar modo Mattia, Lancia,
Della, Menga e Bobby con cui ho passato diverse ore a studiare; si sono dimostrati veri
amici e credo potrò sempre contare su di loro. Non posso poi non menzionare Kenzo e
Ruset per le goliardiche serate passate assieme. Un ulteriore grazie a tutti i compagni di
attività sportive, specialmente quelli della pallanuoto con cui sono rimasto in contatto
nonostante l'abbia dovuta abbandonare. Devo un grazie anche alle mie amiche Elisa e
Alice che mi hanno sempre ascoltato e hanno sempre avuto parole di conforto quando
ne avevo bisogno. Infine un grazie a tutti coloro che in qualche modo hanno creduto in
me e mi hanno sostenuto.
3
Introduzione
Un sistema operativo (SO, o in inglese OS) è il componente di infrastruttura software di
un sistema informatico (computer) responsabile della gestione, del coordinamento delle
attività e la condivisione delle risorse hardware del computer. Il sistema operativo mette
a disposizione dell'utente una interfaccia software (grafica o testuale) per accedere alle
risorse hardware (dischi, memoria, I/O in generale) del sistema.
Il compito principale del sistema operativo è quello di permettere all'utente, umano o
non, di interagire direttamente con la macchina.
Quando invece parliamo di sistema operativo realtime, intendiamo un sistema operativo
multitasking (che permette l'esecuzione contemporanea di più processi) programmato
per applicazioni realtime cioè genericamente con vincoli temporali. Queste applicazioni
includono sistemi embedded (progettati per uno specifico scopo), robot industriali,
macchine a controllo numerico, equipaggiamento scientifico, etc.
Come si vedrà nel capitolo uno del presente elaborato, un sistema operativo realtime
rende possibile la creazione di un sistema realtime, ma non garantisce che il risultato
finale sia realtime; questo richiede infatti il corretto sviluppo del software. Un sistema
operativo realtime non deve necessariamente avere grandi capacità elaborative quanto
piuttosto garantire di riuscire a fare il proprio lavoro entro i tempi prefissati. I SO
realtime sono valutati in modo migliore più velocemente e/o deterministicamente
rispondono a particolari eventi piuttosto che alla quantità di lavoro che riescono a
svolgere in un determinato periodo. Nel capitolo uno inoltre vedremo poi come un
sistema realtime riesce attraverso algoritmi di scheduling (organizzazione del lavoro) a
fornire gli strumenti che gli permettono di essere predicibile nel tempo.
La diffusione di dispositivi embedded che utilizzano sistemi operativi realtime è
sicuramente sottostimata dalla popolazione media; questo perché sono generalmente
“nascosti”. Solitamente hanno risorse limitate e sono studiati per avere una bassa
interazione con l'uomo, oppure quando permettono l'interazione, questa avviene in
maniera diversa rispetto a quella classica mouse-tastiera-monitor. L'interazione, nei casi
di sistemi operativi realtime per dispositivi embedded, avviene solitamente con attuatori
(pulsanti) e/o sensori. Un esempio di dispositivi commerciali che fanno uso di questo
tipo di sistemi operativi sono: lettori mp3, console portatili da gioco, stampanti,
fotocamere, dispositivi GPS, robot, telefoni cellulari etc.
4
Vista la diffusione di questi sistemi operativi, nel capitolo due andremo ad introdurre
eCos, un sistema operativo realtime, open source, royalty-free per sistemi embedded,
che viene utilizzato per il tipo di applicazioni poc'anzi descritte. Vedremo come e
perché è nato, come è strutturato, quali sono i suoi componenti chiave, come si
configura e con quali piattaforme hardware può essere utilizzato.
Il capitolo tre è dedicato all'approfondimento delle caratteristiche chiave di eCos: il
kernel, HAL, lo scheduler e i meccanismi di sincronizzazione dei thread.
Nel quarto capitolo poi andremo a vedere un esempio di processo di build di eCos, cioè
come si riesce attraverso l'ambiente fornito da eCos a realizzare una propria
applicazione che girerà poi su una piattaforma hardware reale.
Infine l'elaborato si conclude con alcune considerazioni e commenti relativi a quanto
appreso.
5
1 Sistemi operativi Realtime
1.1 Concetto di Realtime
Nel panorama informatico vi sono molteplici definizioni di realtime, ma il più di esse
sono contraddittorie. Il tema è piuttosto discusso poiché non si trova un accordo sulla
terminologia.
La definizione canonica di un sistema realtime, data da Donald Gillies (matematico e
informatico), è la seguente: “Un sistema è realtime quando la correttezza della
computazione dipende non solo dalla correttezza logica della computazione, ma anche
dal tempo richiesto per produrre il risultato di questa. Se la restrizione temporale del
sistema non sono rispettate, questo può portare alla crisi del sistema”.
Questa definizione, ha portato altri ad aggiungere: “è essenziale che che le restrizioni
temporali del sistema abbiano una garanzia che vengano rispettate. Questa garanzia
richiede che il sistema sia di tipo prevedibile. Sarebbe inoltre gradito che il sistema
mantenga un altro grado di utilizzazione mentre soddisfa le restrizioni temporali”.
Il classico esempio di software che deve essere realtime è quello del sistema frenante
ABS: se non viene azionato in tempo il sistema ABS, questo può causare un incidente.
Quindi è estremamente importante che i progettisti di sistemi realtime conoscano tutte le
possibili casistiche di funzionamento del sistema in modo da poterne prevedere il
comportamento. Per questo motivo i progettisti spendono gran parte del loro tempo a
studiare quello che è definito il “caso peggiore” in termini prestazionali.
L'istituto degli ingegneri elettrici ed elettronici (IEEE) definisce invece il concetto di
realtime attraverso lo standard POSIX 1003.1: “Real time in un sistema operativo:
l'abilita del sistema operativo di soddisfare un determinato carico di lavoro in un
determinato tempo di risposta”.
Anche il dipartimento di ingegneria aerospaziale del politecnico di Milano dà la sua
definizione di sistema realtime: “un sistema capace di garantire requisiti temporali del
processo sotto il suo controllo”. Il sistema deve quindi essere veloce e predicibile.
Veloce significa con basse latenze, per esempio nel rispondere ad eventi esterni
asincroni in tempi ridotti. Più è bassa la latenza, meglio il sistema risponde ad eventi
che richiedono attenzione immediata. Predicibile significa che deve essere possibile
determinare il periodo di completamento del processo in un tempo certo.
6
Un'altra interessante definizione di sistema operativo realtime (o RTOS) è quella data
dal prof. Claudio Melchiorri del DEIS (Dipartimento di Elettronica, Informatica e
Sistemistica dell'università di Bologna): “un RTOS è un sistema in cui per valutare la
correttezza delle operazioni si considera anche la variabile tempo”. Devono essere
garantite quindi due tipologie di correttezza: la correttezza logica e quella temporale. La
prima implica che i risultati e le risposte forniti dal sistema siano quelli previsti (giusta
computazione dei dati), mentre la seconda deve fare in modo che i dati siano prodotti
entro certi limiti temporali fissati (deadlines).
Nel marzo 2003, presso la nostra Università, si è tenuto un seminario sulla
progettazione dei sistemi embedded e realtime, durante il quale il Prof. Valenti ha
illustrato il suo punto di vista sulle caratterizzazioni realtime: “Le specifiche tecniche
dei sistemi embedded contengono spesso vincoli sui tempi di risposta agli eventi esterni
tali, da soli, a giustificare l'avvio di una progettazione hardware dedicata.”
Tali vincoli temporali, indicati dal Prof. Valenti, possono essere di vario tipo:
•
Deadline: è la richiesta temporale più restrittiva; consiste nella pretesa di
assicurare un tempo massimo di risposta prevedibile e sempre inferiore ad un
certo limite fra il presentarsi di un evento e la generazione dell'evento effetto. Si
consideri, come esempio, un sistema di controllo dei freni di un veicolo che, in
alcun caso, può ammettere un ritardo imprevedibile fra il comando di frenatura e
l'attuazione dello stesso.
•
Average: è una richiesta piuttosto generica che consiste nello specificare un
ritardo tipico fra evento stimolo ed evento effetto. Questo si traduce nel
dimensionamento del tempo medio di risposta in una situazione standard senza
considerare il caso peggiore che potrebbe anche essere notevolmente più lento.
•
Burst: è una richiesta che non influisce sul tempo di risposta ma, piuttosto, sulla
capacita del sistema di non perdere eventi, eventualmente utilizzando strumenti
di accodamento hardware (fifo o similari). Si consideri, ad esempio, un frame
grabber che deve acquisire una immagine senza, ovviamente, perdere alcun
pixel, pur potendo impiegare un tempo variabile nella successiva elaborazione
dell'informazione.
I sistemi che hanno almeno un vincolo del tipo deadline sono identificati come sistemi
hard realtime mentre quelli che hanno almeno un vincolo "average" o "burst" sono detti
sistemi soft realtime. Nel caso in cui le specifiche funzionali non contengano alcun
vincolo temporale, invece, si ha un sistema senza caratterizzazione realtime.
7
1.2 RealTime OS – Hard vs Soft Realtime
Una volta introdotto il concetto di realtime, possiamo approfondire l'argomento andando
ad analizzare le due modalità appena annunciate: la modalità hard-realtime e softrealtime.
La modalità hard-realtime considera inutile il completamento dell'operazione dopo la
sua deadline temporale, poiché questo può portare (nell'ambito di utilizzo) a un guasto
completo del sistema.
I sistemi hard-realtime sono usati quando è imperativo che il completamento
dell'elaborazione rientri nei tempi prestabiliti. Questi sistemi sono rivolti ad ambiti in
cui il non rispetto della deadline può causare danni fisici al sistema e all'ambiente che lo
circonda: per esempio un pacemaker o il sistema di frenata di un auto.
Nei sistemi soft-realtime invece possiamo pensare che le deadline vengano mediamente
rispettate, ma non vi sono garanzie che questo accada, né si possono fare previsioni
deterministiche sui tempi di esecuzione delle operazioni successive. I sistemi softrealtime, sono tipicamente usati dove vi è un accesso di tipo concorrenziale dei dati con
più sistemi interconnessi tra di loro che ne fanno uso. Un esempio tipico è quello del
sistema che sincronizza i voli aerei di linea:
i piani aerei devono rimanere
costantemente aggiornati, ma si può operare senza danni anche con latenze di qualche
secondo.
Generalmente anche i sistemi audio-video sono di questo tipo: se la garanzia temporale
non viene rispettata, si avrà un degrado della qualità del segnale, ma il sistema può
continuare a funzionare.
1.3 Panoramica sui Sistemi operativi RealTime
Innanzitutto dobbiamo definire cosa rende realtime un sistema operativo (RTOS):
•
un RTOS deve essere multi-threaded e preemptible. Deve cioè permettere
l'esecuzione di più thread e deve essere munito di un sistema che permetta
l'interruzione temporanea di un processo che è in esecuzione senza la sua
cooperazione. Tale processo verrà poi ripristinato quando il processo a priorità
più alta che è stato messo in esecuzione al suo posto, ha concluso le sue
operazioni.
8
•
Deve essere presente un meccanismo di priorità. Nella progettazione del sistema,
si sa a priori che alcuni thread hanno più priorità di esecuzione rispetto ad altri;
il sistema operativo deve prevedere un meccanismo di gestione di queste
priorità.
•
L'OS deve supportare un meccanismo di sincronizzazione dei thread di tipo
prevedibile (per esempio mutex, semafori, flags, monitor, etc..).
•
Il comportamento deve essere noto.
Ciò implica che i produttori di RTOS rilascino determinate specifiche:
•
massima latenza nel servire una richiesta di interrupt, determinato verificando
sia analiticamente che sperimentalmente il numero di cicli macchina (clock) che
intercorre nel caso peggiore fra l'IRQ (interrupt request) e l'esecuzione della
prima istruzione della ISR (interrupt service routine): questo deve essere
prevedibile, ripetibile e compatibile con i requisisti dell'applicazione. Questo
valore, detto interrupt latency, non dipende dal numero di interrupt simultanei in
attesa essendo per definizione quello del caso peggiore (worst case).
•
il massimo tempo che richiede ogni chiamata di sistema (system call). Questo
valore può essere eventualmente dato in forma tabulare per determinate
configurazioni, ad esempio il numero totale di task o oggetti di sistema. Il
progettista ne dovrà tenere conto.
•
il tempo massimo di mascheramento degli interrupt da parte di OS e drivers.
Lo sviluppatore ha inoltre la completa responsabilità di caratterizzare opportunamente
dal punto di vista temporale ogni elemento che possa introdurre ritardi nel
processamento degli eventi da trattare in realtime – ad esempio dovrà essere posta molta
attenzione ai canali DMA ed all'eventuale adozione di cache per dispositivi di memoria
intrinsecamente lenti (DRAM).
L'offerta commerciale di sistemi operativi Real Time è piuttosto ampia. Senza entrare
troppo nel dettaglio, andremo ad elencare quelli più conosciuti:
•
eCos (Red Hat)
•
LynxOS (LynuxWorks)
•
Neutrino (QNX Software System)
•
Nucleus (Mentor Graphics)
•
pSOSystem (Wind River)
9
•
QNX (QNX Software System)
•
Quadros (RTXC)
•
Linux/RT (TimeSys)
•
VxWorks (Wind River)
•
RTAI (Politecnico di Milano)
1.4 Content Switch, Stack, Task Control Block, Preemption e
Timeslices
Ogni sistema operativo per permettere l'esecuzione contemporanea di thread e processi
(sistema operativo multitasking), ha bisogno di un sistema che salvi lo stato della CPU
nei momenti in cui si deve eseguire un cambio di processo attivo. Questo stato, cioè il
contenuto dei registri della CPU e del program counter, è chiamato contesto e
l'operazione di cambio contesto è detto context switch. Un registro è una piccola
quantità di memoria molto veloce che risiede all'interno della CPU che è usata per
velocizzare l'esecuzione di programmi, fornendo un accesso veloce ai dati più usati,
solitamente durante l'elaborazione. Il program counter invece è un registro specifico che
memorizza l'indirizzo di memoria della prossima istruzione che deve essere eseguita. Si
noti che su alcune architetture, il program counter memorizza l'indirizzo dell'istruzione
che si sta eseguendo.
Il contesto normalmente si trova su una porzione dello stack di ogni processo e concorre
a formare il task control block (TCB) insieme a informazioni di carattere più generale
come il nome del task, la priorità o dati statistici di esecuzione utili per il debug (figura
1.1).
10
Figura 1.1: Contesto e Task Control Block
Lo stack è infatti una struttura dati con politica di accesso di tipo LIFO (Last Input First
Output) cioè i dati vengono letti in modo inverso rispetto a cui sono stati scritti. Oltre al
contesto, lo stack può contenere:
•
variabili automatiche
•
indirizzo di ritorno di chiamate (call)
•
argomenti relativi ai registri
Il meccanismo del context switch è una caratteristica fondamentale dei sistemi operativi
multitasking poiché anche in caso di CPU singola, si ha l'illusione di avere l'esecuzione
simultanea di due o più processi: la rapida esecuzione di questo meccanismo (centinaia
o migliaia di volte al secondo) dà appunto questa illusione (figura 1.2).
Figura 1.2: Meccanismo del context switch
Il cambio di contesto può avvenire come risultato di un processo che ha volontariamente
rinunciato al suo tempo disponibile di CPU, come decisione presa dallo scheduler in
conseguenza del fatto che il processo ha terminato il timeslice di CPU oppure in seguito
ad una preemption causata dall'arrivo di un thread a priorità più alta. Il timeslice è un
periodo di tempo predefinito in fase di progettazione entro il quale ogni processo ha il
11
permesso di funzionare; al termine di questo tempo ovviamente il lavoro di quest'ultimo
non viene perduto, ma viene congelato per poi essere ripreso al momento opportuno. Lo
scheduler è quella parte del sistema operativo che si occupa di scegliere quale processo
mandare in esecuzione (riesumandolo o facendolo partire ex novo).
Nelle figure 1.3 e 1.4 viene illustrato per una particolare architettura (H8S), la
situazione della CPU idle (libera) con il task 1 pronto e poi con il task 1 in esecuzione.
È importante notare che il context switch è generalmente abbastanza avido di risorse,
richiedendo un tempo di CPU considerevole (qualche microsecondo) per ogni cambio di
contesto; se da una parte infatti il diminuire del tempo di timeslice potrebbe darci
maggiore illusione di esecuzione contemporanea di processi, dall'altra ci porta ad un
degrado prestazionale causato dalle richieste di sistema effettuate durante il cambio di
contesto.
Vediamo ora i punti essenziali del context switch partendo dal caso di avere due task,
task 1 e task 2, di cui task 1 è in esecuzione (figura 1.4) e subisce preemption a causa
dell'arrivo del task 2 più prioritario.
1. Sospensione del processo corrente attraverso il salvataggio del contesto
2. Recupero del contesto del prossimo processo da mettere in esecuzione
3. Inserimento del contesto appena recuperato nei registri della CPU (figura 1.5)
4. Ritorno alla locazione di memoria puntata dal program counter (ritorno alla linea
di codice che rimette in esecuzione il processo che era stato interrotto) e quindi
dopo al context switch il processo in esecuzione è il task 2 (figura 1.6).
Figura 1.3: Stato della CPU con il task1 pronto
12
Figura 1.4: Figura – il task 1 si mette in esecuzione
Figura 1.5: il task 2 a priorità più alta di task 1 effettua un
Context Switch
13
Figura 1.6: Il Task 2 è in esecuzione
1.5 Concorrenza
La gestione del multitasking in un sistema operativo è tanto importante quanto delicata.
Per capire meglio come si gestisce il multitasking è necessario mettere in evidenza la
differenza che c'è tra thread e processi. Mentre i processi sono solitamente indipendenti
tra di loro, utilizzando diverse aree di memoria, i thread condividono risorse di sistema,
memoria e informazioni di stato.
La progettazione di applicativi concorrenti in un ambiente orientato ai processi richiede
dei servizi di sistema (system call) dedicate alla comunicazione come le pipe o i socket
di unix. La memoria viene infatti solitamente gestita attraverso MMU (Memory
Managment Unit). In questo caso non sono richiesti particolari accorgimenti nel codice
applicativo per assicurare la consistenza dei dati scambiati in quanto è il kernel ad
occuparsi di questo (atomicità della read o della write, accessi concorrenti).
La progettazione degli stessi applicativi in un ambiente orientato ai thread invece viene
da un lato agevolata dalla condivisione della memoria; ogni thread infatti può accedere
alla medesima locazione di memoria per leggere o modificarne il contenuto senza
richiedere alcun servizio al SO. Il software applicativo deve però disporre di alcuni
14
strumenti per assicurare la consistenza dei dati condivisi. Ad esempio: due thread
accedono ad una variabile di tipo “char” che normalmente (dipendente comunque
dall'architettura), viene acceduta con una istruzione non interrompibile. In questo caso
non esistono particolari problemi in quanto in un accesso concorrente in scrittura si
perde il precedente valore ma si mantiene l'ultimo scritto. Ipotizziamo comunque che
questa variabile di tipo char (detto comunemente tipo atomico) debba essere
incrementata da due thread concorrenti. Il thread A legge il valore corrente della
variabile (ad esempio 0) poi si accinge a scrivervi il nuovo valore (1). Nel mentre il
thread B opera una preemption di A e decide di fare lo stesso, quindi legge ancora 0 (A
non ha ancora scritto il suo nuovo valore) e scrive il suo nuovo valore 1. A questo punto
il thread A viene ripreso ed esegue la scrittura di 1 mentre il doppio incremento avrebbe
richiesto la scrittura del valore 2. I thread A e B devono essere sincronizzati per evitare
questo tipo di comportamento che facilmente degenera se il tipo di dati acceduti non è
atomico o se le operazioni su questi sono più complesse del semplice incremento. Il SO
deve mettere a disposizione dei meccanismi di sincronizzazione (in questo caso dei
mutex) e il software applicativo deve utilizzarli; è quindi responsabilità del
programmatore/sistemista evitare il crearsi di situazioni quali race condition (corse
critiche) e deadlock (stallo).
1.6 Interrupt
Lo stato di interruzione rappresenta un contesto aggiuntivo a quello dei processi o dei
thread. Si definisce interrupt un tipo particolare di interruzione della CPU che provoca
l'interruzione di un processo qualora si verifichino determinate condizioni oppure il
processo in esecuzione debba effettuare una richiesta al sistema operativo. È come un
segnale o messaggio, generalmente di natura asincrona, che arriva alla CPU per
avvisarla del verificarsi di un certo evento.
Ci sono due tipi di interrupt:
• Interrupt hardware generati da dispositivi esterni alla CPU, che hanno il compito
di comunicare il verificarsi di eventi esterni, di solito dispositivi di Input/Output.
• Interrupt software che sono delle istruzioni assembly, tipo INT xx o SYSCALL,
che possono essere assimilate alle chiamate di sottoprogrammi, ma che sfruttano
il meccanismo delle interruzioni per passare il controllo dal programma
15
chiamante a quello chiamato, e viceversa; vengono utilizzati per accedere
direttamente alle risorse del sistema operativo.
L'uso di interrupt è una tecnica ampiamente utilizzata in sistemi multitasking e in
particolare in sistemi di tipo realtime. Quando si presenta un interrupt il SO ha poca
libertà di azione in quanto normalmente è bloccata la rilevazione di altri eventi
asincroni. Come è stato detto, nei sistemi realtime il tempo massimo di blocco di una
interruzione, deve essere dichiarato.
Per un sistema operativo general purpose come UNIX o Linux, il trattamento
dell'interruzione viene eseguito dal kernel stesso, eventualmente delegando parte della
elaborazione ai device drivers. In un sistema operativo realtime invece, il trattamento
viene solitamente delegato all'applicativo che è stato scritto in modo che sappia come
deve operare. Il kernel mette solo a disposizione i mezzi per sincronizzare i thread con
l'evento (segnalazione di semafori, accodamento dei dati, schedulazione di thread).
1.7 Scheduler
Sebbene sia già stata messa in evidenza l'importanza dello scheduler, cerchiamo di fare
un po' di chiarezza sul comportamento nei sistemi operativi convenzionali, nei sistemi
operativi soft-realtime e nei sistemi operativi hard-realtime. Per i primi possiamo dire
che il meccanismo di schedulazione ha l'obiettivo di ottimizzare le prestazioni globali
del sistema, per esempio cercando il compromesso tra la minimizzazione dell'overhead
(cioè richieste aggiuntive a quelle strettamente necessarie) e la distribuzione delle
risorse di processore ai vari task. Invece nei sistemi soft-realtime si cerca di ottimizzare
i tempi di risposta, mentre nei sistemi hard-realtime lo scheduler ha il compito di
garantire il rispetto delle deadline. In questi ultimi sistemi, interruzioni e processi hanno
tutti una priorità definita in quanto è imperativo che vi sia sempre la corrispondenza tra
tempo fisico e tempo di clock.
Riassumendo possiamo dire che lo scheduler provvede a scegliere quale thread mettere
in esecuzione ogni qualvolta un evento interno od esterno modifichi lo stato globale del
sistema.
16
2 Caratteristiche di eCos
2.1 Dove è cominciato tutto – Cygnus Solutions
Cygnus Solutions, fu fondata nel 1989 da John Gilmore, Michael Tiemann e David
Henkel-Wallace con lo scopo di fornire supporto commerciale al free software. Il suo
motto era: “Making free software affordable”, cioè “Rendiamo il free software
conveniente”. Cygnus è un acronimo di "Cygnus, Your GNU Support", "Cygnus, il
Tuo Supporto a GNU”.
L'idea che ebbero questi sviluppatori fu quella di concentrare il loro lavoro sulla
creazione di un piccolo set di strumenti open source che sarebbe poi stato venduto.
Iniziarono quindi vendendo il compilatore GNU (GCC) e il debugger (GDB) come un
piccolo pacchetto software. Questo fu possibile grazie all'enorme talento di Tiemmann,
il quale contribuì a numerosi port del compilatore GNU e scrisse il primo compilatore
nativo in C++. L'altro importante contributo venne da Henkel-Wallace e Gilmore che
svilupparono rispettivamente le binutils (utility binarie) e il debugger GDB.
Questo lavoro ebbe talmente grandi proporzioni che Gilmore divenne il nuovo
mantainer di GDB; quando la comunità internet lo venne a sapere, vi fu una
inondazione di differenti versioni del debugger; questo portò a integrare in GDB le
nuove caratteristiche proposte dalla comunità.
Tutto questo duro lavoro è poi stato ripagato in quello che oggi chiamiamo GNUPro
Developers Kit, il quale include:
•
GCC – Gnu Compiler Collection, un compilatore con supporto a numerosi
linguaggi di programmazione, fra cui il C in particolare;
•
G++ - Compilatore C++ che fa parte di GCC;
•
GDB - GNU DeBugger;
•
GAS – GNU Assembler;
•
LD – GNU Linker;
•
Cygwin – Un set di strumenti per migrare applicazioni da UNIX/Linux alla
piattaforma Microsoft Windows;
•
Insight – Interfaccia grafica per fare debug;
17
•
Source-Navigator - Un strumento per la comprensione e l'analisi del codice
2.2 L'origine di eCos
Alla fine degli anni '90 il mercato dei sistemi operativi realtime era piuttosto
frammentato. Cygnus, grazie all'esperienza maturata e al rapporto con i produttori di
semiconduttori, volle creare una soluzione software per dispositivi embedded che fosse
di alta qualità e concorrenziale dal punto di vista dei costi. Questa soluzione si andava
ad affiancare al set GNUPro, espandendo l'offerta di Cygnus. Quello che questo team
andò a sviluppare fu un sistema operativo realtime che permetteva l'astrazione
dell'hardware e che era altamente configurabile. Nacque cosi eCos (embedded
Configurable operative system), un RTOS che si adattava a numerosi sistemi embedded
e che grazie alla sua flessibilità permetteva una forte riduzione dei tempi per lo sviluppo
di questi sistemi: la riduzione dei tempi e quindi dei costi è sempre un aspetto
fondamentale nei sistemi embedded. Utilizzando il modello di sviluppo open source,
eCos è a costo zero dato che può essere scaricato e provato gratuitamente. Inoltre un
altro aspetto estremamente importante è l'essere royalty-free, cioè non vi sono neppure
costi a posteriori. Gli sviluppatori hanno accesso completo a tutto il codice sorgente,
strumenti inclusi, che possono essere modificati a piacere. Non ci sono costi iniziali
associati a licenze di utilizzo del codice e neppure ai tools relativi; tutto ciò che serve
per inizializzare lo sviluppo di un sistema embedded può essere fatto senza alcuna
spesa. Gli sviluppatori non devono neanche dare nessun contributo relativo al codice
sviluppato per componenti aggiuntivi o applicazioni sviluppate, ma devono fornire le
eventuali modifiche fatte al codice di eCos. Questo permette alla comunità open source
di sviluppare un prodotto sempre migliore.
2.2.1 Configurabilità e configurazione
Per capire meglio l'architettura di eCos, è importante analizzare le peculiarità del
framework che compongono il sistema eCos. Il framework dei componenti è
specificamente orientato ai sistemi embedded e si adatta perfettamente al modello dei
sistemi embedded.
18
Usando questo framework, un enorme quantità di funzioni per una applicazione può
essere costruita da componenti software già utilizzati o da blocchi di esso. Il framework
dei componenti di eCos è stato progettato per minimizzare l'uso di memoria dei
componenti del sistema, permettere agli utenti di tenere sotto controllo le tempistiche
per soddisfare le caratteristiche di realtime, ed utilizzare i più diffusi linguaggi di
programmazione (C, C++ e assembly).
La maggior parte dei sistemi embedded oggi sul mercato supporta più funzionalità di
quelle che servono per una specifica applicazione. Spesso viene incluso software
aggiuntivo che dà un supporto generico a caratteristiche a cui gli sviluppatori di sistemi
embedded non sono interessati o di cui non hanno bisogno. Questo software aggiuntivo
concorre a rendere il sistema più complesso ed inoltre più il codice è lungo e più ci sono
probabilità che qualcosa non vada. Un esempio estremo è quello del programma “Hello
world”: usando i tradizionali RTOS, che hanno supporto a mutex, task switching ed
altre caratteristiche integrate, tutte queste funzionalità sarebbero presenti nonostante non
ce ne sia il bisogno. In questo senso eCos dà la maggiore possibilità di controllo dei
componenti di run-time, dando la possibilità agli sviluppatori di rimuovere ciò che non è
necessario. Il sistema eCos è quindi un sistema altamente scalabile: si possono creare
sistemi con dimensioni dell'ordine delle centinaia di bytes fino a migliaia di kilobytes
quando caratteristiche come lo stack di rete e componenti di terze parti come un web
server vengono utilizzate.
Gli sviluppatori possono scegliere i componenti che soddisfano le richieste base delle
loro applicazioni e configurare quel particolare componente per una specifica
implementazione richiesta dall'applicazione. Questo significa potere abilitare o meno
una specifica caratteristica di un componente, o selezionare una particolare
implementazione di quel componente. Un esempio pratico è quello della configurazione
dello scheduler del kernel: eCos dà la possibilità di selezionare il numero di livelli di
priorità e se utilizzare i time slicing. Ogni linea di codice non necessaria per
l'applicazione viene eliminata dall'immagine finale dell'applicazione.
La configurabilità permette alle ditte di costruire una base di componenti riutilizzabili,
con l'accesso al codice sorgente del componente. Questo può ridurre il tempo di
sviluppo e il tempo di immissione sul mercato poiché i componenti sono altamente
portabili e possono essere utilizzati in un ampio range di applicazioni.
Il framework di eCos incoraggia lo sviluppo di codice di terze parti in modo tale da
estendere caratteristiche e funzionalità dei componenti chiave di eCos. Se gli
19
sviluppatori lavorano per estendere funzioni sul prodotto e contribuiscono a renderle
disponibili in eCos, la crescita delle funzionalità di eCos sono senza limiti. Inoltre, se la
funzionalità non è al momento disponibile, il codice sorgente è disponibile e permette di
risolvere il problema da sé.
La filosofia del controllo dei componenti nell'implementazione di eCos è quella di
ridurre le dimensioni del codice, sempre e il più possibile. In questo modo anche sistemi
minimali non soffrono dell'inserimento di codice aggiuntivo necessario al supporto di
caratteristiche avanzate che vengono usate solo in sistemi più complessi.
Nello sviluppo di applicazioni, i metodi di controllo dei componenti software possono
essere di 3 tipi: a tempo di esecuzione, a tempo di link e tempo di compilazione. Il
metodo utilizzato da eCos è quest'ultimo, in combinazione con il linking selettivo
fornito dal GNU Linker: in questo modo si hanno i migliori risultati in termini di
dimensione del codice e ciò lo rende adatto allo sviluppo di sistemi embedded.
L'uso del metodo di controllo a tempo di compilazione, anche detto metodo di
configurazione a livello sorgente, avviene grazie al preprocessore C e ciò offre
numerosissime opzioni specifiche che possono essere applicate al codice.
Oltre alla generazione di codice più corto, la configurazione a livello sorgente offre
molti altri importanti vantaggi nello sviluppo di software per sistemi embedded:
•
le applicazioni sono più veloci perché le variabili non devono essere controllate
durante l esecuzione per determinare quale azione intraprendere;
•
il codice è più reattivo e le latenze sono ridotte, il che permette di avere sistemi
più deterministici che è molto importante in dispositivi realtime;
•
il codice generato è più semplice, rendendo verifiche e test più facili da eseguire
•
il codice è generato su misura dell'applicazione e si crea quindi una specifica
applicazione per RTOS;
•
i costi possono essere ridotti perché l'utilizzo di risorse è ottimizzato e il numero
di cicli di CPU sono sfruttati in modo efficiente, permettendo l uso di hardware
più economico.
2.2.2 I componenti chiave di eCos
Le funzionalità standard che si aspettano di avere in un sistema operativo realtime per
dispositivi embedded, sono tutte incluse assieme al kernel realtime come componenti
20
chiave e sono:
•
Hardware Abstract Layer (HAL) – fornisce uno strato software che da accesso
generale all'hardware.
•
Kernel – include interruzioni, supporto alle eccezioni, thread e meccanismi di
sincronizzazione, scelta del tipo di scheduler, timers, contatori e allarmi.
•
Librerie matematiche ISO C – compatibilità standard con le chiamate di queste
funzioni.
•
Driver dispositivi – include la porta seriale, ethernet, ROM flash e altri.
•
Supporto al debugger GNU (GDB) – fornisce un software diretto per la
comunicazione con l'host GDB abilitando il debug dell'applicazione.
Entrambi, eCos e l'applicazione, vengono eseguite in modalità supervisor cioè non c'è
distinzione tra user mode e kernel mode.
Una infrastruttura minimale è poi inclusa in eCos. I test vengono configurati allo stesso
modo delle applicazioni e ciò assicura che l'esatta configurazione selezionata, venga
sottoposta ai test. Il tool di configurazione dà gli strumenti per distribuire i test.
L'espansione dell'infrastruttura di test è pianificata per i prossimi rilasci di eCos.
2.2.3 Supporto a processori e piattaforme di valutazione
Il supporto di architetture e processori di eCos è molto ampio. Questo lo rende una
buona scelta per le aziende che sviluppano su diverse architetture hardware e differenti
linee di produzione.
Una volta che viene effettuato il porting dell'HAL di eCos per una nuova architettura, l'
applicazione precedentemente sviluppata può essere tranquillamente montata sulla
nuova piattaforma.
Il supporto software ad eCos è disponibile per le piattaforme di valutazione commerciali
che sono sul mercato oggi. Le principali architetture di CPU supportate includono:
•
ARM
•
Fujitsu Fr-V
•
Hitachi H8/300
•
Intel x86
•
Matshushita AM3x
•
MIPS
21
•
NEC V8xx
•
PowerPc
•
Samsung CalmRISC16/32
•
SPARC
•
SPARClite
•
SuperH
Grazie al modello di sviluppo open source pero questa lista è in continuo aggiornamento
ed
è
consultabile
sul
sito
web
di
eCos
all'indirizzo
http://sources/redhat.com/ecos/hardware.html
2.2.4 Supporto tecnico ad eCos
La valutazione della qualità del supporto tecnico è un aspetto molto importante da
tenere in conto per determinare se un prodotto può essere usato per i propri scopi. Ci
sono più modalità possibili per avere supporto con eCos. Il percorso che si fa per
ottenere questo supporto dipende largamente dalla quantità di assistenza necessaria.
Sei differenti mailing list sono disponibili per eCos:
•
Lista di discussione – dà supporto e assistenza tecnica su vari argomenti relativi
ad eCos attraverso gli sviluppatori.
•
Lista delle patch – usata per proporre patch, al codice di eCos, al mantainer
prima che vengano affidate al repository ufficiale del codice sorgente. Qui
troviamo anche le discussioni relative alle patch proposte.
•
Lista di sviluppo – Vi sono le discussioni relative ai miglioramenti da
sviluppare, come ad esempio nuovi ports e nuove caratteristiche.
•
Lista Annunci – una lista a basso traffico che tratta delle novità importanti di
eCos come nuove versioni di eCos e/o importanti miglioramenti.
•
Lista delle pagine web CVS – contiene le notifiche dei cambiamenti delle pagine
web che vengono mantenute nel sistema CVS (Concurrent Version System).
Questa è una lista a sola lettura.
•
Lista CVS – è una lista a sola lettura che notifica i cambiamenti fatte al codice
sorgente di eCos.
Come buona norma, è bene cercare tra la mailing list e provare a risolvere il problema
22
da sé, prima di fare una richiesta di aiuto. Generalmente le richieste di aiuto vengono
processate in due-tre giorni. Bisogna tenere in considerazione che non a tutte le
domande viene data risposta. Fare domande specifiche e dettagliate, può aiutare il
mantainer e gli sviluppatori a dare una mano. Le risposte che vengono date possono
aiutare altre persone a risolvere problemi analoghi e questo è uno dei punti di forza del
sistema di sviluppo open-source e delle open mailing-list.
L'iscrizione alle mailing list appena citate è completamente gratuito e può essere fatto
collegandosi al sito web http://source.redhat.com/ecos/intouch.html
Il sistema invece che si occupa di indicizzare i bug di eCos sono contenuti in un
database Bugzilla. Il database Bugzilla ha un motore ricerca avanzato che permette di
fare ricerche attraverso parole chiave, in particolari piattaforme e versioni specifiche di
eCos. Questo database si trova all'url http://bugs.ecos.sourceware.org/
Per questioni tecniche private relative allo sviluppo di eCos e alla collaborazione, i
mantainers hanno inoltre un indirizzo su cui possono essere contattati: [email protected]
2.3 Visione d'insieme del sistema eCos
L'obiettivo con cui è stato progettato eCos è quello di permettere la costruzione di un
sistema per dispositivi embedded completo partendo da tanti componenti software che
possono poi essere riutilizzati. Lo sviluppatore può quindi scegliere la configurazione ad
hoc, rimuovendo componenti non necessari, in modo da ottenere un prodotto che si
adatta perfettamente ai requisiti dell'applicazione. Prestazioni e utilizzo della memoria
vengono cosí ottimizzati al massimo. La figura 2.1 mostra un esempio di come i vari
blocchi base e alcuni componenti aggiuntivi, sono organizzati a strati per rendere
possibile l'incorporamento di tutte le funzioni necessarie per l'applicazione.
2.4 Terminologia di eCos
Il sistema di configurazione di eCos coinvolge una serie di termini specifici importanti
che vengono usati sia in questa tesi che nella documentazione ufficiale, in inglese che
verranno quindi spiegati nel seguito.
23
Figura 2.1: Organizzazione a strati di eCos
2.4.1 Il component framework
L'insieme degli strumenti che permette agli utenti di configurare eCos e gestire i vari
pacchetti presenti nel repository è chiamato component framework. Incluso ad esso vi
sono lo strumento di configurazione in modalità linea di comando, quello in versione
grafica, lo strumento per la gestione della memoria e quello per l'amministrazione dei
pacchetti.
Il framework salva le scelte dell'utente in una configurazione, la quale contiene i
pacchetti che sono stati scelti con le relative opzioni desiderate che possono essere
attivate, disattivate o avere un valore selezionato. Gli strumenti del framework lavorano
sulla configurazione insieme alle opzioni di quest'ultimo per determinare i valori di
default e i range validi che possono avere. La configurazione è salvata in un file con
24
estensione .ecc.
La figura 2.2 mostra una porzione del pacchetto del kernel di eCos proveniente dallo
strumento di configurazione. Si noti come i vari blocchi sono incapsulati uno nell'altro a
formare un pacchetto completo e indipendente. Possiamo inoltre osservare la gerarchia
della configurazione a partire dai pacchetti poi ai componenti, alle opzioni di
configurazione e alle sotto-opzioni. I blocchi in costruzione vengono raggruppati in un
pacchetto in base alla funzionalità che esso include. Nella figura 2.2 vediamo appunto
che il pacchetto del kernel di eCos contiene il componente della gestione delle eccezioni
del kernel e il componente che gestisce lo scheduler del kernel; altri componenti non
sono visibili in questa figura. Possiamo però notare in quest'ultima, la nidificazione
delle opzioni di configurazione, per esempio nello scheduler del timeslice e le sottoopzioni che esso include.
Figura 2.2: Esempio di configurazione a blocchi che compongono un pacchetto.
2.4.2 Component Repository
Il componente repository è una struttura a directory che contiene tutti i pacchetti
provenienti dall'installazione di eCos. Per aggiungere o aggiornare nuovi pacchetti, o
per rimuovere quelli vecchi, possiamo utilizzare lo strumento di amministrazione dei
pacchetti di cui abbiamo parlato in precedenza. La directory principale, “ecos” che
contiene appunto tutti i file della distribuzione di eCos. La sottodirectory che contiene il
component repository si chiama “packages”. All'interno di quest'ultima troviamo un file
“ecos.db” che contiene i dettagli relativi alla varie versioni dei pacchetti presenti nel
component repository. Può capitare che questo file debba essere modificato a mano, per
25
esempio quando si fa il porting su di una nuova architettura, per fare in modo che il
nuovo HAL venga riconosciuto dalla configurazione. In generale, gli sviluppatori di
applicazioni, possono considerare il component repository come una risorsa a sola
lettura che può essere sempre riutilizzata per applicazioni differenti. La figura 2.3
mostra la struttura della directory del component repository.
Figura 2.3: Struttura della directory del component repository.
Essendo eCos in continua evoluzione, quello che si vede in figura è una fotografia del
component repository della versione 2 di eCos che mostra il modello generale di
organizzazione.
Quando però vi sono nuove aggiunte al progetto eCos, i mantainers decideranno se
queste aggiunte vanno messe all'interno di sottodirectory esistenti o se si deve creare
una nuova sottodirectory.
Una descrizione della struttura della directory del component repository è riassunta
nella tabella 2.1.
26
Directory
Descrizione
compat
Contiene i pacchetti per la compatibilita con POSIX (IEE 1003.1) e μITRON 3.0
cygmon
Pacchetto per il debug monitor Cygmon
devs
Contiene i driver specifici di hardware come la seriale, ethernet e PCMCIA
error
Contiene i codici di stato e di errore comuni
fs
Contiene il pacchetto del filesystem di RAM e ROM
hal
Contiene i pacchetti relativi ad HAL
infra
Contiene i pacchetti dell'infrastruttura di eCos come le macro, opzioni di inizializzazione etc..
io
Pacchetti per la gestione dell'I/O Hardware
isoinfra
Pacchetti per il supporto alle librerie ISO C (come stdlib e stdio) e implementazioni POSIX
kernel
Pacchetto per le funzionalità chiave del kernel di eCos (scheduler, semafori etc..)
language
Supporto per le librerie matematiche ISO C
net
Supporto alle funzionalità di networking (TCP/IP, UDP etc..)
redboot
Pacchetto per il ROM monitor RedBoot
services
Pacchetto per l'allocazione dinamica della memoria e supporto alle librerie di compressione
/decompressione
Tabella 2.1: Descrizione dei componenti del component repository.
2.4.3 Opzioni di Configurazione
Le opzioni di configurazione sono la parte fondamentale della configurabilità di eCos:
permettono infatti di abilitare, disabilitare o impostare un valore ad una specifica
opzione. Ognuna di queste, ha associata una macro che lavora a livello sorgente del file
di configurazione e include valori prestabiliti che possono essere usati come riferimento.
Una volta completata l'applicazione poi, attraverso le opzioni è possibile ottimizzarla
per soddisfare i requisiti di sistema.
Il component framework descrive ogni pacchetto usando il cosiddetto Component
Definition Language (CDL) e in ogni pacchetto c'è almeno uno script CDL che lo mette
in relazione con il component framework.
L'annidamento delle opzioni di configurazione viene usato per dare un controllo più fine
27
del sistema. Se una opzione che ha delle sotto-opzioni viene disabilitata, certamente
queste sotto-opzioni sono inutili e quindi non possono essere selezionate e/o modificate.
può pero accadere che alcune opzioni abbiano delle dipendenze su altre, rendendole
quindi dei vincoli; se per esempio si seleziona l'opzione “Bitmap Scheduler” allora
l'opzione “Scheduler Timeslicing” deve necessariamente essere disabilitata.
In altri casi le opzioni non possono essere modificate: è il caso ad esempio di alcuni
processori che supportano solo un metodo di memorizzazione dei dati (endian mode).
A seconda dell'hardware selezionato nella configurazione, l'endian mode può essere o
meno definito.
Altre opzioni di configurazione invece, possono accettare solo determinati valori. Il
numero di livelli di priorità deve infatti essere compreso tra 1 e 32.
Una volta completata la configurazione, possono verificarsi dei conflitti. Questi
vengono segnalati dallo strumento di configurazione in modo che possano essere
corretti. Se questi conflitti vengono ignorati è si possono verificare degli errori durante
il processo di compilazione o di linking. In questo caso si devono assolutamente
risolvere i conflitti per completare l'applicazione: lo strumento di configurazione può
proporre una soluzione oppure viene chiesto l'intervento dell'utente per la risoluzione
del conflitto.
2.4.4 Pacchetti e componenti
Un componente è una opzione di configurazione che incapsula altre opzioni più
dettagliate al suo interno. I componenti possono essere abilitati o disabilitati a seconda
delle necessità di quella particolare applicazione. La gerarchia delle opzioni dei
componenti da un controllo ottimale della configurazione: rimuovendo componenti non
necessari, il tempo di compilazione e la dimensione dell'immagine di eCos saranno
minori.
Un pacchetto è un tipo di componente che è pronto per la distribuzione. All'interno vi
sono tutti i files sorgenti necessari, i file header, i file che descrivono la configurazione,
la documentazione e altri file importanti. Spesso un pacchetto è racchiuso in unico file,
permettendo attraverso il tool appropriato l'installazione o l'aggiornamento nel futuro se
vengono fatte variazioni. Avere un pacchetto di distribuzione come unita indipendente,
permette agli sviluppatori di terze parti di estendere le funzionalità di eCos. Utilizzando
28
inoltre il tool specifico per caricare un pacchetto, permette di avere il controllo delle
versioni dei pacchetti usati nel sistema.
2.4.5 Target
Un target è un insieme di componenti hardware nella quale l'applicazione realizzata
verrà eseguita; può essere una scheda commerciale, hardware auto-costruito oppure un
simulatore. Quando si effettua la configurazione è necessario selezionare il target in
modo che il component framework possa caricare i relativi pacchetti che supportano il
dispositivo e l'HAL riferito al target. Inoltre vengono settate le opzioni di
configurazione ai valori di default in relazione al target selezionato.
Questo lavoro è ovviamente più automatizzato per le piattaforme di valutazione
supportate da eCos, mentre è richiesto un lavoro maggiore nel caso di proprio hardware
in quanto è necessario determinare quali pacchetti e quali valori devono essere caricati
nella configurazione.
2.4.6 Template
Un template è una configurazione parziale molto utile come punto di inizio: è una
combinazione di target e un gruppo di pacchetti. Questo gruppo di pacchetti ha un nome
che ne descrive le funzionalità (tabella 2.2). Quando si inizia una nuova configurazione,
il template viene usato come punto di inizio in relazione ai requisiti generali
dell'applicazione. Le opzioni di configurazione vengono poi successivamente
modificate ad hoc per la propria applicazione. Il tool di configurazione mostra poi i
pacchetti specifici inclusi nel template.
29
Nome del Template
Descrizione
All
Contiene i pacchetti per un hardware specifico
Cygmon
Pacchetto per costruire eCos con Cygmon
Cygmon kernel
Pacchetto per costruire eCos con Cygmon senza il supporto del kernel
Default
Contiene le infrastrutture, il kernel, librerie matematiche e C piu il supporto a pacchetti necessari
Elix
Contiene il pacchetto per la compatibilita con EL/IX
Kernel
Contiene HAL, le infrastrutture e il kernel eCos
Minimal
Contiene HAL e le infrastrutture
net
Pacchetti per il supporto allo stack di rete di OpenBSD
New_Net
Pacchetti per il supporto allo stack di rete di FreeBSD
Posix
Contiene HAL, le infrastrutture, il kernel eCos e il supporto POSIX
RedBoot
Supporto per la costruzione dell'immagine del RedBoot monitor
Stubs
Pacchetto per il supporto a GDB
Uitron
Pacchetto per la compatibilita con μITRON
Tabella 2.2: Template di eCos
30
3 Caratteristiche di eCos
3.1 Portabilità
Uno dei componenti chiave del sistema eCos è l'Hardware Abstraction Layer (HAL).
Questo componente è quello che permette infatti di far girare in modo diretto la stessa
applicazione sulle diverse piattaforme che eCos supporta. È inoltre possibile estendere
la compatibilità delle piattaforme realizzando un porting dell'HAL per i nuovi hardware.
Per porting si intende l'adattamento o la modifica di un componente (software) in modo
da rendere possibile l'esecuzione dell'applicazione in un ambiente diverso da quello di
origine: se effettuare il porting è una operazione semplice e quindi economica, il
software si dice portabile.
È facile intuire che la grande portabilità di eCos è uno dei suoi punti forti, rendendolo
uno dei prodotti più flessibili del mercato.
3.2 Caratteristiche di base di HAL
L' HAL ha il compito di isolare funzioni specifiche di una architettura e di convertirle in
una forma generica per permettere la portabilità dei componenti dell'infrastruttura.
Fondamentalmente l' HAL è uno strato software con API (Application Programming
Interface) generalizzate, che contengono le specifiche operazioni hardware necessarie
per completare la funzione desiderata.
Un esempio di come l'HAL astrae specifiche implementazioni dell'hardware per la
stessa chiamata dell'API si vede nel listato 3.1 per l'architettura ARM e nel listato 3.2
per l'architettura PowerPC.
31
1 #define HAL_ENABLE_INTERRUPTS()
2 asm volatile (
3 "mrs r3,cpsr;"
4 "bic r3,r3,#0xC0;"
5 "msr cpsr,r3"
6:
7:
8 : "r3"
9 );
\
\
\
\
\
\
\
\
\
Listato 3.1: Implementazione della macro HAL_ENABLE_INTERRUPTS() su
architettura ARM
1 #define HAL_ENABLE_INTERRUPTS()
2 CYG_MACRO_START
3 cyg_uint32 tmp1, tmp2;
4 asm volatile (
5 "mfmsr %0;"
6 "ori %1,%1,0x8000;"
7 "rlwimi %0,%1,0,16,16;"
8 "mtmsr %0;"
9 : "=r" (tmp1), "=r" (tmp2));
10 CYG_MACRO_END
\
\
\
\
\
\
\
\
\
\
Listato 3.2: Implementazione della macro HAL_ENABLE_INTERRUPTS() su
architettura PowerPC
La chiamata che vediamo nei 2 listati è la HAL_ENABLE_INTRERRUPTS(), ed è la
stessa per entrambi indipendentemente dall'architettura. Come si nota però, il processo
che l'abilitazione di un interruzione varia da una architettura all'altra (come mostrano le
righe da X a Y nel listato X e da X a Y nel listato X). L HAL permette allo strato di
applicazione di accedere direttamente all'hardware e ad ogni funzione di architettura.
La struttura di HAL segue alcuni vincoli. In primo luogo è interamente implementata in
linguaggio C e assembly. Secondariamente gli interfacciamenti ad HAL sono
implementate con delle macro in linguaggio C. Questo permette la massima efficienza
di implementazione che non intacca l'interfaccia. Le interfacce possono essere scritte in
assembly o C come funzioni inline, oppure come chiamate a funzioni esterne. Usando il
metodo inline, i costi operativi di esecuzione associati alla funzione sono assenti ma la
dimensione del codice può aumentare.
L'HAL è formato da tre moduli separati:
•
architettura
32
•
varianti
•
piattaforma
Il primo modulo si occupa di gestire le famiglie di processori supportati da eCos. Ogni
sotto-modulo dell'architettura contiene il codice per l'inizializzazione della CPU,
gestione degli interrupt, context switching e altre funzionalità specifiche al set di
istruzioni dell'architettura associata alla famiglia dei processori.
Una variante è invece associata ad uno specifico processore all'interno di una famiglia
di processori descritta dall'architettura. Per esempio in una stessa famiglia di processori
si può avere il supporto della MMU (Memory Managment Unit) di alcuni processori,
mentre di altri no.
Una piattaforma invece è uno specifico hardware che include l'architettura del
processore scelto o una sua variante. Generalmente si include il codice per
l'inizializzazione della piattaforma, la configurazione dei chip select e dei timer.
Nel mantenere la configurabilità di eCos un obiettivo prioritario, solo i componenti che
sono realmente necessari per una specifica piattaforma o applicazione, vengono
integrati nel kernel. La selezione dei componenti viene semplificata attraverso l'uso
dello strumento di configurazione di eCos. L'interfaccia grafica mostra i dettagli di ogni
componente e permette all'utente una selezione mirata.
3.2.1 Funzionalità di HAL
Oltre a rendere eCos un prodotto portabile, HAL fornisce anche alcune funzionalità
realtime specifiche per alcune piattaforme includendo un gestore delle eccezioni
(exception handler), un gestore delle interruzioni (interrupts handler) e virtual vector. Il
gestore delle interruzioni permette a un sistema embedded di ripristinarsi in seguito ad
una eccezione hardware come gli overflow, un accesso errato alla memoria o una
divisione per zero. Questi eventi non possono permettere il crollo del sistema, quindi
devono essere opportunamente gestiti dall'HAL, dal kernel o dall'applicazione stessa. Le
routine di risposta agli interrupts sono spesso usati nei sistemi di tipo realtime, ma per
essere davvero efficienti, devono essere scritti in modo da sfruttare le caratteristiche del
processore in uso. Sono supportati due tipi di routine: ISR (Interrupt Service Routine),
utilizzati per semplici task che possono essere velocemente portati a termine e DSR
(Deferred Service Routine) che sono usati per task complessi che possono essere attuati
il prima possibile, ma con la riabilitazione di interrupt mantenuta a livelli di bassa
33
latenza per le ISR. Avere entrambi i tipi di routine disponibili, permette allo
sviluppatore di gestire una priorità di questi, garantendo l'esigenza di bassi tempi di
risposta. Virtual vectors è il nome della tabella che ha indirizzamento statico nello
spazio di memoria del dispositivo: essa contiene 64 vettori che puntano a funzioni di
sistema o a dati. I vettori hanno sempre lo stesso indirizzamento e ciò permette alla
RAM e alla ROM di accedere a queste funzioni di sistema. Per esempio, si ha quindi la
possibilità di fare debug sull'applicazione usando una comunicazione di tipo seriale o
ethernet.
3.2.2 Configurazione di HAL
Come è stato detto nel capitolo 2, eCos utilizza un metodo di configurazione a livello
sorgente, il quale determina quali componenti includere nell'immagine finale della
nostra applicazione. La configurazione a livello sorgente imposta i valori per specifiche
macro in funzione delle opzioni scelte, poi l'HAL viene generato tenendo conto delle
specifiche impostate nella configurazione.
Le opzioni di configurazione possono essere divise in due parti: quelle specifiche di una
architettura e quelle comuni a tutte le architetture. I componenti di configurazione
comune contengono le opzioni generali per la gran parte o tutti i pacchetti dell'HAL del
sistema eCos. I componenti specifici dell'architettura invece possono essere
ulteriormente suddivisi in opzioni generali della piattaforma o specifiche di quest'ultima
che si riferiscono ad un particolare hardware.
3.2.2.1 Componenti di configurazione comuni
I componenti di configurazione comuni sono standard per tutti i pacchetti HAL del
sistema e sono sei. Ogni componente contiene le opzioni di configurazione per
impostare l'HAL in modo da soddisfare le specifiche dell'applicazione. La tabella 3.1 dà
una descrizione dei sei componenti fornendo anche il nome in formato CDL.
34
Nome Componente
Nome CDL
Descrizione
Opzioni di HAL indipendenti dalla piattaforma
CYGPKG_HAL_COMMON
Controlla gli interfacciamenti generali al kernel e altre opzioni quali il supporto alle eccezioni di HAL,
installazione delle tabelle MMU e supporto alla diagnostica
Nome Componente
Nome CDL
Descrizione
Gestione delle interruzioni di HAL
CYGPKG_HAL_COMMON_INTERRUPTS
controlla la configurazione della struttura degli interrupt e la configurazione della dimensione dello
stack degli interrupt
Nome Componente
Nome CDL
Descrizione
Supporto al Context Switch
CYGPKG_HAL_COMMON_CONTEXT
Permette al codice del context switch di sfruttare le convenzioni di specifiche architetture per ridurre la
quantità di informazioni di stato da salvare durante il context switch
Nome Componente
Nome CDL
Descrizione
Comportamento di inizializzazione della cache
CYGPKG_HAL_CACHE_CONTROL
Permette l'abilitazione della cache per dati e istruzioni durante il processo di startup. Queste opzioni
devono essere disabilitate se opzioni specifiche per l'hardware devono essere utilizzate.
Nome Componente
Nome CDL
Descrizione
Supporto al debug a livello sorgente
CYGPKG_HAL_DEBUG
Definisce il livello di debug da includere nel supporto ad HAL.
Nome Componente
Nome CDL
Descrizione
Supporto al ROM monitor
CYGPKG_HAL_ROM_MONITOR
Definisce l'interazione tra l'applicazione e il ROM monitor. L'applicazione può essere generata per
lavorare con un ROM monitor oppure comportarsi come un ROM monitor.
Tabella 3.1: Componenti comuni di configurazione di HAL
3.2.2.2 Componenti di configurazione specifici dell'architettura
Queste opzioni possono cambiare enormemente tra una piattaforma e l'altra poiché
dipendono dal template hardware che è stato scelto.
Per esempio usando lo strumento grafico di configurazione e selezionando “Motorola
MBX860/821 board”, il template hardware abilita i pacchetti seguenti nella
configurazione (i nomi nel formato CDL sono tra parentesi):
•
PowerPC Architecture (CYGPKG_HAL_POWERPC)
•
PowerPC MPC8xx Variant HAL (CYGPKG_HAL_POWERPC_MPC8xx)
•
Motorola MBX PowerPC Evaluation Board
(CYGPKG_HAL_POWERPC_MBX)
•
Motorola MBX PowerQUICC Support (CYGPKG_HAL_QUICC)
Altre sotto-opzioni per questo template includono la selezione della velocità di clock
della scheda hardware e il dispositivo di boot della ROM da usare.
In un altro caso invece, selezionando ARM PID Development Board come template, si
35
abilitano questi pacchetti:
•
ARM Architecture (CYGPKG_HAL_ARM)
•
ARM PID Evaluation Board (CYGPKG_HAL_ARM_PID)
Le opzioni di configurazione in questo caso sono: la selezione dell'endian mode e l'uso
di porte di controllo per la diagnostica.
Una sotto-opzione che hanno tutti i componenti specifici dell'architettura è lo Startup
Type (CYG_HAL_STARTUP): questo impone dei vincoli sul pacchetto del supporto al
ROM monitor. Lo Startup Type può essere ROM o RAM e nelle piattaforme
ROMRAM, il codice contenuto nella ROM viene copiato nella RAM durante il
processo di inizializzazione.
3.2.3 Inizializzazione di HAL
Per capire meglio le funzionalità offerte da HAL, analizziamo il processo di startup del
software mentre inizializza l'hardware. I sotto-moduli di HAL hanno il compito di
inizializzare i processi, come il coordinamento con un ROM monitor, l'invocazione di
costrutti statici C++ e il salto all'inizio del codice dell'applicazione.
La figura 3.1 mostra il diagramma di flusso della routine di inizializzazione di HAL per
la scheda di valutazione basata su PowerPc Motorola MBX860. Si tenga in
considerazione che la procedura di startup può differire in funzione dell'architettura e
della piattaforma usata. La routine descritta nella figura 3.1 può essere implementata in
linguaggio C o assembly.
36
Figura 3.1: Procedura di inizializzazione di
HAL
Descriviamo ora i vari passi numerati della figura 3.1:
1. Il punto di partenza del sistema avviene dopo il ciclo di inizializzazione
chiamato Hardware Powerup. Questo viene anche usato per un soft-reset.
2. Dopo un soft-reset (o un hard-reset) il processore punta ai suoi vettori di reset
(reset_vector nel diagramma). Il vettore di reset si trova nel file vectors.S nella
sottodirectory dell'architettura. Questo file contiene il punto di inizio per tutti i
pacchetti dell'HAL. Il vettore di reset effettua la configurazione minimale dei
registri del processore per permettere all'applicazione di inizializzarsi.
3. Il vettore di reset punta a _start che si trova anch'esso in vectors.S ed è il punto
principale di inizio per l'avvio di HAL.
4. Viene chiamata la routine hal_cpu_init contenuta in variant.inc o in arch.inc a
seconda dell'architettura. Questa funzione configura i registri specifici del
processore.
5. Si invoca hal_hardware_init che è una funzione specifica della piattaforma e
quindi si trova nel file assembly di questa. In questa routine vi è anche il setup
37
della cache, dei registri dell'interrupt a valori di default, dei registri di clock e dei
registri specifici della piattaforma hardware in uso.
6. La configurazione dell'area di stack dell'interrupt consente di riservare un'area di
memoria per salvare le informazioni di stato della CPU quando avviene una
interruzione. La quantità di spazio da riservare si può settare nella
configurazione dei componenti comuni.
7. Il codice relativo a hal_mon_init che si trova in variant.inc o platform.inc
dipende dalla configurazione: quando eseguita come ROM monitor o
applicazione ROM, lo scopo principale di questa routine è assicurare che il
gestore delle eccezioni supportino tutte le condizioni di eccezione della CPU.
8. Pulizia della sezione BBS: contiene tutte le variabili globali e locali non
inizializzate con una classe statica di memorizzazione.
9. Lo stack è inizializzato e permette di fare chiamate di funzioni C all'interno del
codice assembly di vectors.S.
10. Viene chiamata hal_platform_init che si trova nel file hal_aux.c della
piattaforma in uso. Questa a sua volta chiama hal_if_init che si trova in hal_if.c
nella sottodirectory di HAL chiamata “common”: questa funzione inizializza la
tabella dei virtual vector in funzione delle opzioni selezionate.
11. Inizializzazione della MMU: gestisce la traduzione di indirizzi logici ad indirizzi
fisici provvedendo inoltre a meccanismi di protezione e caching attraverso la
routine hal_MMU_init.
12. Abilitazione
di
cache
per
dati
e
istruzioni
attraverso
la
funzione
hal_enable_caches.
13. Esecuzione
della
routine
hal_IRQ_init:
avviene
il
setup
del
CPM
(Communication Processor Module) che accetta e prioritarizza interrupts interni
ed esterni. In questo caso è una opzione specifica dei processori PowerPC.
14. Chiamate dei costruttori C++ da parte cyg_hal_invoke_constructors. Il linker
gestisce la generazione della lista dei costruttori globali.
15. Se la configurazione include un ambiente di debug e non vi è supporto ad un
ROM monitor, viene chiamata initialize_stub il quale installa il gestore delle trap
e inizializza l'hardware per il debug.
16. L'ultimo processo di inizializzazione di HAL è poi quello di passare il controllo
al kernel per la sua configurazione: questo viene fatto con la routine cyg_start.
38
3.3 Il kernel di eCos
Il kernel di eCos è stato progettato per soddisfare quattro obiettivi principali:
1) Bassa latenza agli interrupt; il tempo necessario per rispondere a un interrupt e
cominciare l'esecuzione di una ISR. Minore è questo tempo e migliori sono le
performance di sistema.
2) Bassa latenza di commutazione dei task; il tempo da quando un thread diventa
disponibile al momento in cui inizia l'esecuzione effettiva. Un tempo basso,
rende migliore un RTOS.
3) Uso di poca memoria; risorse di memoria sia per programma e dati sono ridotti
al minimo. Si consente la configurazione di tutti i componenti di memoria a
seconda delle necessità.
4) Comportamento deterministico; in tutti gli aspetti di esecuzione, le prestazioni
del kernel devono essere prevedibili, per soddisfare i vincoli temporali.
ECos offre un interessante caratteristica per migliorare ulteriormente le prestazioni delle
applicazioni: la possibilità di realizzare una applicazione, con o senza un vero e proprio
kernel. In applicazioni semplici che non necessitano di programmazione o multitasking, funzioni di eCos per inizializzare e gestire l'hardware possono essere create
senza il kernel, portando al miglioramento della velocità di esecuzione e riducendo
l'ingombro di memoria. In molte applicazioni per DSP questo metodo di procedere è
comune.
Spostandosi nella direzione opposta, eCos può essere invece un OS a tutti gli effetti ,con
un set completo di kernel e componenti fondamentali, tra cui: lo scheduler e la gestione
delle sincronizzazioni, interrupt e gestione delle eccezioni, contatori, allarmi, clock,
timer, compatibilità POSIX e μITRON (una serie di specifiche di kernel realtime per
sistemi embedded su piccola scala), ROM monitor , RAM e ROM file system, il
supporto PCI, il supporto al protocollo di rete TCP/IP e la possibilità di essere
continuamente migliorato grazie alle contribuzioni di parte di terzi. Come già detto in
precedenza, il tool di configurazione eCos consente una facile configurazione e build
del kernel.
39
3.4 Meccanismi di gestione del tempo in eCos
ECos utilizza un meccanismo di timer hardware per gestire le sue funzionalità
temporali, basato su alcuni componenti:
•
Counter: si tratta di un'astrazione che mantiene il conteggio di una sorgente di
tick. Il tick può essere generato da un componente hardware oppure da un thread
e non è necessariamente periodico
•
Clock: è un contatore con associata una risoluzione il quale è guidato da una
sorgente periodica di tick che rappresenta il periodo. Il kernel di eCos
implementa di default un clock di sistema detto RTC (Real Time Clock)
•
Allarme: e connesso con ad un contatore e provvede a generare eventi in base al
valore del contatore associato. L'evento può essere configurato in modalità
periodica o one shot. Quando un allarme viene configurato viene fornito anche
un “handler” associato che processa l'evento.
•
Timer: è un allarme collegato al clock.
3.5 Scheduler nativi in eCos
Gli scheduler realtime nativi supportati da eCos sono: lo scheduler MLQ (Multi Level
Queue) e quello bitmap. Entrambi supportano il sistema di preemption ed entrambi
utilizzano un sistema di priorità a 32 livelli (da 0 a 31, dove 0 è il livello più alto). Lo
scheduler MLQ supporta inoltre il multiprocessore simmetrico (SMP), cioè
un'architettura dotata di più CPU che possono accedere equamente alla memoria di
sistema.
3.5.1 Bitmap Scheduling
Il bitmap scheduling consiste in una coda contenente i thread che sono caricati in
memoria. Ogni thread nella coda ha una priorità associata. Come è stato detto vi sono
32 livelli di priorità disponibili (figura 3.1) e ogni livello di priorità può essere associato
con solo un thread, limitando quindi il numero di thread presenti nella coda a 31 (un
thread è usato dal thread detto di idle).
40
Figura 3.2: Bitmap Scheduler : un livello univoco di priorita per ogni thread
Lo scheduler permette sempre l'esecuzione del thread corrente con priorità più alta.
Inoltre è possibili abilitare o meno il supporto alla preemption. Se questa è abilitate e un
thread a priorità maggiore di quello in esecuzione entra nella coda, lo scheduler
sospende quello corrente e lancia quello con priorità più alta (figura 3.2).
Figura 3.3: Linea temporale dello scheduler Bitmap
Grazie al design molto semplicistico di questo scheduler, trovare quale thread ha
priorità più alta e metterlo in esecuzione rende il sistema veloce e reattivo. Si riesce
inoltre a predire facilmente il comportamento del sistema, rendendolo di tipo
deterministico. Questi vantaggi sono pero limitati ad un sistema con massimo 31
threads.
41
3.5.2 MLQ scheduler
Nello scheduler MLQ invece di una coda per tutti i thread e tutte le priorità, si usa un set
di code dove ognuna di esse contiene un numero di thread che hanno tutti la stessa
priorità (figura 3.3). Ogni coda ha il suo algoritmo di scheduling che solitamente è un
algoritmo a timeslice che condivide il tempo di CPU tra i vari thread in modo eguale. I
livelli a diversa priorità possono avere scheduler di tipo diverso.
Figura 3.4: Coda Multilivello (MLQ)
Queste code sono gestite in modo che quelle con priorità più alta vengono messe in
esecuzione per prime. (figura 3.4). I thread sono suddivisi in differenti livelli di priorità
in relazione alle loro proprietà. Nel caso di supporto a processori SMP, ogni processore
ha il suo scheduler.
Figura 3.5: Grafico temporale dello scheduler MLQ
Questo scheduler come si vede è più complicato di quello bitmap e questo comporta una
latenza leggermente più alta. Lo scheduler MLQ permette pero la realizzazione di
sistemi più complessi, permettendo allo sviluppatore di creare una separazione distinta
tra task in background e foreground (i quali hanno richieste temporali differenti) e di
42
non avere il limite del numero dei thread come nel caso del bitmap scheduler. La
complessità però rende più difficile la generazione di un sistema di tipo deterministico.
3.6 Sincronizzazione dei thread con eCos
ECos supporta numerosi meccanismi di sincronizzazione per permettere la
comunicazione tra threads e per gestire l'uso condiviso delle risorse. Questi sono:
mutex, semafori, flags, spinlock, variabili di stato e mailbox.
Mutex o oggetti a mutua esclusione permettono ai threads di condividere le risorse in
modo seriale. Ogni thread a turno blocca la risorsa, la usa, e poi la sblocca per
permetterne l uso al thread successivo. I semafori usano un contatore associato ad ogni
risorsa per tenere traccia della sua disponibilità. Se la risorsa non è in uso, il primo
thread che ne richiederà l utilizzo, avrà il permesso di usarla. Se invece molti thread
stanno aspettando di poter usare la stessa risorsa, verrà dato per primo l accesso al
thread con priorità più alta. I flags sono parole a 32 bit, dove ogni bit della parola può
rappresentare un requisito della risorsa. I thread possono essere eseguiti quando un
singolo requisito è soddisfatto o quando una specifica combinazione di requisiti sono
rappresentati dal flag. ECos supporta SMP con spinlock. Ogni volta che il thread ha
bisogno della risorsa, controlla il suo flag di stato: se la risorsa è in uso il thread
continua ciclicamente a testare il flag finché non trova la risorsa libera. Le variabili di
stato permettono a un thread che sta usando la risorsa, di segnalare ad altri thread
quando la risorsa diventa disponibile. Queste variabili possono essere usate quando il
thread in esecuzione ha processato i dati e vuole segnalare ad un secondo thread che i
dati sono pronti per essere letti. Le mailbox servono infine per passare messaggi tra
threads.
43
4 Esempio di applicazione usando eCos
4.1 Processo di build di eCos
L'obiettivo del processo di build di eCos è la generazione di una libreria di eCos
chiamata libtarget.a. Vengono poi generati anche altri file per il nostro dispositivo,
come lo script linker e in alcuni casi anche altre librerie.
A questo punto è necessario introdurre RedBoot: una applicazione open source che usa
l'HAL di eCos per fornire l'inizializzazione, il caricamento e volendo il debug della
nostra applicazione (bootstrap). RedBoot supporta il caricamento e l'esecuzione di
applicazioni attraverso l'interfaccia seriale o ethernet.
Il processo di build di RedBoot è leggermente differente da quello di eCos perché si
genera un file binario che viene poi installato sul nostro dispositivo hardware: il
RedBoot monitor viene utilizzato per fare debug sulla nostra applicazione utilizzando
GDB sul nostro sistema di sviluppo.
Il processo di build di eCos utilizza i makefiles e le GNU make utility per la
generazione della libreria libtarget.a e segue tre diramazioni: “sorgenti”, “build” e
“installazione”. La diramazione dei “sorgenti” è il repository del codice sorgente che si
trova sotto la directory packages. La diramazione “build” è generata dagli strumenti di
configurazione e contiene files intermedi come i makefiles e i file oggetto. Solitamente
ogni pacchetto nella configurazione globale di eCos ha la sua sottodirectory che viene
utilizzata per salvare i relativi makefiles e files oggetto, ma questa struttura può variare
tra i vari processi di build.
L'ultima diramazione, quella di “installazione”, si trova nella sottodirectory “lib” per la
libreria principale di eCos e nella sottodirectory “include” per i file headers esportati.
Solitamente le diramazioni “build” e “installazione” si trovano sotto la stessa directory
di lavoro.
4.2 Un'occhiata più da vicino
Vediamo ora da vicino come si genera la libreria di eCos per una piattaforma PC intel
i386.
44
Il processo di build inizia con una configurazione: in base alle necessità, utilizziamo il
tool di configurazione per includere i pacchetti e settare i valori delle opzioni in modo
opportuno. Fatto ciò salviamo la configurazione nel file ecos.ecc. Questo genererà le
sottodiramazioni “build” e “installazione” nella nostra directory di lavoro (figura 4.1).
Figura 4.1: Struttura generata dalla configurazione di RedBoot
Una volta salvata la configurazione, il tool provvederà anche a generare i file necessari
per il processo di build: i makefiles e i files headers.
Concentriamoci per un momento sul pacchetto HAL i386 e come i settaggi delle
opzioni di configurazione vengono usate per generare i file relativi al processo di build.
La figura 4.2 mostra una porzione della finestra del tool di configurazione, assieme ai
file generati in funzione delle opzioni selezionate.
45
Figura 4.2: Diagramma di generazione del tool di configurazione
Nell'angolo in alto a sinistra della figura 4.2, si vede il pacchetto dell'architettura i386
(CYGPKG_HAL_I386). L'opzione che abilita il supporto alla FPU (Float Point Unit) è
abilitata (CYGPKG_HAL_I386_FPU), mentre le altre due opzioni sono disabilitate. La
seguente descrizione corrisponde ai numeri nei cerchietti della figura 4.2 e i puntini di
sospensione (...) nel codice sono stati usati per eliminare alcune parti in modo da
evidenziare specifiche parti dei file sorgenti:
1. Il pacchetto dell'architettura i386 è rappresentato con il suo script CDL
hal_i386.cdl che fa parte dei sorgenti: una volta caricato lo script, il tool di
configurazione genererà i files necessari per il processo di build. Il comando
cdl_package per CYGPKG_HAL_I386 che si vede in linea 1, contiene i file
necessari alla compilazione della linea 3: questa verrà poi usata dal tool di
configurazione a tempo di build per determinare quali files devono essere
compilati per includere le caratteristiche del pacchetto di architettura i386. Dalla
linea 5 alla 9 ci sono le proprietà del “make”, usate dal tool per generare il giusto
makefile usato per compilare il pacchetto.
2. Qui si vede una porzione del makefile generato dopo aver salvato la nostra
configurazione. Questo makefile si trova sotto ecos_build/hal/i386/arch/current.
46
Nella figura 4.2 si osserva la traduzione dallo script CDL relativo alle proprietà
del make, alla generazione del makefile (dalla linea 2 alla linea 4).
3. In funzione dell'abilitazione al supporto FPU dell'architettura i386, quando
salviamo il file ecos.ecc, lo script CDL viene generato come si vede dalla linea 2
alla linea 6.
4. Infine il tool di configurazione genera il file header hal_i386.h che include le
opzioni di configurazione CYGPKG_HAL_I386_FPU. Questo file si trova
nella directory ecos_install/include/pkgconf. Siccome l'opzione è abilitata, nella
linea 2 vediamo che CYGPKG_HAL_I386_FPU è posta a 1.
Una volta generati i due files, il processo di build può continuare: il tool di
configurazione infatti determina quali files devono essere compilati dallo script CDL,
come mostrato in figura 4.2 nel file hal_i386.cdl.
Flag globali di compilazione (CYGBLD_GLOBAL_FLAGS) vengono utilizzati durante
lo stadio di compilazione del processo di build, ma alcuni pacchetti hanno le proprie
opzioni di compilazione: queste opzioni si possono settare come tutte le altre opzioni di
configurazione.
Durante il processo di build, i file oggetto vengono messi nella directory di “build”, poi
il tool di configurazione, attraverso un processo di link, collegherà i file assieme. Flag
globali di linker (CYGBLD_GLOBAL_LDFLAGS) possono essere settati allo stesso
modo dei flag di compilazione.
Entrambe queste tipologie di flag possono essere visualizzate attraverso una sottoschermata del tool di configurazione (come si vede in figura 4.3) selezionando Build ->
Option e poi scorrendo il menu a tendina. Il pannello a sinistra mostra i pacchetti usati
nella configurazione, mentre quello a destra mostra i flag specifici del pacchetto.
Selezionando l'intera configurazione come nell'immagine, vengono mostrati tutti i flag.
Come passo finale nel processo di build, il tool di configurazione invoca le utility di
archivio per creare la libreria che verrà poi messa nella directory ecos_install/lib. Nel
caso di build di RedBoot, il prodotto finale sarà un file binario che verrà posizionato
nella directory ecos_install/bin.
47
Figura 4.3: Opzioni nel processo di build del tool di
configurazione
4.3 Setup dell'hardware di sviluppo
Per l'esempio che andremo ad analizzare verranno utilizzati (figura 4.4):
•
Sistema di sviluppo host: contiene l'intero ambiente di sviluppo eCos e il
debugger GDB.
•
Sistema target PC i386: computer basato su tecnologia Pentium usato per
lanciare RedBoot e la nostra applicazione. È munito di floppy drive.
Entrambi i PC sono muniti di scheda ethernet e porta seriale. Possono comunicare tra di
loro con entrambi i metodi: per poter comunicare con la porta seriale, è necessario un
cavo seriale di tipo null-modem, mentre per la comunicazione via ethernet è necessario
un hub di rete. Per il sistema target è necessario che il controller ethernet sia l'INTEL
82559 poiché è quello supportato dai driver di eCos. In questo esempio inoltre, per
semplicità, gli indirizzi IP sono configurati in modo statico: il sistema host ha indirizzo
192.168.0.2 mentre il sistema target avrà indirizzo 192.168.0.10. Entrambi hanno subnet
mask 255.255.255.0. É bene ricordare che per sistemi destinati al rilascio commerciale,
non è consigliato utilizzare gli indirizzi IP statici, quanto piuttosto utilizzare un sistema
di indirizzamento IP dinamico come DHCP o BOOTP.
48
Figura 4.4: Ambiente di sviluppo dell'esempio
4.4 Tool di configurazione di eCos
Nel nostro esempio andremo ad utilizzare il tool grafico di configurazione “configtool”,
il quale si trova sotto ecos-2.0/tools/bin. La directory di lavoro in cui andremo a salvare
le configurazioni e i file immagine invece è sotto ecos-2.0/test. I sorgenti dei programmi
di esempio che compileremo si trovano infine sotto ecos-2.0/examples.
4.5 Redboot
Come primo passo dobbiamo fare il build, caricare su floppy e fare il boot di Redboot
sul nostro target. Nel nostro esempio andremo a generare una immagine che verrà poi
messa su floppy e che verrà eseguita sul nostro PC target.
Vediamo ora i passi che si devono compiere per il nostro scopo:
1. Dopo aver lanciato il tool di configurazione, selezioniamo Build -> Templates.
Nella finestra di dialogo che appare impostiamo poi come hardware “i386 PC
Target”, “redboot” come package e diamo conferma con “ok”. Nel caso ci
fossero dei conflitti causati dalle impostazioni, il tool di configurazione ci viene
in aiuto proponendo una finestra con le soluzioni possibili. Clicchiamo ora su
“Continue” e lasciamo che il tool carichi i pacchetti e le relative configurazioni
per il nostro target PC i386.
49
2. Ora vogliamo impostare i valori delle opzioni di configurazione di RedBoot. Ciò
è possibile selezionando manualmente le opzioni, oppure importando un file preconfigurato (.ecm) che imposta automaticamente i valori. Per importare una
configurazione minimale clicchiamo su File->Import e selezioniamo il file
redboot_FLOPPY.ecm
che
si
trova
nella
sottodirectory
ecos-
2.0/packages/hal/i386/pc/v2_0/misc. Premiamo il tasto “Open”, risolviamo i
conflitti nel caso ce ne siano e clicchiamo su “Continue”.
3. Andiamo adesso a configurare le opzioni di rete della nostra build, impostando il
valore
192,168,0,10
in
Default
IP
Address
(CYGDAT_REDBOOT_DEFAULT_IP_ADDR) che si trova sotto RedBoot
ROM Monitor
(CYGPKG_REDBOOT) nel pacchetto RedBoot Networking
(CYGPKG_REDBOOT_NETWORKING). Mettiamo inoltre la spunta su Do
Not Try To Use BOOTP (CYGSEM_REDBOOT_DEFAULT_NO_BOOTP). È
importante notare che di default eCos utilizza come canale di comunicazione la
prima porta COM da cui riceve input. Nel nostro esempio inoltre è abilitata
l'opzione Output to PC Screen (CYGSEM_HAL_I386_ PC_DIAG_SCREEN)
che ci permetterà di utilizzare come canali di comunicazione con il nostro target,
il monitor e la tastiera.
4. Salviamo ora la nostra configurazione con File->Save As. Dobbiamo poi
impostare un nome per il nostro file (.ecc); nel nostro caso usiamo “redboot” e lo
salviamo sotto la directory ecos-2.0/test. Il tool di configurazione andrà ora a
generare le directory di cui abbiamo parlato nei paragrafi precedenti,
aggiungendo i suffissi _build e _install al nome del file della configurazione
salvata (figura 4.1). La sottodirectory redboot_build viene usata per
memorizzare i file necessari durante il processo di build, la sottodirectory
redboot_install contiene l'immagine binaria e i file header del processo di build e
redboot_mlt contiene i file di layout della memoria usati dal tool di
configurazione.
5. A questo punto possiamo creare l'immagine di RedBoot. Se nell'angolo in basso
a destra del tool vediamo la dicitura “No Conflict” possiamo procedere con il
build vero e proprio; in caso contrario con la combinazione di tasti “ALT+F5”
possiamo vedere i conflitti che vi sono. Per lanciare il processo di build
clicchiamo su Build->Library: durante il processo vedremo una serie di
messaggi che mostrano lo stato di compilazione. Quando la compilazione è
50
terminata la finestra mostrerà “build finished”. In caso di errori durante la
compilazione questi saranno visualizzati nella finestra di stato e fintanto che non
vengono corretti il processo non può continuare. Il file che viene creato a
processo completo è redboot.ini che si trova nella sottodirectory redboot_install/
bin/.
4.5.1 Installazione di RedBoot
A questo punto è necessario creare il floppy di boot con l'immagine appena creata.
Con l'utility dd copiamo l'immagine dal nostro sistema al floppy con il comando dd
conv=sync
if=redboot.bin
of=/dev/fd0,
dopo
esserci
spostati
nella
directory
redboot_install/bin/.
4.5.2 Boot di RedBoot
Possiamo ora inserire il nostro floppy nel PC i386 target impostando come dispositivo
di boot il floppy drive. Sul monitor del target si vedrà una cosa del tipo (figura 4.5):
1
2
3
4
5
6
7
8
Ethernet eth0: MAC address 00:d0:bd:43:9d:d2
IP: 192.168.0.10, Default server: 0.0.0.0, DNS server IP: 0.0.0.0
RedBoot(tm) bootstrap and debug environment [FLOPPY]
Non-certified release, version UNKNOWN - built 12:22:06, Jan 20 2009
Platform: PC (I386)
Copyright (C) 2000, 2001, 2002, Red Hat, Inc.
RAM: 0x00000000-0x000a0000, 0x0008ac30-0x000a0000 available
RedBoot>
Figura 4.5: Messaggi di inizializzazione di RedBoot
Vengono mostrati: la configurazione di rete ethernet, la versione dell'immagine, la data
di creazione, il tipo di piattaforma, la memoria utilizzata, quella disponibile e il prompt
di RedBoot che indica che è pronto a ricevere un input.
Successivamente ci possiamo collegare al PC target con HyperTerminal usando le
seguenti impostazioni: baud rate di 38400, 8 bit di dati, 1 bit di stop e controllo del
51
flusso disabilitato (flow control). Oppure è possibile collegarsi con il programma telnet
usando come host di destinazione l'IP 192.168.0.10 e come porta la 9000, come
impostato
in
TCP
Port
To
Listen
For
Incoming
Connections
(CYGNUM_REDBOOT_NETWORKING_TCP_PORT). Una volta connessi al PC
target, sul computer host verrà visualizzato il prompt di RedBoot che ci permetterà in un
secondo tempo di lanciare le nostre applicazioni.
4.6 Processo di build di eCos
Continuando il nostro esempio, dobbiamo ora configurare e compilare una immagine di
eCos che sarà poi linkata con la nostra applicazione. L'immagine che andremo a creare
utilizza la configurazione di inizializzazione RAM, il che permetterà di caricare la
nostra applicazione in questa memoria. Potremo poi lanciare tale applicazione ed
eventualmente fare debug di essa.
Lo scopo principale di questo punto è quello di generare le libreria eCos secondo quanto
impostato nella configurazione.
In modo analogo a quanto fatto per la generazione dell'immagine di RedBoot, apriamo
il tool di configurazione e scegliamo Build->Template. In template metteremo “i386 PC
Target” e in package useremo “default”. Diamo poi “ok”, risolviamo gli eventuali
conflitti e premiamo su “Continue” per procedere al passaggio successivo.
Ora che abbiamo una configurazione di base, possiamo adattarla alle nostre esigenze:
verifichiamo che Startup Type (CYG_HAL_STARTUP) sia impostato su “RAM”.
Questa opzione si trova sotto il pacchetto HAL di eCos, sotto il pacchetto i386
Architecture (CYGPKG_HAL_I386), sotto il pacchetto della piattaforma i386 PC
Target (CYGPKG_HAL_I386_PC). Inoltre visto che utilizziamo il RedBoot monitor,
abilitiamo il supporto ad esso con l'opzione Work With a ROM Monitor
(CYGSEM_HAL_USE_ROM_MONITOR).
A questo punto possiamo salvare la nostra configurazione nella sottodirectory ecos2.0/test con File->SaveAs utilizzando il nome ecos.ecc. Il tool di configurazione, come
per RedBoot andrà a creare le directory ecos_build, ecos_install e ecos_mlt.
Siamo ora pronti per generare la libreria eCos: risolviamo gli eventuali conflitti,
verificando la dicitura in basso a destra della finestra, poi selezioniamo Build->Library
e attendiamo la compilazione, che si conclude con “build finished”. É stata ora generata
52
la libreria libtarget.a che si trova sotto ecos_install/lib. Come per il caso di RedBoot se
si presentano degli errori di compilazione, è necessario risolverli per poter proseguire.
4.7 Applicazioni
A questo punto possiamo effettuare il processo di build delle nostre applicazioni
incorporando la libreria eCos appena creata.
Figura 4.6: Diagramma di flusso della procedura di
creazione dell'applicazione di eCos.
Le applicazioni che andremo a generare sono quelle che si trovano sotto la directory
ecos-2.0/examples. Senza entrare nel dettaglio, utilizzeremo il Makefile già presente
nella directrory degli esempi. Il Makefile è quel file che descrive le modalità di
compilazione della nostra applicazione, tra cui i flag globali di linker e di compilazione.
Spostiamoci quindi nella directory degli esempi e diamo il comando make
INSTALL_DIR=/ecos-2.0/test/ecos_install. In questo modo il Makefile potrà reperire le
informazioni di compilazione specifiche dell'applicazione che stiamo andando a creare,
poiché le legge dai file della directory precedentemente generata dal tool di
configurazione. Con questo comando si andrà anche a generare i files eseguibili delle
53
applicazioni che potranno poi essere inviate a RedBoot e poi eseguite. Prima di fare ciò,
però è necessario convertire i file eseguibili nel formato S-record, con il comando: i386elf-objcopy -O srec hello hello.srec (hello è uno degli applicativi di esempio che sono
stati generati). Si può notare in figura il diagramma di flusso della procedura appena
descritta (figura 4.6).
Il file .srec potrà poi essere trasferito al PC target mediante uno dei metodi
supportati dal RedBoot precedentemente installato, ovvero streaming su seriale
RS232 oppure TFTP (Trivial File Transfer Protocol) su ethernet.
Una volta caricato il file .srec con il metodo che si ritiene più comodo, siamo pronti per
lanciare il nostro applicativo di esempio “hello” dando il comando “go” al prompt di
RedBoot. Sul monitor del PC Target si dovrebbe visualizzare il testo “Hello eCos
World!!!” che era ciò che ci si aspettava.
Per una spiegazione più dettagliata del processo di build di applicazioni con eCos si può
fare riferimento alla documentazione online all'url http://ecos.sourceware.org/docslatest/user-guide/ecos-user-guide.html.
54
Considerazioni finali e Conclusioni
Una delle attività principali comprese nel processo di progettazione di un sistema
realtime è quella della selezione del sistema operativo. Tale scelta viene eseguita
valutando da un lato i sistemi operativi sviluppati da terze parti e dall'altro la
possibilità di sviluppare un sistema operativo in proprio.
Contrariamente a quanto avviene infatti per i sistemi "general purpose", per i
quali siamo abituati ad avere un CD/DVD di installazione pronto all'uso, difficilmente
il
progettista
potrà
contare
su
un
sistema
operativo
adattato
al
proprio
specifico "target", magari per il semplice fatto che l'hardware è stato progettato
ex-novo.
I sistemi sviluppati da "terze parti", fra cui troviamo eCos, normalmente rendono
disponibile all'utente finale:
•
o i sorgenti completi del sistema operativo, magari previa sottoscrizione di
un opportuno accordo di non divulgazione per quelli "non open source";
•
oppure forniscono il sistema operativo in due parti, una libreria binaria
contenente le primitive del kernel ed una parte in forma sorgente modificabile
dall'utente, che costituisce il "board/platform support package" (BSP/PSP).
Una delle caratteristiche più evidenti che contraddistingue tutti i package
open source, fra cui eCos, è senz'altro quella dell'assenza di costi diretti
per l'acquisto di licenza d'uso.
In realtà il progettista deve valutare il sistema operativo nel suo complesso,
tenendo anche conto di:
•
caratteristiche tecniche (prestazioni, benchmark, algoritmi usati, ecc..)
costo per l'adattamento al proprio target (spesso i S.O. commerciali
comprendono nel costo di licenza la fornitura di uno o più BSP/PSP)
disponibilità del codice sorgente per eventuali certificazioni (safety critical, ad
esempio);
•
disponibilità di strumenti di analisi e debug (per eCos, RedBoot con stub GDB).
Gli RTOS commerciali possono essere rilasciati in licenza per singolo progetto o per
una famiglia di progetti e tali licenze possono valere per l'intero ciclo di vita dell'OS
oppure deve essere rinnovato ogni anno: questo può comportare investimenti e quindi
costi non indifferenti nello sviluppo.
Riassumendo possiamo dire che, oltre ad avere un Real Time Kernel, gli aspetti che si
55
devono tenere conto per sviluppare applicazioni su un determinato RTOS sono:
•
qualità della documentazione
•
flessibilità di utilizzo su diverse piattaforme
•
qualità degli strumenti di sviluppo
•
qualità del supporto tecnico
•
costi di licenza
OS realtime?
si
no
si
Uso del kernel opzionale?
no no
no
Il kernel è configurabile e scalabile?
si
si
si
I componenti dell'OS possono
no
si
no
essere modificati?
È presente uno scheduler?
si
si
si
Supporta i thread?
si
si
si
Supporta
l'allocazione
della
si
si
si
memoria?
È fornito il codice sorgente?
no
si
no
Gli strumenti di sviluppo sono free?
no
si
no
Gli strumenti di sviluppo girano su
si
si
si
Solaris?
Gli strumenti di sviluppo girano su
si
si
si
Windows?
Gli strumenti di sviluppo girano su
no
si
si
Linux?
L'esecuzione è royalty-free?
no
si
no
Permette
l'accesso
diretto
si
no
no
all'hardware?
Tabella 5: Comparazione tra sistemi operativi per dispositivi
embedded
eCos
Linux RT
Linux
Caratteristica
VxWorks
Facciamo ora un confronto sintetico tra alcune tra le più popolari soluzioni per
dispositivi embedded (tabella 5):
si
si
si
si
si
si
si
si
si
si
si
si
si
si
56
Come si nota anche dalla tabella, eCos offre alcuni chiari vantaggi agli sviluppatori di
applicazioni embedded. È un sistema open source
con una alta flessibilità di
configurazione che permette quindi di creare una applicazione su misura atta a
soddisfare i requisiti dell'applicazione con le risorse hardware disponibili. Non sono
presenti licenze di utilizzo e gli strumenti free lo rendono molto attraente a sviluppatori
con budget ridotto. Eccellenti performance realtime, basse latenze e comportamento
deterministico rendono eCos un'interessante soluzione per i propri applicativi.
Alcuni possibili svantaggi nell'uso di eCos devono però essere valutati attentamente
prima di decidere il suo utilizzo in una applicazione embedded.
La toolchain (l'insieme degli applicativi usati per lo sviluppo) utilizzata in modo
preferenziale nel build di eCos è quella derivata dal progetto GNU della Free Software
Foundation.
Gcc, Gdb, Insight e le Binutils sono senza ombra di dubbio gli strumenti preferiti
dagli sviluppatori embedded, principalmente per la qualità e l'affidabilità del codice
prodotto
e
per
l'intrinseca portabilità verso
svariate piattaforme
hardware.
Esistono di questi strumenti anche versioni rilasciate con licenze commerciali, magari
abbinate a front end grafici integrati.
Si tratta comunque di strumenti "difficili" da usare, almeno per chi non è abituato
all'uso delle command line di Unix. La configurazione si ottiene attraverso
innumerevoli opzioni di invocazione, che devono essere redatte dall'utente in opportuni
Makefile.
Gli strumenti di sviluppo commerciali (alcuni dei quali, fra l'altro, utilizzano
proprio gcc come compilatore interno, ad esempio la suite Rowley per ARM)
dispongono normalmente di un IDE nel quale la selezione delle opzioni di compilazione
avviene in modo "user friendly". Come sviluppatori di eCos, bisogna inoltre prendersi
carico della responsabilità della ricerca delle risorse per il proprio progetto all'interno
della comunità degli sviluppatori e che eventualmente alcuni componenti che non
esistono, vanno creati con le proprie capacità.
Molti RTOS commerciali offrono supporto tecnico aggiuntivo, alcuni anche con
garanzie sulle tempistiche di risposta per la risoluzione dei problemi.
Lo sviluppatore di eCos può però decidere se lavorare con un consulente specializzato
in eCos o utilizzare come supporto solo la comunità: come è stato detto si possono
infatti utilizzare le mailing list presenti sul sito. Questo tipo di supporto potrebbe però
essere un rischio non accettabile per applicativi a breve ciclo di sviluppo.
57
Ponderati i lati positivi e negativi dell'uso di eCos, pare evidente che questo sistema
possa essere una valida soluzione per molti applicativi embedded: eCos sta infatti
guadagnando nel tempo fette di mercato. A supporto di questo si può vedere
all'indirizzo internet http://www.ecoscentric.com/ecos/examples.shtml un lungo elenco
di dispositivi commerciali che ne fanno uso: dal controller di rete WIFI della playstation
3, ai televisori top di gamma Samsung, ad alcuni router Netgear, ai dispositivi di
accesso biometrico nella concept car Volvo, ad alcune stampanti Brother, a dispositivi
di posizionamento aerospaziale dell'ESA (European Space Agency) etc.
Sicuramente ha centrato l'obiettivo degli sviluppatori che l'hanno creato, di produrre un
sistema operativo leggero, altamente configurabile, realtime, con buone prestazioni ed
esente da licenze: quindi concludendo vale sicuramente la pena di considerarlo nello
sviluppo di applicazioni embedded.
58
Riferimenti Bibliografici
[Arpinen]
Tero Arpinen “Introduction to eCos Real-Time Operating System”,
Tempere University Of Technology.
[IEEE]
IEEE Computer Society “Standardized Application Enviroment Profile
(AEP) – POSIX Realtime and Embedded Application Support”.
[Kalinsky]
David Kalinsky “Basic concept of real-time operating system”,
Linuxdevices website
[Newsgroup] Comp.realtime “Frequently Asked Questions”, Newsgroup online
[Massa]
Anthony J. Massa “ Embedded software development with eCos”,
Prentice Hall.
[Melchiorri] Claudio Melchiorri “Introduzione a RTAI-LINUX” , DEIS – Università
di Bologna.
[OsDevWiki] url: http://wiki.osdev.org per l'argomento “Context Switcing”.
[Salenby]
Gusatv Salenby, Daniel Lundgren “Comparison if scheduling in
FreeRTOS and eCos”.
[Sgandurra]
Robert Sgandurra “An Introduction to eCos”, Pentek, Inc.
[Thomas]
Michael Thomas “Real Time Operating System”, Renesas Technology
America, Inc.
[UdsCagliari] Università degli studi di Cagliari “Real-timing in ambito Linux: teoria e
applicazioni reali.
[Valenti]
Alessandro Valenti “I sistemi embedded: considerazioni sulla
progettazione dei sistemi dedicati con e senza sistema operativo”,
Università degli studi di Modena e Reggio Emilia.
[Wikipedia]
url: http://wikipedia.org/ per gli argomenti: Preemption, Context switch,
Thread, Context, Sistemi Operativi Realtime, Real- time computing,
eCos, Embedded system, Cygnus Solutions, RedBoot.
59