Mi ero un po' abituato a usare lo ADC del dsPic33 a modo mio, scrivendo e leggendo sui registri "normali".
Una applicazione più pesante del solito mi sta costringendo a tentare la tecnica del DMA.
Mannaggia, non credevo che al mondo esistesse roba tanto complicata e farraginosa. Se non avessi i Sample Code della Microchip e il relativo compilatore C, dovrei assolutamente rinunziare in partenza!
Quindi sto tentando di partire da un Sample Code, che mette insieme tutto lo scibile ma almeno funziona, e poi a ritroso togliere ciò che non mi serve e così tentare di arrivare a fare la mia applicazione senza capire un tubo del DMA. Chissà che nel frattempo non si produca qualche "illuminazione".
Piccola esternazione sul DMA nelle MCU
Moderatore: Paolino
4 messaggi
• Pagina 1 di 1
0
voti
Ciao,
Il DMA "ruba" alla CPU qualche ciclo di bus per poter copiare velocemente uno o piu' dati presenti in uno o piu' registri hardware in celle di memoria RAM ad un indirizzo definibile dall'utente.
Il DMA e' utile quando i dati hardware da trasferire dai registri hardware in memoria sono almeno 16 come nelle FIFO delle UART. In questo caso, quando la FIFO ha ricevuto 16 byte dalla porta COM, la CPU viene fermata dal DMA per 16 cicli di bus.
Il DMA a fine trasferimento crea un interrupt per la CPU la quale chiama la tua funzione di interrupt che trovera' in memoria, a partire dall'indirizzo da te scelto, i 16 byte.
In questo esempio hai un interrupt ogni 16 byte ricevuti dalla porta COM e non 16 interrupt.
Ciao
Il DMA "ruba" alla CPU qualche ciclo di bus per poter copiare velocemente uno o piu' dati presenti in uno o piu' registri hardware in celle di memoria RAM ad un indirizzo definibile dall'utente.
Il DMA e' utile quando i dati hardware da trasferire dai registri hardware in memoria sono almeno 16 come nelle FIFO delle UART. In questo caso, quando la FIFO ha ricevuto 16 byte dalla porta COM, la CPU viene fermata dal DMA per 16 cicli di bus.
Il DMA a fine trasferimento crea un interrupt per la CPU la quale chiama la tua funzione di interrupt che trovera' in memoria, a partire dall'indirizzo da te scelto, i 16 byte.
In questo esempio hai un interrupt ogni 16 byte ricevuti dalla porta COM e non 16 interrupt.
Ciao
0
voti
OK. Nel frattempo sono riuscito a usare il DMA avvalendomi del compilatore C xc16 di Microchip.
In pratica le linee interessate sono:
unsigned int Buffer[2] __attribute__((space(dma)));//DMA x2 ingressi analogici
.....................
//DMA5CONbits.AMODE = 0;//DMA Register indirect mode with post-increment
DMA0PAD = (volatile unsigned int)&ADC1BUF0;//Point DMA to ADC1BUF0 conv.reg.
DMA0CNT = 1; // 2 DMA request ??
DMA0REQ = 13; // Select ADC1 as DMA Request source
DMA0STA = __builtin_dmaoffset(Buffer);//buffer per 2 ingressi analogici
DMA0CONbits.CHEN=1; // Enable DMA
.....................................
pot=Buffer[0]-por;//lettura ultima encoder rispetto al suo riferimento
Veramente in questo caso non c'era bisogno del DMA comunque va bene. Non c'è la ISR, il dato viene ciclicamente preso dal buffer ed è comunque il più recente che sia disponibile.
In pratica le linee interessate sono:
unsigned int Buffer[2] __attribute__((space(dma)));//DMA x2 ingressi analogici
.....................
//DMA5CONbits.AMODE = 0;//DMA Register indirect mode with post-increment
DMA0PAD = (volatile unsigned int)&ADC1BUF0;//Point DMA to ADC1BUF0 conv.reg.
DMA0CNT = 1; // 2 DMA request ??
DMA0REQ = 13; // Select ADC1 as DMA Request source
DMA0STA = __builtin_dmaoffset(Buffer);//buffer per 2 ingressi analogici
DMA0CONbits.CHEN=1; // Enable DMA
.....................................
pot=Buffer[0]-por;//lettura ultima encoder rispetto al suo riferimento
Veramente in questo caso non c'era bisogno del DMA comunque va bene. Non c'è la ISR, il dato viene ciclicamente preso dal buffer ed è comunque il più recente che sia disponibile.
0
voti
Ciao
>> Non c'è la ISR, il dato viene ciclicamente preso dal buffer ed è comunque il più recente che sia disponibile
Se accedi al dato in RAM mentre il DMA sta scrivendo potresti incorrere nel famoso problema di accesso concorrente ad una "Critical Section".
Prima di accedere in lettura da programma io disabiliterei il DMA a meno che il manuale non garantisca l'accesso atomico in RAM e in questo caso devi verificare che il compilatore emetta la sequenza giusta di codice assembly.
----
Esempio su CPU a 32 bit:
int tmp;
DMA_DESTINATION_ADDRESS = 0x0204FF53;
DMA_ENABLE = 0x00; /* Begin of Critical Section */
tmp = &0x0204FF53; /* Atomic access */
DMA_ENABLE = 0x01; /* End of Critical Section */
----
Io ho provato sulla mia pelle questi problemi di Critical Section.
Leggevo da programma una variabile intera a 16 bit che veniva aggiornata da un interrupt e ogni tanto leggevo dati non consistenti.
>> Non c'è la ISR, il dato viene ciclicamente preso dal buffer ed è comunque il più recente che sia disponibile
Se accedi al dato in RAM mentre il DMA sta scrivendo potresti incorrere nel famoso problema di accesso concorrente ad una "Critical Section".
Prima di accedere in lettura da programma io disabiliterei il DMA a meno che il manuale non garantisca l'accesso atomico in RAM e in questo caso devi verificare che il compilatore emetta la sequenza giusta di codice assembly.
----
Esempio su CPU a 32 bit:
int tmp;
DMA_DESTINATION_ADDRESS = 0x0204FF53;
DMA_ENABLE = 0x00; /* Begin of Critical Section */
tmp = &0x0204FF53; /* Atomic access */
DMA_ENABLE = 0x01; /* End of Critical Section */
----
Io ho provato sulla mia pelle questi problemi di Critical Section.
Leggevo da programma una variabile intera a 16 bit che veniva aggiornata da un interrupt e ogni tanto leggevo dati non consistenti.
4 messaggi
• Pagina 1 di 1
Torna a Firmware e programmazione
Chi c’è in linea
Visitano il forum: Google [Bot] e 4 ospiti