Hallo,
ich bin gerade dabei, eine SPI-Kommunikation mit zwei gleichen
Controllern aufzubauen (Vollduplex). Der Controller-Typ ist ein ARM
Cortex M3 von Atmel (ATSAM3S4B).
Da die Übertragungsgeschwindigkeit ca. 10 MBit beträgt, möchte ich die
zu übertragenden Daten mit Hilfe des PDC (DMA-Controller) übertragen.
Die SPI-Kommunikation mit PDC funktioniert soweit schon, jedoch habe ich
noch ein Problem:
Die übertragenen Daten kommen beim Slave verschoben an:
Es werden 16 Bytes übertragen, wobei das erste Byte das letzte Byte der
vorherigen Übertragung ist.
Es sieht danach aus, dass nach Senden (Master) des letzten Bytes dieses
im Slave im Empfangsregister (RDR) bleibt und nicht durch den PDC in den
Speicher übertragen wird.
Mit einem Oszilloskop wurde die gesamte SPI-Übertragung analysiert und
festgestellt, dass die Daten richtig gesendet werden. Somit liegt das
Problem höchstwahrscheinlich beim PDC.
Die Themen zu SPI und PDC aus dem Datenblatt kenne ich schon auswendig,
komme jedoch trotzdem nicht weiter, wobei diese auch nur knapp
beschrieben sind.
Hat jemand auch solche oder ähnliche Probleme gehabt oder kennt das
Problem?
Dieter
Hallo,
Danke für die Antwort.
Natürlich habe ich die SPI-Modes vorher überprüft und
ausgiebig getestet - leider ohne Erfolg.
Hier erstmal noch ein paar weitere Infos:
Die beiden Controller laufen mit 64 MHz und die SPI-Geschwindigkeit
beträgt 10,6 MBit.
Es werden 16 Bytes gesendet und empfangen. Die zu sendenden Testdaten
sehen wie folgt aus (Master und Slave):
Oberes Nibble = Byte-Nummer (0x0 bis 0xF)
Unteres Nibble = Testzähler (0x0 bis 0xF)
Dadurch können die einzelnen Bytes in der Position genau zugeordnet
werden (Senden und Empfangen beim Master und Slave).
Zum SPI-Master:
Auf dem Master läuft der SysTick-Interrupt, der alle 125 µs ausgeführt
wird. In der Interrupt Service Routine wird der PDC zyklisch gestartet
und somit die SPI-Kommunikation ausgelöst.
Nachfolgend einige Codeausschnitte:
SysTick-Interrupt Master:
SPI-Slave:
Auf dem Slave läuft ebenfalls ein Interrupt mit der Frequenz von 8 kHz.
Da die Quarze der beiden Controller nicht 100% dieselbe Frequenz haben,
werden die Interrupts synchronisiert, wobei der Regler natürlich schon
funktioniert.
Im Anhang ist dazu ein Oszilloskopbild dargestellt. Das gelbe Signal
(Kanal 1) ist dabei die Dauer des PWM-Interrupts im Slave (Beim Eintritt
in den ISR-Handler wird ein Ausgang gesetzt, beim Austritt wieder
zurückgesetzt).
Code-Ausschnitt des PWM-Interrupts im Slave:
1
voidPWM_Handler(void)
2
{
3
PIOA->PIO_SODR=PIO_SODR_P17;
4
5
PWM->PWM_ISR1;
6
7
8
9
SPI->SPI_TPR=&spi_tx_buffer;
10
SPI->SPI_TCR=sizeof(spi_tx_buffer);
11
12
SPI->SPI_RPR=&spi_rx_buffer;
13
SPI->SPI_RCR=sizeof(spi_rx_buffer);
14
15
SPI->SPI_PTCR=(SPI_PTCR_TXTEN|SPI_PTCR_RXTEN);
16
17
18
for(uint8_ti=0;i<sizeof(spi_tx_buffer);i++)
19
{
20
spi_tx_buffer[i]&=0xF0;
21
spi_tx_buffer[i]|=(testZaehler&0x0F);
22
}
23
24
testZaehler++;
25
26
PIOA->PIO_CODR=PIO_CODR_P17;
27
NVIC_ClearPendingIRQ(PWM_IRQn);
28
}
Und hier die dazugehörige SPI-Konfiguration des Slaves:
1
voidSPI_init_Slave(void)
2
{
3
// --- Parallel Input/Output Controller A ---
4
PIOA->PIO_WPMR=PIO_WPMR_WPKEY_PASSWD;// Disables the Write Protect (PIOA)
Meine Frage ist jetzt, wie der PDC genau konfiguriert werden muss bzw.
ob der Fehler (verschobene Bytes - siehe Anhang und 1. Beitrag) durch
eine falsche Konfiguration des PDC/SPI zustande kommt oder ob die
Reihenfolge des PDC falsch ist (PDC aktivieren, aktualisieren,
deaktivieren).
Könnt ihr weiterhelfen? Bin für Hinweise und Tipps sehr dankbar.
Dieter
Hallo,
das Atmel-Supportteam hat mich nur auf das SPI/PDC Beispiel aus dem
Atmel-Studio hingewiesen, welches mich jedoch nicht weiter gebracht hat.
Für einen weiteren Tipp wäre ich Euch wirklich dankbar!
Dieter
Das ganze soweit verlangsamen dass du auf deinem oszi den Ablauf der
Kommmunikation auch wirklich erkennen kannst.
Ein Problem mit Polarität/Phase ist naheliegend.
Hallo,
das dargestellte Oszillogramm sollte nur schematisch die
SPI-Kommunikation darstellen. Bei weitern hineinzoomen kann ich die
selben Bits wie im Sende- und Empfangsbuffer ausgelesen, feststellen.
Wenn ich mich nicht täusche, sind vier verschiedene Betriebsmodi für die
Polarität/Phase möglich (hier mittels CPOL und NCPHA -> S. 561 aus dem
Datenblatt: http://www.atmel.com/devices/sam3s4b.aspx?tab=documents).
Selbst bei sinnlosen ausprobieren aller dieser Betriebsmodi ist
bestenfalls dieser Byte-Versatz enthalten. Somit dürfte dieser Fehler
ausgeschlossen sein?!
Dieter
Hallo,
das Problem ist gelöst - hier die Erläuterung, damit alles etwas davon
haben:
Um die empfangenen Daten zu überprüfen (siehe oben, 3. Beitrag), habe
ich mit dem J-Link Debugger (von Segger) den Prozessor gestoppt. Das
Senden (über SPI) wird über den PDC (DMA-Controller) gemacht, wobei
dieser parallel zum Prozessor läuft.
Das Problem hierbei ist, dass durch den Prozessorhalt der
Mikrocontroller-interne (Hardware)-Ablauf offensichtlich durcheinander
gebracht wird und somit der Datenversatz entsteht.
Durch Programmierung von entsprechenden Testfunktion, bei denen auf
einen Prozessorhalt verzichtet werden kann, wurde die Datenübertragung
nun erfolgreich überprüft.
Dennoch, vielen Dank für die Tipps, Hinweise und Anregungen.
Dieter
Hallo,
I think WDRBT bit in SPI_MR should be set during bidirectional SPI
transfer with PDC. This solves our issue with wrong PCSes and maybe help
you too.
--
Konstantin