Il controller DMA nel Freescale MCF5213

Il microcontrollore Freescale (ora NXP) MCF5213 è dotato di un controller DMA a 4 canali per velocizzare le operazioni di accesso diretto alla memoria. MCF5213 rappresenta una famiglia di microcontrollori a 32 bit ad alta integrazione basata su un'architettura ColdFire e core V2 di Freescale  Semiconductor (ora NXP). Ecco una descrizione dettagliata del modulo con i relativi segnali, registri e modalità di trasferimento dati.

Introduzione

I micro di questa famiglia dispongono di SRAM interna fino a 32KB e 256 KB di memoria Flash oltre a quattro timer a 32 bit in grado di inoltrare richieste in DMA, un controller DMA a quattro canali, un modulo CAN, un modulo I2C, tre UART ed una periferica SPI con accodamento.   Di seguito un elenco delle caratteristiche dei micro di questa famiglia:

  • Core ColdFire V2 con unità MAC;
  • 32KB di SRAM interna;
  • 256KB di Flash on-chip;
  • 3 moduli UART;
  • Modulo FlexCAN 2.0;
  • Controller per comunicazione I2C;
  • Convertitore AD a 12 bit;
  • Modulo QSPI;
  • Controller DMA a 4 canali;
  • 4 timer a 32 bit con supporto DMA;
  • 2 timer a 16 bit con interrupt programmabili;
  • Watchdog timer programmabile;
  • Controller di interrupts fino a 63 interruzioni;
  • Modulo oscillatore a 8MHz con PLL.

Per queste caratteristiche il microcontrollore  è indicato per applicazioni di controllo industriale general-purpose. Nella presente trattazione verrà esaminato nei dettagli il controller DMA illustrando i registri relativi alla gestione e configurazione del modulo  ed i processi con cui avviene un trasferimento dati in DMA.

STRUTTURA E REGISTRI COINVOLTI

Il controllore  DMA costituisce un modo  efficiente per il trasferimento di blocchi di memoria minimizzando  l’intervento   della  CPU con  conseguente incremento  delle prestazioni in termini  di velocità ed efficienza. Il controllore DMA del microcontrollore MCF5213 ha la struttura di figura 1 ed è costituito da 4 canali indipendenti che consentono il trasferimento di dati a blocchi di byte, word, longword o 16-byte.

Figura 1. Struttura del modulo DMA controller

Figura 1. Struttura del modulo DMA controller

Nella presente trattazione il suffisso n indicherà il riferimento al generico canale n (n=1..3). Ad ogni  canale sono  associati cinque  registri:  Source Address Register (SARn),  Destination Address Register (DARn), Byte Count Register (BCRn), Control Register (DCRn) e Status Register (DSRn). Il processore genera internamente le richieste DMA portando ad livello alto il bit START del registro DCR, mentre il modulo UART ed i timer possono scatenare una richiesta di trasferimento in DMA utilizzando il segnale interno DREQ. Il controller DMA supporta trasferimenti dual-address ovvero una lettura seguita da una scrittura coinvolgendo quindi un indirizzo sorgente ed un indirizzo destinatario. Una operazione che coinvolge il modulo DMA prevede sempre i seguenti passi:

  1. inizializzazione del canale: prevede il caricamento dei registri associati al canale DMA con tutte  le informazioni   necessarie (controllo,   indirizzi  e numero di byte da trasferire);
  2. trasferimento dati: accettazione della richiesta di trasferimento in DMA e conseguente occupazione del bus per il trasferimento dei dati;
  3. chiusura del canale: avviene una volta completato il trasferimento dati sia che questo sia avvenuto correttamente, sia che si siano verificati eventuali errori.

I  registri  associati a  ciascun canale DMA  sono riportati in tabella 1.

Tabella 1. I registri associati al controller DMA

Tabella 1. I registri associati al controller DMA

Registro DMAREQC

Il registro DMAREQ (Dma REQuest Control) trasferisce le richiesta DMA dalle periferiche (timers o UART) ai canali del controller DMA e la sua struttura è quella di figura 2.

Figura 2. Il registro DMAREQC

Figura 2. Il registro DMAREQC

