domenica 16 marzo 2014

FPGA: Comunicazione ad alta velocità tramite USB 2.0 (terza parte) - Software

L’IC FT232H di cui abbiamo parlato nei precedenti articoli (parte I, parte II) permette una comunicazione col pc tramite due interfacce: VCP e D2XX.

L’interfaccia VCP (Virtual COM Port) è pensata per sostituire sistemi con la vecchia porta seriale senza modifiche nei software esistenti, il dispositivo viene visto dal sistema operativo come una porta COM seriale. Gli svantaggi di questa interfaccia riguardano le prestazioni, difficilmente si riusciranno a superare i 3M Baud.

L’interfaccia D2XX è un’interfaccia proprietaria per i dispositivi FTDI che permette di raggiungere le massime prestazioni e fornisce accesso a tutte le funzionalità esposte dagli IC.

cdm
Windows CDM Driver Architecture

Nella distribuzione Windows entrambe le interfacce vengono fornite in un unico pacchetto driver denominato CDM (Combined Driver Model) mentre per gli altri sistemi operativi le interfacce corrispondono a differenti driver mutualmente esclusivi.

Dopo aver installato il driver CDM è possibile procedere alla programmazione tramite D2XX utilizzando le API documentate nella D2XX Programmer's Guide e visionando gli esempi nei diversi linguaggi di programmazione.

Per semplificare la comprensione del software svilupperemo in questo articolo un programma console per scrivere e leggere i dati dalla FPGA.

Come ulteriore facilitazione utilizzeremo il linguaggio C# tramite la libreria wrapper fornita da FTDI per velocizzare ulteriormente i tempi di sviluppo.

La libreria incapsula nella classe FTDI tutte le funzionalità esposte dalle API, aggiungendo una serie di controlli e diagnostica per rendere più developer-friendly l’utilizzo a programmatori C#.

Importante: Alcuni messaggi di errore vengono mostrati dalla libreria wrapper tramite MessageBox, sarà necessario includere nel progetto il riferimento all’assembly System.Windows.Forms per poter compilare correttamente l’applicazione se si include il sorgente della libreria nel proprio progetto per evitare di distribuire una DLL aggiuntiva.

Per avere accesso al dispositivo come prima cosa dobbiamo creare una nuova istanza della classe FTDI e aprire il dispositivo.

code1

La prima funzione da chiamare sarà OpenByDescription, OpenByIndex, OpenByLocation o OpenBySerialNumber dove sarà possibile aprire il dispositivo in base alla descrizione, indice, locazione o numero di serie.

Utilizzeremo OpenByDescription specificando la descrizione “UM232H”, corrispondente alla descrizione di default del modulo. In caso di problemi sarà possibile impostare il nome della descrizione del chip tramite il programma FT Prog. La stringa della descrizione è memorizzata nella EEPROM collegata al chip FT232H sul modulo UM232H.

La libreria offre un meccanismo un po’ antico per la gestione degli errori che non è stato convertito nella libreria wrapper con l’utilizzo di eccezioni C#. Ogni chiamata in genere restituisce un valore di tipo FT_STATUS, da controllare per verificare se tutto è andato a buon fine.

Prima di poter leggere e scrivere dati dobbiamo impostare la modalità operativa di comunicazione ed alcuni parametri.

code2

Innanzitutto resettiamo il dispositivo chiamando la funzione SetBitMode con modalità FT_BIT_MODE_RESET, ignoriamo il primo parametro che consiste in una maschera di bit per impostare quale bit sono di ingresso e quali di uscita, parametro utile per configurare i pin di I/O dell’ACBus.

Dopo il reset attendiamo 10ms per impostare il dispositivo nella modalità 245 FIFO sincrona tramite il parametro FT_BIT_MODE_SYNC_FIFO.

Impostiamo poi altri parametri come la latenza tramite SetLatency il cui valore di default è 16ms. Il timer di latenza è una caratteristica del driver, un timeout per trasmettere brevi pacchetti di dati al pc. Cambiare la latenza è un’operazione opzionale e può servire per migliorare in alcuni casi le prestazioni in base alla propria applicazione.

Tramite InTransferSize impostiamo la dimensione dei trasferimenti in ingresso ed uscita dell’USB, aumentiamo questo valore per migliorare le prestazioni nel trasferimento sequenzialmente di grosse quantità di dati.

Infine impostiamo tramite SetFlowControl il flusso di controllo a FT_FLOW_RTS_CTS per evitare rari errori di corruzione dati.

Siamo adesso pronti a trasferire ad alta velocità i nostri bit.

Senza riportare tutto il codice sorgente che potrete trovare alla fine di questo articolo, riportiamo le parti salienti descrivendo a grandi linee il resto.

Come prima operazione apriamo il file di ingresso da trasmettere alla FPGA, ne leggiamo un blocco composto da qualche migliaia di bytes e tramite la funzione Write inviamo all’IC FT232H i bytes letti che verranno quindi inviati alla FPGA.

code3

La funzione write è molto semplice e così dichiarata:

code5

dove il primo parametro è il buffer contenente i dati da scrivere, il secondo parametro indica il numero di bytes da scrivere ed il terzo riporta i bytes effettivamente scritti.

swWrite è un’istanza della classe C# Stopwatch per misurare la durata dell’operazione e permettere di riportare successivamente le statistiche di velocità delle operazioni.

Dopodiché leggiamo i dati dalla FPGA utilizzando la funzione Read:

code4

Con sintassi analoga alla funzione Write, molto semplice da utilizzare. Ricevuti i dati controlliamo byte per byte se corrispondono ai dati del file inviato ed aggiorniamo ad intervalli regolari le statistiche.

Sotto è riportata una schermata del programma in esecuzione:

console

In questo articolo è stata sviluppata una semplice interfaccia console per evitare di aggiungere le complessità di un interfaccia grafica multithreading mostrando le operazioni basilari da compiere per gestire la comunicazione tramite USB 2.0ad alta velocità con il chip di FTDI.

Importante: Prima di lanciare l’applicazione è necessario inserire nella cartella contenente l’eseguibile (cartella Debug o Release) un file nominato dataIn.bin che sarà inviato alla FPGA ed il cui contenuto sarà ricevuto indietro

1 commento: