Forum: Mikrocontroller und Digitale Elektronik DMA Controller im LPC1837


von Ludwig S. (big_l)


Lesenswert?

Moin Moin liebe µC-Community,

ich habe mal wieder ein paar Probleme mit meinem LPC1837. Ich wollte 
mich mal mit der DMA Geschichte auseinander setzen weil ich den ja 
offensichtlich für meinen integrierten Ethernet-Controller brauche. 
Daher wollte ich mal ein kleines Programm schreiben und einfach nur 
versuch via DMA-Controller (bei mir heist das Ding General Purpose DMA) 
ein 32bit wort in einen register GPIO Register zu schreiben, die dann - 
ihr ahnt es sicherlich schon - eine LED zum leuchten bringen soll.

Kleine Anmerkung und Auszug aus dem Datenblatt: "The GPIO block, the 
WWDT, and the Timers can be accessed by the GPDMA as memory-to-memory 
transfers."

Leider passiert bei mir genau garnix. Die Register werden alle 
beschrieben. Aber nachdem Channel-enable hat sich im GPIO Register 
absolut nix getan!

Hier ist mein Quelltext:
1
#include "chip.h"
2
#include <cr_section_macros.h>
3
4
static uint32_t source, dest;
5
6
int main(void)
7
{
8
volatile static int i = 0 ;
9
source=0xFFFFFFFF;            //probier-daten
10
dest=(uint32_t)&LPC_GPIO_PORT->SET[0];  //mein Kopierziel
11
12
LPC_SCU->SFSP[1][0]=0b00010000;
13
LPC_GPIO_PORT->DIR[0]=0xFFFFFFFF;    //PORT auf output gesetzt
14
15
LPC_GPDMA->CONFIG=0x1;  //
16
17
LPC_GPDMA->CH[0].SRCADDR=(uint32_t)&source;  //Setze die Source Address auf meine "source" variable
18
LPC_GPDMA->CH[0].DESTADDR=dest;        //Setze die Dest Address auf "DIR[0]" register
19
20
#define TRANSFERSIZE  0x004  /*4 byte sollen übertragen werden*/
21
#define SBSIZE      0x4    /*Sicherheitshalber auf 4 bytes gesetzt*/
22
#define DBSIZE      0x4
23
#define SWIDTH      0x2    /*Ein 32bit word soll übertragen werden*/
24
#define DWIDTH      0x2    /*Ein 32bit word soll übertragen werden*/
25
#define S        0x0    /*AHB-Master ausgewäht, da M2M Transfer*/
26
#define D        0x0    /*AHB-Master ausgewäht, da M2M Transfer*/
27
#define SI        0x0    /*not incremented*/
28
#define DI        0x0    /*not incremented*/
29
#define PROT1      0x0    /*usermode*/
30
#define PROT2      0x0    /*not bufferable*/
31
#define PROT3      0x0    /*not cacheable*/
32
33
LPC_GPDMA->CH[0].CONTROL= TRANSFERSIZE + SBSIZE + DBSIZE + SWIDTH + DWIDTH + S + D + SI + DI + PROT1 + PROT2 + PROT3;
34
LPC_GPDMA->CH[0].CONFIG=0x1;
35
36
//infinite loop
37
while(1){
38
    i++ ;
39
    }
40
return 0 ;
41
}

Wenn ihr mir dabei weiterhelfen könntet dann wäre das absolut der 
Oberknaller!

: Bearbeitet durch User
von Jim M. (turboj)


Lesenswert?

Da fehlen mindestens die korrekten Shifts für die Bits in CONTROL, wie 
SBSIZE, SWIDTH etc. Die sind nicht auf Bit Position null.

Außerdem ist TRANSFERSIZE gleich eins, wenn SWIDTH gleich 2 für 32-bit 
Transfer ist. Du willst ja nur ein 32 bittiges Wort übertragen, richtig?

Übrigens ist Kanal 0 der mit der höchsten Prio. Für Memory-to-Memory 
würde ich lieber den mit der niedrigsten Priorität nehmen, insbesondere 
wenn Transfersize größer ist.

