2
I processori embedded sono presenti nella maggior parte degli oggetti che vengono
utilizzati quotidianamente, anche in quelli in cui mai ci si aspetterebbe di trovare un
microprocessore. Attraverso i microprocessori infatti si possono implementare algoritmi
sofisticati in grado di automatizzare e rendere molto più efficace la risoluzione di un
determinato problema, oltre che di poter aggiungere un’interfaccia utente in grado di
facilitare l’interazione tra il sistema e l’utente finale.
Un esempio diffuso di sistema embedded sono le centraline elettroniche installate a
bordo degli autoveicoli per il controllo del motore e dell'ABS. Altri esempi di sistemi
embedded molto diffusi sono apparecchi POS, telefoni cellulari, centralini telefonici,
apparati di reti informatiche come router o firewall, altri apparecchi elettronici come
stampanti, fotocamere digitali, palmari, fotocopiatrici, console e videogiochi, hard disk,
sistemi di automazione casalinghi come termostati, elettrodomestici come forni a
microonde, lavatrici o TV, apparecchi medici come ecografi o risonanza magnetica, ecc.
Ovviamente i sistemi embedded sono molto utilizzati anche in altri ambiti meno
commerciali e più specifici come quello industriale (PLC per l’automazione
industriale), quello aeronautico (sistemi di simulazione di volo o sistemi integrati di
guida di missili), oltre che in controlli di processi fisici, chimici, termodinamici, ecc.
Lo scopo della trattazione sarà quindi di fornire una panoramica sui sistemi embedded,
partendo da una breve introduzione sulla storia e la diffusione di questi sistemi per
arrivare alla descrizione del loro processo di progettazione. Il primo passo consiste
nell’analisi dell’architettura hardware di un sistema embedded ed in particolare dei
processori più diffusi che lo equipaggiano: ARM e SHARC. Successivamente verranno
analizzati anche gli altri componenti di un sistema come le memorie e i dispositivi di
I/O; anche in questo caso partendo con una descrizione generica della loro architettura
per arrivare all’implementazione nei sistemi embedded. Il passo successivo consiste
nello studio del processo di sviluppo del software: dalla scrittura del codice in
linguaggio ad alto livello alla traduzione in linguaggio macchina, ponendo particolare
attenzione alle tecniche di ottimizzazione che consentono di ottimizzare il software per
l’esecuzione sui sistemi embedded. In conclusione verranno trattati gli acceleratori
hardware come strumento per incrementare le prestazioni di un sistema, mantenendo
relativamente contenuti i costi.
3
1
I SISTEMI EMBEDDED
1.1 Storia
Il primo sistema embedded moderno fu l'Apollo Guidance Computer, sviluppato da
Charles Stark Draper presso l’Instrumentation Laboratory del MIT a Boston. Su ogni
volo sulla luna ne venivano imbarcati due su cui venivano eseguiti i programmi per i
sistemi di guida inerziale del modulo di comando e del modulo LEM.
Al momento della concezione, l'Apollo Guidance Computer era considerato uno dei più
rischiosi oggetti all'interno del progetto Apollo. L'utilizzo di nuovi circuiti integrati per
ridurne le dimensioni e il peso, aumentò considerevolmente il fattore di rischio.
Il primo sistema embedded prodotto in massa fu il sistema di guida computerizzato
Autonetics D-17 che si occupava della guida del missile Minuteman (1961). Questo
sistema utilizzava circuiti logici realizzati con transistor e un hard disk come memoria.
Quando nel 1966 venne prodotto il Minuteman II, il D-17 fu rimpiazzato da un nuovo
computer che utilizzava dei circuiti integrati.
La principale caratteristica di questo sistema era la possibilità di modificare
successivamente l'algoritmo di guida per rendere il missile più preciso. Il computer
inoltre eseguiva la diagnostica del missile consentendo un risparmio sul peso di cavi e
connettori.
4
In seguito, proprio grazie all’utilizzo dei circuiti integrati, i sistemi embedded hanno
subito una notevole diffusione grazie alla riduzione dei costi e alla crescita delle
capacità di calcolo e delle funzionalità.
Il primo microprocessore a singolo chip progettato per essere messo in commercio è
stato l'Intel 4004, che venne montato su calcolatrici ed altri sistemi embedded di piccole
dimensioni. Esso richiedeva chip di memoria esterni ed ulteriore logica di supporto.
Verso la fine degli anni settanta, i microprocessori a 8 bit erano ormai molto diffusi, ma
necessitavano sempre di memoria esterna e logica di decodifica. In ogni caso, i prezzi
erano in caduta libera e sempre più applicazioni cominciarono ad adottare questo
approccio, piuttosto che metodologie di progetto di circuiti con logica personalizzata.
Nel settore delle automobili ad esempio, l’utilizzo dei microprocessori prese il via
subito dopo l’uscita delle CPU a singolo chip. Il motivo scatenante fu una decisa
impennata del costo della benzina nei primi anni settanta. I progettisti e gli ingegneri
capirono che la possibilità di ottenere un motore con consumi inferiori si aveva solo
attraverso l’utilizzo di complessi algoritmi di controllo, implementabili quindi solo
attraverso i microprocessori. Si instaurò allora un trend, che continua tuttora, per cui i
sistemi elettronici iniziarono a sostituire diverse parti meccaniche in quanto
assicuravano notevoli vantaggi rispetto ad esse.
Verso la metà degli anni ottanta, un maggiore grado di integrazione e in particolar modo
la diffusione della tecnologia VLSI (Very Large Scale Integration), permise il
montaggio di altre componenti, in precedenza collegate esternamente, sullo stesso chip
del processore. Questi sistemi integrati vennero chiamati microcontrollori ed ebbero
subito una rapida diffusione. Con un così basso costo per componente infatti,
risultavano molto più efficienti ed economici rispetto ai circuiti logici dedicati.
Dalla fine degli anni ottanta, i sistemi embedded rappresentano la regola piuttosto che
l'eccezione per gran parte dei dispositivi elettronici, tendenza che continua ancora oggi.
1.2 Caratteristiche
Come detto un sistema embedded può implementare algoritmi molto sofisticati, la cui
complessità dipende dalle funzionalità richieste e dalle operazioni che verranno eseguite
dal microprocessore.
5
Nell’implementare le funzionalità richieste un sistema deve anche rispettare alcuni
vincoli importanti, come ad esempio operare in tempo reale o contenere il più possibile i
consumi. Può accadere anche che un sistema debba essere molto veloce nell'esecuzione
di alcune funzioni, ma possa tollerare velocità inferiori per altre attività (multirate).
Molti sistemi embedded poi devono implementare un’interfaccia utente che includa
diversi menu e una notevole quantità di opzioni (ad esempio uno sportello bancomat).
I sistemi embedded devono perciò fornire funzionalità molto sofisticate rispettando però
alcuni vincoli fondamentali (performance, consumi, dimensioni, ecc.).
Fortunatamente, la maggior parte dei sistemi embedded necessita di performance che
possono essere soddisfatte con una combinazione di hardware dedicato ed una quantità
limitata di software ad alte prestazioni. Per avere un'idea, basti pensare ad un decoder
per una televisione satellitare. Nonostante un sistema come questo debba elaborare
megabit di dati al secondo, la maggior parte del lavoro è svolta da hardware dedicato
che separa, regola e decodifica il flusso digitale multicanale in un'uscita video. Alla
CPU embedded spetta determinare i percorsi dei dati nel sistema, gestire gli interrupt,
generare e disegnare la grafica, e così via. Spesso quindi, la maggior parte dell'hardware
di un sistema embedded deve sottostare a dei requisiti di prestazioni molto meno severi
di quelli che, invece, deve rispettare l'hardware primario del sistema. Questo permette
all'architettura di un sistema embedded di essere intenzionalmente semplificata rispetto
a quella di un computer generico che deve eseguire le stesse operazioni, usando ad
esempio una CPU più economica, ma dedicata.
Nel caso di sistemi che devono essere commercializzati su larga scala, ridurre i costi
diventa una priorità. Sistemi di questo genere sono dotati di una CPU altamente
integrata, un chip dedicato a tutte le altre funzioni ed un singolo banco di memoria.
Ogni componente viene selezionato e progettato per ridurre il più possibile i costi.
Per progettare sistemi embedded che non devono gestire una grossa mole di dati,
possono essere utilizzati anche i personal computer, riducendo il numero di programmi
installati, ed utilizzando un sistema operativo specifico.
I sistemi embedded spesso non hanno sistema operativo, oppure ne hanno uno
embedded specializzato, solitamente un RTOS (Real-Time Operating System).
Alcuni sistemi embedded devono poter restare attivi continuativamente per anni senza
errori, devono pertanto essere progettati e collaudati con molta attenzione.
6
Inoltre, alcuni sistemi potrebbero non essere fisicamente accessibili (come le trivelle dei
pozzi di petrolio, oppure i componenti lanciati nello spazio) e spesso in applicazioni
real-time non è possibile arrestare il sistema per effettuare dei controlli; il sistema deve
quindi essere capace di eseguire una auto-verifica interna e resettarsi autonomamente in
caso di perdita o corruzione dei dati. Questa funzionalità è molto spesso ottenuta con
l'inserimento di un componente elettronico chiamato watchdog, che riavvia il computer
a intervalli regolari; il software, periodicamente, provvede a resettare il timer interno del
componente.
Ci sono diversi tipi principali di verifiche, divise in base alla funzione o componente
controllata:
• Verifica Calcolatore (CPU e memoria): si effettua una volta all'accensione. Nei
sistemi critici si effettua anche periodicamente o continuativamente.
• Verifica Periferiche: simula gli ingressi e misura gli output corrispondenti.
• Verifica Alimentazione: controlla il tipo di ingresso (batterie o rete) e ne
verifica l’effettiva capacità di alimentazione.
• Verifica Comunicazione: verifica la ricezione di semplici messaggi da parte
delle unità connesse.
• Verifica Cablaggi: verifica lo stato dei vari collegamenti.
• Verifica Attrezzaggio: permette di regolare un sistema quando viene installato.
• Verifica Consumi: misura le risorse utilizzate dal sistema e avvisa quando sono
insufficienti.
• Verifica Operativa: viene effettuata lavorando effettivamente sul sistema
mentre è in funzione.
• Verifica di Sicurezza: eseguita periodicamente secondo un intervallo di
sicurezza, assicura che il sistema sia ancora affidabile.
1.3 Progetto
I componenti usati più frequentemente sono i microprocessori o i microcontrollori.
Perché proprio i microprocessori? Esistono infatti molti altri metodi per creare sistemi
digitali come ad esempio l’utilizzo di logica personalizzata, o di FPGA (Field-
Programmable Gate Arrays).
7
La scelta ricade sui microprocessori innanzitutto perché permettono di sviluppare
facilmente famiglie di prodotti in grado di offrire caratteristiche diversificate e, in
secondo luogo, perché garantiscono la possibilità di estendere facilmente il sistema per
soddisfare nuove richieste. Inoltre, sebbene potrebbe non sembrare così, attraverso un
processore con un set istruzioni preimpostato l’implementazione di un’applicazione
risulta più veloce piuttosto che con gli altri metodi. Si potrebbe pensare infatti che le
fasi di fetching, di decoding e di esecuzione delle istruzioni comportino un notevole
dispendio di risorse ma vi sono due fattori che rendono la progettazione attraverso
microprocessori maggiormente efficiente. Il primo consiste nel fatto che spesso questo
dispendio viene nascosto con un intelligente utilizzo del parallelismo dentro la CPU. Il
secondo è che le grandi case produttrici investono molto nello sviluppo per
incrementare le prestazioni dei microprocessori e lo sviluppo di nuovi esemplari sempre
più potenti. Così anche se la logica risparmia il dispendio di risorse e tempo dovuto a
fetch ed esecuzione delle istruzioni, di fatto, spesso dà luogo a sistemi più lenti.
Inoltre un microprocessore può essere utilizzato da diversi algoritmi solo cambiando il
programma che questo esegue, mentre per implementare diversi algoritmi attraverso la
logica bisognerebbe creare diversi blocchi personalizzati.
1.3.1 Processo di Progettazione
Come detto in precedenza il progetto di un sistema embedded deve assicurare un giusto
compromesso tra l’implementazione delle funzionalità richieste e il rispetto di alcuni
vincoli, in modo da far risultare il sistema il più efficiente possibile.
Il processo di progettazione si può definire attraverso alcuni passi fondamentali:
1. Definizione dei requisiti: sono una descrizione informale di ciò che il committente
vuole e possono essere funzionali o non funzionali.
• Requisiti funzionali: descrivono le funzionalità del sistema, cioè i servizi che
deve fornire, come dovrebbe reagire a particolari input e il comportamento in
particolari situazioni; sono esplicitabili attraverso funzioni matematiche.
• Requisiti non funzionali: vincoli sui servizi o sulle funzioni offerte dal
sistema, solitamente si applicano al sistema completo e sono più critici da
definire e da implementare di quelli funzionali.
8
Esempi tipici di requisiti non funzionali sono performance, costi, dimensioni
e consumi di un sistema.
Il primo step si conclude con la convalida dei requisiti. Una buon modo per raffinare
il sistema, o almeno l’interfaccia utente, è la costruzione di un mock-up,
un’anteprima di come sarà il prodotto che permette al cliente di avere un’idea sul
soddisfacimento dei requisiti richiesti.
2. Specifiche: definiscono come il sistema si comporta, indipendentemente da come
viene costruito. Devono essere più precise dei requisiti e costituiscono in pratica un
contratto tra cliente e sviluppatore; devono quindi riflettere scrupolosamente ciò che
il committente vuole, non devono perciò presentare nessun tipo di ambiguità. Le
specifiche vengono spesso descritte in linguaggio UML.
3. Architettura: descrive come il sistema deve implementare le specifiche e le
funzionalità richieste; viene descritta attraverso schemi a blocchi che mostrano le
operazioni più importanti e il flusso di dati attraverso le varie parti del sistema,
evidenziando quali operazioni devono essere svolte sequenzialmente e quali invece
possono agire in parallelo.
Solo dopo aver definito un’architettura iniziale si può affinare lo schema a blocchi.
L’architettura deve essere concepita per rispettare sia i requisiti funzionali che quelli
non funzionali, bisogna quindi conoscere come hardware e software impiegano le
risorse, le loro velocità, i loro consumi, ecc.
4. Componenti: la descrizione dell’architettura definisce quali componenti verranno
utilizzati (sia parti hardware che moduli software) nel sistema. Bisogna fare
un’analisi dettagliata dei singoli componenti; alcuni saranno già stati creati, altri
andranno creati al momento.
5. System Integration: una volta che si hanno a disposizione tutti i componenti si
passa alla loro integrazione nel sistema finale, fase che comporta ulteriori
aggiustamenti per far sì che tutto interagisca in modo adeguato. Gli errori infatti
sono quasi tutti scoperti in fase di integrazione. È dunque la fase più critica in
quanto può nascondere parecchi problemi che possono anche comportare il ritorno a
fasi precedenti per la loro risoluzione.
Questi passi costituiscono la modellizzazione top-down del processo di progettazione.