L’Atmega 128

L’architettura AVR è del tipo RISC e dispone di un ricco ed efficiente set di istruzioni con 32 registri general purpose: questi sono connessi direttamente all’ALU in modo da renderne accessibili due contemporaneamente in un singolo ciclo di clock e poter in tal modo raggiungere velocità di esecuzione fino a dieci volte superiori rispetto ai tradizionali microcontrollori CISC. 

Una visione d’insieme delle caratteristiche hardware del modello Atmega128 rivela 128K bytes di memoria flash programmabile in-circuit, con la possibilità di lettura e scrittura contemporanee; 4K bytes di SRAM; 53 linee di I/O, 32 registri di uso generale; un Real Time Counter (RTC); quattro Timer-Contatori che possono essere utilizzati in modalità Capture/Compare e PWM; 2 USARTs; un interfaccia seriale Two-wire orientata al byte, un ADC ad 8 canali e con la risoluzione massima di 10-bit con ingressi differenziali opzionali a guadagno variabile; un Watchdog con oscillatore dedicato; una porta seriale SPI; un’interfaccia JTAG in accordo al protocollo IEEE 1149.1 per il debug e la programmazione del dispositivo dall’esterno e sei differenti modalità di bassoconsumo selezionabili via software. Il modo IDLE prevede lo spegnimento della CPU mentre la SRAM,  i Timer-Contatori, la porta SPI e gli interruptus continuano a funzionare;  il modo Power-down salva il contenuto dei registri ma blocca l’oscillatore principale, disabilitando tutte le altre funzioni del Chip fino al successivo interrupt o Reset. Nella modalità Powersave il timer asincrono continua a funzionare, mantenendo una base dei tempi mentre il resto del dispositivo è spento. L’ADC Noise-Reduction ferma la CPU e tutti i  moduli di Input-Output ad eccezione del timer asincrono e dell’ADC, per ridurre possibili sorgenti di rumore durante la conversione ADC. Nel modo Standby l’oscillatore a cristallo o risuonatore continua a funzionare, mentre il resto del dispositivo è inattivo, permettendo al contempo rapidi riavvii basso consumo.

Lo Stanby Esteso prevede il funzionamento sia dell’oscillatore principale che del timer asincrono. L’ISP Flash permette la riprogrammazione in-circuit della memoria di programma attraverso l’interfaccia seriale SPI mediante un programmatore convenzionale o tramite un programma di Boot in esecuzione nel micro. Quest’ultimo può servirsi di varie interfacce per scaricare  il programma nella memoria ad esso dedicata, permettendo una contemporanea lettura e scrittura della stessa. I progettisti AVR hanno dovuto assicurare piena compatibilità tra i modelli ATmega103 e ATmega128, dal momento che quest’ultimo eccede le 64 locazioni di memoria riservate all’Input/Output come avveniva nel modello precedente: tutte le locazioni di memoria presenti nel 103 sono state mappate nella stessa maniera nella versione 128 e quelle in più sono presenti in un’area riservata che va dall’indirizzo $60 al $FF. Queste sono accessibili tramite le istruzioni LD/LDS/LDD e ST/STS/STD e non tramite le IN e le OUT. Anche il maggior numero dei vettori di interrupts nell’ATmega128 comporta l’uso, per i sistemi dotati del modello precedente, di una modalità di funzionamento compatibile con quest’ultimo. La piedinatura dei due modelli è la stessa e perciò possono occupare lo stesso zoccolo sulle demo-board. Nella modalità compatibile  il modello 128 perde alcune caratteristiche:

➤ un USART invece di due e funzionante solo in modalità asincrona: solo gli otto bits meno significativi del registro del Baud Rate sono accessibili;

➤ un timer-contatore a 16 bits con due registri dedicati alla funzione compare invece di due timers-contatori con tre registri;

➤ l’interfaccia seriale a due fili non è supportata;

➤ la porta C è solo d’uscita;

➤ la porta G non ha più la funzione generale di Input-output;

➤ il boot-loader non supportato;

