Forum: Mikrocontroller und Digitale Elektronik STM32 und SPI - DMA Handling


von Stephan M. (stmiko)


Lesenswert?

Hallo zusammen!

Ich betreibe einen STM32 mit 72Mhz. Dieser hat unter anderem die Aufgabe 
eine ADS1178 (16-Bit ADC) über SPI auszulesen. Dieser IC hat ein "Data 
Ready" Pin Ausgang, der eine fallende Flanke bei einen neuen Messwert 
ausgibt. In dem uC wird daraufhin ein Interrupt ausgelöst, der eine 
Rouitine ausführt, in der Berechnungen mit den Werten durchgeführt wird.
Außerdem gibt es noch einen Interrupt für den DMA, wo das SPI-Signal 
(ADC-Werte) in eine Struktur eingelesen werden.
Der Bus wird mit 9Mhz betrieben und der ADC hat eine Abtastrate von ca 
35KSPS.
Nun kommt es leider vor, dass scheinbar "zufällig" Werte verloren gehen 
oder "falsch" ausgelesen werden.
Das ganze System läuft zudem unter FreeRTOS, welches "nebenbei" noch 
andere Routinen ausführt, die aber geblockt werden, wenn dieser 
Interrupt für einen neuen Messwert ausgelöst wird.
Ich könnte auch denn Source mal reinstellen, um mehr Klarheit zu 
verschaffen :-)
Deswegen mein Anliegen an euch, hat jemand von Euch Erfahrung im 
Auslesen des SPI Buses mittels DMA.

Viele Grüße
Stephan

von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


Lesenswert?

In der FW-Lib von STM (V3.2.0) gibt es ein Demo wie man SPI in das RAM 
bekommt mit dem DMA.

Siehe hier STM32.

von Stephan M. (stmiko)


Lesenswert?

Hallo Markus,

ich habe das "DMA1 Channel2 transfer complete flag" mit eingebaut und es 
ist scheinbar Besserung in Sicht! Am Montag werde ich es nochmal genauer 
unter die Lupe nehmen ;-)

von (prx) A. K. (prx)


Lesenswert?

Wenn man mit SPI per DMA arbeitet, dann muss man darauf achten, dass der 
Transfer erst beendet ist, wenn das letzte Byte/Wort davon empfangen 
wurde. Wenn man CS deaktiviert sobald Tx-DMA durch ist, dann hat man 
verloren, weil noch Daten im SPI Puffer sein können.

NB: Das bedeutet, dass man auch dann, wenn nur Daten gesendet werden, 
mit Rx-DMA arbeiten sollte, weil man nur so einen sinnvollen 
Abschluss-Interrupt bekommt, um CS abzuschalten. Notfalls mit einem 
Dummy-Puffer ohne Adressinkrement.

PS: Deine Problembeschreibung suggeriert, dass du erst mit den 
ADC-Werten rechnest und sie danach einliest. Merkwürdige Reihenfolge 
;-). Eine etwas systematischere Beschreibung könnte helfen.

von (prx) A. K. (prx)


Lesenswert?

Noch was zu DMA allgemein: Wenn man DMA bzw. DMA-Steuerung und Zugriff 
auf das davon verwendete RAM sehr zeitnah oder gar gleichzeitig 
verwendet, dann sollte man sich vorsichtshalber mal die memory barrier 
Befehle ansehen.

von Stephan M. (stmiko)


Lesenswert?

Hallo A.K.,
danke erstmal für deine Kommentare!

Es gibt 2 Interrupt-Routinen, die eine liest mittels DMA den SPI Buffer 
aus, in dem auch die ADC Werte eingelesen werden und die andere wird von 
einem externen Signal ausgelöst, wo die Werte in einen Ringpuffer 
geschrieben, aufsummiert und ausgewertet werden.
Ich denke die Reinfolge ist in Ordnung. Alles weitere kann ich nur am 
Montag wieder testen.

von (prx) A. K. (prx)


Lesenswert?

Ohne Code oder präzise Schilderung bleibt mir das immer noch weitgehend 
unverständlich, denn die 99%, die in deinem Kopf aber nicht im Posting 
stehen, kennst nur du. Insofern können meine Kommentare nur allgemeines 
Gewäscht sein, nicht direkt auf das Problem bezogen.

von Stephan M. (stmiko)


Lesenswert?

Ich habe den Code nicht zur Hand, da ich im Studienpraxissemester bin
und das Teil einer Aufgabe in meinen Betrieb ist.
Schau doch bitte nochmal Montag ins Forum, dann poste ich den Code 
mal...

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.