ARM7 LPC2364 Probleme mit DMA

OP #1433665
Lesenswert?

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
Gast #1435698
Lesenswert?

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
OP #1436096
Lesenswert?

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
}
Angehängte Dateien:
Gast #1437107
Lesenswert?

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
OP #1446370
Lesenswert?

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

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