➤ non è possibile modificare la frequenza la frequenza dell’oscillatore interno RC;

➤ l’interfaccia verso memorie ester ne non può elaborare indirizzi di input/output;

➤ l’usart non dispone di buffer FIFO.

Il modello 128 dispone di sette porte di ingresso-uscita: le porte A,B,C,D,E,F sono dotate di otto bits con resistenze di pull-up interne (associate a ciascun bit); i loro buffers sono di elevata capacità per l’ingresso e l’uscita dei dati. Come ingressi i pins che sono esternamente collegati a massa si comportano da generatori di corrente se sono attivate le resistenze di pull-up. I  loro pins sono messi ad alta impedenza (tri-stated) quando interviene una condizione di reset, anche se il clock non è attivo. Nella modalità compatibile all’indietro verso il 103, la porta C funziona solo da uscita e i suoi pins non sono tri-stated in caso di reset. La porta F può anche essere utilizzata come ingresso analogico per l’ A/D. Se è attivata l’interfaccia JTAG, le resistenze di pull-up dei pins PF7, PF5 e PF4 non sono scollegate nemmeno in caso di reset. Nella modalità 103 la porta F funziona solo da input. La porta G è a 5 bits e in modalità 103 i suoi pins funzionano da segnali di strobe per la memoria esterna o da input per l’oscillatore a 32 kHz; i pins PG0, PG1 e PG2 sono posti rispettivamente a 1,1 e 0 in modo asincrono in caso di reset. I pin PG3 e PG4 possono funzionare da oscillatori. Il pin denominato PEN può essere programmato in modo da attivare la programmazione seriale SPI ed è internamente collegato verso l’alimentazione. Nel Power-on-Reset questo pin viene posto a livello logico basso e il dispositivo entra nella modalità SPI.

Figura 1: schema dell’architettura ATmega128.

Figura 1: schema dell’architettura ATmega128.

Architettura AVR

L’architettura AVR è del tipo Harvard con memorie dati e programma, e rispettivi buses, distinti (vedi figura1). Le istruzioni sono precaricate ed eseguite secondo un singolo livello di pipeline: in un solo ciclo di clock, mentre un’istruzione viene eseguita, la successiva viene già caricata dalla memoria di programma. I trentadue registri general-purpose (file Register) sono anch’essi accessibili nel medesimo tempo; in questa maniera può essere eseguita in un unico ciclo una tipica operazione ALU: questa infatti comporta il prelevamento  di due operandi dal file Register, un’elaborazione  (quelli del prelevamento precedente) e il successivo  immagazzinamento del risultato (dell’operazione precedente) nello stesso File-register. Sei dei trentadue registri possono essere usati come tre puntatori a 16 bit (registri X, Y e Z) alla memoria dati e uno di essi può anche servire per indirizzare look-up table nella memoria di programma. L’ALU supporta operazioni aritmetiche, logiche o bitwise e dopo ogni operazione aritmetica il Registro di Stato è aggiornato in base al risultato:  il bit 0 (C) rappresenta  il riporto, il bit 1 (Z) rappresenta un risultato pari a zero, il bit 2 (N) indica un risultato negativo, il bit 3 (V)  indica un overflow nelle operazioni in aritmetica in complemento a due, il bit 4 (S) è un or esclusivo tra il flag N e il flag di overflow V, il bit 5 (H) rappresenta  un mezzo riporto in alcune operazioni aritmetiche tipo in quelle BCD. Molte istruzioni AVR sono rappresentate da singole word a 16 bits (alcune a 32); la memoria di programma che le contiene è divisa in due sezioni, la sezione di Boot e quella delle Applicazioni ed entrambe possiedono bits di protezione per la lettura e la scrittura: l’istruzione SPM, che serve a scrivere nella sezione delle Applicazioni, risiede nella sezione di Boot. Alcune architetture dispongono anche di un moltiplicatore in grado di eseguire moltiplicazioni con e senza segno. Quando ci sono interrupts o subroutine nel corso dell’esecuzione del programma, l’indirizzo dell’istruzione che deve essere eseguita al ritorno della chiamata (Program Counter), viene salvato nello Stack; quest’ultimo è allocato nella SRAM e perciò può al limite averne le stesse dimensioni. Tutti i programmi devono inizializzare  il puntatore allo Stack all’interno della routine di reset (prima dell’esecuzione di subroutine o interrupts);  il puntatore allo Stack può essere letto o scritto tramite i re gistri dedicati alle operazioni di Input/Output. In figura 2 viene riportato uno schema dei 32 registri general-purpose con i tre puntatori X,Y,Z: questi possono eventualmente essere usati come base e offset per l’indirizzamento indiretto.

