Forum: Mikrocontroller und Digitale Elektronik Xmega192A3U DMA


von Markus F. (blackflip)


Lesenswert?

Hallo ich hoffe mir kann jemand helfen,

ich versuche gerade das Beispiel 2.1 aus der Applikation Note 1304 von 
Atmel zu 
verstehen.(http://www.atmel.com/Images/Atmel-8046-Using-the-XMEGA-DMA-Controller_Application-Note_AVR1304.pdf)

Dabei habe ich dafür das folgende Programm:
1
#include <avr/io.h>
2
3
int main(void)
4
{
5
  uint8_t gewinn[1000];
6
  uint8_t umsatz[1000];
7
  uint_fast16_t i;
8
  for(i=0; i<1000; i++) {
9
    gewinn[i]=i+1;
10
  }
11
  
12
  DMA.CTRL = (1 << DMA_ENABLE_bp)    //Enable
13
    | (0 << DMA_RESET_bp)      //no Reset
14
    | DMA_PRIMODE_CH0123_gc      //Priority Ch0 >..>..> Ch3
15
    | DMA_DBUFMODE_DISABLED_gc;    //Disable Buffering
16
  DMA.CH0.ADDRCTRL = DMA_CH_SRCRELOAD_NONE_gc  // Source address reload mode : _NONE, BLOCK, BURST, TRANSACTION
17
        | DMA_CH_SRCDIR_INC_gc       // Source addressing mode: FIXED, INC, DEC
18
        | DMA_CH_DESTRELOAD_NONE_gc  // Destination adress reload mode: NONE, BLOCK, BURST, TRANSACTION
19
        | DMA_CH_DESTDIR_FIXED_gc;   // Destination adressing mode: FIXED, INC, DEC
20
  DMA.CH0.TRIGSRC=DMA_CH_TRIGSRC_OFF_gc;        //only Software Trigger
21
  DMA.CH0.TRFCNT=0x0400;        //Blocksize=1K bytes 16bit register =1kbytes
22
23
  DMA.CH0.DESTADDR0 = *umsatz;
24
  DMA.CH0.DESTADDR1 = 0;
25
  DMA.CH0.DESTADDR2 = 0;
26
  DMA.CH0.SRCADDR0 = *gewinn;
27
  DMA.CH0.SRCADDR1 = 0;
28
  DMA.CH0.SRCADDR2 = 0;
29
  //DMA.CH0.CTRLA|=0x80; //Enable Channel 0  
30
  DMA.CH0.CTRLA= (1 << DMA_CH_ENABLE_bp)    //  Channel Enable
31
    | (0 << DMA_CH_RESET_bp)      // Channel Software Reset
32
    | (0 << DMA_CH_REPEAT_bp)      // Channel Repeat Mode bit position.
33
    | (0 << DMA_CH_TRFREQ_bp)      // Channel Transfer Request bit position.
34
    | (0 << DMA_CH_SINGLE_bp)      // Channel Single Shot Data Transfer bit position.
35
    | DMA_CH_BURSTLEN_8BYTE_gc;
36
  DMA.CH0.CTRLA |= (1 << DMA_CH_TRFREQ_bp);// Channel Transfer Request bit position.
37
38
  
39
  while(1)
40
    {
41
    if((DMA.INTFLAGS&0x01)==0x01){
42
      asm volatile ("nop");
43
    }
44
        //TODO:: Please write your application code 
45
    }
46
}

Bei den Programm soll der Inhalt des Arrays gewinn in das Array umsatz 
kopiert werden. Derzeit habe ich leider das Problem mit den Simulator, 
das der Vorgang als abgeschlossen bewertet wird(Haltepunkt bei NOP), 
aber sich der Inhalt vom 2. Array nicht verändert hat.

Ich denke das liegt sicher an falsch gesetzten Registern 
DMA.CH0.DESTADDR und DMA.CH0.SRCADDR. Leider komme ich nicht auf die 
richtige Lösung

von Jim M. (turboj)


Lesenswert?

Ich sehe da einen Buffer overflow. Du hast 1000 Byte Puffer, aber machst 
dann 0x400 = 1024 Byte Transfers.

Allerdings scheint auch Dest INC nicht an zu sein, deshalb knallt es 
vermutlich nicht.

Für memcopy via DMA müssen AFAIK sowohl src als auch dest jeweils 
inkrementert werden.

von Timmo H. (masterfx)


Lesenswert?

>DMA.CH0.DESTADDR0 = *umsatz;
>DMA.CH0.DESTADDR1 = 0;
>DMA.CH0.DESTADDR2 = 0;

Da muss die Adresse vom In- bzw. Outbuffer rein
=>
1
DMA.CH0.DESTADDR0 = umsatz & 0xFF; //oder auch &umsatz[0] >> 0xFF
2
DMA.CH0.DESTADDR1 = (umsatz >> 8) 0xFF;
3
DMA.CH0.DESTADDR2 = (umsatz >> 16) 0xFF; //bzw. 0x00
Ditto für SRC

: Bearbeitet durch User
von Markus F. (blackflip)


Angehängte Dateien:

Lesenswert?

Vielen Dank, nachrechnen hätte man mal sollen :-/
Ich habe jetzt die folgenden Sachen geändert:
1
DMA.CH0.TRFCNT=0x03E8;          // Blocksize=1K bytes 16bit register =1kbytes
2
3
  DMA.CH0.ADDRCTRL = DMA_CH_SRCRELOAD_NONE_gc  // Source address reload mode : _NONE, BLOCK, BURST, TRANSACTION
4
        | DMA_CH_SRCDIR_INC_gc        // Source addressing mode: FIXED, INC, DEC
5
        | DMA_CH_DESTRELOAD_NONE_gc      // Destination adress reload mode: NONE, BLOCK, BURST, TRANSACTION
6
        | DMA_CH_DESTDIR_INC_gc;      // Destination adressing mode: FIXED, INC, DEC

Jetzt erkennt er in der Abfrage leider keine beendigung dieser Aufgabe 
und selbst wenn ich bei der Abfrage nach 5 Sekunden einen Breakpoint 
setze, ist das gewünschte Array leider leer.


Edit:

Jetzt habe ich wie gewünscht die Destaddr und Srcaddr geändert, aber 
erhalte die Fehlermeldung aus dem Anhang.
1
  DMA.CH0.DESTADDR0 = umsatz & 0xFF;
2
  DMA.CH0.DESTADDR1 = (umsatz >> 8)& 0xFF;
3
  DMA.CH0.DESTADDR2 = (umsatz >> 16)& 0xFF; //bzw. 0x00
4
  DMA.CH0.SRCADDR0 = gewinn & 0xFF;
5
  DMA.CH0.SRCADDR1 = (gewinn >> 8)& 0xFF;
6
  DMA.CH0.SRCADDR2 = (gewinn >> 16)& 0xFF; //bzw. 0x00

das gleiche bei:
1
  DMA.CH0.DESTADDR0 =&umsatz[0] >> 0xFF

Jetzt werde ich mal dort weiter schauen. Vielen Dank

: Bearbeitet durch User
von Dieter F. (Gast)


Lesenswert?

Markus F. schrieb:
> DMA.CH0.DESTADDR0 = umsatz & 0xFF;
>   DMA.CH0.DESTADDR1 = (umsatz >> 8) 0xFF;
>   DMA.CH0.DESTADDR2 = (umsatz >> 16) 0xFF; //bzw. 0x00
>   DMA.CH0.SRCADDR0 = gewinn & 0xFF;
>   DMA.CH0.SRCADDR1 = (gewinn >> 8) 0xFF;
>   DMA.CH0.SRCADDR2 = (gewinn >> 16) 0xFF; //bzw. 0x00

Da fehlt 4 mal ein & vor dem 0xFF ...

von Markus F. (blackflip)


Lesenswert?

Vielen dank für die Antwort, das habe ich gerade gemerkt und so 
funktioniert es, vielen dank für die schnelle hilfe!
1
int main(void)
2
{
3
  uint8_t gewinn[1000];
4
  uint8_t umsatz[1000];
5
  uint_fast16_t i;
6
  for(i=0; i<1000; i++) {
7
    gewinn[i]=i+1;
8
  }
9
  
10
  DMA.CTRL = (1 << DMA_ENABLE_bp)      //Enable
11
    | (0 << DMA_RESET_bp)        //no Reset
12
    | DMA_PRIMODE_CH0123_gc        //Priority Ch0 >..>..> Ch3
13
    | DMA_DBUFMODE_DISABLED_gc;      //Disable Buffering
14
  DMA.CH0.ADDRCTRL = DMA_CH_SRCRELOAD_NONE_gc  // Source address reload mode : _NONE, BLOCK, BURST, TRANSACTION
15
        | DMA_CH_SRCDIR_INC_gc        // Source addressing mode: FIXED, INC, DEC
16
        | DMA_CH_DESTRELOAD_NONE_gc      // Destination adress reload mode: NONE, BLOCK, BURST, TRANSACTION
17
        | DMA_CH_DESTDIR_INC_gc;      // Destination adressing mode: FIXED, INC, DEC
18
  DMA.CH0.TRIGSRC=DMA_CH_TRIGSRC_OFF_gc;  // only software trigger
19
  DMA.CH0.TRFCNT=0x03E8;          // Blocksize=1K bytes 16bit register =1kbytes
20
21
  DMA.CH0.DESTADDR0 = (int16_t)umsatz & 0xFF;
22
  DMA.CH0.DESTADDR1 = ((int16_t)umsatz >> 8)& 0xFF;
23
  DMA.CH0.DESTADDR2 = 0x00; //bzw. 0x00
24
  DMA.CH0.SRCADDR0 = (int16_t)gewinn & 0xFF;
25
  DMA.CH0.SRCADDR1 = ((int16_t)gewinn >> 8)& 0xFF;
26
  DMA.CH0.SRCADDR2 = 0x00; //bzw. 0x00
27
  //DMA.CH0.CTRLA|=0x80; //Enable Channel 0  
28
  DMA.CH0.CTRLA= (1 << DMA_CH_ENABLE_bp)  // Channel Enable
29
    | (0 << DMA_CH_RESET_bp)      // Channel Software Reset
30
    | (0 << DMA_CH_REPEAT_bp)      // Channel Repeat Mode bit position.
31
    | (0 << DMA_CH_TRFREQ_bp)      // Channel Transfer Request bit position.
32
    | (0 << DMA_CH_SINGLE_bp)      // Channel Single Shot Data Transfer bit position.
33
    | DMA_CH_BURSTLEN_8BYTE_gc;
34
  DMA.CH0.CTRLA |= (1 << DMA_CH_TRFREQ_bp);// Channel Transfer Request bit position.
35
  //funct_port_init();
36
    //funct_dma_init();
37
  
38
  while(1)
39
    {
40
    if((DMA.INTFLAGS&0x01)==0x01){
41
      asm volatile ("nop");
42
    }
43
        //TODO:: Please write your application code 
44
    }
45
}

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.