Capitolo 3
Progetto FPGA e firmware
Introduzione
Descritta la piattaforma di sviluppo del sistema si può passare a mostrare come le varie risorse sono state sfruttate per raggiungere gli obbiettivi preposti. Nei prossimi paragrafi si descriveranno l’architettura scelta per l’hardware implementato sul FPGA e l’applicazione sviluppata per il firmware del DSP nell’ambito del progetto SPADA.
3.1 Architettura FPGA
L’architettura implementata sul FPGA assolve alle seguenti funzioni:
• Conteggio degli impulsi provenienti dai ricevitori differenziali connessi agli iAQC della detection board su finestre temporali variabili impostate tramite il DSP.
• Interfacciamento col DSP rendendo ad esso possibile accedere in lettura e scrittura ai registri interni.
• Riconoscimento dei segnali di Gate e Interlock in ingresso provenienti dalla scheda GPIO attraverso il connettore micro-line e generazione degli stessi segnali verso il connettore micro-line a seguito della scrittura del DSP in un apposito registro interno di controllo.
• Interfacciamento con il LLC del chipset IEEE1394 per la trasmissione isocrona di un flusso continuo di dati verso il PC remoto attraverso il link FireWire.
L’approccio progettuale alla definizione dell’architettura del sistema è stato di tipo top-down. Si seguirà questo tipo di approccio anche
nella presente trattazione, partendo dalla funzionalità dei vari pin del modulo principale e scendendo via via nella gerarchia del progetto fino ai livelli più bassi.
3.1.1 Top Module : SPADA
Il modulo principale del progetto è stato denominato SPADA e i due moduli base costituenti l’architettura sono il modulo SDPM (Spada Data Processing Module) la cui architettura è stata definita dal gruppo di lavoro dell’Università di Pisa e il modulo DMPORT IP CORE (Data Mover Port Intellectual Property Core), modulo IP fornito da Orsys della cui architettura non si conosce la descrizione in linguaggio VHDL ma solo una definizione dei registri interni, sufficiente al suo utilizzo per la gestione della trasmissione isocrona di dati al LLC del chipset IEEE1394.
Vcc Vcc CPU_A_PAD(20..2) SDPM_CS_RD CPU_AREn_PAD CPU_AWEn_PAD CPU_EXT_INT5_PAD SDPM_CS_WR CPU_D_PAD(31.. 0) GSR SYSTEM_CLK Sdmp_Data_O S1 S2 D C ENB Multiplexer 32 32 DM_CS_RD DM_CS_WR Dsp Data 32 0 CPU_ECLK_OUT_PAD ClockManager DCM_I CPU_AOen_PAD DCM_I_lock CPU_CE2n_PAD CPU_A_PAD_21 CPU_A_PAD_20 CPU_A_PAD_19 CPU_A_PAD_18 60 INPUT_SPADA_SIGNAL ML_pin_A 30..1 ML_pin_C 30..1 SDPM Sdpm_Clk_I Sdpm_Rst Sdpm_Int_o Sdpm_Rdstrb_n_I Sdpm_Rd_I Sdpm_Addr Sdpm_Green_n_led_o Sdpm_Data_I Sdpm_Wrstrb_n_I Sdpm_Red_n_led_o Sdpm_Wr_I DM_PORT IP CORE DM_REG_DATA_O SDPM_REG_DATA_O Sdpm_Spada_Signal_I Dmport_Rd_I Dmport_Wr_I Dmport_Data_O Iobuf Ibuf
all unused inputs are connected to an IBUF to avoids warnings about unused pads
I O I O T IO SPADA Dmport_Rst Dmport _Int_o Dmport_Rdstrb_n_I Dmport_Addr Dmport _Data_I Dmport _Wrstrb_n_I from GSR from CPU_A_PAD(5..2) from CPU_AREn_PAD from CPU_AWEn_PAD 1 Dmport_16..32 CPU_EXT_INT4_PAD from CPU_D_PAD(31.. 0) D S P C P U E M I F M i c r o l i n e c o n n e c t o r 1 3 9 4 L L C Rst_in Clk_in Lock_out Clk_out Sdpm_generic_I Sdpm_generic_o Sdpm_receiver_enable Fpga_green_led Fpga_red_led ML_pin_D_13..10 ML_pin_D_17..14 ML_pin_D_18 0 1 Tristate buffer SDPM_CS DMPORT_CS
3.1.1.1 Interfaccia lato DSP
Come visto nel capitolo precedente l’interfaccia privilegiata tra il DSP e il mondo esterno è la EMIF tramite la quale si può sfruttare un bus indirizzi a 20 bit (corrispondenti ai bit da 21 a 2 degli indirizzi interni del processore) e quattro segnali di abilitazione (/CE0, /CE1, /CE2, /CE3) ognuno corrispondente ad un diverso spazio di indirizzamento. La EMIF è in grado inoltre di fornire un segnale di clock fruibile dai dispositivi ad essa connessi con frequenza impostabile via software agendo sui registri di configurazione del PLL interni al DSP. Nel caso in esame l’FPGA riceve un segnale di clock dalla EMIF con frequenza pari a 90 MHz. Tale segnale viene preventivamente instradato a un DCM (Digital Clock Manager), che garantisce la corretta distribuzione del clock a tutto il sistema limitando problemi come il clock skew dovuti a ritardi di propagazione interni al dispositivo e l’uscita del DCM è stata connessa al segnale SDPM_CLK_I. Si noti che lo SDPM e il DMPORT IP CORE non ricevono lo stesso segnale di clock. Il modulo DMPORT IP CORE riceve infatti il suo segnale di sincronizzazione alla frequenza di 24.576 MHz direttamente dal LLC sulla linea LLC_DMCLK. Per quanto riguarda il bus indirizzi, sono direttamente connessi all’FPGA i bit di selezione /CE2 e /CE3. Per la selezione del modulo SDPM o del modulo DMPORT IP CORE è stato utilizzato il bit /CE2 corrispondente allo spazio di indirizzamento logico che va da 0xA0000000 a 0xAFFFFFFF. Per discriminare i due moduli sono state predisposte delle maschere sui bit più significativi del bus indirizzi. In particolare, come si nota in figura 3.1, il modulo DMPORT IP CORE è selezionato quando il bit CE2n è attivo (cioè basso) e quando i quattro bit più significativi del bus indirizzi sono bassi. Si noti inoltre che solo i quattro bit meno significativi partecipano all’indirizzamento dei registri interni del modulo. Ciò comporta che i registri appaiano replicati nello spazio di indirizzamento del processore per un numero di locazioni dipendente dalla dimensione del registro in questione. Nel caso dello SDPM la maschera predisposta è costituita dal bit più significativo del bus
indirizzi posto al livello logico alto e dall’attivazione sul livello logico basso del bit CE2n. In tal modo gli indirizzi dei registri interni al modulo sono costituiti da 19 bit e poiché il bit meno significativo individua una locazione a 32 bit, si assegna al modulo uno spazio di memoria profondo 2Mbyte che va dalla locazione con indirizzo logico 0xA02000000 a quella con indirizzo 0xA02FFFFC. La presenza di una configurazione di bit che soddisfi la maschera afferma il bit di selezione SDPM_CS o DMPORT_CS e quindi permette l’accesso al modulo da parte del processore. Per quanto concerne il bus dati si noti la presenza di una porta tristate, implementata per connettere il bus dati a 32 bit esterno bidirezionale proveniente dalla EMIF ai due bus dati di ingresso e uscita di ogni modulo. Si notano in figura 3.1 anche i segnali di sincronizzazione per gli accessi in lettura e in scrittura del processore ai due moduli. Si tratta dei segnali CPU_AOEn_PAD, CPU_AWEn_PAD e CPU_AREn_PAD. CPU_AOEn_PAD determina se l’accesso ad un modulo è effettuato in lettura o scrittura mentre gli altri due segnali sono i segnali per il campionamento dei dati da scrivere (CPU_AWEn_PAD) o da leggere (CPU_AREn_PAD). Si osservi la presenza dei segnali CPU_EXT_INT5_PAD e CPU_EXT_INT4_PAD. Tali segnali completano l’interfacciamento dei due moduli con il DSP, e sono direttamente connessi al controllore di interrupt del processore. In seguito verrà esplicitato come è stato sfruttato il meccanismo dell’interruzione nello sviluppo del firmware del sistema.
3.1.1.2 Interfaccia lato micro-line
Quanto detto riguarda l’interfacciamento dei due moduli del sottosistema implementato su FPGA col DSP. Come detto in precedenza il FPGA è anche direttamente connesso al connettore micro-line della C6713 Compact. Tramite tale connettore sì è pensato di fare arrivare al modulo
provenienti dai pin (30..1) dei connettori A e C. Questi segnali, opportunamente sincronizzati, vengono instradati ai 60 contatori a 16 bit presenti all’interno del modulo SDPM di cui si darà ampia descrizione in seguito. Il connettore D è stato sfruttato per la gestione dei segnali connessi alla scheda GPIO e per l’abilitazione dei chip presenti sulla scheda ricevitori. Si notano infatti i segnali SDPM_GENERIC_O, SDPM_GENERIC_I e SDPM_RECEIVER_ENABLE connessi rispettivamente ai pin (13..10), (17..14) e 18 del connettore D. Si notano infine i segnali SDPM_Red_n_Led_O e SDPM_Green_n_Led_O, utilizzabili, a scopo di debug, per accendere o spegnere i led connessi al FPGA presenti sulla C6713 Compact.
3.1.1.3 Interfaccia lato LLC
Per quanto riguarda i segnali del modulo DMPORT_IP_CORE non connessi al DSP essi possono essere visti divisi in due gruppi distinti, in quanto il modulo è pensato per essere connesso sia ad un dispositivo LLC di un chipset IEEE1394 che ad una porta esterna per garantire un flusso continuo di dati a 32 bit provenienti da una fila di connettori del bus micro-line. Nell’ambito del progetto SPADA non è richiesta una connessione esterna tramite il connettore micro-line per sostenere tale flusso di dati in quanto, come si vedrà in seguito nella descrizione dell’applicazione DSP, la trasmissione dei dati da trasferire al LLC sfruttando il DM_PORT_IP_CORE avviene a livello di board, pertanto i segnali in questione restano inutilizzati. Sono invece usati i segnali di interfacciamento tra il DMPORT_IP_CORE e il chip LLC che consentono un trasferimento bidirezionale tra il modulo stesso e il chipset IEEE1394.
Data una descrizione dei segnali di interfacciamento tra i due moduli principali dell’architettura e il mondo esterno si passa ora ad una descrizione più dettagliata dei due moduli esponendo le funzionalità dei moduli a gerarchia inferiore presenti nello SDPM e i registri caratteristici del DMPORT_IP_CORE.
3.1.2 SDPM
Come precedentemente esposto la funzionalità principale a cui deve assolvere il modulo è il conteggio del numero di impulsi provenienti dai 60 buffer delle schede ricevitori su finestre temporali di acquisizione impostabili esternamente nel range tra 10 µs a 100 ms con una risoluzione di 10µs. Si è trattato quindi, nel rispetto delle specifiche di progetto, di implementare una batteria di 60 contatori a 16 bit con notifica di saturazione i quali contino in modo ciclico gli impulsi e il cui contenuto, alla fine di ogni finestra di acquisizione, venga reso disponibile al mondo esterno. Il modulo che assolve a questa funzione è stato nominato INPUT_COUNTER. Come si vede in figura 3.2 tale modulo è dotato di quattro ingressi e due uscite, una ad un bit per la notifica di saturazione (IC_SAT) e una a 16 bit che riporta il risultato del conteggio (IC_COUNT). In ingresso si ha, ovviamente il clock (IC_CLK), il segnale di cui effettuare il conteggio (IC_SPADA_SIGNAL_I), un segnale per azzerare il conteggio in maniera sincrona (IC_CLEAR) e un segnale di reset (IC_RST) connesso al reset globale del sistema.
Restando sullo stesso livello gerarchico si trova, accanto al modulo INPUT_COUNTER, di cui sono state fatte 60 istanze all’interno del modulo SDPM, il modulo TIMER, il quale assolve alla funzione di fornire, a partire dal clock di sistema a 90Mhz, degli impulsi di durata pari a un ciclo di clock distanziati temporalmente tra loro di una quantità pari alla finestra temporale impostata esternamente attraverso la scrittura di una parola di configurazione nei 14 bit meno significativi del registro CFG_REG (vedi tabella 3.1). In tal modo, connettendo l’uscita del modulo TIMER al clear di ogni contatore si fa in modo che i risultati dei conteggi corrispondano proprio al numero di impulsi rilevati durante la finestra temporale.
scrittura da parte del processore su uno dei registri accessibili in scrittura. Il funzionamento della macchina consiste nell’introdurre due cicli di attesa in seguito ad una scrittura prima che il dato appena scritto possa essere considerato valido. rst clk Ic_count 16 Ic_sat Ic_clear Spada_signal rstclk Ic_count 16 Ic_sat Ic_clear Spada_signal Ic_counter pari 0..28 Ic_counter dispari 1..29 32 Count_reg_matrix_ff 32 clk en Timer rst clk Tmr_pulse-o Tmr_period_I Tmr_lnp 14 Write valid state machine rst clk LNData Data_en Valid_bit Clear_valid_bit Clk rst 32 Count_info_reg_ff clk en 13..0 32 13..0 Cfg_reg_FF 32 Clk Cfg_reg Wrvalid_FF 60 … clear Int_o Wrstrb_n_I 32 2 15 14 Green_ed Red_red 32 Rd_I En Addr 19 Cpu_a_pad(20..2) To all rst To all clk
SDPM ( Spada Data Processing Module )
GSR System_clk SDPM_CS_RD CPU_AREn_PAD CPU_AWEn_PAD Sdpm_data_I 32 60 … … … ……… ………. .. INPUT_SPADA_SIGNAL LED_GREENn_PAD LED_REDn_PAD CPU_EXT_INT5_PAD SDPM_REG_DATA_O 30x32 0..3 0 Selector Wr_I SDPM_CS_WR CPU_D_PAD(31.. 0) Sdmp_Data_O Sdpm_Clk_I Sdpm_Rst Sdpm_Int_o Sdpm_Rdstrb_n_I Sdpm_Rd_I Sdpm_Addr Sdpm_Green_n_led_o Sdpm_Wrstrb_n_I Sdpm_Red_n_led_o Sdpm_Wr_I 32 …... rst Data_I(0) Sel_mask 32 from cfg_reg clear_wr 21 SAT Generic_reg Clk rst en En Selector 19 Clk rst Clk 2 4 31 4 22 SDPM_GENERIC_I SDPM_GENERIC_O RECEIVER_ENABLE 4 4 32 2 Gate_I Interlock_I Ga te _ S W Interlock_SW Safety_Mode Gate_O Interlock_O 14 2 20 19 18 17 16 15..14 0 2 2 1..02 3 16 9 8
Figura 3.2: Architettura del modulo SDPM
Nella descrizione del modulo SDPM sono definiti tutti i registri interni assieme alla definizione dei processi necessari alla lettura e scrittura dei registri stessi. Oltre al CFG_REG, a cui si accennava sopra, è stato implementato un registro a 10 bit, accessibile in scrittura, per la gestione degli otto segnali GPIO connessi al bus microline e dell’abilitazione dei chip della scheda ricevitori. In particolare a questo registro, nominato GENERIC_REG, è anche connessa la logica necessaria alla generazione dei segnali di Gate e Interlock in safety mode (si ricorda che in questa modalità la saturazione di un solo contatore indica la necessità di generare un segnale di Interlock per il distacco dell’alimentazione dei sensori) o in funzionamento normale, per cui l’attivazione via software o hardware dei segnali di Gate o Interlock deve
comportare l’attivazione dei segnali di uscita corrispondenti sulla scheda GPIO. Il registro GENERIC_REG contiene inoltre un bit, risultato dell’OR logico tra tutti i bit di saturazione dei contatori, recante pertanto l’informazione sullo stato di saturazione, indipendentemente dall’attivazone del safety mode o meno. Ultimo registro accessibile in scrittura è il registro WRITE_VALID_DFF, utilizzato, in sinergia con il modulo WRITE_VALID_STATE_MACHINE, per validare le scritture effettuate dal processore sui registri interni dello SDPM.
Sono stati implementati inoltre 30 registri a 32 bit accessibili in lettura da parte del processore col compito di immagazzinare e rendere disponibili gli ultimi risultati di conteggio dei contatori. In questo modo ogni registro contiene le uscite di una coppia di contatori in modo da poter sfruttare tutta la larghezza del bus a 32 bit presente sulla scheda Orsys.
Di seguito si riporta in modo sintetico il nome, la descrizione, la modalità di accesso da parte del processore e gli indirizzi logici dei registri implementati nell’architettura del modulo SDPM.
Nome Indirizzo Accesso Funzione
SDPM_COUNT_INFO_REG 0xA0200000 R Contiene informazioni circa il periodo impostato, l’attivazione del safety mode, lo stato di saturazione dei contatori e i segnali di gate e interlock.
COUNT_REG_MATRIX(0) 0xA0200004 R Prima coppia di risultati di conteggio.
COUNT_REG_MATRIX(1) 0xA0200008 R Seconda coppia di risultati di conteggio
… R Altri registri di uscita per i
risultati.
COUNT_REG_MATRIX(29) 0xA0200078 R Trentesima e ultima coppia di risultati.
SDPM_CFG_REG 0xA020007C W/R Consente di impostare il periodo di conteggio dei contatori e di accendere i led connessi al FPGA.
SDPM_WRITE_VALID_DFF 0xA0200080 W Flip flop per la validazione della scrittura.
SDPM_GENERIC_REG 0xA0200084 W/R Settaggio dei quattro segnali GPO connessi al bus microline via software, impostazione del safety mode e abilitazione dei chip della scheda ricevitori.
Risulta necessario ora fornire una descrizione più dettagliata dei tre sottomoduli esposti sinteticamente in questo paragrafo per comprendere più a fondo l’architettura dell’intero sistema.
3.1.2.1 INPUT_COUNTER
Il modulo INPUT_COUNTER è costituito dai sottomoduli COUNTER_N_SAT e RETP. Il primo modulo consiste, in un contatore a 16 bit con saturazione, abilitazione e clear, tuttavia vista la asincronia rispetto al clock degli impulsi provenienti dai ricevitori, è stato previsto un modulo di sincronizzazione RETP, costituito dalla cascata di due flip-flop DFF, che provvede a fornire un impulso di durata pari a un ciclo di clock per ogni fronte in salita ricevuto in ingresso. L’uscita del modulo RETP, sincrona col clock di sistema, viene utilizzata per abilitare il contatore, il quale al successivo fronte di clock, incrementa il valore dell’uscita di un’unità. Come è noto l’errore che si commette utilizzando contatori digitali è l’errore di quantizzazione, pari a ±1 ciclo di clock. In questo caso tuttavia vi è il rischio di commettere un errore maggiore nel caso si presenti la situazione in cui i segnali di abilitazione proveniente dal RETP e di azzeramento, proveniente dal TIMER, sono entrambi alti, in quanto all’errore intrinseco del contatore si sommerebbe quello dovuto alla ricezione dell’impulso di clear durante l’abilitazione. Nel caso si presenti una situazione di questo tipo pertanto si fa in modo che il contatore inizi a contare da 1 anziché da 0 in modo da evitare di perdere il primo impulso. Di seguito si mostra lo schema a blocchi dei moduli COUNTER_N_SAT e RETP.
3.1.2.2 TIMER
Il modulo TIMER è una macchina a stati che provvede, in base al contenuto del registro CONFIG_REG e quindi alla durata della finestra temporale di conteggio, a generare il segnale di sincronizzazione principale del sistema in quanto l’uscita del modulo, oltre che ad azzerare il contenuto dei contatori ogniqualvolta sia trascorso un periodo pari alla finestra temporale, è connessa direttamente al DSP tramite la linea CPU_INT5_PAD in modo da informare il processore della disponibilità di nuovi risultati di conteggio utili da prelevare. Il modulo costituisce quindi la base dei tempi dell’intero sistema. In base al valore della parola di configurazione presente nei 14 bit meno significativi del registro CFG_REG il segnale in uscita da TIMER ha un periodo che varia da 10µs a 163,84ms corrispondenti a valori del registro CFG_REG pari rispettivamente a 0x00000000 e a 0x00003FFF. Al variare del bit meno significativo del registro la durata della finestra temporale varia di 10µs. Ciò si ottiene sfruttando un secondo modulo, istanziato all’interno della descrizione del TIMER, denominato TIME_BASE, il quale fornisce continuamente, a partire dal clock di sistema, un impulso di durata pari a un ciclo di clock ogni 10µs. Questo segnale viene sfruttato come ingresso di un contatore che provvede a confrontare, ad ogni nuovo impulso ricevuto, il risultato di conteggio con la parola di configurazione attuale. Quando l’uguaglianza è verificata il contatore viene azzerato, ricomincia a contare confrontando continuamente il risultato di conteggio con la parola di configurazione attuale e viene generato un impulso di durata pari ad un ciclo di clock che provvederà ad azzerare i contatori dei segnali provenienti dai sensori e ad informare la CPU della presenza di nuovi risultati di conteggio utili da prelevare. E’pertanto necessario che il processore sia in grado di servire la richiesta di interruzione proveniente dall’FPGA che nel caso peggiore si verifica ogni 10µs. A tale scopo, come
background del trasferimento di dati tra due locazioni qualunque dello spazio di indirizzamento.
Figura 3.4: Architettura del modulo Timer
3.1.2.3 WRITE_VALID_STATE_MACHINE
Il modulo WRITE_VALID_STATE_MACHINE è una macchina a stati realizzata per far sì che le scritture del processore sui registri accessibili in questo modo implementati nello SDPM vadano a buon fine, impedendo eventuali errori di scrittura dovuti ai noti fenomeni di asincronia nella comunicazione tra dispositivi diversi montati sullo stesso sistema. Il modulo presenta tre segnali di ingresso (RST, CLK, WRITE_VALID_DFF) e tre di uscita (WV_CLEAR_VALID_BIT, WV_DATA_ENABLE, WV_LOAD_NEW_DATA). WRITE_VALID_DFF è connesso esternamente all’uscita del registro WRITE_VALID_DFF. Una volta che il contenuto di tale registro viene posto a 1 a seguito di una scrittura del processore al suo indirizzo, vi sono due cicli di attesa per evitare eventuali alee, passati i quali vengono posti a livello logico alto i bit di uscita WV_CLEAR_VALID_BIT e WV_DATA_ENABLE. Il primo bit resetta il contenuto del registro WRITE_VALID_DFF, mentre il secondo segnale abilita il caricamento dei registri CFG_REG e GENERIC_REG.
Figura 3.5: Modulo Write Valid State Machine: ingressi e uscite.
L’uscita di CFG_REG viene aggiornata con la nuova parola di configurazione al ciclo di clock successivo. Nell’ultimo stato, prima di tornare nello stato di attesa, la macchina abilita il caricamento della nuova finestra temporale, codificata nei 14 bit meno significativi del registro CFG_REG, ponendo a livello alto il bit di uscita WV_LOAD_NEW_DATA, connesso al segnale di ingresso TMR_LOAD_NEW_PERIOD del modulo TIMER. Quanto detto si traduce, a livello di sviluppo dell’applicazione DSP, nella necessità di notificare la validità di un dato che si desidera scrivere nei registri dello SDPM facendo seguire ad ogni scrittura una ulteriore scrittura del valore 0x00000001 all’indirizzo corrispondente al registro WRITE_VALID_DFF. Di seguito si riporta il diagramma di stato che chiarisce il funzionamento della macchina a stati WRITE_VALID_STATE_MACHINE. Valid clear_valid_bit=0 data_en=0 load_new_data=0 Valid 3 clear_valid_bit=0 data_en=0 load_new_data=0 Enable_Data clear_valid_bit=1 data_en=1 load_new_data=0
Load New Data clear_valid_bit=0 data_en=0 load_new_data=1 Valid 2 clear_valid_bit=0 data_en=0 load_new_data=0 Valid_bit=0 Valid_bit=0
Valid_bit=1 Valid_bit=1 Valid_bit=1
Valid_bit=0
others
Descritto il modulo SDPM fino ai più bassi livelli della sua struttura gerarchica si passa ora ad esporre le caratteristiche funzionali del modulo DMPORT IP CORE fornito da Orsys per la comunicazione con il chipset IEEE1394 presente sulla Data Processing Board. Verrà descritta la struttura interna solo a livello dei registri in quanto, come già detto, essendo un modulo IP non è nota l’architettura nei minimi dettagli.
3.1.3 DMPORT IP CORE
Come accennato precedetemente, il modulo DMPORT_IP_CORE comunica col mondo esterno attraverso tre gruppi di segnali che lo interfacciano rispettivamente al DSP, al LLC e al connettore micro-line, come si vede in figura 3.7. Nel caso di flusso di dati provenienti dal DSP di parla di software streaming. Nel caso in cui invece si faccia uso di un dispositivo esterno connesso al connettore micro-line si parla di flusso dati tramite la streaming port.
Nell’ambito del progetto SPADA la connessione al connettore microline non è stata sfruttata, mentre sono state utilizzate le interfacce con il DSP e il dispositivo LLC per la trasmissione dei risultati di conteggio dai registri di uscita del FPGA al PC remoto tramite il link IEEE1394. L’utilizzo del modulo a livello FPGA è stato piuttosto semplice in quanto è stato sufficiente istanziare lo stesso nel top module del progetto e interconnettere come esposto precedentemente i vari segnali ai corretti pin del FPGA e alla logica per il montaggio nello spazio di memoria del DSP. Internamente il modulo presenta una serie di registri di controllo e di stato a 32 bit montati nello spazio /CE2 che permettono di impostare i parametri della trasmissione FireWire e di verificarne lo stato via software. Oltre a questi registri, è implementato nel modulo un buffer FIFO (First In First Out) da 8 Kbyte (organizzata in 2048 parole da 34 bit) sul quale vengono immagazzinati temporaneamente i dati che vengono da e vanno verso il LLC. Ogni parola del buffer FIFO è costituita da 34 bit in quanto 32 costituiscono il dato vero e proprio e gli altri due sono bit di sincronizzazione.
Si dà ora una rapida esposizione della funzione dei registri presenti nel modulo senza soffermarci sul significato dei singoli campi per dettagli sui quali si rimanda alla bibliografia ([24]). La tabella seguente riporta una descrizione sintetica degli indirizzi dei vari registri e dei loro nomi simbolici.
Tabella 3.2: Registri interni del DMPORT IP CORE.
STR_CTL (Streaming Control & Status Register): Questo registro
permette di impostare le caratteristiche di base del flusso dati da e verso il LLC. Definisce infatti la larghezza delle singole parole (32 o 16 bit), permette di decidere se includere o meno nel singolo pacchetto di dati un
header ovvero una serie di bit che contengano informazioni sul formato dei
dati trasferiti, come il numero di byte che costituiscono il pacchetto, il numero identificativo del canale su cui vengono trasmessi i dati o la presenza o meno di bit di sincronizzazione. Si può impostare la modalità con cui inizia un trasferimento verso il LLC che può essere manuale, ovvero i dati vengono trasferiti dalla FIFO verso il LLC solo per un pacchetto o automatica, per cui il trasferimento inizia ogniqualvolta vi sia nella FIFO un numero di byte sufficienti a costituire un pacchetto. E’ possibile inoltre impostare il tipo di streaming in ingresso che può essere di tipo software attraverso l’interfaccia col DSP o esterno attraverso la
streaming port.
STR_HDR1, STR_HDR2 (Streaming Header Register): Questi
registri permettono di impostare i bit dell’header dei pacchetti trasmessi al LLC se previsto nel registro STR_CTL.
STR_AFL, STR_AEL (Streaming FIFO Almost Full/Empty Register): Questo registri definiscono rispettivamente lo stato di “quasi
pieno” e di “quasi vuoto” per il buffer FIFO presente nel DMPORT IP CORE. Questa condizione può essere utilizzata, in caso di software
streaming come evento di sincronizzazione per l’inizio di un trasferimento
oppure come evento scatenante dell’attivazione del segnale di interrupt sulla linea CPU_EXT_INT4 connessa al DSP.
STR_IE, STR_IF (Streaming Interrupt Enable/Flag Register): Con
questi registro è possibile impostare, abilitare e segnalare tramite dei flag l’evento scatenante per la richiesta di interruzione verso il processore sulla linea CPU_EXT_INT4. Le cause di interrupt possono essere legate ad errori segnalati dal LLC tramite la linea DMERR oppure, come si accennava prima, essere connesse al livello di riempimento del buffer FIFO.
STR_LEVEL (Streaming FIFO Fill Level Register): Questo registro
riporta in ogni momento il livello di riempimento del buffer FIFO espresso in quadlets, ovvero in double words.
STR_DATA1, STR_DATA2 (Streaming Data Registers): Si tratta
in realtà di un unico registro a 32 bit per la scrittura dei dati da inserire nella FIFO sfruttando il software streaming.
Si è ultimata così la descrizione dell’architettura hardware implementata sul FPGA. Si ricorda che allo stato dell’arte dell’progetto SPADA le soluzioni esposte sono sufficienti all’implementazione di una sola delle tre applicazioni target del progetto, la FTI. Tuttavia esse rappresentano la base portante anche delle altre due applicazioni. Per lo
TIMER con caratteristiche differenti che garantiscano una risoluzione temporale superiore a quella attuale. La risoluzione di 10 µs non è più sufficiente infatti in quanto, essendo necessario impostare una frequenza della sinusoide esterna variabile con la risoluzione di 1 Hz nel range tra 1.5 KHz e 3 KHz e dovendo contare gli impulsi provenienti dai sensori durante i semiperiodi delle onde sinusoidali, risulta che, nel caso peggiore, ovvero passando da una frequenza pari a 2999 Hz a 3000 Hz le relative finestre di conteggio devono differire in durata di una quantità pari a 55.57 ns, valore non ottenibile con il TIMER attuale. Il minimo quanto temporale disponibile è quello del clock di sistema, con frequenza pari a 90 MHz e periodo 11.12 ns. Una possibile soluzione è quella quindi che prevede l’utilizzo come base dei tempi non più del modulo TIME_BASE bensì del clock di sistema. Tale soluzione comporta ovviamente l’implementazione nel modulo TIMER di un contatore ad almeno 24 bit per poter raggiungere il conteggio del numero di cicli di clock necessari a coprire il valore limite superiore di 100 ms imposto dalla finestra temporale a durata maggiore.
Descritta l’architettura FPGA si può ora passare a illustrare l’applicazione DSP sviluppata nell’ambito del progetto SPADA mostrando anche in questo caso lo stato dell’arte del sistema e i passi futuri da compiere.
3.2 Applicazione DSP
In questo paragrafo verrà illustrato lo stato attuale dell’applicazione software sviluppata per il DSP. Al DSP è affidata, in quanto master dell’intero sistema, l’inizializzazione di tutti i dispositivi presenti sulla Data Processing Board i cui registri interni sono montati nello spazio di memoria del processore attraverso la EMIF. In particolare, parlando di
Board level ci si riferirà a quella parte di codice eseguita DSP che si riflette
direttamente a livello dei dispositivi esterni montati sulla scheda. A questo livello il DSP si occupa di:
• programmare il FPGA scaricando la configurazione relativa all’architettura, descritta precedentemente, nella RAM interna del FPGA.
• inizializzare i registri del PLD presente sulla C6713 compact
• inizializzare il dispositivo UART per la gestione della connessione RS-232.
• configurare i registri del DMPORT IP CORE per realizzare il trasferimento sincrono di dati attraverso il link IEEE1394.
• inizializzare il dispositivo LLC per la ricezione e l’invio asincrono di dati attraverso il link IEEE1394.
Per compiere le operazioni sopra esposte sono state sfruttate le funzioni di libreria fornite da Orsys che hanno consentito una facile gestione di tutte le risorse presenti sulla scheda.
Oltre a ciò si sfruttano le potenzialità del processore TMS320C6713 e parleremo di CPU level facendo riferimento alla parte di codice che agisce su risorse quali:
• La periferica EMIF per interfacciare correttamente il processore con i dispositivi esterni quali la SDRAM o la EEPROM per le quali devono essere rispettate le corrette temporizzazioni di accesso. • Il controllore di interrupt per la gestione dei segnali di interruzione
esterni provenienti dal modulo SDPM, dal LLC o dalla UART e dei segnali di interrupt interni associati alla periferica McASP e al controllore EDMA.
• Il controllore EDMA per il trasferimento dei dati dal modulo SDPM al DMPORT IP CORE.
• La periferica McASP per la generazione dei campioni del segnale sinusoidale.
Il terzo livello su cui agisce il software sviluppato è il cosiddetto CPU
core level che riguarda l’impostazione dei valori dei registri CSR (Control
& Status Register), IER (Interrupt Enable Register), ICR (Interrupt Clear Register) e DEVCFG (Device Config) del processore.
Operando sui tre livelli sopra esposti si è realizzata una applicazione software in grado di:
• inizializzare correttamente i registri del processore e dei dispositivi ad esso connessi.
• gestire le memorie SDRAM e EEPROM attraverso la EMIF.
• compiere un trasferimento sincrono di dati dai registri di uscita del FPGA al PC remoto tramite il link IEEE1394.
• ricevere e interpretare i comandi inviati dal PC remoto attraverso la comunicazione asincrona tramite il link IEEE1394.
• comunicare informazioni di debug o ricevere comandi attraverso la porta seriale secondo lo standard RS-232.
• generare un segnale PCM in formato IIS (Inter Integrated Sound) corrispondente ad una sinusoide a ampiezza, frequenza e fase variabili impostabili dal PC remoto.
Il codice, scritto in linguaggio C, è organizzato nei moduli:
• initialization.c : contiene le definizioni delle funzioni che sono state scritte per l’inizializzazione delle periferiche del DSP e del bus IEEE1394.
• callq.c : modulo fornito da Orsys che contiene le definizioni delle funzioni per la gestione della coda di callback, meccanismo di cui si parlerà in seguito.
• interruptHandler.c : contiene le definizioni delle routine di interrupt.
• spada_fpga.c : contiene la configurazione da scaricare nel FPGA. • sys6713.c : modulo fornito da Orsys che contiene le funzioni per
l’inizializzazione dei registri interni del DSP e dei registri di configurazione della scheda.
• cfgrom.c : contiene la configuration ROM necessaria all’identificazione della C6713 compact sul bus IEEE1394
• main.c : è il programma principale e contiene le definizioni delle funzioni della API per la gestione del bus IEEE1394.
Nel progetto sono inoltre incluse le librerie:
• csl6713.lib : contiene le definizioni delle funzioni presenti nelle CSL per il processore TMS320C6713.
• rts6700.lib : è la cosiddetta run-time support library ovvero contiene le definizioni delle funzioni standard del linguaggio C++ e di supporto per il corretto collegamento tra i moduli e l’esecuzione del programma disassemblato dal compilatore in linguaggio macchina. • LYNXAPI : contiene le definizioni delle funzioni dell’API per la
gestione del LLC del chipset IEEE1394.
Si mostrano ora le azioni svolte dall’applicazione ai vari livelli hardware esposti precedentemente. Si concluderà il paragrafo dando una visione schematica attraverso un diagramma di flusso dell’applicazione.
3.2.1 CPU core level
Per settare correttamente i registri che costituiscono il core del processore si è sfruttata la struttura sC6xCpuInitRegs definita nella libreria fornita da Orsys e i cui campi permettono di scrivere nei registri CSR, IER e ICR del DSP. Il registro CSR viene inizializzato in modo da disabilitare globalmente le richieste di interrupt azzerando il bit GIE (Global Interrupt Enable). Tutti gli altri campi del registro sono posti a zero. Vengono resettati inizialmente anche tutti i bit del registro IER (Iterrupt Enable Register) in modo da disabilitare ogni richiesta di interruzione e vengono cancellate eventuali richieste di interruzione pendenti scrivendo nel registro ICR (Iterrupt Clear Register). I registri CSR e IER verranno in seguito utilizzati per l’abilitazione dei segnali di interrupt provenienti dal FPGA, dal LLC, dal controllore EDMA e dalla McASP. Oltre a questi tre registri, a livello del core processor è stato necessario impostare, una volta per tutte il registro DEVCFG, in modo da rendere possibile l’utilizzo della periferica McASP in quanto tramite questo registro si può selezionare l’origine dei pin condivisi tra le periferiche interne del processore, tra cui figurano i pin di uscita della McBSP e della McASP.
3.2.2 CPU level
Come detto precedentemente, per CPU level si intende quella porzione di codice sviluppato per la gestione delle periferiche interne del DSP. In questo paragrafo si mostrerà come sono state sfruttate le periferiche interne del processore e le modalità di utilizzo delle stesse a livello di linguaggio di programmazione. Come illustrato nei capitoli
rendono il processore estremamente versatile e utilizzabile in un vasto range di applicazioni. Nel caso specifico tuttavia non si è reso necessario sfruttare tutte le periferiche disponibili ma è risultato sufficiente l’utilizzo di un loro sottoinsieme e nella fattispecie sono stati sfruttati:
• i PLL interni per la generazione dei segnali di clock • la EMIF per l’interfacciamento col mondo esterno
• il controllore EDMA e QDMA per il trasferimento di dati in background
• il controllore di interrupt • la periferica audio McASP •
3.2.2.1 PLL
I PLL interni del processore vengono configurati un’unica volta nella fase di inizializzazione utilizzando la funzione di libreria C6xCptInit che imposta i registri di controllo del PLL in modo da configurare il processore per una frequenza del clock del core processor pari a 200Mhz. Il clock della EMIF e delle altre periferiche esclusa la McASP è settato a 90Mhz mentre per la McASP la frequenza del clock è impostata a 25Mhz. I registri di configurazione agiscono sul prescaler e sui divisori di frequenza visti nel capitolo 2.
3.2.2.2 EMIF
L’inizializzazione della EMIF viene effettuata scrivendo nei registri di controllo della periferica al fine di rispettare le caratteristiche di accesso ai dispositivi esterni ad essa connessi. Per compiere questa operazione è necessario scrivere nei registri di controllo della EMIF che configurano i quattro spazi di indirizzamento precedentemente descritti denominati /CE0, /CE1, /CE2, /CE3. Lo spazio /CE1 è dedicato alla SDRAM e per esso è necessario configurare il tipo di accesso alla memoria (a 32 bit) e le
relativo alla EEPROM e agli altri dispositivi diversi dal FPGA e dalla SDRAM indirizzabili dal DSP. Gli spazi di indirizzamento /CE2 e /CE3 sono relativi al FPGA e vengono configurati rispettivamente come spazi di indirizzamento organizzati a 32 e 16 bit.
Per compiere queste operazioni si sfruttano i campi della struttura
sC6xCptInitRegs con la quale è possibile impostare i valori dei registri
della EMIF semplicemente scrivendo negli appositi campi.
3.2.2.3 Controllori EDMA e QDMA
Il controllore EDMA presente sul DSP TMS320C6713 è stato utilizzato per ottemperare il trasferimento dei risultati di conteggio dai registri di uscita del modulo SDPM alla SDRAM ogniqualvolta venga presentato dallo stesso una richiesta di interruzione sulla linea EXT_INT5. Dopo essere stati trasferiti nella SDRAM, i dati vengono prelevati e inviati al DMPORT IP CORE il quale dà il via al trasferimento isocrono al LLC, sfruttando il controllore QDMA, caratterizzato dal fatto di far partire il trasferimento dati con la scrittura dell’ultimo parametro nel corrispondente descrittore. Grazie alla possibilità di concatenazione dei trasferimenti si è sfruttata una tecnica di ping pong buffering in modo da evitare perdite di dati durante il trasferimento via QDMA. Questa tecnica consiste nella dichiarazione di due buffer di uguale dimensione (in grado di accogliere 20 frame da 31 dwords ciascuno), risiedenti nella SDRAM, che vengono acceduti in scrittura o in lettura alternativamente. In questo modo ogni volta che viene completato un trasferimento via EDMA dal FPGA alla SDRAM ed è stato riempito uno dei due buffer, oltre a far partire il trasferimento via QDMA verso la FIFO del DMPORT IP CORE, viene eseguito in background il trasferimento dal FPGA al secondo buffer che costituirà il pacchetto dati successivo. Questo procedimento viene messo in pratica configurando opportunamente il descrittore del canale 5 (corrispondente all’evento scatenante che si verifica sulla linea EXT_INT5 connessa al modulo SDPM) del controllore EDMA e altri due descrittori
per il ricaricamento dei parametri al termine di ogni trasferimento. La segnalazione del completamento del trasferimento da parte del controllore EDMA avviene tramite la linea INT8 del controllore di interrupt e nella routine vengono settati dei flag per la segnalazione al programma principale dell’operazione appena svolta.
Ogni INT8 via EDMA SDPM Conteggi e registri PONG buffer (20*31 dwords) PING buffer PONG buffer PING buffer (20*31 dwords) Ogni INT8 via
QDMA
DMPORT_IP_CORE LLC
FIFO IEEE1394
Figura 3.8: Schema di funzionamento del ping-pong buffering.
La funzione che inizializza il descrittore del canale 5 del controllore EDMA è stata definita a parte e nominata Spada_DMA_Init. Essa riceve come argomento una struttura contenente i parametri con cui inizializzare il descrittore e un puntatore alla prima delle locazioni della PaRAM contenenti il descrittore stesso e restituisce un tipo void. Per abilitare il
Enable Register) e CIPR (Channel Interrupt endine Register) del controllore EDMA il valore necessario ad abilitare il canale 5 del controllore stesso a riconoscere l’evento EXT_INT5 e a interrompere la CPU tramite la linea INT8 del controllore di interrupt una volta completato il trasferimento.
Per quanto riguarda il controllore QDMA l’inizializzazione del set di parametri del descrittore QDMA eccetto uno, corrispondente all’indirizzo della sorgente attuale coinvolta nel trasferimento, avviene nella fase di inizializzazione del bus IEEE1394. L’impostazione dell’ultimo parametro avviene ogni volta che un trasferimento EDMA è stato completato e comporta l’inizio del trasferimento QDMA alla FIFO del DMPORT IP CORE.
3.2.2.4 Controllore di interrupt
Il meccanismo dell’interruzione di programma è stato utilizzato per la gestione delle richieste di interrupt proveniente dispositivi esterni connessi al DSP come il dispositivo UART e il LLC e per servire le richieste di interruzione segnalate dalle periferiche interne come il controllore EDMA e la periferica di trasmissione audio McASP.
La gestione dei segnali di interrupt avviene sia attraverso i registri del core processor CSR, IER e ICR visti nella descrizione del CPU core
level che attraverso i registri MUXH e MUXL, visti nel capitolo 2, che
permettono di assegnare a ciascun tipo di interrupt una differente sorgente. Per quanto riguarda il controllore EDMA, connesso alla linea INT8, la UART, connessa alla linea EXT_INT7 e il LLC, connesso alla linea EXT_INT6, le impostazioni dei registri MUXH e MUXL sono state lasciate invariate, essendo valida la configurazione di default dei due registri. Per quanto riguarda le richieste di interrupt provenienti dalla McASP, non essendo prevista di default la connessione diretta tra il segnale AXINT proveniente dalla McASP e il controllore di interrupt, è stato necessario
impostare il campo relativo alla sorgente della linea INT10 del controllore con il valore atto ad assegnare tale linea al segnale AXINT.
Per la scrittura dei registri CSR, IER e ICR, oltre all’utilizzo della struttura sC6xCpuInitRegs in fase di inizializzazione dei registri del core processor, sono state utilizzate le funzioni di libreria fornite da Orsys
C6xIntHook, C6xIntEnable, C6xIntDisable, C6xGlobalIntEnable. La
prima funzione riceve come argomento un numero intero corrispondente al tipo dell’interruzione in questione e un puntatore alla prima locazione del codice corrispondente alla routine di interrupt che servirà la richiesta corrispondente. Essa permette di inserire l’indirizzo della routine nel vettore contenente gli indirizzi di tutte le routine di interrupt ovvero nella IST (Interrupt Service Table). Le altre tre ricevono come argomento un numero intero corrispondente al tipo dell’interruzione in questione e assolvono rispettivamente al compito di abilitare la richiesta di interrupt corrispondente asserendo l’apposito bit del registro IER, disabilitare la richiesta di interrupt asserendo il corrispondente bit del registro ICR e abilitare globalmente le richieste di interrupt affermando il bit GIE nel registro CSR del DSP.
3.2.2.5 McASP
La periferica di riproduzione audio è quella col più ampio set di registri tra le periferiche presenti sul DSP TMS320C6713. Come si è visto nel secondo capitolo questa periferica è in grado di supportare diversi formati audio, tuttavia quello scelto per la generazione dei campioni costituenti il segnale sinusoidale è il formato IIS (Inter Integrated Sound) sia per la sua intrinseca semplicità che per ragioni storiche del progetto. La difficoltà maggiore nella gestione della periferica sta nella sua corretta inizializzazione, in quanto il gran numero di possibilità disponibili rende ardua la corretta identificazione dei parametri da impostare per ottenere il
(Chip Support Library) presenti all’interno del pacchetto software di Code Composer Studio v2. E’ stato possibile, grazie alla dichiarazione all’interno della CSL di strutture e di funzioni per la gestione della periferica, inizializzare i registri della McASP con i corretti valori e nella sequenza corretta in modo da ottenere sul pin di uscita un segnale costituito da campioni su 32 bit in formato IIS con un sample rate pari a 48.83Khz. La funzione che inizializza la periferica è stata nominata
SpadaMcASPInit. Le operazioni che vengono svolte con una chiamata a
questa funzione sono:
• Abilitazione dei pin della McASP al posto di quelli della McBSP scrivendo nel registro DEVCFG del core processor.
• Attivazione della connessione AXINT con il controllore di interrupt sulla linea INT10 scrivendo il valore corrispondente della tabella del selettore di interrupt nel registro MUXH.
• Dichiarazione di un handler alla periferica McASP0.
• Inizializzazione delle strutture dichiarate nella CSL con i parametri per impostare i vari campi dei registri della McASP0. • Apertura della periferica mediante la chiamata alla funzione
MCASP_open passandole come argomento l’handler
precedentemente dichiarato.
• Configurazione della periferica tramite la funzione
MCASP_config che imposta i registri globali, i registri di
trasmissione e i registri di controllo dei serializzatori in modo da configurare un trasferimento con le seguenti caratteristiche:
¾ Configurazione della funzionalità e della direzione dei pin della McASP connessi al bus micro-line. I pin AXR0, AFSX0, ACLKX0, AHCLKX0 e AMUTE sono configurati come “McASP pin”. La polarità del pin AMUTE nel suo stato attivo viene impostata bassa in accordo alla polarità attiva del modulatore PWM presente sulla scheda audio.
¾ Configurazione del serializzatore corrispondente al canale 0 della McASP0 come trasmettitore. Gli altri serializzatori vengono lasciati nel loro stato di default.
¾ Impostazione dell’evento per la richiesta di interruzione: condizione di buffer di uscita vuoto e pronto a trasmettere un nuovo campione al serializzatore.
¾ Formato di trasmissione IIS a 32 bit con il solo canale sinistro attivo (si ricorda che il modulatore PWM presente sulla scheda audio pilota l’amplificatore sul solo canale sinistro)
¾ Frequenza del clock ad alta frequenza: 12.5Mhz. Questo segnale va a pilotare il master clock del modulatore PWM presente sulla scheda audio
¾ Frequenza dello shift clock: 3.125Mhz ¾ Frequenza di uscita dei campioni: 48.83Khz
• Attivazione nell’ordine di:
1. Divisore di frequenza per la generazione del clock ad alta frequenza.
2. Divisore di frequenza per la generazione del bit clock.
3. Richieste di interruzione tramite le funzioni C6xIntHook, C6xIntEnable, C6xGlobalIntEnable.
4. Azzeramento del registro XSTAT che segnala situazioni di errore della periferica.
5. Serializzatore 0.
6. Macchina a stati della sezione di trasmissione.
Si noti che le operazioni 1, 2, 5, 6 vengono effettuate scrivendo nel registro GBLCTL della periferica. Tale registro riceve come clock il segnale AUXCLK generato dal PLL con frequenza pari a 25Mhz, un ordine di grandezza inferiore alla frequenza del core processor, con
read back, ovvero una rilettura del registro ogni volta che vi si scrive
un valore per verificare la riuscita dell’operazione. Tale operazione viene effettuata tramite la funzione MCASP_getGblctl definita nella CSL.
Per il calcolo dei campioni sono state sfruttate le funzioni presenti nella libreria di funzioni matematiche fornita con Code Composer Studio. In essa esiste infatti un insieme di funzioni per il calcolo delle funzioni trigonometriche. Sono state sfruttate le funzioni sinf e asinf che ricevono come argomento un numero di tipo float che rappresenta rispettivamente l’angolo espresso in radianti di cui si vuole calcolare il seno o il numero di cui si vuole calcolare l’arcoseno e restituiscono come risultato un numero, sempre di tipo float, risultato della funzione trigonometrica in questione. Si noti che nella libreria matematica sono definite anche le funzioni sin e asin che ricevono come argomento un tipo double e restituiscono lo stesso tipo. L’utilizzo del tipo float anziché double consente di ottenere un risparmio in termini di utilizzo di risorse di calcolo in quanto la codifica di quest’ultimo tipo avviene, come è noto, su un numero di bit doppio (64) e comporta istruzioni più lunghe da eseguire.
Il riconoscimento della ricezione dei parametri ampiezza, frequenza e fase della sinusoide comporta il calcolo, tramite la funzione sinf, di un numero di campioni sufficiente a rappresentare un intero periodo della sinusoide e l’inserimento dei campioni in una tabella realizzata tramite un buffer con elementi a 32 bit. Calcolato il primo insieme di campioni si effettua una chiamata alla funzione SpadaMcASPInit che inizializza la periferica e le consente di interrompere la CPU per l’invio dei campioni al serializzatore e quindi all’uscita sul connettore micro-line. La routine di interrupt provvede alla sola scrittura sul buffer di uscita della periferica ed è quindi di immediata esecuzione. I successivi periodi richiedono il ricorso alla funzione asinf per determinare l’argomento da passare alla funzione
sinf. Non essendovi infatti un rapporto razionale tra il periodo della
sinusoide desiderata e la frequenza di uscita dei campioni, perché i campioni calcolati abbiano significato coerente con l’andamento della sinusoide alla frequenza desiderata è necessario calcolare la fase corrispondente al primo campione di ogni periodo in base al valore dell’ultimo campione del periodo precedente. In pratica il valore del primo campione di ogni periodo successivo al primo è dato dalla formula generale:
FirstSample = Amplitude·sin( Φ )
Φ = Φ0 + (Tsample_rad + arcsin( LastSample/Amplitude) )
Dove FirstSample è il valore del primo campione di ogni periodo, Amplitude è l’ampiezza desiderata per la sinusoide, Tsample_rad è
l’espressione in radianti della frazione del periodo della sinusoide corrispondente al periodo di campionamento, LastSample è il valore dell’ultimo campione del periodo precedente e Φ0 è la fase iniziale della
sinusoide. Questa operazione evita l’accumulo dell’errore sulla fase che si avrebbe utilizzando una tabella di valori sempre uguale per ogni periodo.
La sinusoide può essere visualizzata su Code Composer Studio associando un grafico alla prima locazione della tabella contenente i campioni. Il risultato ottenuto è il seguente:
Figura 3.9: Andamento dei campioni della sinusoide nella tabella. Il grafico è stato ottenuto associando un grafico alla prima locazione della tabella dei campioni con Code Composer Studio.
Di seguito si riporta l’immagine catturata dall’oscilloscopio relativa ai tre segnali ACLKX, AFSX, AXR0 per due campioni successivi.
Figura 3.10: Andamento dei segnali AHCLKX, AFSX e AXR0 della McASP misurati sul connettore micro-line. Si vede in fugura la frequenza pari rispettivamente a 3.125Mhz e 48.83Khz del clock ad alta frequenza e del segnale di sincronizzazione dei frame.
3.2.3 Board level
A questo livello l’applicazione agisce sui registri dei dispositivi esterni connessi al DSP. In particolare si mostrano le macro e le funzioni utilizzate per:
• Scaricare la configurazione del FPGA corrispondente all’architettura esposta precedentemente.
• Inizializzare i registri di controllo implementati sul PLD presente sulla C6713 compact
• Inizializzare e utilizzare il dispositivo UART per la gestione dell’interfaccia seriale RS-232.
• Impostare i registri del modulo SDPM implementato sul FPGA. • Inizializzare e utilizzare il dispositivo LLC per la ricezione e l’invio
di dati in modo isocrono e asincrono tramite il link IEEE1394.
• In sinergia con l’ultimo punto, sfruttare la risorsa rappresentata dal modulo DMPORT IP CORE implementato sul FPGA per la comunicazione isocrona verso il LLC.
3.2.3.1 Configurazione FPGA
Nel progetto su Code Composer Studio è stato possibile inserire un file sorgente contenente tutte le informazioni necessarie alla configurazione delle interconnessioni interne del FPGA in accordo con l’architettura definita per il progetto SPADA. Tale file è stato ottenuto sfruttanto il tool denominato bintohex fornito da Orsys che permette di generare un file .c a partire dal file .rbt generato con Xilinx ISE. Il file .c è stato nominato spada_fpga.c e non contiene altro che la conversione in esadecimale del file di programmazione binario generato dal tool Xilinx. Per poter sfruttare queste informazioni è stato necessario compiere, nella fase di inizializzazione, una chiamata alla funzione FpgaLoad che permette di scaricare la configurazione di bit contenuta in spada_fpga.c
3.2.3.2 Registri PLD
Come mostrato nei capitoli precedenti il PLD presente sulla scheda Orsys consente di impostare diverse opzioni di funzionamento della scheda stessa come la possibilità di configurare il FPGA come master e il DSP come slave o la configurazione di connessioni programmabili tra le linee di interrupt dei vari dispositivi connessi al DSP.
La gestione dei registri del PLD avviene nella fase di inizializzazione del sistema sfruttando la struttura definita nella libreria fornita da Orsys C6xCptInitRegs i cui campi corrispondono ai registri interni del PLD. I registri vengono inizializzati in modo tale da:
• Abilitare il driver della periferica UART scrivendo nel registro MCR.
• Abilitare le interconnessioni tra EXT_INT7 e la UART, EXT_INT5 e il FPGA ed EXT_INT4 e il LLC.
In fase di esecuzione e a scopo di debug i registri del PLD sono stati utilizzati anche per controllare lo stato dei due led rosso e verde connessi a due bit del registro MCR.
3.2.3.3 Dispositivo UART
In una prima fase del progetto in cui non era ancora stato studiato il funzionamento del protocollo IEEE1394 la funzione dell’interfaccia seriale RS-232 è stata, oltre a quella di fornire informazioni di debug durante l’esecuzione del programma, quella di eseguire il trasferimento dei risultati di conteggio al PC remoto e di ricevere i comandi per l’impostazione delle finestre temporali. Nella attuale versione l’interfaccia RS-232 viene utilizzata per inviare ad un terminale esterno informazioni sullo stato di esecuzione dell’applicazione e per ricevere i parametri di configurazione ampiezza, frequenza e fase della sinusoide. Per configurare e utilizzare il dispositivo UART sono state utilizzate le funzioni di libreria fornite da Orsys denominate DebugInit per
l’inizializzazione dei parametri di trasmissione seriali,
DebugOutDwordBytes per la scrittura nel buffer di uscita di una parola a
32 bit e DebugFlush per lo svuotamento del buffer di uscita della periferica. Per la ricezione di dati attraverso la porta seriale si è impostato il dispositivo UART in modo da interrompere la CPU sulla linea EXT_INT7. Ciò avviene ogni volta che viene ricevuta dal dispositivo una stringa a 8 bit. Nella routine di interrupt, con una chiamata alla funzione
DebugReceive, viene via via riempito un array circolare di caratteri alle
cui locazioni puntano due puntatori con cui fare riferimento per poter utilizzare i dati ricevuti.
3.2.3.3 Gestione modulo SDPM
Per la scrittura sui registri interni implementati nel modulo SDPM sono stati innanzitutto definiti dei nomi simbolici a cui fare riferimento in un apposito file di intestazione e in seguito sono state definite delle macro con le quali poter scrivere nei registri CFG_REG e GENERIC_REG descritti precedentemente. Le macro definite permettono di:
• Impostare una nuova finestra temporale tramite la macro SDPM_SET_PERIOD.
• Scrivere nel registro GENERIC_REG impostando il safety mode o attivando i segnali di Gate e Interlock sul connettore microline. • Rendere valido il dato appena scritto secondo il funzionamento
della Write Valid State Machine tramite la macro SDPM_VALIDATE_DATA.
• Accendere o spegnere i led connessi al FPGA tramite le macro SDPM_RED_LED_ON/OFF, SDPM_GREEN_LED_ON/OFF, SDPM_GREEN_LED_TOGGLE, SDPM_RED_LED_TOGGLE.
E’ necessario ora, per poter comprendere la gestione del LLC e del DMPORT IP CORE, aprire una parentesi e illustrare le caratteristiche principali del protocollo FireWire definito dallo standard IEEE1394.
3.2.3.4 Protocollo IEEE1394
Il protocollo IEEE1394 del 1995 consente un facile utilizzo, basso costo, alta velocità di comunicazione, fino a 400 Mbps, ampia scalabilità e permette una comunicazione di tipo sincrono (detta anche isocrona) o asincrona.
Figura 3.11: Stratificazione del protocollo IEEE1394 nei vari layers e distribuzione delle competenze per la gestione del bus tra i nodi.
La gestione del bus richiede la distribuzione di diversi compiti che possono essere assegnati a più nodi costituenti la rete IEEE1394. Alcuni nodi sul bus devono assumere il ruolo di Cycle Master, Isochronous Resource Manager e Bus Manager.
• Il Cycle Master avvia i cicli di trasferimento inviando un Cycle Start packet ogni 125 µs. Il Root Node deve essere anche Cycle Master.
• L’Isochronous Resource Manager è il gestore delle risorse isocrone e deve essere capace di effettuare transazioni isocrone. Inoltre tale gestore deve anche implementare numerosi registri opzionali. Questi registri includono il registro Bus Manager ID, il registro di allocazione della larghezza di banda del bus e il registro di allocazione del canale. I nodi che desiderano utilizzare larghezza di banda isocrona devono sottrarre la quantità di larghezza di banda loro necessaria dal Bandwidth Available Register.
• Il Bus Manager ha numerose funzioni inclusa la divulgazione di una mappa topologica e di una mappa delle velocità, la gestione dell’alimentazione e l’ottimizzazione del traffico sul bus. La mappa delle velocità è utilizzata dai nodi per determinare quale velocità possono utilizzare per comunicare con altri nodi. Il Bus Manager è anche responsabile della determinazione del Root Node. Non sempre potrebbe esserci sul bus un nodo capace di assumere il ruolo di Bus Manager, in questo caso almeno alcune delle funzioni di gestione del bus sono eseguite dall’Isochronous Resource Manager.
Il bus 1394 appare al programmatore come un grande spazio di memoria in cui ogni nodo occupa un certo intervallo di indirizzi. Lo spazio di memoria è regolato dall’architettura IEEE 1212 Control e Status Register (CSR). Ogni nodo supporta fino a 48 bit di spazio di indirizzamento (256 TeraBytes). Inoltre, ogni bus può supportare fino a 64 nodi e la specifica del bus seriale 1394 supporta fino a 1024 bus. Il risultato è un totale di 64 bit di indirizzo, per un totale di 16 ExaBytes di spazio di indirizzamento.
Figura 3.12: Organizzazione dello spazio di indirizzamento sul bus IEEE1394.
Il protocollo IEEE1394 come detto supporta il trasferimento dati sia asincrono che isocrono. I trasferimenti asincroni sono destinati ad un nodo specifico con un esplicito indirizzo. Nella trasmissione asincrona è possibile il controllo degli errori e il meccanismo di ritrasmissione in caso di errore.
I trasferimenti isocroni sono sempre di tipo “uno a uno” o “uno a tanti” e non è possibile, a differenza della trasmissione asincrona, alcuna correzione degli errori di trasmissione. Fino all'80% della larghezza di banda disponibile del bus può essere utilizzata per trasferimenti isocroni e ciò rende la connessione firewire un’interfaccia eccellente per applicazioni in tempo reale in cui il tempo è un fattore critico ma i dati sono sufficientemente robusti da consentire un margine di errore più ampio nella trasmissione. Per ulteriori dettagli si veda la bibliografia ([G]).
Descritte le principali caratteristiche del protocollo IEEE1394 è possibile proseguire la descrizione dell’applicazione illustrando come è stato realizzata la comunicazione con il PC remoto tramite il link FireWire.
3.2.3.5 Gestione LLC e DMPORT IP CORE
Per l’utilizzo della connessione FireWire è stata sfruttata una API per la gestione del bus IEEE1394 fornita da Orsys e progettata appositamente per la scheda C6713 Compact. Tale API comprende funzioni per l’inizializzazione del chipset IEEE1394 presente sulla scheda Orsys e il settaggio dei registri del DMPORT IP CORE implementato nell’architettura FPGA in modo da poter realizzare un trasferimento di dati sia in modalità isocrona che asincrona. L’obiettivo è quello di svincolare il programmatore dalla conoscenza dettagliata dello standard IEEE1394 per concentrarsi sulle applicazioni, una volta capiti i concetti e le possibilità del bus IEEE1394.
Per la corretta gestione del bus IEEE1394 è necessario compiere alcune operazioni di setup prima di poter iniziare il vero e proprio trasferimento. Le operazioni da effettuare sono:
• Inizializzazione del bus : effettua l’inizializzazione dei dati richiesti dai più bassi livelli del software e determina quale nodo sia il Bus Manager e quale l’Isocronus Resource Manager.
• Reset ed enumerazione del bus : una volta effettuato il reset del bus parte il processo di enumerazione che crea un dispositivo per ogni nodo attualmente collegato al bus e ne raccoglie le informazioni come lo stato attuale, l’ID del nodo, la massima velocità, la massima dimensione del pacchetto asincrono ecc.
Fatto questo si attende la chiamata da parte dell’utente di funzioni da mandare in esecuzione secondo il metodo delle callback che permette al programmatore di controllare il bus IEEE1394 senza polling (vedi nota 1).
Le funzioni di callback sono chiamate dall’API quando deve essere fatta
una specifica azione indicata dal LLC. Pertanto le funzioni da inserire nella coda devono essere definite in un file sorgente e oltre ad alcune presenti in libreria, altre sono state scritte per effettuare le operazioni specifiche richieste all’applicazione.
Le trasmissioni sia asincrone che isocrone necessitano di una specifica sequenza di operazioni perché possano essere completate con successo.
La trasmissione isocrona per avere successo prevede che si compiano le seguenti operazioni:
• L’inizializzazione hardware del LLC, dei driver dei dispositivi connessi al bus e della API. Ciò si realizza con una chiamata alla funzione sbiInitialize.
• Ottenere la banda di trasmissione desiderata. Ciò si può fare chiamando la funzione sbiAllocateBandwith.
• Ottenere il canale isocrono per la trasmissione attraverso la funzione sbiAllocateChannel.
• Realizzare l’operazione di trasmissione e si può fare con una chiamata alla funzione sbiIsoTalk. Il chiamante deve controllare le routine di callback per conoscere lo stato dell’operazione.
• Liberare la banda e il canale utilizzati quando è finita la trasmissione. Questo viene svolto dalle due funzioni
sbiFreeBandwith e sbiFreeChannel.
• Chiudere l’interfaccia IEEE1394 se non si intende fare ulteriori trasferimenti e si effettua con la funzione sbiTerminate.
Per quanto riguarda la trasmissione asincrona le operazioni da compiere in sequenza sono:
• L’inizializzazione hardware del LLC, dei driver dei dispositivi e della API; questo viene effettuato tramite la funzione sbiInitialize.
• Allocare e ottenere un handle al dispositivo a cui si deve trasmettere o da cui si deve ricevere, e lo si fa con la funzione
sbiGetDeviceHandle.
Queste due operazioni devono essere fatte una sola volta e in seguito si possono chiamare le funzioni sbiAsyncWrite e
sbiAsyncRead per leggere da e scrivere verso qualsiasi spazio di
indirizzamento del bus IEEE1394 che sia stato reso disponibile dal dispositivo selezionato. La funzione termina immediatamente e sono le funzioni di callback a informare l’applicazione circa lo stato della transizione. La solita funzione sbiTerminate viene chiamata per chiudere l’interfaccia se non si intende compiere ulteriori operazioni.
Se invece la transizione asincrona è di ingresso, cioè avviene in risposta a una richiesta di un altro nodo si deve seguire una ulteriore diversa serie di operazioni:
• L’inizializzazione hardware del LLC, dei driver dei dispositivi e della API; questo viene effettuato tramite la funzione
sbiInitialize.
• La creazione di un buffer di acquisizione per la ricezione dei dati durante il traffico asincrono, l’associazione di questo buffer al range di indirizzi del dispositivo chiamante e l’abilitazione di altri dispositivi ad accedere a questi indirizzi. Tutto questo viene fatto chiamando la funzione sbiAllocateAddressRange. • Dopo che lo spazio di memoria è stato acceduto viene chiamata
una funzione di callback detta appNotificationCallback che può essere usata per modificare i dati tipo riempire il buffer dopo una lettura con nuovi dati o decodificare i messaggi che sono stati scritti nel range di indirizzi e far partire su questi nuove elaborazioni.
• Terminati gli accessi al buffer vengono resi disponibili per altre operazioni gli indirizzi sul bus precedentemente assegnati al buffer tramite la funzione sbiFreeAddressRange.
• La chiusura dell’interfaccia IEEE1394 se non si intende fare ulteriori trasferimenti viene effettuata con la funzione
sbiTerminate.
Nelle trasmissioni vengono spediti dei pacchetti di informazioni con le seguenti caratteristiche:
• Un pacchetto asincrono è una sequenza di quadlet (1 quadlet = 4 bytes). Tutti i pacchetti asincroni contengono un packet header, seguito da un blocco dati.
• Un pacchetto isocrono consiste di un packet header e di un campo dati.
Il packet header è composto dai campi:
• Destination_ID – Un campo di 16 bit che specifica il nodo ricevente.
• Destination Offset – Questo campo contiene l’indirizzo del nodo destinazione (48 bit).
• Source_ID – Un campo di 16 bit che specifica il nodo sorgente. • Transaction Label – Un campo di 6 bit che specifica una
particolare etichetta per ogni transazione del nodo.
• Retry Code – Sono 2 bit che specificano se si sta tentando di trasmettere nuovamente il pacchetto.
• Transaction Code – Un campo di 4 bit che specifica il formato del pacchetto e il tipo di transazione da eseguire.
• Data Length – Stabilisce il numero di byte che devono essere trasferiti.
• Header CRC – Questo campo di 32 bit contiene il carattere CRC (Cycle Redoundance Check) per il controllo di ridondanza ciclica..
Per ogni dispositivo attivo sul bus deve inoltre essere definita una
configuration ROM che contiene tutte le informazioni riguardanti il nodo
come ad esempio la possibilità di diventare Isocronous Resource Manager (IRM) o Bus Manager, i parametri per i trasferimenti come le velocità, le informazioni del produttore sul modello del dispositivo e molte altre. Nel caso della C6713 la configuration ROM è definita nel file cfgrom.c
Per ulteriori dettagli sulla gestione del protocollo IEEE1394 tramite le API Orsys si faccia riferimento alla bibliografia ([26]).
Il modo più efficiente e chiaro per illustrare il funzionamento di un programma è l’utilizzo dei diagrammi di flusso o Flow Chart. Di seguito sono riportati i diagrammi di flusso dell’applicazione sviluppata per il DSP nell’ambito del progetto SPADA.
3.3 Diagrammi di Flusso
Inizializzazione Hardware .CPU core level
.CPU level .Board level
Inizializzazione Callback Queue System e IEEE1394 API
InitCallQ() sbiInitialize(&sInitInfo)
Reset e inizio enumerazione dispositivi connessi al bus
sbiCauseBusReset() Abilitazione Interrupt LLC su EXT_INT_6 Enumerazione ultimata? No Sì
Chiamata di una eventuale funzione di Callback posta
nella coda dall’API YieldToCallQ()
Presenza di Cycle Start Packets sul bus?
No
Inizializzazione strutture sRangeInfo1, sRangeInfo2 e sRangeInfo3 per allocazione
indirizzi sul nodo locale tramite la funzione sbiAllocateAddressRange()
Sì
Inizializzazione UART
Inserimento Routine di interrupt nella IST e abilitazione INT7 (UART) e INT8 (EDMA)
Inizializzazione SDPM con SDPM_CFG_REG = 99 (100us) Ricezione di dati da DB su buffer UART? Sì Invio a PC remoto di informazioni sullo stato della DB con AsyncWrite No
Inizio nuovo esperimento e
nessun esperimento in corso? No
Si
Esperimento in corso e richiesta di stop per
l’esperimento?
Si
Si
Aggiornamento stato esperimento: -esperimento in corso -finestra di integrazione impostata -tempo di presentazione delle immagini
-durata dell’esperimento in uiaSPADA_status[0..4] Reset buffer per conteggi
da presentare auiAccBuffer[i]=0
i=31..0 Scrittura nuovo periodo di
conteggio in SDPM Invio stato esperimento a PC
remoto con AsyncWrite Setup del trasferimento Isocrono e del trasferimento via EDMA e QDMA con
IsoTransmitInit e SpadaDmaInit
Si
Condizione di FIFO almost empty su DMPORT_IP_CORE? Sì Invio di frame nulli No Trasferimento EDMA ultimato? (ISO_TX_EN=1?) Sì
Si sono verificati errori nel trasferimento con ping
pong buffering?
Sì
Invio codice errore a PC remoto con
AsyncWrite No
Spazio sufficiente per un pacchetto nella FIFO? No
Invio codice errore a PC remoto con
AsyncWrite Si
Inizio trasferimento dati da SDRAM a FIFO via QDMA e
QDMA_completion=0 Aggiornamento auiAccbuffer con gli ultimi dati prelevati da
SDPM
Sono trascorsi 100ms dall’inizio dell’esperimento o dall’ultima
verifica?
No Sì
Invio a PC remoto dei dati per la visualizzazione contenuti in auiAccBuffer con AsyncWrite
Interruzione trasferimento EDMA e invio di pacchetti extra per lo
svuotamento di tutti i buffer
Aggioramento array uiaSPADA_config_param e uiaSPADA_status Termine trasmissione isocrona con IsoTransmitStop() Invio di uiaSPADA_status a PC remoto con AsyncWrite
No
Reset auiAccbuffer Fine trasferimento QDMA? No Sì Disabilitazione trasmissione isocrona ISO_TX_EN = 0 Controllo errori DMPORT_IP_CORE: -FIFO overflow -FIFO underflow -DMPORT error Chiamata di eventuali callback in coda di esecuzione YieldToCallQ() W A B C D
Figura 3.13: Diagramma di flusso dell’applicazione sviluppata per il DSP per la gestione delle periferiche esterne e la comunicazione sul bus IEEE1394.