Hallo
Ich möchte den internen stm adc an einem fpga nutzen. Datenkommunikation
über SPI (fpga spi slave).
Da 1 msps sollte dies am besten per DMA geschehen. Wie?
zudem 2. Frage: ist es möglich ins spi frame ebenfalls ohne cpu Aufwand
einen crc anzuhängen?
Wenn ich mich korrekt erinnere, kann der DMA des STM32 nur
- Memory to Memory
- Memory to Peripheral
- Peripheral to Memmory,
jedoch nicht Peripheral to Peripheral.
Insofern wird es ohne CPU-Eingriff nicht gehen
und mit ihr läßt sich dann auch ein CRC anhängen.
U.U. lässt sich die Aufgabe mit zwei DMAs lösen,
dann aber wieder ziemlich sicher nur ohne CRC.
Ein Timer müsste einerseits den Transfer
Memory to SCI triggern, andererseits den ADC starten,
dessen EOC wiederum den Peripheral to Memroy Transfer
des zweiten DMA. Man müsste den den ersten DMA etwas
verzögert starten oder in Kauf nehmen, dass der erste
Wert noch nicht vom ADC kommt.
Mit dem SCI hab' ich noch nicht gearbeitet - bin mir
nicht sicher, ob damit ein kontinuierlicher Stream
per DMA erzeugt werden kann oder ob nur Pakete einer
bestimmten Länge aufgesetzt werden können - vielleicht
kann das ein anderer hier beantworten.
Danke für die ausführliche Antwort.
Hätte schon grosse lust dies über DMA zu lösen, da 1 MHz ISR frequenz.
CRC berechnung+paket zusammenbauen wird vermutlich auch einige
instruktionen benötigen.
Habe ich es korrekt verdstanden, dass mit deiner vorgeschlagenen timer
methode die zusätzliche latenz von 1us vermieden werden kann? Also
erster DMA getriggert auf den EOC und dann einige 10ns danach den selben
Datenwert mit dem timer DMA ins SPI register schreiben und SPI
übertragung starten?
fpga schrieb:> Danke für die ausführliche Antwort.> Hätte schon grosse lust dies über DMA zu lösen, da 1 MHz ISR frequenz.> CRC berechnung+paket zusammenbauen wird vermutlich auch einige> instruktionen benötigen.> Habe ich es korrekt verdstanden, dass mit deiner vorgeschlagenen timer> methode die zusätzliche latenz von 1us vermieden werden kann? Also> erster DMA getriggert auf den EOC und dann einige 10ns danach den selben> Datenwert mit dem timer DMA ins SPI register schreiben und SPI> übertragung starten?
Noch 2 Sachen habe ich vergessen:
1. CRC ist nicht zwingend erforderlich; für eine DMA lösung würde ich
CRC opfern.
2. Gibt der 1. DMA ein signal bei transferabschluss auf welches der 2.
DMA getriggert werden kann?
Man könnte überlegen mit einem DMA das Ergebnis des ADC auf RAM zu
schaffen.
Ist wahrscheinlich 4-12 Clocks für den ADC und 1 Clock für den Transfer.
Der End-DMA-ISR Triggert dann die CRC Engine. Ich meine dass die pro
Byte 1 Clock braucht aus dem RAM.
Die CRC Engine müsste dann wiederum nach Beendigung wiederum einen neuen
DMA triggern der die CRC und die Daten in die SPI Puffer kopiert.
Dann brauchst du wahrscheinlich noch irgend eine Art Doppelpuffer für
den Ausgangspuffer damit du dir während der Übertragung nicht die Daten
überschreibst.
Ich würde die Daten ohne Anfrage rausballern. Der Rest muss der FPGA
richten. Der könnte sich dann noch überlegen zwischen 2 Punkten zu
inter/extrapolieren auf einen anderen Zeitpunkt hin falls notwendig.
N. M. schrieb:> Dann brauchst du wahrscheinlich noch irgend eine Art Doppelpuffer für> den Ausgangspuffer damit du dir während der Übertragung nicht die Daten> überschreibst.
Das sollte inkeitisch sein, der SPI würde ich einfach genügend schnell
laufen lassen; damit die Übertragung schneller als der ADC ist (1MSPS).
N. M. schrieb:> Ich würde die Daten ohne Anfrage rausballern. Der Rest muss der FPGA> richten. Der könnte sich dann noch überlegen zwischen 2 Punkten zu> inter/extrapolieren auf einen anderen Zeitpunkt hin falls notwendig.
Genau FPGA ist als SPI slave vorgesehen.
N. M. schrieb:> End-DMA-ISR
Hmm also hier ISR?
Nun CRC ist nicht zwingend; wenns ohne CRC ohne ISR geht ist das ein
guter tradeoff.
OT: Wie kann ich im cube genau feststellen, wie lange die ISR dauert?
(also nicht nur Anzahl Instruktionen sondern wirklich Anzahl Systemclk)
N. M. schrieb:> Vielleicht hat er einen STM Überschuss.
OT: Ne auch Mangel, unser EMS hat noch ca. 180stk lagernd. Viele EMS
Kunden giengen wegen STM mangel zu renesas (nun sind die auch
ausverkauft). Anyway für neue designs wurde uns renesas empfohlen, da
die Verfügbarkeit etwas besser ausschaut als bei ST.
Anyway dies hier ist ein kleineres projekt mit weniger al 1k stk daher
STM.
fpga schrieb:> Nun CRC ist nicht zwingend; wenns ohne CRC ohne ISR geht ist das ein> guter tradeoff.
Das sollte doch ganz einfach funktionieren, ohne Interrupts und ohne
Zwischenpuffer? Zumindest mit den STM32L4?
SPI wird als Master, nur TX, 8 oder 16 Bit, kein DMA konfiguriert. Beim
ADC wird DMA eingeschaltet, Peripheral to Memory, Cyclic Mode, 16-Bit
lesen und schreiben und als Ziel wird das SPI-TX-FIFO eingetragen. Das
geht, weil alles Memory Mapped ist.
Der Slave Select Ausgang wird und bleibt dabei aktiv, sobald SPI
eingeschaltet wird. Evt. kann man zwischen den einzelnen Datenworten
einen Impuls erzeugen, indem man das NSSP Bit setzt.
Wenn mehr als ein Kanal gewandelt wird, kann der SPI-Slave nur
mitzählen...
Die Länge eines DMA-Transfers (CNDTR) ist eigentlich genau 1, aber wenn
man hier einen größeren Wert einträgt, könnte man Interrupts mit
entsprechend niedrigerer Frequenz erzeugen.
Der ADC kann in Hardware den Mittelwert über 2,4,8... Wandlungen bilden.
Wenn die Timer knapp werden, kann man den ADC frei laufen lassen und das
Abtastintervall per Vorteiler plus Sample Time plus Kanalzahl
einstellen.
fpga schrieb:> Wie kann ich im cube genau feststellen, wie lange die ISR dauert?> (also nicht nur Anzahl Instruktionen sondern wirklich Anzahl Systemclk)
Garnicht, dazu müsste cube wissen, wie der Compiler optimiert. Auf einen
einzelnen Taktzyklus genau geht es sowieso nicht, weil DMA, Flash Cache
und andere Interruptroutinen dazwischen funken können. Auch, wenn die
eine niedrigere Priorität haben, brauchen die einige wenige unteilbare
Zyklen.
Man kann Interruptroutinen ein wenig optimieren, indem man sie auf eine
runde Adresse linkt. Bei den kleineren Chips reicht ALIGN(8), weil das
Flash nur 64 Bit breit ist; aber es gibt breitere.
> Hätte schon grosse lust dies über DMA zu lösen, da 1 MHz ISR frequenz.> CRC berechnung+paket zusammenbauen wird vermutlich auch einige> instruktionen benötigen.
Üblicherweise wird ja auch nicht nach jedem Sample ein Interrupt
ausgelöst, sondern per DMA z.B. 1024 Samples ins RAM geschrieben und
dann ein Interrupt für den gesamten Block. Erst dann macht ja auch eine
Paket mit CRC und Pipapo Sinn. Das Paket wird dann wiederum per DMA auf
SPI rausgeschoben. Bandbreite bleibt die gleiche, nur die Latency ist
höher.
fpga schrieb:> OT: Wie kann ich im cube genau feststellen, wie lange die ISR dauert?> (also nicht nur Anzahl Instruktionen sondern wirklich Anzahl Systemclk)
Ab CM3 kannst du z.B. DWT->CYCCNT als watch nutzen.
Hmmm habe grade im cobe entdeckt, dass die SPI cores bereits jeweils
einen integrierten CRC core haben.
Damit sollte doch Timer controlled ADC (1msps)-> MEM DMA
Timer controlled ca. 100us phasenverschoben(wie ichs verstanden habe ist
dma ende nicht direkt mit dma start verlinkbar) MEM DMA -> SPI tx
register
Im SPI core ist dann der CRC aktiviert und SPI speed so eingestellt, das
TX (inkl. CRC) unter 1us dauert.
fpga schrieb:> Hmmm habe grade im cobe entdeckt, dass die SPI cores bereits> jeweils einen integrierten CRC core haben.> Damit sollte doch Timer controlled ADC (1msps)-> MEM DMA> Timer controlled ca. 100us phasenverschoben(wie ichs verstanden habe ist> dma ende nicht direkt mit dma start verlinkbar) MEM DMA -> SPI tx> register> Im SPI core ist dann der CRC aktiviert und SPI speed so eingestellt, das> TX (inkl. CRC) unter 1us dauert.
*100ns