Hallo, ich versuche derzeit ein Programm von einem ATXMEGA auf einen STM32F4 zu übertragen um die Abtastrate eines externen ADC's von 200 kHz auf 400 kHz zu erhöhen. (2 16-Bit ADC's im Daisy-Chain-Betrieb = 32 Bit mit 200 / 400 kHz) Mit dem ATXMEGA bin ich mittlerweile sehr fit. Für den STM fehlt mir leider noch die Ertfahrung wie ich das ganze umsetzen kann. Durch die hohe Abtastrate bin ich an DMA gebunden, da ich auch noch einfache Routinen parallel zur Abtastung ausführen möchte. Beim ATXMEGA habe ich zur Kopplungt von Timern und DMA das Event-System verwendet. Dieses fehlt mir jedoch beim STM und macht mir die Aufgabe schwerer. Der ADC arbeitet als Slave. Zum Start einer Wandlung muss ein PWM-Signal angelegt werden. 1,4 µs nach dem Start werden die Ergebnisse mit dem anliegenden SCK-Signal ausgegeben. Dieses wird seitens des µC durch das Ausgeben von "Dummy-Bytes" erzeugt. Ich schaffe es einen DMA zum senden von 4 * 8 Bit = 32 Bit über den SPI aufzusetzen. Die Werte werden damit unimttelbar aneinander gereiht(keine Pause zwischen den Bytes). Für die DMA-Übertragung der 4 Bytes muss jedoch jedes mal das Enabled-Flag gesetzt werden. Das mache ich momentan über ein Interrupt. Leider ist die Latenz des Interrupts für diese Anwendung zu hoch (ca. 450 ns bei 168 MHz µC-Takt). Daher suche ich einen Weg Interrupts zu umgehen. Ich möchte hier keinen Code besprechen, sondern suche eine "Taktik" um an dieses Problem und dessen Lösung heranzutreten. Kann ich einen DMA geschickt über andere DMAs, Timers oder ähnliche Module enablend/disablen? Welche anderen Möglichkeiten gäbe es? Gruß Erik
f4 reference manual DMA controller DMA functional description Channel selection So ziemlich jede Peripherie kann DMA-Requests auslösen, in deinem Fall müsstest du einfach nur den passenden Stream/Channel raussuchen und im SPI den DMA-Request für TX einschalten. Und schon wird der komplette Datensatz ohne CPU-Beteiligung gesendet, also so wie DMA eigentlich gedacht ist.
Danke für die Antwort! Vielleicht habe ich ein wenig an Erklärung gesparrt, um das ganze genau zu erläutern. Das mit dem DMA-Request ist mir klar - diesen nutze ich auch: Ein Zyklus dauert 2,5 µs. Nach dem Startsignal (Timer/PWM) wird nach 1,4 µs der DMA über das Timer-Interrupt enabled. Der DMA nutzt dann den SPI-TX als Request um 4 Bytes zu übertragen. (Also der Request wird hier schon verwendet um die Bytes unmittelbar nacheinander zu senden). Das TC-Interrupt des DMAs nutze ich dann, um diesen zu deaktivieren damit ich ihn beim nächsten Zyklus neu starten kann. Ich würde das Enable/Disable auch gerne umgehen! Aber wie kann ich den DMA über einen anderen DMA dazu befähigen von neuem anzufangen? Gibt es andere Möglichkeiten DMA ohne Interrupts neu zu starten?
Erik Z. schrieb: > Ich würde das Enable/Disable auch gerne umgehen! Ach so, ok. Das könnte etwas kompliziert werden, weil du ja nach dem 4. Byte einen DMA-Request vom SPI bekommst, aber gar nicht mehr weiter senden willst. Ein Workaround könnte sein, mit einem Timer die Bytes einzeln zu triggern. Dafür wird's dann wahrscheinlich vier Kanäle eines Timers brauchen, aber es könnte gehen. Der DMA muss dann natürlich im circular Mode sein. Effektiv hast du dann vier Trigger für einen DMA Channel, aber das macht vermutlich/hoffentlich nichts. Du willst doch eigentlich die Daten vom ADC einlesen, oder? Hast du noch einen zweiten DMA am Laufen, der parallel die Daten vom SPI in den RAM schiebt?
Die Idee hatte ich auch schon! Ich kann ja auch theoretisch 2 x 16 Bit per SPI senden. Leider habe ich hierfür aber nicht den DMA mit dem Timer verknüpfen können (wollte nicht funktionieren). Vermutlich benötige ich hier auch wieder Interrupts zum behandeln des Timers welches mich Zeit kostet, die ich nicht habe....
Hi, Ich würde - wenn möglich - eine CPLD zwischen STM32 und externem ADC setzen der auf beiden Seiten eine passende Datenübertragung herstellt. Gruß Martin
Martin K. schrieb: > eine CPLD zwischen STM32 und externem ADC Ich dachte, hier wird nach der einfachsten Schaltung gesucht. Erik Z. schrieb: > Leider ist die Latenz des Interrupts für diese > Anwendung zu hoch (ca. 450 ns bei 168 MHz µC-Takt). Das kann ich so nicht glauben. Kannst Du Deine Interruptroutine zeigen?
Wenn es möglich wäre würde ich externe Schaltungen oder gar einen FPGA ausschließen wollen. Das ganze scheitert bis jetzt knapp am Timing, eher würde ich daher die Abtastrate senken wenn es absolut nicht möglich ist. Mit den Interrupts habe ich nochmal geprüft. Ich hatte vergessen die Optimierung zu aktivieren. So komme ich jetzt auf ca. 150 ns bei 168 MHz. (Gemessen mit einer PWM-Ausgabe und einem Interrupt mit getoggeltem Ausgang) Wenn ich den DMA im Interrupt aktiviere um am SPI etwas auszugeben verzögert sich die Ausgabe nochmals (ca 300 ns Gesamtverzögerung). Kann die Ursache hierfür am festen Takt des SPIs liegen, dass die Ausgabe erst mit dem nächsten Zyklus erfolgt? Ich überlegte momentan, ob ich vielleicht eine "Pseudo-Clock" per PWM ausgebene und von außen an den STM32 anlege um den STM32 als Slave laufen zu lassen... dieser Idee werde ich heute man nachgehen! [EDIT] Ich habe nochmal die Funktion für das Enable des DMA-Kanals ersetzt - jetzt komme ich auf 260 ns Verzögerung.
:
Bearbeitet durch User
Hi Erik, a) Wie wäre es, wenn der ADC den DMA triggerte? Wenn der ADC ein "Sample Ready" Signal zur Verfügung stellt, könnte dies den DMA anwerfen. Wenn das Dein ADC nicht kann, gäbe es sicher was passendes bei den üblichen Herstellern. b) Alternativ kannst Du auch den kompletten Sample-Vorgang an einen Timer hängen, der dann wieder den DMA-Request auslöst. Schau Dir mal alle DMA-Request Quellen des STM32F4 an, irgendwas wird doch passen? :) Grüße, Marcus P.S.: ADC? STM32F4xx/Taktrate? P.P.S.: ein Interface wie z.B. beim LTC14071 würde passen P.P.P.S: und ja, vor zehn Jahren hätte ich da auch noch ein CPLD zwischengehängt, aber die STM32 sind wirklich ausreichend ausgestattet
Marcus H. schrieb: > a) Wie wäre es, wenn der ADC den DMA triggerte? > Wenn der ADC ein "Sample Ready" Signal zur Verfügung stellt, könnte dies > den DMA anwerfen. wie kannst du bei einem STM32F4 von einem GPIO aus direkt (ohne Umweg über Interrupt) einen DMA auslösen lassen?
Gerd E. schrieb: > Marcus H. schrieb: >> a) Wie wäre es, wenn der ADC den DMA triggerte? >> Wenn der ADC ein "Sample Ready" Signal zur Verfügung stellt, könnte dies >> den DMA anwerfen. > > wie kannst du bei einem STM32F4 von einem GPIO aus direkt (ohne Umweg > über Interrupt) einen DMA auslösen lassen? In RM0090 - Chapter 10 - DMA was passendes zusammensuchen. Und schauen, was es im Web so gibt. Im vorliegenden Fall hatte ich gar nicht an GPIO gedacht, sondern dass der externe ADC die SPI triggert und diese wiederum den DMA. Oder der STM32 ist wieder Master und gibt einen Timertakt vor. Im einfachsten Fall kann man bei den vorgegebenen Taktraten aber auch mit Interrupt arbeiten. In einem meiner Geräte (SSI USB Konverterplattform) pumpt der STM32F405 mit über 1MHz Daten in die GPIOs, getriggert durch externen Interrupt. GCC 4.8 -o3 168MHz. Wenn der Interrupt selbst in -o3 zu viel Overhead hat, bieten sich ein paar Zeilen Maschinencode an. Sollte aber nicht notwendig sein.
Jetzt hatte ich doch nicht die Zeit mich damit weiter zu beschäftigen und dann schon wieder neue (hilfreiche) Ratschläge hier! Bei dem ADC handelt es sich um einen ADS8319 mit 500 kHz. Die SPI-Schnittstelle wird mit 42 MHz betrieben. Der ADC ist recht einfach (10-Pin Gehäuse) wobei die Spannungsversorgung und die SPI-Pins alle Ein- und Ausgänge belegen. Über einen Pull-Up-Winderstand ist es jedoch möglich, dass der SDO (MISO) Ausgang nach beendeter Wandlung kurzzeitig auf low gezogen wird. Hier könnte man eventuell den DMA über einen parallelen Pin koppeln. -> nur müsste man diesen schnell deaktivieren um ein dauerhaftes Triggern während der Übertragung zu unterbinden. Heute habe ich aber leider wenig/keine Zeit dafür, ich werde mich frühstens heute Abend nochmal daran setzten. Wenn ich Fortschritte (Erkenntnisse) erziele werde ich hier berichten!
Da STM32 keine 32-bit SPI Transfers kann, hast Du ein Problem: Du kannst nicht den circular DMA mode verwenden! Damit musst Du in jeden Zyklus im DMA TC Interrupt den DMA Transfer neu aufsetzen. Bei 16-Bit Transfers koennest Du dagegen einen Circular DMA Transfer aufsetzten ohne dass Du Kannst Du nicht die ADC Kette auftrennen und jeden ADC von jeweils einen SPI Kanal bedienen lassen? Ich habe ein aehnliche Problem wie folgt geloest: * ADC Signale * - SPI1 (oberer Kanal) * TIM2 Periode: 4 us, CH3 aktiv: 3 us * Compare started ueber DMA_CH1 SPI1 * SPI1 RX wird ueber DMA_CH2 ausgelesen * - SPI2 (unterer Kanal) * TIM15 Periode: 4 us, CH3 aktiv: 3 us * Compare started ueber DMA_CH5 SPI2 * SPI2 RX wird ueber DMA_CH4 ausgelesen * * - HTIF/CTIF DMA1_CH1 signalisiert Auswertethread. * - Thread akkumuliert SPI Werte.
Marcus H. schrieb: >> wie kannst du bei einem STM32F4 von einem GPIO aus direkt (ohne Umweg >> über Interrupt) einen DMA auslösen lassen? > > In RM0090 - Chapter 10 - DMA was passendes zusammensuchen. ja, genau. 10.3.3, Table 42 und 43 um genau zu sein. Doch dort sehe ich wie schon geschrieben keine Möglichkeit, durch einen GPIO einen DMA-Request auszulösen. Bei anderen Controllern, z.B. Kinetis, geht das. > Im vorliegenden Fall hatte ich gar nicht an GPIO gedacht, sondern dass > der externe ADC die SPI triggert und diese wiederum den DMA. Der ADC also als SPI-Master? Ist das nicht eher unüblich? Ich behaupte nicht schon hunderte ADCs gesehen zu haben, aber von denen die ich kenne, kann das kein einziger. > Oder der STM32 ist wieder Master und gibt einen Timertakt vor. genau. Doch wie bekommst Du dann das "Konvertierung fertig"-Signal in einen DMA-Request umgewandelt? Erik schreibt ja daß er das an einen GPIO leiten könnte: Erik Z. schrieb: > Über einen Pull-Up-Winderstand ist es jedoch möglich, dass der SDO > (MISO) Ausgang nach beendeter Wandlung kurzzeitig auf low gezogen wird. > Hier könnte man eventuell den DMA über einen parallelen Pin koppeln. Und ich wüsste gerne wie man daraus dann beim STM32 einen DMA-Request gemacht bekommt. Wäre es evtl. möglich den SPI kontinuierlich und ohne Unterbrechnung per DMA Daten lesen zu lassen und danach dann per Software die tatsächlichen Daten aus dem Puffer rauszupicken? Den Chip Select könnte man z.B. von einem Timer per PWM-Ausgabe erzeugen lassen, damit sollte das den ADC nicht durcheinander bringen. Die Herausforderung dürfte nur sein, die Position der Nutzdaten im Puffer zuverlässig vorherzusagen. Oder übersehe ich hier was?
Ich versteh das Problem ehrlich gesagt nicht ganz. Das Datenblatt gibt vor, dass der F4 für den Daisy Chain Mode als Receive Only Master zu betreiben ist. Man beachte die Pfeile des Clocks, der bei einer SPI ausschließlich vom Master ausgehn kann. -> CONVST setzen -> entweder auf IRQ reagieren oder tconv warten -> Master Receive der Daten, getriggert durch a) EVENT/IRQ (nur über Umwege möglich denk ich, etwa mit einem Input Capture auf den Flanken und einem etwas missbrauchten DMA request, der statt dem Input Capture halt SPI Daten schaufelt) Dadurch missbraucht man einen eigentlichen Timer DMA request als "quasi" externen IRQ request, dens aber halt leider nicht gibt. Glücklicherweise gibts ja genug Timer... b) Timer Update nach tconv Wartezeit Das ganze ist mehr oder weniger ohne einzigen CPU Cycle zu bewerkstelligen.
:
Bearbeitet durch User
Gerd E. schrieb: > Marcus H. schrieb: >>> wie kannst du bei einem STM32F4 von einem GPIO aus direkt (ohne Umweg >>> über Interrupt) einen DMA auslösen lassen? >> >> In RM0090 - Chapter 10 - DMA was passendes zusammensuchen. > > ja, genau. 10.3.3, Table 42 und 43 um genau zu sein. Doch dort sehe ich > wie schon geschrieben keine Möglichkeit, durch einen GPIO einen > DMA-Request auszulösen. Bei anderen Controllern, z.B. Kinetis, geht das. > >> Im vorliegenden Fall hatte ich gar nicht an GPIO gedacht, sondern dass >> der externe ADC die SPI triggert und diese wiederum den DMA. > > Der ADC also als SPI-Master? Ist das nicht eher unüblich? Ich behaupte > nicht schon hunderte ADCs gesehen zu haben, aber von denen die ich > kenne, kann das kein einziger. MAH-> ADC ist nicht SPI Master, sondern er triggert den DMA - "irgendwie". Wenn wir keine passende DMA-Request finden, dann wäre doch der Timer unser Freund. Es spricht doch sicher nichts dagegen, dass der STM32 die Samplerate vorgibt? > >> Oder der STM32 ist wieder Master und gibt einen Timertakt vor. > > genau. Doch wie bekommst Du dann das "Konvertierung fertig"-Signal in > einen DMA-Request umgewandelt? > > Erik schreibt ja daß er das an einen GPIO leiten könnte: > > Erik Z. schrieb: >> Über einen Pull-Up-Winderstand ist es jedoch möglich, dass der SDO >> (MISO) Ausgang nach beendeter Wandlung kurzzeitig auf low gezogen wird. >> Hier könnte man eventuell den DMA über einen parallelen Pin koppeln. > > Und ich wüsste gerne wie man daraus dann beim STM32 einen DMA-Request > gemacht bekommt. > > Wäre es evtl. möglich den SPI kontinuierlich und ohne Unterbrechnung per > DMA Daten lesen zu lassen und danach dann per Software die tatsächlichen > Daten aus dem Puffer rauszupicken? Den Chip Select könnte man z.B. von > einem Timer per PWM-Ausgabe erzeugen lassen, damit sollte das den ADC > nicht durcheinander bringen. Die Herausforderung dürfte nur sein, die > Position der Nutzdaten im Puffer zuverlässig vorherzusagen. Oder > übersehe ich hier was? MAH->Yep, siehe oben. Nun haben wir ja eine Menge Ansätze gesehen. Wie man das in jedem einzelnen Fall aufzieht, ergibt sich aus den Leistungsanforderungen an die Baugruppe. Der STM32F4 kann, teilweise über seltsame Klimmzüge, die wildesten Dinger. Allerdings muss ich zugeben, dass bei mir so eine Lösung meistens über Tage (und Nächte im Halbschlaf) im Hinterkopf reift.
Der Rückzieher war ein etwas kleineres Problem, was ich unmittelbar nach dem Einstellen der Frage lösen konnte -> daher gleich gelöscht. Momentan nutze ich jetzt doch erstmal die Interrupts, auch wenn ich damit unzufrieden mit der CPU-Auslastung bin (geschätzt 30 %). Den geistigen Blitz hatte ich bis jetzt noch nicht, und daher versuche ich es erstmal auf diesem Wege. Je mehr man sich mit der Materie beschäftigt umso mehr Gefühl bekommt man für die potentiellen Möglichkeiten!
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.