: Bearbeitet durch User
von Ludwig S. (big_l)


Lesenswert?

Jim M. schrieb:
> Da fehlen mindestens die korrekten Shifts für die Bits in CONTROL, wie
> SBSIZE, SWIDTH etc. Die sind nicht auf Bit Position null.

NEIN!!!! das gibts nicht! Wie konnte ich das übersehen??? Ok Danke 
schonmal! Okay das ändere ich mal sofort und probiers aus...
wegen der Prios: hab ja keine konkurrierenden DMA aktionen will ja nur 
mal erfolgreich n bytes hin- und herschicken.

von Jim M. (turboj)


Lesenswert?

Übrigens sollte es von NXP auch irgendwo Beispielcode für den LPC18xx 
DMA geben, dort wären dann auch die korrekten Bitdefinitionen drin 
gewesen.

von Ludwig S. (big_l)


Lesenswert?

jein. Also es gibt Beispiel-code und sicher auch mit den korrekten 
Bit-Bezichnungen. Leider gibt es nur ein Beispiel und da wird irgendwie 
der timer mit dem dma gekoppelt und da werden natürlich LPC_Open Befehle 
verwendet und die sind alle sehr verschachtelt und kompliziert. Zum 
lernen ungeeignet.
Alles was ich will ist ja ein DWord über DMA zum GPIO schicken.

Ich habe jetzt mal meinen Quelltext korrigiert die Bits anständig 
verschoben -> Funktioniert immernoch nicht.

In den Registern steht eigentlich alles drinne wies soll. Das einzige 
was auffällig ist, ist das im Register bei TRANSFERSIZE erst ein wenig 
später nach dem schreiben die "1" steht. also nicht DIREKT nach dem 
schreiben sondern erst ein paar takte später...

von Jim M. (turboj)


Lesenswert?

Ludwig S. schrieb:
> Bit-Bezichnungen. Leider gibt es nur ein Beispiel und da wird irgendwie
> der timer mit dem dma gekoppelt und da werden natürlich LPC_Open Befehle
> verwendet und die sind alle sehr verschachtelt und kompliziert. Zum
> lernen ungeeignet.

Aber man hätte sich die Header Dateien anschauen und deren 
Bitdefinitionen verwenden können. Und wie Du grade feststellen musst, 
ist die direkte Verwendung von Registern auch nicht wirklich einfach.

Ich schaue mir eigentlich immer den Source Code von solchen Libs an. Oft 
gibt es dann den Momement: "Ach so haben die sich das gedacht..."

Weitere Frage: Sind die entsprechenden Clocks eingeschaltet?

: Bearbeitet durch User
von Ludwig S. (big_l)


Lesenswert?

Ja das habe ich natürlich auch gemacht. Ich habe auch ehrlich gesagt 
auch schon die LPC_Open Befehle verwendet da sind ja alle Bit 
definitionen und strukturen schon dabei bzw man muss sie garnicht mehr 
setzen. Aber bei diesen LPC_Open Befehlen funzts auch nicht. Ich glaube 
eher das ich da einen ganz fiesen denkfehler habe oder irgendwas total 
billiges übersehen habe...(Ähnlich wie das shifting vorhin)

Vllt versuchen wirs mal in Worten und der Reihen nachL:

- als erstes erstelle ich eine variable für source und destination, die 
Adressen dieser Variablen caste ich in ein DWord wie laut Datenblatt 
vorgschrieben
- dann sehe ich zu, das meine Pins auf output gestellt sind und die auch 
die GPIO-Funktion zugewiesen bekommen haben
- dann schalte ich meinen DMA Controller an (nicht den channel)
- die source und destination variablen schreibe ich jetz in die 
dazugehörigen register
- Ins control-register schreibe ich sachen wie das der transfersize=1 
ist, weil will ja ein dword übertragen. "source transfer width"=4 weil 
is ja n Dword also 4byte genau dasselbe bei "destination transfer 
width". Der rest kann Null sein.
- Dann enable ich meinen Channel 0 eigentlich müsste der transfer doch 
jetzt losgehen oder nicht? Oder muss da noch irgendwas anderes aktiviert 
werden?

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.