Oscilloscopio USB: Progetto PitaScope
Cominciamo a entrare nel particolare...
Vengono innanzitutto ripresi e rivisti in modo più approfondito i concetti della parte precedente.
Nelle comunicazioni USB i bit vengono trasmessi partendo dal bit meno significativo (LSB) fino al più significativo (MSB), cioè secondo la codifica Little-Endian; questo si applica a tutti i campi costituenti un trasferimento.
Di ciò non ci si deve però preoccupare perchè della trasmissione si occupa il SIE del microcontrollore (Serial Interface Engine).
Ogni pacchetto inizia con un campo di SYNC (sincronizzazione) da 8 bit, usato dalla circuiteria USB per allineare i dati in ingresso con il clock interno.
Il delimitatore SOP (Start Of Packet, inizio di pacchetto) è contenuto nel campo SYNC.
Il campo SYNC è seguito dal campo PID (Packet Identifier) che serve ovviamente a identificare il tipo di pacchetto; è composto nel seguente modo (notare la codifica Little-Endian) :
ovvero i 4 bit meno significativi corrispondono all'esatto valore PID, mentre i 4 più significativi sono il complemento a 1 dello stesso (questo consente di accorgersi della presenza errori di trasmissione); è necessario controllare la presenza di errori nel campo PID, e nel caso in cui il ricevitore noti un tale errore deve ignorare l'intero pacchetto.
Quanto detto vale anche nel caso in cui una periferica riceva un PID relativo a una richiesta non supportata (per esempio un endpoint configurato come IN deve ignorare un eventuale OUT-TOKEN).
Segue la codifica dei soli PID tra i quali il PIC18F4550 deve discriminare in fase di trasferimento:
Nome PID | Codifica binaria PID<3:0> |
SETUP | 1101 |
OUT | 0001 |
IN | 1001 |
La tabella completa, contenente la lista completa dei PID, si trova sulla documentazione ufficiale USB.
Gli stati USB
Dopo la connessione ad un hub USB, una periferica USB passa attraverso vari stati di funzionamento.
Transitando tra questi stati, variano le sue possibilita di interagire con l'host, ovvero variano le richieste che l'host può avanzare verso la periferica stessa (qualche richiesta è vietata in certi stati).
Questi stati sono:
1 - Connesso
La periferica USB viene connessa ad un hub, il quale informa l'host di ciò. La porta alla quale è stata connessa la periferica è disabilitata.
2 - Alimentato
Un dispositivo USB può essere alimentato tramite bus (dispositivo bus-powered) o tramite alimentazione esterna (self-powered). L'host attende per 100 millisecondi che l'alimentazione della periferica si stabilizzi e conseguentemente abilita la relativa porta.
3 - Default
Dopo essere stato alimentato il dispositivo non deve rispondere a nessuna transazione fino a che non riceve una richiesta di reset dal bus.
Dopo il reset il dispositivo è indirizzato all'indirizzo di default (0000000 in binario) e deve rispondere alle eventuali richieste di descrittori mandate sul default control pipe (endpoint zero) che deve essere attivo e funzionante fin da ora.
Dopo un segnale di RESET il dispositivo è nello stato Default e può essere alimentato via bus ma non deve pero richiedere piu di 100 mA.
4 - Indirizzato
Al dispositivo viene assegnato un indirizzo univoco sul bus, mediante la richiesta standard SET_ADDRESS
5 - Configurato
In questa fase l'host manda alla periferica (sull'endpoint zero) una richiesta di SET_CONFIGURATION, che seleziona una delle configurazioni definite nelle specifiche del dispositivo, e ricevute precedentemente dallo stesso mediante la richiesta GET_DESCRIPTOR.
Si conclude in questa fase il processo di enumerazione, con il quale l'host identifica le capacità della nuova periferica connessa.
6 - Sospensione
Questo stato non è incluso nel processo di enumerazione ma ogni dispositivo lo può incontrare nel suo funzionamento.
Allo scopo di consumare meno energia i dispositivi USB devono entrare in questo stato dopo un certo periodo di inattività. In questo stato il dispositivo mantiene il suo indirizzo e la sua configurazione.
Un dispositivo esce dalla sospensione se trova attività sul bus o se invia un particolare segnale all'host (segnale di remote-wakeup che deve essere disabilitato dopo il reset).
Le richieste standard
La seguente tabella mostra la struttura dei pacchetti di SETUP:
Offset | Campo | Dimensione | Valore | Descrizione |
0 | bmRequestType | 1 | Bitmap | Caratteristiche della richiesta |
1 | bRequest | 1 | Valore | Specifica richiesta |
2 | wValue | 2 | Valore | campo per opzioni specifiche della richiesta |
4 | wIndex | 2 | Indice o Offset | campo per opzioni specifiche della richiesta: tipicamente usato per passare un indice o un offset |
6 | wLength | 2 | Conteggio | Numero di bytes da trasferire (se è richiesta una fase dati) |
Ogni periferica USB deve poter rispondere a certe richieste standard definite dal protocollo, anche se non ha ancora un indirizzo o se non è stato configurato. Il tipo di richiesta è specificato nel campo bmRequestType:
bmRequestType | bRequest | wValue | wIndex | wLength | Data |
00000000 00000001 00000010 |
CLEAR_FEATURE | Selezione caratteristica |
Zero Interfaccia Endpoint |
Zero | - |
10000000 | GET_CONFIGURATION | Zero | Zero | Uno | Numero della configurazione |
10000000 | GET_DESCRIPTOR | Tipo e indice del descrittore | Zero o ID del linguaggio | Dimensione descrittore | Descrittore |
10000001 | GET_INTERFACE | Zero | Numero dell'interfaccia | Uno | Interfaccia alternativa |
10000000 10000001 10000010 |
GET_STATUS | Zero |
Zero Interfaccia Endpoint |
Due | Stato del dispositivo, dell'interfaccia o dell'endpoint |
00000000 | SET_ADDRESS | Nuovo indirizzo del dispositivo | Zero | Zero | - |
00000000 | SET_CONFIGURATION | Numero della configurazione | Zero | Zero | - |
00000000 | SET_DESCRIPTOR | Tipo e indice del descrittore | Zero o ID del linguaggio | Dimensione del descrittore | Descrittore |
00000000 00000001 00000010 |
SET_FEATURE | Selezione caratteristica |
Zero Interfaccia Endpoint |
Zero | - |
00000001 | SET_INTERFACE | Impostazione alternativa | Interfaccia | Zero | - |
10000010 | SYNCH_FRAME | Zero | Endpoint | Due | Numero frame |
bRequest | valore |
GET_STATUS | 0 |
CLEAR_FEATURE | 1 |
SET_FEATURE | 3 |
SET_ADDRESS | 5 |
GET_DESCRIPTOR | 6 |
SET_DESCRIPTOR | 7 |
GET_CONFIGURATION | 8 |
SET_CONFIGURATION | 9 |
GET_INTERFACE | 10 |
SET_INTERFACE | 11 |
SYNCH_FRAME | 12 |
Ultimo aggiornamento: 3 agosto 2011