Forum: Mikrocontroller und Digitale Elektronik stm32 DMA adc-spi


von fpga (Gast)


Lesenswert?

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?

von U.G. L. (dlchnr)


Lesenswert?

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.

von fpga (Gast)


Lesenswert?

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?

von fpga (Gast)


Lesenswert?

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?

von N. M. (mani)


Lesenswert?

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.

von fpga (Gast)


Lesenswert?

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)

von PittyJ (Gast)


Lesenswert?

Wäre es nicht einfacher, einen SPI-ADC direkt am FPGA zu betreiben?

von N. M. (mani)


Lesenswert?

PittyJ schrieb:
> Wäre es nicht einfacher, einen SPI-ADC direkt am FPGA zu
> betreiben?

Doch :-)
Vielleicht hat er einen STM Überschuss.

von fpga (Gast)


Lesenswert?

PittyJ schrieb:
> Wäre es nicht einfacher, einen SPI-ADC direkt am FPGA zu
> betreiben?

Ja, sind aber extra kosten; STM32 ist schon da

von fpga (Gast)


Lesenswert?

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.

von Bauform B. (bauformb)


Lesenswert?

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.

von foobar (Gast)


Lesenswert?

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

von Lutz (Gast)


Lesenswert?

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.

von fpga (Gast)


Lesenswert?

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.

von fpga (Gast)


Lesenswert?

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

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
Noch kein Account? Hier anmelden.