DMA

Aus der Mikrocontroller.net Artikelsammlung, mit Beiträgen verschiedener Autoren (siehe Versionsgeschichte)
Wechseln zu: Navigation, Suche

von Benutzer:Andreas

DMA steht für "Direct Memory Access". Der Begriff taucht fast nur im Zusammenhang mit PCs und größeren Mikrocontrollern auf, deswegen sind viele der Meinung, DMA wäre etwas furchtbar Komplexes das man bei Mikrocontrolleranwendungen nur in seltenen Fällen braucht. In Wirklichkeit handelt es sich dabei aber um ein sehr einfaches Konzept das sich in ein paar Sätzen erklären lässt.

Das Grundprinzip von DMA ist, dass Transfers zwischen Speicher und Peripherie (UART, SPI, AD-Wandler) automatisiert im Hintergrund ablaufen, ohne die CPU nennenswert zu belasten.

Angenommen man möchte einen großen Datenblock über das SPI-Interface eines Controllers übertragen, zum Beispiel an eine SD-Karte. Bei der klassischen Implementierung einer SPI-Übertragung muss die CPU für jedes Byte das gesendet werden soll warten bis der SPI-Controller bereit ist Daten entgegenzunehmen und dann das Byte in den Sendepuffer schreiben. Bei der Verwendung von Interrupts kann zwar die Wartezeit genutzt werden, trotzdem muss jedes Byte einzeln behandelt werden. Bei hohen Übertragungsraten führt das dazu, dass der Interrupthandler immer mehr Rechenzeit in Anspruch nimmt oder sogar überhaupt nicht mehr nachkommt den SPI-Controller schnell genug mit Daten zu beliefern und damit die Übertragung bremst.

Mit DMA funktioniert der Transfer folgendermaßen: Man schreibt die Anzahl der zu übertragenden Datenworte und die Speicheradresse an der der zu übertragende Datenblock steht in ein Register und startet den DMA-Transfer, z. B. durch Setzen eines Bits. Der DMA-Controller überträgt nun das erste Datenwort, zählt die Adresse um einen Schritt nach oben, die Anzahl nach unten und wartet, bis das SPI-Interface wieder bereit ist. Das wiederholt sich so lange, bis das Zählregister bei 0 angekommen ist. Das ganze läuft praktisch unbemerkt im Hintergrund ab, das Programm wird währenddessen ganz normal weiter ausgeführt.

Beim AT91SAM7 sieht das unter Verwendung des sogenannten "Peripheral DMA Controller" (PDC) z. B. so aus:

<c> unsigned char data[512];

// das Array wird mit irgend welchen Daten gefüllt // ...

  • AT91C_SPI_TPR = data; // Adresse des Arrays
  • AT91C_SPI_TCR = sizeof(data); // Anzahl der zu übertragenden Datenworte (hier Bytes)
  • AT91C_SPI_PTCR = AT91C_PDC_TXTEN; // Transfer starten

while(! (*AT91C_SPI_SR & AT91C_SPI_ENDTX)); // auf das Ende der Übertragung warten

  • AT91C_SPI_PTCR = AT91C_PDC_TXTDIS; // DMA deaktivieren

</c>

Ein komplettes Beispiel für die Verwendung von DMA zum Schreiben und Lesen von einer SD-Karte (SPI) und einem Audio-Codec (SSC) findet man im Sourcecode des Projektes ARM MP3/AAC Player.