La parte alta di questo registro (i 16 bit più significativi) sono riservati, mentre la parte bassa può essere pensata costituita da 4 gruppi  di quattro bit ciascuno che determinano l’associazione tra il canale DMA e l’evento sulla periferica. L’associazione viene fatta in accordo alla tabella 2, valori diversi da quelli specificati non producono richieste DMA.

Tabella 2. Identificazione di un evento per l’associazione ad un canale DMA

Tabella 2. Identificazione di un evento per l’associazione ad un canale DMA

Registri SAR

I registri SAR (uno per ciascun canale e identificati come  SAR0, SAR1, SAR2 e  SAR3) contengono l’indirizzo a partire dal quale il controller DMA andrà a prelevare i dati. La struttura di questi registri è riportata in figura 3 ed al reset viene inizializzato con il valore 0.

Figura 3. Struttura di un registro SARn

Figura 3. Struttura di un registro SARn

Registri DAR

Analogamente ai registri SAR, contengono l’indirizzo di destinazione a partire dal quale il trasferimento DMA memorizzerà i dati trasferiti. Le figure 3 e 4 riportano la struttura di tali registri che contengono 0 al reset.

Figura 4. Struttura di un registro DARn

Figura 4. Struttura di un registro DARn

Registri BCR e DSR

BCR (Byte  Count  Register) e  DSR (Dma  Status Register) sono in realtà campi di un unico registro a 32 bit la cui struttura è riportata in figura 5.

Figura 5. I registri BCRn e DSRn

Figura 5. I registri BCRn e DSRn

BCR contiene il numero di byte che dovranno essere trasferiti per un dato blocco. Il campo BCR viene decrementato (di 1, 2, 4, 16, 32 o 64 byte) ogni volta che un trasferimento viene completato con successo. Il campo DSR è costituito da 8 bit la cui struttura è riportata in figura 6.

Figura 6. La struttura del byte DSRn

Figura 6. La struttura del byte DSRn

Esso costituisce un registro di stato in cui ogni bit fornisce informazioni sullo stato del trasferimento DMA.

In particolare:

  • CE (Configuration Error): viene messo ad 1 quando BCR,  SAR o DAR contengono  informazioni  discordanti  per il trasferimento del blocco o se BCR=0 all’inizio di un trasferimento. Viene azzerato con un reset hardware o automaticamente scrivendo un 1 nel bit DONE.
  • BES (Bus Error on Source): se è 1 significa che il trasferimento DMA relativo allo specifico canale è stato terminato a seguito di un errore durante la fase di lettura del sorgente.
  • BED (Bus Error on Destination): vale 1 quando il trasferimento viene interrotto a seguito di un errore durante la fase di scrittura in uno degli indirizzi destinatari.
  • REQ (REQuest): vale 1 se il canale ha una richiesta di trasferimento pendente e non è selezionato.
  • BSY (BuSY): viene messo a 1 la prima volta che viene abilitato  il canale. Se vale 0 significa che il canale è inattivo e viene azzerato al termine di un trasferimento dati.
  • DONE: viene messo a 1 quando sono state effettuate tutte le trasizioni richieste. Se usato in scrittura il bit DONE può  essere impiegato  per  annullare un trasferimento in corso. Una volta completato un trasferimento il bit DONE deve essere azzerato manualmente dal software.

Registri DCR

