Oscilloscopio USB: Progetto PitaScope

 


Il protocollo USB

Adesso servono un pò di generalità sull'USB (spero di non annoiare nessuno :-D ).
Il bus USB è comandato dall' Host Controller del PC, il quale avvia ogni trasferimento di dati (sia in ingresso che in uscita).
Ogni trasferimento USB si divide concettualmente in transazioni, ognuna delle quali è un insieme di pacchetti.
Un pacchetto si divide a sua volta in vari campi.
Nella documentazione USB vengono definiti i TOKEN: non sono altro che i pacchetti che iniziano una transazione: come si vedrà più avanti, ci sono gli IN-TOKEN, gli OUT-TOKEN, i SETUP-TOKEN e gli SOF-TOKEN.
Il primo pacchetto di una transazione è sempre un pacchetto TOKEN.
Leggendo le specifiche usb, si legge spesso di "trasferimenti in ingresso" e "trasferimenti in uscita": si intende che la periferica manda dati all'host nel primo caso, o li riceve dall'host nel secondo caso (ovvero si parla riferendosi al "lato host").
Ogni trasferimento ha come destinazione o sorgente un "endpoint" della periferica USB, il quale rappresenta il punto di arrivo o di partenza del flusso di dati.
Ogni endpoint è definito da un numero identificativo, una "lunghezza di pacchetto" (che definisce il massimo numero di byte trasferibili con un pacchetto DATI attraverso l'endpoint), dal tipo di trasferimento supportato, da una direzionalità e da un buffer di una certa dimensione.
Nelle specifiche USB ci si riferisce a una connessione tra l'host e un endpoint di una periferica tramite la parola "pipe" (cioé canale, conduttura): un pipe è quindi una connessione logica.
Ci sono principalmente 2 tipi di pipe:
» le "message pipe" comunicano alla periferica particolari richieste alle periferiche, in una forma definita dallo standard USB; sono bidirezionali
» le "stream pipe" servono a trasmettere dati di senza una struttura prefissata; sono unidirezionali
Nella pratica le "stream pipe" servono a trasferire dati.
Una particolare "message pipe" è la Default Control Pipe assegnata all'endpoint zero: obbligatoriamente presente su qualsiasi dispositivo USB è usata per configurare il dispositivo alla connessione con l'host.
Per la Default Control Pipe devono essere abilitate sia le comunicazioni in ingresso che in uscita (pipe bidirezionale).
Un dispositivo USB Low-Speed al massimo può essere dotato di un unico endpoint (oltre all'endpoint zero); per un dispositivo Full-Speed invece gli endpoint possono arrivare a 15 (sempre oltre all'endpoint zero).
Inoltre, mentre l'endpoint zero può essere usato appena dopo l'evento di reset USB, gli altri endpoint necessitano di una inizializzazione.

 

Lo standard USB definisce una "base tempi" di:
» 1 millisecondo per i bus operanti in Low-Speed/Full-Speed, chiamata "frame"
» 125 microsecondi per i bus operanti in High-Speed, chiamata "microframe"
In ogni frame/microframe possono essere contenute più transazioni, e il loro numero massimo consentito è variabile, dipendente dal tipo di trasferimento.
Ad esempio i trasferimenti Isochronous e Interrupt (vedi piu avanti) possono avere accesso al bus ogni N frame, ciò consente di avere una frequenza di trasferimento minima garantita.

Da qui in poi tutto è relativo alla comunicazione su bus Full-Speed, quella su cui è basato questo progetto (vengono tralasciate la Low-Speed, che comunque è simile alla Full in varie caratteristiche, e la High-Speed, visto la sua relativa alta diversità)

Come già detto, ogni transazione USB si divide in più pacchetti, e ogni transazione è preceduta dal "protocol overhead" (un'intestazione comune formata da una serie di bit), il quale è composto da:
» un campo di SYNC da 8 bit per ogni pacchetto
» un campo di PID (Packet Identifier) da 8 bit per ogni pacchetto
» un campo di EOP (End Of Packet, fine pacchetto) di 3 bit per ogni pacchetto
» per ogni pacchetto TOKEN un campo con il numero dell'endpoint a cui è diretto il pacchetto, l'indirizzo del dispositivo e un campo di controllo per errori (CRC5), per un totale di 16 bit
» per ogni pacchetto DATI un campo per il controllo degli errori (CRC16) da 16 bits più il campo per i dati
» per ogni pacchetto DATI, un campo contenente dati

 

Struttura dei pacchetti

Nelle tabelle riassuntive seguenti sono riportat le strutture dei pacchetti, ma senza i campi di SYNC e di EOP.

I pacchetti TOKEN
Campo PID ADDR ENDP CRC5
Numero bit 8 7 4 5

Per transazioni OUT e di SETUP i campi ADDR ed ENDP indicano l'endpoint che riceverà  il successivo pacchetto DATI; per transazioni IN indicano l'endpoint che trasmetterà  il pacchetto DATI.
Solo l'host può mandare pacchetti TOKEN.

I pacchetti SOF
Campo PID Numero Frame CRC5
Numero bit 8 11 5

Sono mandati dall'host alle periferiche operanti in Full-Speed ogni millisecondo; non serve che le periferiche rispondano con un pacchetto di avvenuta ricezione.

I pacchetti DATI
Campo PID Dati CRC16
Numero bit 8 0÷8192 16

I PID di un pacchetto DATI possono essere 4: DATA0, DATA1, DATA2 e MDATA. I primi due sono gli unici che interessano in questo progetto. Come già detto i PID DATA0 e DATA1 servono alla sincronizzazione e al controllo del trasferimento.

I pacchetti HANDSHAKE
Campo PID
Numero bit 8

I pacchetti handshake usati in Full-Speed sono formati solo da un PID, che può essere di 3 tipi:
» ACK, indica la corretta ricezione (senza errori) di un pacchetto dati e del PID. Può essere mandato dall'host in seguito a una transazione IN (per informare alla periferica l'avvenuta ricezione) o dalla periferica in seguito a una transazione OUT o di SETUP.
» NAK, indica che la periferica non è riuscita ad accettare dati dall'host (in una transazione OUT), perchè impegnata in altre operazioni, o che la periferica non ha nessun dato da trasmettere all'host (durante una transazione IN). L'host non manda mai NAK.
Il pacchetto di handshake NAK viene automaticamente mandato dal PIC18F4550 nel caso in cui la coda FIFO sia piena.
» STALL, indica che la periferica non riesce a trasmettere/ricevere dati o che una richiesta mandata sul control pipe non è supportata. L'endpoint di una periferica può entrare in condizione di STALL a seguito di una specifica richiesta dell'host (se la funzionalità  di HALT su tale endpoint è abilitata; in tal caso si parla di "stallo funzionale" che si rimuove con richiesta dell'host) o, nel caso di un "control pipe", durante la fase DATI o STATUS di un trasferimento di controllo (questo si chiama "protocol stall" e termina all'inizio del successivo trasferimento di controllo). L'host non può mandare STALL.
Nel caso che una periferica rilevi un errore in un TOKEN, non deve rispondere fino all'arrivo del prossimo TOKEN valido.

<-- Prima parte

Terza parte -->