Hallo!
Ich möchte gerne mit einem ATXMEGA 64A3U Daten im Slave Modus mit einem
externen Controller austauschen.
Es kommen alle 125 µs insgesamt 16 Bytes mit 2MHz Takt an.
Da ich nicht nach jedem Byte ein Interrupt verarbeiten kann, verwende
ich DMA um die Daten vom SPI Register in ein Array zu kopieren. Das
funktioniert auch ganz gut.
Jetzt möchte ich allerdings mit einem zweiten DMA Kanal in der gleichen
Weise eine Antwort senden , welche ebenfalls in einem Array abgelegt
ist. (klar, es ist die Antwort auf das vorangegangene Datenpaket, da
full duplex) Das funktioniert allerdings nicht. Es kommt nur Blödsinn an
bzw. das erste Byte sieht noch gut aus, danach sieht es so aus, als ob
alle zwei Bytes ein um ein Byte verzögertes Echo der Empfangsdaten
gesendet wird (also als ob der DMA nicht in das Register geschrieben
hätte.)
Habt Ihr ein funktionierendes Beispiel?
Ich poste gerne, falls erforderlich, meinen Code zwecks Diskussion.
Ich habe die Kanäle 0 und 1 konfiguriert, 0 ist für den Empfang
zuständig, 1 für das Aussenden. Beide haben als Modus Single shot, 1
Byte Burst und 16 Byte Telegrammlänge. Beide bekommen als Trigger den
Empfangsinterrupt von der SPI Schnittstelle.
Mache ich einen Denkfehler?
Viele Grüße,
Paul
Paul schrieb:> Es kommen alle 125 µs insgesamt 16 Bytes mit 2MHz Takt an.
Welchen Takt hat der XMEGA? Der muss für den SPI Slave verdammt hoch
sein, selbst für DMA.
Hatte auch schon das Problem mit mehreren DMA-Kanälen.
Die müssen den Datenbus benutzen und haben geringere Priorität als die
CPU.
Also würde ich mal den Systemtakt auf 32MHz hoch, und in der
main-Schleife etliche NOPs einstreuen, zwecks Datenbus frei machen...
PS:
Es sind doch 64µs bei 2MHz SPI-CLK? Nur so am Rande.
Jim M. schrieb :
> Welchen Takt hat der XMEGA? Der muss für den SPI Slave verdammt hoch> sein, selbst für DMA.
Der XMEGA läuft mit 32 MHz.
Ich werde mal den Takt vom Master verlangsamen, mal sehen, ob sich etwas
ändert.
Wenn beide DMA Kanäle den gleichen Trigger bekommen (0x4A für SPI C) und
die Reihenfolge auf CH0-CH1-CH2-CH3 fest eingestellt ist (Priority
Mode=3),sollte doch nach Wegkopieren des Empfangsbytes mit CH0 das
Hinkopieren des Sendebytes via CH1 theoretisch funktionieren, oder?
Danke und Grüße!
>> als ob alle zwei Bytes ein um ein Byte verzögertes Echo der Empfangsdaten
gesendet wird (also als ob der DMA nicht in das Register geschrieben
hätte.)
Das verstehe ich nicht richtig. Kannst du das genauer erklären?
Du hast einen Puffer für Datenempfang und zum Senden?
Wie synchronisierst du die beiden?
Zum Senden nimmst du keine Slave-SPI?
Tipp: Die USART-MASTER-SPI ist besser, da Sendepuffer.
Hallo!
So, der Test mit 1MHz SPI Clock hat funktioniert.
Mir ist nur noch nicht klar, was da so lange braucht, dass es mit 2MHz
nicht mehr geht. Der Prozessor ist mit 32MHz getaktet, die Datenbits
kommen mit 2MHz rein, d.h. die Bytes stehen mit 250kHz an.
Alle 4 µs kommt also das Signal der SPI Schnittstelle, dass ein neues
Byte da ist. Es sind demnach 4µs, die der DMA Controller hat die Daten
von der SPI zu lesen (1 Byte), zwischenzuspeichern, die Adresse (3 Byte)
aus seinen Registern zu lesen (und evtl schon zu inkrementieren)und auf
den Adressbus zu legen, das Datenbyte aus dem Puffer zu speichern und
dann den zweiten Kanal zu bearbeiten, welcher das Ganze in die andere
Richtung macht.
4µs sind bei 32MHz 128 Takte, also ungefähr 64 Takte pro Richtung und
Byte.
Ist das realistisch?
Es vergehen sicherlich auch noch Takte eh der Prozessor den Bus
überhaupt freigibt, das kommt natürlich noch dazu.
Ich hätte ja gehofft, dass der Performancegewinn durch DMA im Vergleich
zum Interrupt nach jedem Byte höher ist...
Interessanterweise ist jedes 2. gesendete Byte ok, das liegt wohl an der
Taktung vom Master, welche nach jedem 16. Bit eine zusätzliche Pause von
ca. 250ns einlegt (16 Bit Schieberegister, reload)
Mal sehen, ob eine künstliche Pause nach 8 Bit etwas hilft...
Ich glaub, ich muss mein Lesen/Schreiben in diesem Thread auch besser
synchronisieren... :-)
Anno schrieb:>>> als ob alle zwei Bytes ein um ein Byte verzögertes Echo der Empfangsdaten> gesendet wird (also als ob der DMA nicht in das Register geschrieben> hätte.)>> Das verstehe ich nicht richtig. Kannst du das genauer erklären?
Ich sende vom externen SPI Master (FPGA) alle 125µs (ist ein spezieller
Systemtakt) ein Datenpaket mit 16 Bytes (momentan nur Dummy Daten) :
0x00, 0x01, 0x02, 0x03, 0x04, 0x05...0x0F. Der Slave liefert mir zurück:
0x0F, 0x00, 0x0D, 0x02, 0x0B, 0x04, 0x09, 0x06...0x00
Beides ist gleichzeitig mit einem SPI Analysator auf dem Bus
aufgezeichnet.
Der ATXMEGA (Slave) hat zwei CHAR Arrays, eines mit den empfangenen
Daten und eins mit den zu sendenden Daten. Die zu sendenden Daten habe
ich mit einer absteigenden Folge von 0x0f..0x00 belegt, zum besseren
Unterscheiden am Scope.
Wenn ich den Takt reduziere, sind die Daten vom Xmega auf dem Bus ok.
Die Empfangsdaten (gebe ich per serieller Schnittstelle in einer Loop
aus) sind immer ok.
NOPs sind mal ne gute Idee, werde ich probieren.
Anno schrieb:> Du hast einen Puffer für Datenempfang und zum Senden?> Wie synchronisierst du die beiden?> Zum Senden nimmst du keine Slave-SPI?> Tipp: Die USART-MASTER-SPI ist besser, da Sendepuffer.
Achso: Momentan ist mein FPGA der Master, ich könnte das eventuell noch
drehen, würde mir das was bringen?
Senden und Empfangen wird beides gleichzeitig über SPI C gemacht.
Synchronisieren mache ich mit der Chipselect Leitung (Interrupt-> DMA
freigeben)
Sorry, aber du drückst dich immer zu unpräzise aus.
Irgendwie passen dein Aussagen nicht richtig zusammen.
- "...Der Slave liefert mir zurück...": Die Empfangs-SPI? Wohin
"zurück"? Ist das der Empfangs-Speicherblock, der von der DMA
beschrieben wird?
- "Beides ist gleichzeitig mit einem SPI Analysator auf dem Bus
aufgezeichnet."
Was genau ist da aufgezeichnet? Was die Slave-SPI intern empfängt,
ist ja nicht "auf dem Bus" zu sehen, sondern nur was der FPGA sendet!
Ist etwa die Empfangs- und Sende-SPI die selbe???
Was ist das zweite, vom Analysator aufgezeichnete Signal? Die Sende-SPI?
Wo liegt eigentlich dein Problem? Nach dem Empfangen (Speicherblock),
oder beim Senden ("auf dem Bus")?
Wo werden die Daten falsch?
Wieso können Daten-Bytes vom Empfangspuffer auf der Sende-SPI ausgegeben
werden???? Der Sendepuffer ist doch mit 0x0f..0x00 belegt???
Außerdem wäre gut, wenn du vor dem Test den Empfangspuffer löschst
und nurmal ein Datenpaket schickst und im Debugger anschaust,
was im Empfangs-Puffer liegt
PS:
Also ich habe mit dem XMega schon 4MBit(!) auf einer Slave-SPI mit DMA
'rein, CRC-Berechnung und 280KByte/s auf einer USART-Master-SPI wieder
'raus (auch mit DMA) hinbekommen.
>> "Senden und Empfangen wird beides gleichzeitig über SPI C gemacht."
Oh je, wie soll das mit 2 DMAs gehen? Die SPI hat doch nur einen
Interrupt!
Kann man mit einem Interrupt 2 DMAs gleichzeitig triggern?
Der erste Interupt kommt doch erst, nachdem das erste Byte empfangen
wurde. Das erste Datenbyte müsstest du aber schon vor dem Empfang des
des ersten Bytes in das Data-Reg. der SPI schreiben.
Da gibt es also einen Versatz von einem Byte...
Probiere es mit einer separaten USART-Master-SPI zum Senden!
Mit der ist es problemlos möglich die DMA zu triggern.
- "Synchronisieren mache ich mit der Chipselect Leitung (Interrupt-> DMA
freigeben)"
Hä, was für eine Chipselect Leitung? Die !SS-Leitung von der Slave-SPI?
Das synchronisiert nur die SPI.
Sorry, wenn meine Angaben etwas wirr klingen.
Vielleicht zum Hintergrund: Die Schaltung mit dem ATXmega dient als
Analog Frontend (4*Analog Eingang, 4* Analog Ausgang), welches
galvanisch getrennt über schnelle Koppler an einem FPGA hängt. SPI C vom
ATxmega ist mit Clock, MOSI, MISO und SS (nicht CS :-) ) zum FPGA hin
verbunden.
Es geht darum, mit festem Zeittakt die Analogeingänge am ATXMEGA
einzulesen und Richtung FPGA zu senden und gleichzeitig Daten vom FPGA
auf den Analogausgängen des ATXMEGA auszugeben. Die Daten haben also
erstmal nix miteinander zu tun und sind von der zeitlichen Abfolge auch
einen Zeittakt versetzt, das ist ok.
Dass der SPI Interrupt zwei DMA Kanäle triggert ist so gewollt, die SPI
Schnittstelle ist ja schließlich dazu da, Daten zu empfangen und
gleichzeitig zu senden.
Das ganze habe ich bisher mit 8 Bytes im Interruptbetrieb gemacht, hat
gut funktioniert. Leider reichen 8 Bytes aber nicht mehr aus. Da der
Zeittakt aber vorgegeben ist (125µs), machen mir bei mehr als 8 Bytes
die Interruptzeiten Probleme.
Ich habe keinen durchgehenden Datenstrom, daher kann ich "relativ
gemütlich" wenn das Slave Select Signal vom FPGA kommt das erste zu
sendende Byte in das SPI Datenregister legen, das funktioniert auch.
(ich sehe am Oszilloskop, dass die Daten korrekt auf der MISO Leitung
ankommen)
Nur die nächsten Bytes sind kaputt, liegt wohl am timing wann genau der
DMA auf das Datenregister schreibt.
Ich habe leider keine Möglichkeit eine zweite SPI Schnittstelle zum FPGA
zu verdrahten, die Schaltung ist schon fertig.
Achso: das SS Signal triggert bei mir einen Interrupt der auch die DMA
Logik resettet (und danach neu konfiguriert) das meinte ich mit
Synchronisieren.
Viele Grüße und Danke!