Sono i registri di controllo usati per la configurazione del controller DMA. Le informazioni fornite da questo registro sono le seguenti:

  • INT (INTerrupt  on completion  of transfer): se 1 abilita una interruzione al termine di un trasferimento sia che questo sia avvenuto correttamente sia che si sia completato con errori.
  • EEXT (Enable EXternal request): se 1 abilita l’avvio di un trasferimento mediante una richiesta esterna (la richiesta interna avviene settando il bit START ed è sempre abilitata).
  • CS (Cycle Steal): se vale 0 il controller DMA effettua cicli di lettura/scrittura per completare il trasferimento fintanto che BCR non raggiunge il valore 0. Se questo bit vale 1 ad ogni richiesta corrisponde un solo ciclo di lettura/scrittura.
  • AA (Auto-Align): questo bit insieme ai campi SIZE determina se sorgente e destinatario sono auto-allineati e in questo caso il trasferimento avviene in modo ottimizzato.
  • BWC (BandWidth Control): Indica il numero di byte in un blocco. In dettaglio:

 

  • SINC (Source INCrement): permette di incrementare o meno il registro SAR dopo ogni trasferimento. Se vale 1 il registro SAR viene incrementato di 1, 2, 4 o 16 a seconda dell’ampiezza del trasferimento.
  • SSIZE (Source SIZE): è l’ampiezza di un blocco sorgente (00=longword, 01=byte, 10=word, 11=16byte).
  • DINC (Destination INCrement): ha la stessa funzione del bit SINC ma riferito all’indirizzo di destinazione.
  • DSIZE (Destination SIZE): vedi SSIZE ma riferito al blocco destinazione.
  • START: se 1 il DMA avvia un trasferimento. Il bit START viene automaticamente azzerato dopo  un ciclo ci clock e viene sempre letto come 0.
  • SMOD  (Source address MODulo):   definisce  la dimensione del buffer circolare sorgente usato dal controller DMA in accordo alla seguente tabella:

  • DMOD (Destination address MODulo): definisce la dimensione del buffer circolare di destinazione usato dal controller DMA in accordo alla seguente tabella:

  • D_REQ (Disabile  REQuest): se ad 1 il controlle DMA provvede ad azzerare il bit EEXT quando BCR si azzera.
  • LINKCC (LINK Channel Control):  Consente di collegare i trasferimenti dei canali DMA in accordo alla seguente tabella:

  • LCH1 (Link CHannel 1): Indica il canale DMA da associare al  link1:  00=ch0,  01=ch1,  10=ch2, 11=ch3.
  • LCH2 (Link CHannel 2): analogo al precedente.

TRASFERIMENTO IN DMA

Prima di iniziare un trasferimento in dual-address, il controller DMA verifica che SSIZE e DSIZE siano consistenti con l’indirizzo sorgente e destinatario. Se  non  sono consistenti viene settato il bit  CE e non  avviene alcun trasferimento. Il trasferimento consiste nella lettura di dati dall’indirizzo sorgente e conseguente scrittura all’indirizzo destinatario. Al completamento di un trasferimento per uno specifico indirizzo, viene decrementato BCR e quando BCR raggiunge il valore zero, significa che è stato completato il trasferimento di tutti  i byte richiesti.

Modalità di trasferimento DMA

Come già accennato le richieste DMA possono essere interne o esterne. In generale una richiesta può essere fatta settando il bit START o direttamente da una periferica UART o Timer. Alla richiesta di trasferimento deve essere sempre associata la modalità con cui  il  trasferimento  dati  dovrà  essere effettuato: Cycle-steal o Continuous. Nel primo  caso (CS=1) il trasferimento coinvolge il solo indirizzo sorgente e destinatario, mentre nel secondo caso (CS=0) vengono effettuati una serie di trasferimenti consecutivi fino  a che BCR non  si azzera. È  evidente che nel secondo caso il trasferimento di un blocco dati avviene più velocemente a scapito di una maggiore occupazione di banda sul bus.

Trasferimento dual-address

Ciascun canale supporta  un  trasferimento  detto dual-address. Questo comporta  un indirizzo sorgente da cui vengono letti i dati ed un indirizzo destinatario al quale i dati vengono trasferiti. Il trasferimento avviene quindi in due fasi:
Dual-address Read: il controller DMA preleva il valore dal registro SAR e legge i dati sorgenti incrementando SAR del valore opportuno in accordo ai parametri di configurazione. Una volta acquisiti i   dati sorgente, si passa alla seconda fase che prevede la scrittura  all’indirizzo  di  destinazione. In  caso di errori viene interrotto il trasferimento settando i bit BES e DONE.

Dual-address write: Il controller DMA carica l’indirizzo destinazione dal registro DAR quindi inizia la scrittura dei dati incrementando opportunamente il registro DAR e  decrementando  il  registro  BCR che  tiene conto del numero di dati ancora da trasferire. Quando  BCR raggiunge  zero, vene settato  il  bit DONE a notificare che il trasferimento è stato completato. In caso di errori viene interrotto  il trasferimento portando a 1 i bit DES e DONE.

Inizializzazione dei canali

