Renesas ha proposto tempo fa per le applicazioni USB il suo controller M66290. Questo componente è uno strumento estremamente versatile utilizzabile in qualsiasi sistema embedded.
Questo controllore di casa Renesas supporta la modalità full-speed (12Mbps) e permette tutti i tipi di trasferimento, dal bulk alla modalità di trasferimento asincrono (interrupt). Il controller M66296 permette, grazie alla sua programmabilità, di selezionare fino a sei endpoint (da EP0 a EP5); ognuno di questi dispone di una FIFO di 3 Kbyte. All’interno del componente trova posto il transceiver e la circuiteria di gestione del clock; il componente è in grado di lavorare con differenti frequenze: da 6 a 48 MHz. Per aumentare la versatilità del controller, internamente trova posto anche un DMA e una interfaccia JTAG. Il dispositivo è in grado di interfacciarsi, senza problemi, ad una CPU che dispone di un bus a 16-bit. Grazie a queste prerogative, questo controllore è un buon candidato per essere utilizzato benissimo nelle più svariate applicazioni commerciali, figura 1 e 2.
In questo articolo vedremo alcune considerazioni sull’inizializzazione dell’endpoint e il ruolo degli interrupt per gestire il bus USB.
Funzionamento di base
In base allo standard USB, i dati sono trasmessi in forma di pacchetti. Ogni unità di trasferimento può anche essere vista come transizione di un gruppo di pacchetti multipli. Un trasferimento, in questo modo, è formato raggruppando operazioni multiple. La figura 3 mostra il protocollo di comunicazione su USB.
Secondo questo standard, tutte le transazioni coinvolgono vari tipi di pacchetti, la figura 4 mette in evidenza i vari formati: SOF, Token, Data e Handshake.
Un pacchetto è costituito da vari campi: una trama USB inizia con un campo identificato come SYNC seguito, poi, dal PID che permette di individuare il tipo di pacchetto (come possiamo vedere dalla figura). Utilizzare questo controller risulta abbastanza semplice; infatti, è possibile collegarlo come una normale periferica ad un qualsiasi microprocessore. A questo scopo, la figura 5 mostra un possibile esempio con una CPU dotato di un bus a 16-bit.
Possiamo senz’altro affermare che il pin /INT del controller assume un ruolo importante: infatti, è attraverso questo pin che il componente comunica al microprocessore tutte le variazioni dello standard USB. Dopo la fase di inizializzazione, il controller lavora in modalità interrupt sulle transazioni consentite dello standard. Il microprocessore, attraverso questo evento asincrono, e con il relativo firmware di equipaggiamento, è in grado di gestire le comunicazioni USB. Come è evidenziato dalla figura 6, il controller, attraverso il suo sequencer, è in grado di gestire tutte le sue sotto fasi.
Infatti, in base ad ogni richiesta il componente M66290 esegue la funzionalità associata. La tabella 1 pone in particolare risalto ciascuna fase e mostra le relative funzionalità associate.
Interrupt Processing
Gli eventi asincroni, generati dal componente M66296 verso la CPU, sono pilotati attraverso il pin /INT del controller. Per discriminare le ragioni dei vari interrupt si ricorre ad un registro di stato (interrupt status register). La tabella 2 mostra alcuni di questi eventi.
Esistono quattro differenti registri, ognuno è identificato attraverso un numero corrispondente, da 0 1 3; questi sono utilizzati per identificare il numero dell’endpoint relativo, endpoint buffer status interrupt. La figura 7 mostra il diagramma di flusso relativo alla gestione di ogni evento che si presenta durante il suo funzionamento.
Interrupt of Data Transfer
Questo componente è dotato di tre tipi di trasferimenti, e, di conseguenza, di differenti modalità di gestione degli interrupt; il programmatore può selezionare un dato trasferimento in base alle singole esigenze. L’endpoint, dove l’interrupt occorre, è identificato grazie alla presenza dei vari registri di stato (interrupt status register da 1 a 3). Le tabella 3 mostra un esempio su come configurare i vari Endpoint Configuration Register, mentre la tabella 4 mette in evidenza i diversi interrupt per ogni tipo di trasferimento.
Non solo, vediamo come varia, in base ad ogni trasferimento, il registro Endpoint Configuration Register, figura 8.
Inizializzazione Endpoint0
La configurazione dell’endpoint0 può essere fatta solo dopo l’inizializzazione del componente. In questa sezione possiamo vedere come realizzare una ipotetica configurazione dei vari Endpoint del controller M66296. In ogni caso è bene ricordare che quando la lunghezza dei dati da trasmettere, o ricevere, è di almeno 256 byte, il modo continuous transfer non può essere utilizzato. La sequenza per inizializzare correttamente un endpoint è divisa in cinque fasi:
■ 1-Per prima cosa occorre inizializzare le varie opzioni per il trasferimento, utilizzando a questo scopo il Control transfer control register (address 28h) e le operazioni coinvolte sono:
Ctr_Rd_Buf_Nmb <- CTR_RBUF (address 28h, bit13-8)
Ctr_Wr_Buf_Nmb <- CTR_WBUF (address 28h, bit5-0)
CTRR <- CTR_RDMD (address 28h, bit15) CTRW <- CTR_WRMD (address 28h,bit7)
■ 2-La seconda fase è quella di settare il packet size; questo è fatto ricorrendo al EP0 packet size register (address 2Ah): EP0_MXPS <- Device Descriptor tbl[7] (address 2Ah, bit6-0)
■ 3-Nella terza parte si deve settare l’auto-response control register (address 2Ch): ASCN <- CTR_ASCN(address 2Ch, bit1) ASTD <CTR_ASTD (address 2Ch, bit0)
■ 4-La quarta azione riguarda l’inizializzazione dell’EP0_FIFO selection register (address 30h):
RCNT <- CTR_RCNT(address 30h, bit15) Octl <- CTR_OCTL (address 30h, bit10)
ISEL <- 1 (address 30h, bit0)
■ 5-Come ultima cosa occorre azzerare il buffer dell’Endpoint0:
IVAL <- 0 (address 32h, bit13)
BCLR <- 1 (address 32h, bit12)
USB Interrupt Enable
La figura 9 mostra quali sono i passi da seguire per abilitare gli eventi asincroni.
Anche questo tipo di operazione è permessa solo dopo aver inizializzato il componente e dopo aver configurato l’endpoint0. In ogni caso, è bene ricordare che gli eventi di endpoint buffer (BEMPE, INTNE, INTRE) sono generati dopo la ricezione di una richiesta di Set Configuration. Inoltre, gli eventi individuati come device state transition interrupt, control transfer e un control transfer stage transition sono permessi dopo un segnale di reset sul bus USB.
Il controllo dei trasferimenti
I trasferimenti sono principalmente bi-direzionali e consistono di almeno due transazioni: setup stage e status stage. La tabella 5 mette in risalto le varie possibilità offerte dal dispositivo.
Il controller M66296 ha quattro funzioni per facilitare il controllo dei flussi e questi sono identificati in questo modo:
» device state transition management function;
» data stage transition management function;
» continuous transmit/receive function. In questa modalità sono spediti e ricevuti, in maniera continua, fino a 255 byte senza interrupt. Grazie a questa modalità non è richiesto un buffer di tipo FIFO per gestire i dati, in questo modo si nota un miglioramento delle prestazioni del componente;
» auto-response function. La figura 10 mostra le possibili transazioni disponibili.
Il dispositivo M66290 permette di gestire i vari USB device state transition:
» powered;
» default;
» address;
» configured;
» suspend.
Queste transizioni sono notificati alla CPU mediante un interrupt dedicato, DVST (device state transition). Quando Auto-Response è abilitato, le richieste di Set Address e Set Configuration possono essere completate senza inviare un interrupt alla CPU. Come si è scritto, quando una transizione è eseguita normalmente, il componente genera un relativo interrupt (DVST). In ogni modo, questo interrupt, per essere generato, deve essere prima abilitato. L’abilitazione è permessa attraverso il registro Interrupt Enable Register0 (indirizzo 10h) scrivendo al bit appropriato. Questi bit sono così identificati: Detect USB Reset Interrupt, Set Address Interrupt, Set Configuration interrupt, and Suspend Detection Interrupt. La figura 11 mostra lo schema delle transazioni del device state.