Figura 2: shema dei 32 registri.

Figura 2: shema dei 32 registri.

L’ AVR accetta sei diverse sorgenti di interrupts: essi hanno un bit dedicato nel registro di stato per l’abilitazione generale (Global Interrupt Enable) (bit 7) e dispongono di una tabella dedicata con tutti gli indirizzi relativi; la loro priorità dipende proprio dalla posizione relativa nella tabella (più l’indirizzo è basso, più la priorità è alta). Quando si verifica una condizione di interrupt il Global Interrupt Enable (GIE) viene azzerato e tutti gli altri sono temporaneamente disabilitati; via software si possono però abilitare gli interrupts nidificati settando ad uno il GIE: in questa maniera è possibile interrompere la routine di interrupt in corso e passare a quella più recente che si annida nella precedente.  Il GIE viene comunque settato all’uscita di ogni interrupt con l’istruzione RETI. Ci sono fondamentalmente due tipi di interrupt: il primo tipo setta il bit relativo e allora il Program Counter si riempie con l’indirizzo della routine di interrupt. L’hardware provvede a cancellare il flag relativo (esso può comunque essere cancellato via software). Nel caso in cui intervenga una condizione di interrupt mentre il relativo flag è cancellato, esso viene automaticamente settato e rimane tale fino all’esecuzione della relativa routine o alla cancellazione via software. In modo similare, se intervengono una o più condizioni di inerrupts quando il GIE è cancellato, i  corrispondenti flags saranno settati e tali resteranno fino al settaggio del GIE: a questo punto gli interrupts saranno serviti fin ordine di priorità. Il secondo tipo di interrupts triggera fino all’esecuzione della richiesta e pertanto non hanno flags dedicati: nel caso la richiesta cessi prima dell’eventuale esecuzione,allora essa cadrà. Quando l’AVR esce da un interrupt ritorna al programma principale ed esegue almeno un’istruzione prima di servire altri interrupts. Il  registro di stato non viene automaticamente salvato quando si entra in una routine e nemmeno ripristinato all’uscita: questo va fatto via software. Esiste un’istruzione, CLI, per disabilitare gli interrupts: il seguente  esempio mostra come usarla durante la scrittura della EEPROM.

Assembler

In r16, SREG ; memorizzazione
delle variabile r16 in SREG
Cli ; gli interrupts vengono
disabilitati
Sbi EECR, EEMWE ; inizio
della scrittura in EEPROM
Sbi EECR, EEWE
Out SREG, r16 ; ripristino del
valore contenuto in SREG

Esempio in C

Char cSREG;
cSREG = SREG;
_disable_interrupt ( );
EECR |= (1<<EEMWE);
EECR |= (1<<EEWE);
SREG = cSREG;

Con l’istruzione SEI si abilitano gli interrupts, ma l’istruzione immediatamente successiva viene comunque eseguita prima di qualunque interrupt (anche se già richiesto). Il tempo di risposta ad ogni richiesta di interrupts è al minimo di quattro cicli di clock: durante questo periodo il Program Counter viene copiato nello Stack e poi aggiornato con l’indirizzo della routine corrispondente. Se interviene una condizione di interrupt durante l’esecuzione di un’istruzione ciclica, questa viene comunque portata a termine prima di passare alla routine. Se il micro si trova in Sleep mode, il tempo di risposta dell’interrupt viene incrementato di quattro cicli, oltre al tempo di start–up dello sleep mode interessato.

