Diamo uno sguardo ad un particolare mondo, quello dei microcontrollori, per capire cosa sono, come si usano e come si programmano, analizzando similitudini e differenze con la programmazione di PC.
In questi ultimi anni la microelettronica Φ penetrata in ogni aspetto della vita moderna: dai telefonini ai forni a microonde, dai termostati ai videoregistratori, dalle radiosveglie alle fotocopiatrici tutti gli apparecchi elettronici con i quali abbiamo a che fare ogni giorno sono in una certa misura "intelligenti". Il loro "cervello" Φ un computer che li controlla ricevendo informazioni da sensori, elaborandole e generando un output che ne gestisca le varie funzionalitα.
PoichΘ questo controllore Φ quindi un sistema a se stante con ingressi ed uscite si dice che Φ un sistema embedded, cioΦ che va "incastrato" nell'oggetto da controllare.
Si possono schematizzare 3 famiglie di sistemi embedded: i normali PC, i sistemi basati su microprocessore o microcontrollore (in pratica dei computer non standard) e quelli basati solo su microcontrollori (di piccole dimensioni).
I normali PC sono usati come sistemi embedded per esempio nelle biglietterie automatiche delle FS e nel controllo di macchine industriali; i ricevitori digitali via satellite (set-top box) e le stampanti sono controllati da dei veri e propri computer; infine termostati, ABS, forni a microonde, radiosveglie hanno al loro interno un microcontrollore.
In realtα non si considerano diverse famiglie e la distinzione non ha altro valore se non quello di mettere in evidenza come il maggior campo d'uso sia riservato ai microcontrollori e come essi non abbiano sostituti nell'uso in oggetti di piccole dimensioni.
Ma che cosa Φ un microcontrollore? Un microcontrollore (o MCU, Micro Controller Unit) Φ una CPU (Central Processing Unit) con integrate nel chip varie periferiche, tipo dispositivi di I/O, timer, memorie, porte di comunicazione, controller LCD o video che, come abbiamo visto prima, si usa spesso in applicazioni di controllo. Generalmente, quindi, sviluppare un progetto con un microcontrollore significa sviluppare un sistema embedded.
Il progetto di un sistema embedded consiste nello sviluppo contemporaneo di hardware e software dal momento che la sua funzionalitα dipende dal risultato dell'integrazione di questi due aspetti, a differenza di quanto accade nel campo della programmazione PC, dove l'integrazione con l'hardware Φ affidata al sistema operativo. E' quindi necessario conoscere l'elettronica, soprattutto se si usa un microcontrollore ma anche nel caso si usi una soluzione basata su PC normali. Spesso i compiti che il sistema deve svolgere richiedono che il programmatore abbia conoscenze di fisica, di matematica, di controlli automatici, di elaborazione numerica, e naturalmente di elettronica.
Comunque lo scopo di questa serie di articoli Φ solo quello di introdurre alla programmzione di microcontrollori, anche se talvolta tratter≥ di sistemi embedded in generale.
Per compiere i primi passi nel campo della programmazione di microcontrollori serve soprattutto un po' di pazienza per familiarizzare con l'hardware ed i sistemi di sviluppo, dopodichΦ diventerα un gioco divertente.
HARDWARE
Esistono microcontrollori a 4, 8,16 e 32 bit con una gamma vastissima di modelli, ma in genere si usano quelli a 8 o a 16, mentre gli altri sono relegati a specifiche nicchie. Alcuni controllori sono piccolissimi e sono venduti in contenitori DIP da 8-40 piedini, altri sono vere e proprie estensioni di microprocessori (per esempio gli IBM 500 sono in pratica PowerPC) con pi∙ di 100 piedini.
A questo punto Φ necessario una piccola nota: d'ora in avanti user≥ la parola programmare con 2 significati, uno Φ il solito, l'altro indica l'operazione di scrittura del programma in un tipo di memoria dalla quale il microcontrollore pu≥ prelevare le istruzioni da eseguire. Nel caso di memoria RAM si pu≥ anche parlare di downloading (scaricare) altrimenti di burning (bruciare).
I tipi pi∙ comuni di memoria sono RAM, ROM, PROM o OTP (Programmable ROM o One Time Programmable, una memoria che si pu≥ scrivere una sola volta), EPROM (Erasable Programmable ROM, per scriverla prima bisogna azzerarla con l'esposizione a raggi ultravioletti), EEPROM (Electrical EPROM, per scriverla bisogna prima azzerarla con un segnale elettrico), FLASH (simile alla EEPROM, ma realizzata con tecnologia diversa, molto veloce). Evidentemente in fase di sviluppo Φ comodo orientarsi su memoria EEPROM o FLASH, soprattutto se integrata, dal momento che spesso in questo caso Φ fornita la possibilitα di programmazione in-circuit, cioΦ senza la necessitα di dover ogni volta estrarre il microcontrollore dal circuito per programmarlo. A progetto finito e testato si pu≥ passare alla versione del microcontrollore con ROM.
Alcuni microcontrollori con qualche tipo di memoria interna (al massimo 4KB di RAM e 128KB di memoria programma FLASH o ROM) si possono usare anche da soli senza nessuna periferica esterna: si parla allora di modalitα single-chip. Alcuni microcontrollori funzionano solo in modalitα single chip, mentre altri solo in modalitα estesa, cioΦ con bus dati e indirizzi in luogo di porte di I/O.
I dispositivi di I/O possibili sono molti: seriali sincrone, asincrone, bus I2C, bus CAN, ADC, DAC, timer, linee di I/O digitali, PWM, watchdog timer e altro ancora. Grazie a bus seriali come l'I2C un microcontrollore che manchi di alcune funzionalitα pu≥ essere integrato con periferiche esterne pur utilizzandolo in modalitα single-chip.
SISTEMI DI SVILUPPO
Il set di istruzioni disponibile spesso Φ molto limitato e alcune famiglie sono dei RISC nel vero senso della parola (Reduced Instruction Set Code), comunque generalmente ci≥ non causa grossi problemi, anzi semplifica l'apprendimento. Per ogni famiglia di microcontrollori sono disponibili vari linguaggi ad alto livello, tuttavia non bisogna illudersi di poter evitare di imparare l'assembly, non solo per la velocitα e la compattezza dei programmi scritti in tale linguaggio, ma soprattutto per capire le possibilitα ed i limiti del sistema su cui tale programma sarα eseguito.
La piattaforma su cui sviluppare Φ quasi sempre un PC con DOS/Windows o un sistema UNIX sui quali girerα un cross-compiler che produrrα codice per il microcontrollore target e spesso un simulatore per controllare il programma senza passare continuamente per la noiosa fase di programmazione. Per utenze professionali esistono monitor che controllano l'esecuzione del programma sotto test direttamente nelle condizioni di lavoro nel sistema.
Se si usa un 386 embedded (una schedina con un 386 e varie periferiche) o altre soluzioni basate su architettura 8086 si possono usare i normali tools di sviluppo per PC, prestando attenzione al fatto che se non ci fossero sostituti di BIOS e DOS non si potranno usare alcune funzioni: nel caso del C per esempio quasi tutte le funzioni della libreria standard, a meno di non rifarsi il modulo crt0.c fornendo le funzioni di supporto necessarie, prime tra tutte quelle per la gestione della memoria.
Per quasi tutti i microcontrollori esiste almeno un cross-compilatore C ed un basic oltre ai cross-assemblatori, mentre stanno prendendo piede linguaggi RAD e C++. Di solito si programmano i piccoli microcontrollori con poca memoria interna in assembly per risparmiare spazio, mentre se si ha a disposizione una pi∙ capiente memoria esterna si usa il C.
Per ora l'impiego dei RAD Φ basso e limitato a PLC, PC embedded e poco altro, ma in futuro potrebbe crescere molto.
LO SVILUPPO DI UN PROGETTO
Come giα scritto per programmare sistemi embedded Φ necessario avere una certa conoscenza dei principi di funzionamento ed interfacciamento dell'hardware e d'altro canto pu≥ divenire necessario cambiare un progetto hardware rivelatosi durante lo sviluppo del software inadatto al compimento di una determinata funzione.
Per prima cosa bisogna, date le specifiche del progetto, scegliere la soluzione hardware da usare, ossia nel caso dei microcontrollori il modello. I criteri di scelta possono essere la memoria, la capacitα di calcolo, il costo ma anche cose come la facilitα di reperimento e il numero di piedini da saldare.
Per esempio volendo realizzare un termostato sarα utile scegliere un microcontrollore dalle dimensioni contenute, con memoria interna, possibilmente con un ADC per misurare la temperatura, linee di I/O digitali per il controllo di un tastierino e per l'output su di un display.
Il secondo passo Φ quello di individuare le funzioni che il nostro software dovrα realizzare e studiare uno schema che servirα durante l'implementazione per orientarsi nelle scelte da compiere.
In prima approssimazione il programma Φ un loop infinito che legge un dato in ingresso, lo confronta con un valore di riferimento ed il risultato del confronto si riflette sull'attivazione o meno del comando di accensione del termo.
Come si vede il ciclo Φ eseguito continuamente senza alcuna interruzione ed il sistema risponde entro un determinato tempo ad ogni variazione di temperatura rispetto al riferimento. Il processo di controllo in tempo reale di un sistema Φ una caratteristica tanto comune ai sistemi embedded che essi sono detti anche real-time, cioΦ la risposta del sistema agli ingressi deve necessariamente iniziare e terminare entro predefiniti limiti di tempo.
Tornando al nostro esempio bisogna integrare lo schema per tenere presente che l'utente deve avere la possibilitα di impostare il proprio valore di riferimento. Supponiamo di aver fatto una funzione che riceva i dati in ingresso da un tastierino, come la integriamo nel nostro programma?
Ci sono 4 modi:
Ovviamente la 4░ è la soluzione più generale, ma presenta alcuni aspetti negativi:
QuestÆultimo aspetto merita un approfondimento: un kernel multitasking ha bisogno di un minimo supporto hardware per il context-switching ed in particolare di 1) un sistema di interruzioni a tempo che permetta lÆattivazione ciclica di una ISR del kernel 2) la possibilità di cambiare lo stack per far puntare il PC (Program Counter) al task da attivare al termine della ISR. Microcontrollori come i PIC non hanno uno stack abbastanza flessibile, mentre i PIC15Cxx non hanno neppure le interruzioni.
Per segliere la soluzione da adottare bisogna valutare attentamente non solo la complessità delle funzioni allÆinizio dello sviluppo del progetto, ma anche prevedere la possibilità di aggiornamenti e cambiamenti durante la realizzazione. Il controllo di temperatura può divenire un compito più complicato di quello che lascia supporre lo schema: per esempio lÆutente vorrà avere temperature diverse a diverse ore della giornata, inoltre per vari motivi (spostamenti dÆaria, rumore elettronico, errori di quantizzazione dellÆADC) la temperatura può oscillare continuamente attorno al valore di riferimento e bisogna evitare assolutamente continue accensioni e spegnimenti del termo rispettando una soglia minima durante la quale il suo stato non cambi. Per far questo si potrebbe appunto associare una ISR allÆinterrupt di un timer, altrimenti bisognerà complicare ulteriormente il loop principale.
Il terzo passo consiste nella realizzazione concreta del progetto, sia nella parte hardware che software e nel testarne il corretto funzionamento.
DEBUGGING & TESTINGPer piccole applicazioni il debugging si esegue con i simulatori software, se ciò non risultasse possibile o insufficiente si può procedere alla sperimentazione provando una funzione alla volta inserendo il sistema embedded in un ambiente che permetta allo sviluppatore di dare stimoli e ricevere le risposte dalle quali desumere il comportamento del programma. LÆambiente può essere un mini-circuito con interruttori e led oppure una scheda di debug professionale, con uscite e ingressi sotto controllo sullo schermo del PC.
Il testing di un sistema embedded anche piuttosto semplice presenta aspetti complicati: molte volte un programma risultato esente da bug su di un simulatore nellÆambiente operativo reale non riesce a garantire lÆesecuzione delle funzioni previste dal progetto. Questo può essere dovuto a problemi di temporizzazioni, a interazioni non previste tra lÆhardware del sistema embedded e lÆhardware del sistema da controllare (succede molto spesso purtroppo) e qualche volta può essere addirittura necessario ripartire da zero scegliendo soluzioni diverse.
CONCLUSIONITra i vari tipi di sistema embedded i microcontrollori sono certamente i più diffusi grazie alla loro spinta integrazione e al contenimento dei costi che permettono di utilizzarli in oggetti di largo consumo e di piccole dimensioni.
Nel futuro essi conosceranno sicuramente una fase di ulteriore espansione, soprattutto perché i più grandi produttori mondiali rilasceranno a breve nuovissime famiglie con velocità di calcolo 2-3 volte superiori e con unità DSP integrate.
Questo permetterà di utilizzarli sempre più anche in applicazioni avanzate di robotica e di automazione industriale. Inoltre la diffusione di linguaggi come C++ e tools RAD renderà più veloce e conveniente sviluppare su di essi progetti anche abbastanza complessi.
AllÆorizzonte ci sono grosse novità per il mondo dei sistemi embedded: i Java chips e minicomputer basati su Windows CE. Questi ultimi in particolare potrebbero a diventare una alternativa appetibile alle attuali soluzioni di quadri di controllo per macchine automatiche: ad essi sarebbe affidata lÆinterazione con lÆutente, lÆinterfacciamento tramite scheda PCMCIA alla rete ETHERNET aziendale e il comando di un microcontrollore (magari Java-based) che effettuerà esclusivamente le operazioni di controllo.
BIBLIOGRAFIA:
J. Labrosse, "uC/OS: the Real-Time Kernel", R&D Books, 1992
J. Farmer, "A Real-Time Operating System for PIC 16/17", Microchip Technology Application Note 585
"H8/300 SERIES microcontrollers", Hitachi, 1996