Prima dell’inizio di un trasferimento in DMA è necessario inizializzare i  registri  di  ogni  canale con  gli opportuni  valori. I canali hanno priorità  diversa, in particolare il canale 0 è quello a più alta priorità ed il canale 3 è quello a priorità più bassa. Alternativamente è possibile impostare la priorità tra i  canali agendo  sul campo  BWC: se BWC=000 il canale ha priorità  solo su quello  immediatamente precedente. Grazie alla gestione delle priorità, è possibile gestire richieste DMA simultanee. Per inizializzare correttamente  il  modulo  DMA, è necessario seguire i seguenti passi:

  • Configurare  il  registro  DMAREQC assegnando ciascuna periferica ad uno specifico canale DMA;
  • Caricare SAR con il giusto valore per l’indirizzo sorgente;
  • Caricare DAR con il corretto valore per l’indirizzo di destinazione;
  • Inizializzare  BCR con il corretto numero di byte da trasferire;
  • Avviare il trasferimento scrivendo 1 nel bit START.

Controllo  della banda

È possibile  forzare il controllore DMA a liberare il bus per consentirne l’accesso da parte di altri dispositivi. In questo modo  è possibile controllare il livello di occupazione del  bus. Il  campo  BWC del  registro DCR, permette di definire sette possibili dimensioni dei blocchi di trasferimento. Se il decremento di BCR raggiunge un valore multiplo  di uno dei sette livelli previsti da BWC, la richiesta DMA  viene negata fintanto che non è terminato il ciclo di bus. Se BCW=000 la richiesta viene servita fino  all’azzeramento di BCR.

Condizioni  di blocco del trasferimento

Un trasferimento in DMA può terminare prematuramente per una della seguenti ragioni:

  • Errore: La terminazione avviene per un errore durante la lettura dei dati sorgenti (BES=1) o durante la scrittura all’indirizzo di destinazione (BED=1);
  • Interruzione: questo avviene, ovviamente, solo nel caso in cui siano abilitate le interruzioni (INT=1 nel registro DCR).

Leggendo il registro DCR la CPU è in gradi di determinare la causa della terminazione del trasferimento.

Sincronizzazione  e consistenza dei dati

Condividere strutture dati con dispositivi operanti in DMA non è cosa semplice. È possibile  che una operazione in DMA abbia inizio durante l’esecuzione di una istruzione e la cosa diviene particolarmente critica se l’istruzione e l’operazione in DMA interessano lo stesso dato. Il miglior meccanismo per agire su strutture dati in modo  atomico è utilizzare cicli di tipo read-modify-write ovvero un ciclo di lettura seguito da un ciclo di scrittura allo stesso indirizzo senza rilasciare il bus. In questo modo si rende atomica l’operazione (sia essa una trasferimento in DMA o una istruzione eseguita della CPU) rendendo consistente il dato per tutta la durata dell’operazione. L’alternativa è disabilitare il trasferimento in DMA per tutta la durata dell’istruzione in esecuzione negando l’autorizzazione all’accesso in  DMA  da  parte  dei dispositivi. Impiegando queste tecniche si deve prestare sempre molta attenzione. Alcuni processori supportano  la disabilitazione delle operazioni in DMA usando un sistema di bloccaggio del bus: l’istruzione di bloccaggio non consente l’accesso al bus da parte di dispositivi esterni fintanto che non viene eseguita una istruzione di unlock che sblocca il bus.  Il problema è del tutto  analogo a quello che avviene durante un interrupt e l’esecuzione di una ISR  (Interrpt  Service Routine): è buona norma disabilitare le interruzioni per consentire l’operazione sulla struttura dati critica in modo atomico prevenendo l’intervento sulla stessa struttura da parte di altre routine ISR.

Riferimenti

Informazioni generali:
http://it.wikipedia.org/wiki/DMA
G.Frosini, P.Corsini – “Architettura degli elaboratori”
ed. Mc Graw Hill, 1997
DMA nei microcontrollori Freescale:
MCF52xx Datasheet – www.freescale.com
Altre risorse utili:
www.freepatentsonline.com/4901234.html

Una risposta

  1. Maurizio Di Paolo Emilio Maurizio 2 settembre 2016

Scrivi un commento