Assembler

Sei ; abilitazione degli interrupts
Sleep ; il micro entra in sleep
; prima di qualunque interrupt

Esempio in C

_enable_interrupt ( );
_sleep ( );

Il ritorno da una routine occupa quattro cicli di clock: durante questo tempo il Program Counter viene prelevato dallo Stack, quest’ultimo viene incrementato di due e il GIE viene ripristinato.

Periferiche principali

Timers  e contatori

L’AVR 128 dispone di quattro timers-contatori, due a otto bits e due a sedici bits (questi ultimi riportati in figura 3).

Figura 3: schema dei timers a sedici bits.

Figura 3: schema dei timers a sedici bits.

Essi hanno caratteristiche più o meno simili: quelli ad otto bit dispongono di un’unità Output/Compare laddove quelli a sedici ne hanno tre; queste unità permettono la generazione di forme d’onda secondo la tecnica PWM secondo lo schema riportato in figura 4.

Figura 4: shema dell’unità Output/Compare.

Figura 4: shema dell’unità Output/Compare.

Le sorgenti di clock dei timers possono essere interne e dotate di prescaler (sincrone) o esterne(asincrone): queste ultime hanno come pins di ingresso i TOSC1 e TOSC2. In riferimento alla figura 4 il comparatore ad otto bit compara continuamente  il valore del contatore TCNT0 col valore presente nel registro OCR (Output Compare Register). Due valori esatti comportano il settaggio del flag OCF0 (match); questo può eventualmente generare un interrupt se è attivo il  flag OCIE0. Dopo l’esecuzione della routine il flag OCF0 è posto automaticamente a zero (esso si può azzerare via software). Il  generatore di forme d’onda utilizza il segnale di match per generare un’uscita che dipende dal settaggio dei bits 1 e 0 del registro WGM0 e dagli stessi bits del registro associato all’uscita del comparatore COM0. Il  segnale di match può anche essere forzato ad uno in modalità non PWM ponendo ad uno il bit FOC0: in questa maniera non verrà riazzerato o ricaricato  il timer, ma il pin OC0 sarà aggiornato come in presenza di un match reale. Tutte le operazioni di scrittura verso il contatore TCNT0 (le quali possono essere attuate indipendentemente dall’abilitazione o meno del timer/contatore) bloccano il compare-match che potrebbe originarsi nel successivo ciclo del timer; ciò permette di inizializzare il registro OCR0 allo stesso valore di TCNT0 senza provocare un interrupt quando il timer/contatore è attivo; al contempo,però, l’impossibilità di rilevare il match anche per un solo ciclo del timer potrebbe provocare la generazione di forme d’onda errate. Per maggiori dettagli sull’uso dell’ unità Compare-Match e sul settaggo dei registri ad essa relativi, vedere il datasheet.

Comunicazione seriale SPI

La periferica seriale SPI permette il trasferimento sincrono ad elevata velocità tra l’Atmega128 e periferiche esterne o tra più AVR; le caratteristiche principali dell’interfaccia sono:

➤ trasmissione bidirezionale,  trasferimento sincrono su tre-fili;

➤ comunicazione Master o Slave;

➤ precedenza al trasferimento dell’MSB o dell’LSB;

➤ sette velocità di trasmissione programmabili;

➤ flag di fine trasmissione;

➤ flag di protezione da collisioni in scrittura;

➤ wake-up dal modo-idle;

➤ due velocità di trasmissione nel modo Master.

La figura 5 mostra il collegamento tra CPUs Master e Slave tramite l’interfaccia SPI.

Figura 5: interconnessione Master-Slave.

Figura 5: interconnessione Master-Slave.

