ZYNQ Zedboard DMA Datentransfer startet nicht (immer)

Gast #4151669
Lesenswert?

Hallo,

Ich arbeite mit dem ZYNQ Zedboard (version d, PS7000). Ich habe eine 
Hardware synthetisiert, und teilweise getestet. Zu sehen ist das Design 
im Anhang.
Im C Code mache ich folgendes um den DMA anzusteuern, die adressen 
stimmen, da es wie unten beschrieben auch manchmal geht:
1
  // 1 verify CDMASR = idle
2
  uint32_t value;
3
  do{
4
    value = Xil_In32(XPAR_AXI_CDMA_0_BASEADDR + 0x04); // read status register
5
  }while (!(value & 0x02));
6

7
  // deactivate interrupts
8
  Xil_Out32(XPAR_AXI_CDMA_0_BASEADDR + 0x04, (value & ~0x5000));
9

10
  // init dma controller
11
  // programm dma engine to copy data
12
  Xil_Out32(XPAR_AXI_CDMA_0_BASEADDR + 0x18, source); //write source address
13
  Xil_Out32(XPAR_AXI_CDMA_0_BASEADDR + 0x20, dest); //write destination address
14
  Xil_Out32(XPAR_AXI_CDMA_0_BASEADDR + 0x28, len);        //write length
15

16
  do{
17
    value = Xil_In32(XPAR_AXI_CDMA_0_BASEADDR + 0x04); // read status register
18
  }while (!(value & 0x02));
19

20
  // clear interrupt ..
21
  Xil_Out32(XPAR_AXI_CDMA_0_BASEADDR + 0x04, value | 0x1000);

Das ist alles aus dem Reference Manual für den DMA. In der Main rufe ich 
vorher die beiden Funktionen zum Initialisieren der Hardware auf:
1
// init functions
2
init_platform();
3
ps7_post_config();

Das Programm schreibt Daten in das lokale RAM, die dann von dem DMA in 
den Block Memory kopiert werden sollen. Von da lese ich die Werte wieder 
über einen seperaten AXI Controller zurück.

Leider stellt sich folgende Eigenart ein: Erst nach 2 oder 3 maligem 
durchlauf des gesamten Codes (übrigens mit sleep Funktionen) stimmen die 
Datenwerte überein. Als ob der DMA nicht immer gestartet wird, bzw er 
nicht korrekt gestartet wird. Im Manual steht dazu nur, dass er immer 
dann startet, wenn man die zu übertragende Länge neu schreibt. (passiert 
im Code ...)

Habt ihr noch Ideen woran es liegen kann?

Gruß,
Jens
Angehängte Dateien:
Gast #4151960
Lesenswert?

Hast Du auch berücksichtigt, dass dein lokales RAM als nicht cachebar in 
der MMU eingestellt ist?

Das Xilinx BSP stellt standardmäßig das komplette DDR-RAM als L1 und L2 
cachebar ein. Also muss entweder die MMU-Tabelle verändert werden, oder 
die Cachelines müssen nach dem Schreiben/Lesen manuell 
geflusht/invalidated werden.
Gast #4154486
Lesenswert?

Nicht beachten der Cacheeinstellungen ist auch ein sehr gern gemachter 
Fehler bei der DMA Verwendung - unabhängig vom Zynq...

Eine Beschreibung zu den Cacheeinstellungen gibt's im Xilinx UG585 
Kapitel 3, wenns noch etwas tiefer gehen soll, dann hilft ein Blick in 
die entsprechende ARM Dokumente.

Ich weis aus dem Kopf nicht ob Xilinx im BSP den DDR-RAM als 
"write-through" oder "write-back" einstellt, bei letzterem beginnt dein 
Problem schon wenn du mit der CPU ins RAM schreibst. Der Schreibzugriff 
landet beim "write-back" erst mal im Cache, ins externe RAM wird nur 
geschrieben, wenn die Cacheline anderweitigt belegt wird. In deinem Fall 
musst die das Schreiben von der Cacheline ins externe RAM manuell 
anstoßen. Xilinx liefert dir dafür im BSP (xil_cache.h) 
Xil_DCacheFlush() bzw. Xil_DCacheFlushRange(). Erst danach kann ein 
externer DMA-Controller auch deine von der CPU geschriebenen Daten 
transferieren.

Beim Einlesen liegt das Problem im Prinzip darin, dass die CPU die Daten 
erst mal aus dem Cache und nicht vom externen RAM bekommt. Hier liegt es 
wieder an dir den Cache manuell für ungültig zu erklären, damit die 
Daten aus dem externen RAM gelesen werden müssen. Hierfür gibts im BPS 
Xil_DCacheInvalidate() und Xil_DCacheInvalidateRange().

Alternativ kann auch der Speicherbereich in der MMU als "non-cacheable" 
eingestellt werden, aber davor sollte man sich etwas in die Beschreibung 
der MMU-Tabelle einlesen.

Im Xilinx Userforum findest du übrigens auch einige Einträge zu dem 
Thema...
Gast #4154506
Lesenswert?

Ach ja - der Zynq hat auch noch einen speziellen AXI-Port (ACP) bei dem 
der Cache mit berücksichtigt werden kann. Allerdings muss hier im Vivado 
beim Wrapper des Processingssytems entweder bei den Porteinstellungen 
ein Haken gesetzt werden damit alle Zugriffe cache-coherent ablaufen 
oder der AXI-Master liefert die entsprechenden Axi-User-Signale.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren