Forum: FPGA, VHDL & Co. ZYNQ Zedboard DMA Datentransfer startet nicht (immer)


von Jens Schröder (Gast)


Angehängte Dateien:

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

von Guest (Gast)


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.

von Jens Schröder (Gast)


Lesenswert?

Nein daran habe ich noch nicht gedacht. Ich verstehe noch nicht ganz wie 
das gemeint ist mit dem flushen/invalidieren. Wie könnte ich testen ob 
das das Problem ist? Wann sollte ich den Cache flushen?

von Florian Pitzl (Gast)


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...

von Florian Pitzl (Gast)


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.

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.