Hallo zusammen, ich hoffe ich schreibe hier in das richtige Unterforum, konnte mich nicht entscheiden wo das jetz hingehört. Ich bin Anfänger was ARM7 angeht und muss für meine Bachelorthesis nun einen LPC2364 von NXP programmieren. Das Ding soll später mal ein CAN-Telegramm empfangen und über SSP0 (SPI-Interface) an einen FPGA übergeben. Genauso soll vom FPGA ein CAN-Telegramm an SSP1 einkommen und wieder auf den CAN-Bus gesendet werden. Zum Test habe ich nun einfach mal beide SPI schnittstellen verbunden. Das Senden und Empfangen an den SPI Schnittstellen läuft dabei über DMA. Ich schreibe in einen Pufferspeicher eine CAN-Nachricht und Sende diese mit DMA Kanal 0 über SSP0 und Empfange mit DMA Kanal 1 an SSP1 das Telegramm und schreibe es in einen anderen Pufferspeicher. Der CAN-Controller schreibt/ließt dabei aus dem entsprechenden Puffer um mit dem CAN-Bus zu kommunizieren. So weit so gut. Ich habe nun zwei Probleme mit dem DMA. 1. Ich muss den DMA zum Empfangen insgesammt 3 mal Inizialisieren bis er richtig läuft (1 mal Initialisieren und garnichts passiert, 2. mal Initialisieren und es wird nur Datenmüll in den Puffer geschrieben, 3.mal Initialiseren und alles läuft perfekt). Das die SPI Nachricht dabei immer korrekt gesendet wird habe ich mit dem Oszi überprüft (das Ding beherscht SPI). Wieso muss ich hier 3mal initialisieren, bzw. wo soll ich hier denn Anfangen nach dem Fehler zu suchen. Die Initialisierung ist immer gleich, ich wiederhole sie einfach in einer Schleife. 2. Nach dreimaligem Initialsieren läuft alles. Bis nach einer unbestimmten Anzahl CAN-Telegramme der Controller einen Reset macht (da gibts keine Regelmäßigkeit). Also wie wenn ich die Spannung abgezogen hätte beginnt er wieder mit der Initialisierung. Ich habe weder ein Watchdog noch sonstetwas laufen, dass diesen Reset auslößen könnte. Jemand Erfahrung mit sowas? Falls ich hier irgendwelchen Code oder sonstwas anhängen soll, bitte bescheid geben. Gruß Martin
Hallo Martin, habe auch schon mit dem LPC2364 und SSP sowie DMA gearbeitet. Hat alles wie gewünscht, stabil und nachvollziehbar funktioniert. Ich denke Du mußt wohl doch etwas Sourcecode posten, um dem Problem auf die Spur zu kommen. Gruß Microman
Hallo Microman, danke für die Antwort. Habe mal alle .c und .h Files angehängt. Ich hoffe du findest dich zurecht. In der main.c wird verständlicherweiße die Mainloop abgearbeitet. In der DMA.c und SSP.c sind die Initialisierungsfunktionen für DMA und SPI. In der transfer.c sind die Funktionen die die eigentliche Arbeit machen. Einige Funktionen werden nicht aufgerufen oder dienen nur dazu mir Speicherinhalte beim Debuggen an zu zeigen. Also nicht wündern. Ach sind viele Kommentare drinn was noch so fehlt, aber das ganze ist eben noch eine Baustelle. Um den Download zu sparen habe ich die beiden funktionen die den DMA initialisierne mal noch als Text: Erstmalige Initialisierung des DMA:
1 | int32_t DmaInit( int32_t channelNum, int32_t frameSize, int32_t frameAddress ) |
2 | { |
3 | |
4 | PCONP |= (1 << 29); /* Enable GP DMA clock, */ |
5 | |
6 | GPDMA_INT_TCCLR = 0x03; /* Clear any pending interrupts */ |
7 | GPDMA_INT_ERR_CLR = 0x03; /* Clear error interrupt requests */ |
8 | |
9 | if ( channelNum == 0 ) |
10 | { |
11 | /* Ch0 memory to SSP0. */ |
12 | GPDMA_CH0_SRC = frameAddress; |
13 | GPDMA_CH0_DEST = DMA_SSP0DR; |
14 | /* The burst size is set to 8, the size is 8 bit too. */ |
15 | /* Terminal Count Int enable */ |
16 | GPDMA_CH0_CTRL = (frameSize & 0x0FFF) | (0x02 << 12) | (0x02 << 15) | (1 << 26) | 0x80000000; |
17 | |
18 | } |
19 | |
20 | else if ( channelNum == 1 ) |
21 | { |
22 | |
23 | /* Ch1 SSP1 to memory. */ |
24 | GPDMA_CH1_SRC = DMA_SSP1DR; |
25 | GPDMA_CH1_DEST = frameAddress; |
26 | /* The burst size is set to 4, the size is 8 bit too. */ |
27 | /* Terminal Count Int enable */ |
28 | GPDMA_CH1_CTRL = (frameSize & 0x0FFF) | (0x02 << 12) | (0x01 << 15) | (1 << 27) | 0x80000000; |
29 | GPDMA_CH1_CFG |= 0x08001 | (0x03 << 1) | (0x02 << 11); |
30 | } |
31 | |
32 | /*else |
33 | { |
34 | return ( FALSE ); |
35 | } */ |
36 | |
37 | GPDMA_CONFIG = 0x01; |
38 | |
39 | while ( !(GPDMA_CONFIG & 0x01) ); |
40 | |
41 | if ( install_irq( GPDMA_INT, (void *)DMAHandler, HIGHEST_PRIORITY ) == FALSE ) |
42 | { |
43 | return ( FALSE ); |
44 | } |
45 | return (TRUE); |
46 | } |
Alle weiteren neu Initialisierungen nach dem Empfang von Daten:
1 | int32_t DmaReInit( int32_t channelNum, int32_t frameSize, int32_t frameAddress ) |
2 | { |
3 | |
4 | if ( channelNum == 0 ) |
5 | { |
6 | /* Ch0 memory to SSP0. */ |
7 | GPDMA_CH0_SRC = frameAddress; |
8 | GPDMA_CH0_DEST = DMA_SSP0DR; |
9 | /* The burst size is set to 8, the size is 8 bit too. */ |
10 | /* Terminal Count Int enable */ |
11 | GPDMA_CH0_CTRL = (frameSize & 0x0FFF) | (0x02 << 12) | (0x01 << 15) | (1 << 26) | 0x80000000; //wieso an stelle 15 ein 0x01 statt 0x02 |
12 | GPDMA_CH0_CFG |= 0x10001 | (0x00 << 1) | (0x01 << 11) | (0x00 << 15); |
13 | } |
14 | |
15 | else if ( channelNum == 1 ) |
16 | { |
17 | /* Ch1 SSP1 to memory. */ |
18 | GPDMA_CH1_SRC = DMA_SSP1DR; |
19 | GPDMA_CH1_DEST = frameAddress; |
20 | /* The burst size is set to 8, the size is 8 bit too. */ |
21 | /* Terminal Count Int enable */ |
22 | GPDMA_CH1_CTRL = (frameSize & 0x0FFF) | (0x02 << 12) | (0x02 << 15) | (1 << 27) | 0x80000000; |
23 | GPDMA_CH1_CFG |= 0x00001 | (0x03 << 1) | (0x06 << 11); |
24 | } |
25 | |
26 | else |
27 | { |
28 | return ( FALSE ); |
29 | } |
30 | return (TRUE); |
31 | } |
Hallo Martin, habe nur mal schnell drüber geschaut, aber leider huete nicht viel Zeit mir das genauer anzusehen. Werde es aber noch mit meinen Routine vergleichen. was mir auffällt in DmaReInit bei Channel-0 steht die Zeile: GPDMA_CH0_CFG |= 0x10001 | (0x00 << 1) | (0x01 << 11) | (0x00 << 15); Diese fehlt aber in der DmaInit Funktion. Ist das so korrekt? Gruß Microman
Hallo Microman, ja das ist korrekt, der CH0 wird beim erstmaligen Initialisieren nicht mit initialisiert, die if Verzweigung ist quasi nur ein relikt aus der Programmentstehung. Gruß Martin
Hallo Martin, kurze Frage, hast Du immer noch die Probleme mit dem DMA? Würde Dir sonst mal meine Sourcen raussuchen, die Du dann mal testen könntest. Gruß
Hallo Microman, habe den Fehler ende letzte Woche gefunden. Hatte letztendlich eigentlich garnichts mit dem DMA zu tun, hatte in einem Interrupt ausversehen "nested interrupts" aktiviert (besser nicht zuviel aus Beispielen abschreiben...). Wurde diser nun zufällig ausgelöst kam es zum Programmabsturz (hatte ja die Register nicht gesichert, da ich nie die Absicht hatte nested interrupts zu verwenden) bzw. fehlverhalten. Nested interrupts deaktiviert und schon funktioniert alles. An dieser Stelle nochmal Danke für deine Hilfe und deine Mühe!!
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.