Il sistema consiste di due registri a scorrimento e di un generatore di clock Master. Il dispositivo Master inizia la comunicazione mandando bassa la linea SS dello Slave desiderato: entrambi i dispositivi dispongono di Shift register ove salvare i dati da trasmettere o da ricevere e il Master genera gli impulsi di clock necessari alla trasmissione  sulla linea SCK. I dati nella direzione Master-Slave percorrono la linea MOSI, quelli in direzione opposta la linea MISO; dopo ogni pacchetto trasmesso, il  Master sincronizza lo Slave mandando alta la linea SS. In configurazione di Master, l’interfaccia SPI non dispone di un controllo automatico della linea SS; questo deve essere effettuato via software prima dell’ inizio della comunicazione. Ciò effettuato, la scrittura di un byte nel registro dei dati fa partire il generatore di clock dell’SPI e l’hardware provvede a shiftare  il byte nello Slave. Dopo tale trasmissione  il clock si blocca e viene settato il flag (SPIF) di fine trasmissione. In caso di interrupt il Master può continuare a trasferire il byte successivo scrivendolo nel registro SPDR o segnalare la fine del pacchetto mandando alto la linea SS. L’ultimo byte in arrivo (e non trasmesso) sarà mantenuto nel buffer per un uso successivo. In configurazione di Slave l’interfaccia SPI rimane inattiva con la linea MISO ad alta impedenza fino a quando il pin SS rimane basso. Alla fine della trasmissione di ogni byte, il bit SPIF viene posto alto. In caso di richiesta di interrupt lo Slave si comporta in modo analogo al Master a parte il segnalare la fine della trasmissione. L’interfaccia è dotata di buffer che funziona in modo diverso in trasmissione e ricezione: infatti i  bytes che devono essere trasmessi non possono essere scritti nel registro dei dati prima che l’intero ciclo di shift sia completato; invece in ricezione, un carattere ricevuto può essere letto prima dell’arrivo del successivo.

Interfaccia JTAG e sistema  di debug  on board

Il modello 128 dispone di un’interfaccia JTAG per il debug di dispositivi dotati di un’interfaccia analoga: tutte le periferiche interne, memoria RAM interna e memorie esterne, il File-register interno, EEPROM e memorie Flash. Tale interfaccia dispone di un ambiente dedicato AVR Studio, che permette il controllo dell’esecuzione dei programmi con istruzioni di Break: queste consistono in interruzioni o modifiche del flusso delle istruzioni presenti nella memoria di programma. L’interfaccia JTAG basa essenzialmente   il suo funzionamento su un modulo dotato di quattro pins, il TAP controller, che è una macchina a stati finiti con 16 possibili stati la cui funzione è quella di controllare le operazioni di scansione dei vari dispositivi,  i buses di comunicazione dell’interfaccia e il sistema di debug. I quattro pins sono:

➤ il TMS o test mode select, usato per scegliere il particolare  stato del TAP;

➤ il TCK , ingresso al clock che sincronizza le operazioni dell’interfaccia e che determina il ritmo di cambiamento degli stati della macchina;

➤ il TDI, per l’ingresso seriale dei dati da trasferire nel registro delle istruzioni o dei dati dell’interfaccia (Scan Chains);

➤ il TDO, l’uscita seriale dei dati.

Questi pins, quando l’interfaccia è disattivata tramite il flag JTAGEN, si comportano come normali pins e il TAP è in reset. Tutti gli integrati con interfaccia JTAG sono connessi serialmente tramite i pins TDI/TDO a formare un lungo Shift Register e il controller provvede ad esaminare  i pins di output dei dispositivi connessi e a confrontarli con quelli voluti: in questa maniera vengono testate le interconnessioni e l’integrità dei componenti per mezzo di soli quattro segnali TAP. La fase di test si basa su quattro istruzioni dedicate: la IDCODE serve per risalire al codice di identificazione del dispositivo da testare, la BYPASS, per avviare la scansione più breve per giungere al codice del dipositivo di interesse, la SAMPLE/PRELOAD per settare i valori iniziali nella scansione dei vari integrati o leggere i pins di output e la EXTEST, per leggere  i pins di output e caricare i loro dati. Durante la fase di test è opportuno avere l’AVR in condizione di reset per non interferire con essa.

IL SET DI ISTRUZIONI

Scarica subito una copia gratis

Scrivi un commento

Seguici anche sul tuo Social Network preferito!

Send this to a friend