Hi gibt es für dieses Problem eine Standard Lösung: 2 STM32 Boards kommunizieren über UART. Es geht um eine CMD/response Schnittstelle. CMD und Responses haben die gleiche Länge. Ein DMA transferiert genau ein CMD oder Response. Sollte warum auch immer ein Byte zu wenig übertragen werden, transferiert ja ein DMA nicht mehr ein ganzes CMD/Response.... CMD/responses haben CRC und Delimitter. Das Problem um den es geht ist: alle folgenden CMD/Responses sind nicht mehr DMA aligned. Wie wird das typischerweise verhindert? Danke
Mat. K. schrieb: > Wie wird das typischerweise verhindert? UART ohne DMA machen. Es müssen schon sehr viele Daten erwartet werden damit man mit DMA irgendwas gewinnt.
> UART ohne DMA machen. Es müssen schon sehr viele Daten erwartet werden > damit man mit DMA irgendwas gewinnt. Leider brauche ich den DMA aus performance Gründen. Das ist leider keine Option.
Mat. K. schrieb: > Sollte warum auch immer ein Byte zu wenig übertragen werden, Per IDLE Interrupt kann der UART signalisieren dass vorzeitig Ende ist. Und einen Interrupt für Errors gibt es auch. Da kann man dann den DMA abwürgen/neu starten. Weil der Sender ja auch DMA nutzt sollte es keine Lücken zwischen den einzelnen Bytes geben, sodass der IDLE Interrupt nicht versehentlich kommt. Cyblord -. schrieb: > Es müssen schon sehr viele Daten erwartet werden damit man mit DMA > irgendwas gewinnt. Der Overhead für ständiges Betreten/Verlassen der Interrupts kann ein Echtzeitverhalten durcheinander bringen und außerdem den Energieverbrauch nach oben treiben.
Cyblord -. schrieb: > Es müssen schon sehr viele Daten erwartet werden > damit man mit DMA irgendwas gewinnt. Bei Transmit gewinnt man sehr wohl eine Menge. Denn anstatt in der Transmit-Loop zu warten bis das Transmit-Register wieder frei ist (Baudrate ist so niedrig dass sich der Controller "langweilt") um das nächste Datum zu schreiben kann man viele andere Dinge machen. Bei 921600 Baud (z.B.) braucht ein Byte ca. 10 usec, da kann ein STM32 zwischendurch sehr viel erledigen. Bei Receive ohne DMA bekommt man einen Interrupt der sehr schnell abgearbeitet ist, also kein spürbarer Zeitgewinn mit DMA.
Wastl schrieb: > Bei Transmit gewinnt man sehr wohl eine Menge. Denn anstatt > in der Transmit-Loop zu warten bis das Transmit-Register > wieder frei ist (Baudrate ist so niedrig dass sich der > Controller "langweilt") um das nächste Datum zu schreiben > kann man viele andere Dinge machen. Bei 921600 Baud (z.B.) > braucht ein Byte ca. 10 usec, da kann ein STM32 zwischendurch > sehr viel erledigen. Das geht mit Interrupts genau so, da brauchts keinen DMA. Mit DMA spart man sich lediglich das schreiben des Bytes in den TX Register.
:
Bearbeitet durch User
Mat. K. schrieb: > Leider brauche ich den DMA aus performance Gründen. Das würde ich gerne erklärt bekommen, denn das verstehe ich nicht. Vielleicht hast du einen Sonderfall den ich bisher nicht im Blickfeld hatte. Jedenfalls ist serielle Übertragung im Bereich unter 1 MBit/sec arschlangsam im Verhältnis zu dem was ein STM32 zu leisten vermag.
Cyblord -. schrieb: > Mit DMA spart man sich lediglich das schreiben des Bytes in den TX > Register. Und den Overhead für den Interrupt. Der ist viel höher als der Registerzugriff. Warum sonst unterstützt der UART überhaupt DMA...?
Niklas G. schrieb: > Der Overhead für ständiges Betreten/Verlassen der Interrupts kann ein > Echtzeitverhalten durcheinander bringen und außerdem den > Energieverbrauch nach oben treiben. KANN, aber der DMA hat eben auch Nachteile. Und nicht vergessen: Der DMA teilt sich den gleichen Datenbus mit allen anderen Komponenten des Controllers beim STM32. Es wird nur die CPU nicht belastet. Der Bus kann aber blockieren.
Cyblord -. schrieb: > Der Bus kann aber blockieren. Tut er aber nicht da er zwischendrin immer wieder den Core zum Zuge kommen lässt. So eine STM32 Hardware arbeitet "interleaved", wie der Franzose zu sagen pflegt.
Wastl schrieb: > Cyblord -. schrieb: >> Der Bus kann aber blockieren. > > Tut er aber nicht da er zwischendrin immer wieder den Core > zum Zuge kommen lässt. So eine STM32 Hardware arbeitet > "interleaved", wie der Franzose zu sagen pflegt. Genau das meine ich. Er muss zwischendrin eben auch warten und läuft eben nicht, wie manche erwarten, völlig unabhängig vom Rest des Controllers.
:
Bearbeitet durch User
Cyblord -. schrieb: > KANN, aber der DMA hat eben auch Nachteile. Ja, aber meistens kann man damit trotzdem gut arbeiten. Ich benutze den DMA oft mit dem UART ohne Probleme. Sogar bei Paketen mit variabler Länge. Ich würde jetzt nicht auf die Idee kommen das wieder zu lassen. Cyblord -. schrieb: > Der Bus kann aber blockieren. Nur wenn der DMA-Controller wirklich bei jedem einzelnen Takt einen Zugriff macht, was beim UART absolut nicht der Fall ist, da wird die CPU nur bei jedem Byte mal für wenige Takte (je nach Busgeschwindigkeit) "blockiert", falls sie gerade überhaupt einen Zugriff macht - das tut sie aber auch nicht in jedem Takt. Die Instruktionen kommen meist direkt über einen dedizierten Bus vom Flash. Die CPU würde viel mehr Takte verschwenden wenn man es manuell im Interrupt macht. Die einzigen kniffligen Probleme beim DMA treten bei CPUs mit Cache auf (Cortex-M7, Cortex-A) wo man Cache Maintenance Operations zwischen DMA-und CPU-Zugriff machen muss (außer bei SoCs wo der DMA selbst auf den Cache zugreifen kann). Aber auch das ist ein gelöstes Problem. PS: Bei Low-Power-Anwendungen kann es interessant sein den Prozessor zwischenzeitlich auf einen sehr niedrigen Takt zu stellen und dann entweder das Voltage Scaling oder LPRun/LPSleep-Mode (nutzt den LowPower-Regulator) zu aktivieren, und ggf. noch zusätzlich den Flash abzuschalten (außer man sendet konstante Daten vom Flash). Der DMA läuft im (LP)Sleep-Mode noch und kann dann Daten senden/empfangen, aber der Gesamt-Verbrauch reduziert sich stark. Prinzipiell geht das auch wenn man Interrupts nutzt, aber das ständige Aufwachen verbraucht halt definitiv mehr.
:
Bearbeitet durch User
Niklas G. schrieb: > Nur wenn der DMA-Controller wirklich bei jedem einzelnen Takt einen > Zugriff macht, was beim UART absolut nicht der Fall ist, da wird die CPU > nur bei jedem Byte mal für wenige Takte (je nach Busgeschwindigkeit) > "blockiert", falls sie gerade überhaupt einen Zugriff macht - das tut > sie aber auch nicht in jedem Takt. Die Instruktionen kommen meist direkt > über einen dedizierten Bus vom Flash. Die CPU würde viel mehr Takte > verschwenden wenn man es manuell im Interrupt macht. Na das halte ich doch für eine Beschreibung die sich manche Leute mal richtig gut merken sollten. Ich habe es schon geschafft einen String in einem Buffer zu überschreiben während der vorherigen String (im gleichen Buffer) noch über DMA gesendet wurde. Man hält das für einen "Fehler" des Controllers wenn man sich den oben zitierten Absatz nicht zu Herzen nimmt. Dabei ist es eben nur das implementierte Interleaving sowie die Arbeitsgeschwindigkeit des Cores die das möglich machen.
Wastl schrieb: > Ich habe es schon geschafft einen String in einem Buffer zu > überschreiben während der vorherigen String (im gleichen > Buffer) noch über DMA gesendet wurde Hmm? Hast du nicht auf den DMA Interrupt gewartet dass der Transfer fertig ist?
Niklas G. schrieb: > Hmm? Hast du nicht auf den DMA Interrupt gewartet dass der Transfer > fertig ist? Als mir das schliesslich klar wurde: ja. Die Erklärung dazu hatte ich ja bereits vorher geliefert.
Wastl schrieb: > Als mir das schliesslich klar wurde: ja Hmm, also es sollte doch sowieso klar sein dass der UART viel langsamer als der Prozessor-Bus ist. Das DMA kann nur neue Bytes zum UART schaufeln wenn der Puffer frei ist, also nur alle paar Hundert/Tausend Takte. Das hat mit dem DMA eigentlich nicht viel zu tun, sondern liegt einfach am UART. Höchstens wenn man einen Memory-To-Memory Transfer macht kann das DMA mit maximalem Bustakt arbeiten, was dann eventuell tatsächlich die CPU blockiert bis der Transfer fertig ist (die CPU wäre natürlich auch blockiert wenn man stattdessen memcpy machen würde).
Ich musste bei einem STMH743 mal größere Datenmengen über SPI bewegen. Der bietet 3 Möglichkeiten: Polling, Interrupt und DMA Betrieb. Ich habe alle 3 Sachen getestet. Am performantesten war der reine Interrupt Betrieb. Mit DMA war es leicht langsamer als der reine Interrupt-Betrieb, den ich dann genommen habe. Vielleicht sollte der TE einfach mal alles durchtesten, ob DMA wirklich schneller ist. Und vielleicht auch mal auf Nachfragen antworten.
Peter schrieb: > Am performantesten war der reine Interrupt Betrieb. Mit DMA war es > leicht langsamer als der reine Interrupt-Betrieb, den ich dann genommen > habe. Hast du die SPI-Leitungen mal mit dem Oszilloskop analysiert? Waren da Pausen zwischen? Was genau hat da länger gedauert?
Ich habs so gelöst, dass ich auch per DMA empfange aber zyklisch prüfe ob per DMA etwas empfangen wurde. Selbst wenn kein DMA Interrupt kommt, weil 1 Byte fehlt, schlägt mein Timeout zu und löscht den Vorgang und initialisiert neu.
Peter schrieb: > Ich musste bei einem STMH743 mal größere Datenmengen über SPI bewegen. > Der bietet 3 Möglichkeiten: Polling, Interrupt und DMA Betrieb. > Ich habe alle 3 Sachen getestet. > Am performantesten war der reine Interrupt Betrieb. Mit DMA war es > leicht langsamer als der reine Interrupt-Betrieb, den ich dann genommen > habe. Hast du das mit der HAL gemacht ?
Niklas G. schrieb: > Peter schrieb: >> Am performantesten war der reine Interrupt Betrieb. Mit DMA war es >> leicht langsamer als der reine Interrupt-Betrieb, den ich dann genommen >> habe. > > Hast du die SPI-Leitungen mal mit dem Oszilloskop analysiert? Waren da > Pausen zwischen? Was genau hat da länger gedauert? Der Gesamt-Overhead war kleiner. Ich habe mehr Daten pro Sekunde lesen können. Hans-Georg L. schrieb: > Hast du das mit der HAL gemacht ? Ja, wo es ging die HAL benutzt. Funktioniert im Allgemeinen ganz gut, da mache ich dann keine direkten Registerzugriffe.
Peter schrieb: > Ja, wo es ging die HAL benutzt Dann war das wahrscheinlich der Overhead in der HAL. Ohne HAL dürfte der Durchsatz pro Sekunde identisch sein, aber bei Verwendung von DMA braucht es viel weniger CPU-Zeit und Energie.
Wastl schrieb: > Bei Transmit gewinnt man sehr wohl eine Menge. Denn anstatt > in der Transmit-Loop zu warten bis das Transmit-Register > wieder frei ist (Baudrate ist so niedrig dass sich der > Controller "langweilt") um das nächste Datum zu schreiben Dazu braucht man noch kein DMA, sinnloses Polling kann man auch mit Interrupts alleine vermeiden. Nö, DMA macht eigentlich erst bei sehr hohen Bitraten Sinn, denn statt eines Interrupts pro Byte gibt's dann halt nur einen pro Transfer-Block. > Bei Receive ohne DMA bekommt man einen Interrupt der sehr > schnell abgearbeitet ist, also kein spürbarer Zeitgewinn > mit DMA. Beim Empfangen gilt eigentlich dasselbe wie beim Senden. Polling braucht niemand, da nimmt man Interrupts. DMA bringt dieselben Vorteile wie beim Senden, halt eine geringere Interruptlast. Statt einmal pro Byte nur einmal pro Block. Das Problem ist halt nur, dass man sich auf Empfängerseite mit der Behandlung möglicher Übertragungsfehler herumschlagen muss. Das ist trivial beim Polling, schon etwas schwieriger beim Einsatz von Interrupts und doch schon relativ kompliziert beim Einsatz von DMA. Fehlererkennung und Verwerfen des Puffers ist noch einfach. Der eigentliche Kitzel ist die Resynchronisation auf den Datenstrom des Senders nach dem Fehlerfall. Wie kompliziert (und ob überhaupt sinnvoll möglich) das ist, hängt von der Gestaltung des Protokolls oberhalb des UART-Levels ab. Praktisch immer ist es aber nötig, die Resynchronisation zunächst ohne DMA durchzuführen. Erst wenn anhand der so empfangenen Daten wieder ein Blockanfang des übergeordneten Protokolls zu erwarten ist, kann man in den DMA-Mode wechseln. Man könnte also so sagen: DMA für den Empfänger ergibt nur einen Sinn, wenn das übergeordnete Protokoll halt den Versand von Blöcken fester Größe mit einer Pause einer gewissen Minimalgröße vorsieht. Für kontinuierliche Datenströme ohne innere Struktur ist es hingegen wenig bis nicht brauchbar.
Ob S. schrieb: > wenn das übergeordnete Protokoll halt den Versand von Blöcken fester > Größe mit einer Pause einer gewissen Minimalgröße vorsieht. Wenn die Pause ein Frame lang ist, sodass der UART den IDLE Interrupt auslöst, ist das kein Problem. Auch wenn die Frame-Länge variabel ist!
Niklas G. schrieb: > Ob S. schrieb: >> wenn das übergeordnete Protokoll halt den Versand von Blöcken fester >> Größe mit einer Pause einer gewissen Minimalgröße vorsieht. > > Wenn die Pause ein Frame lang ist, sodass der UART den IDLE Interrupt > auslöst, ist das kein Problem. Auch wenn die Frame-Länge variabel ist! Nicht ganz. Dieser Ansatz funktioniert nur, wenn die "Frames" garantiert immer kurzer sind als die DMA-Länge. Wird diese Grenze gerissen, kommt richtig heftiger Müll raus, nämlich Fehler, die u.U. nicht mal erkannt werden. Um sie wenigstens zuverlässig erkennen zu können, müssen nämlich zwei ISRs korrekt zusammenarbeiten. Die HAL-Routinen bieten das nicht.
Ob S. schrieb: > Wird diese Grenze gerissen, kommt richtig heftiger Müll raus Wieso? Man muss nur im DMA-Interrupt das DMA schnell neu starten. Glücklicherweise haben die UARTs der neueren Controller einen FIFO von bis zu 8 Bytes, da hat man viel Zeit um das neu einzustellen. Ob S. schrieb: > Die HAL-Routinen bieten das nicht. Doch, man muss halt im Callback den DMA neu starten. Kann aber sein dass die HAL zu langsam ist.
Mat. K. schrieb: > gibt es für dieses Problem eine Standard Lösung: > Sollte warum auch immer ein Byte zu wenig übertragen werden, > Wie wird das typischerweise verhindert? Falls die Möglichkeit besteht zwischen den Paketen beiderseits ein Break generieren. Entweder kann der STM das direkt oder ein Byte 0 mit halber Baudrate senden (die Empfänger-Baudrate wird nie verändert). Daraufhin wird beim jeweiligen Empfänger ein Framing-Error Interrupt ausgelöst, in dem dann der DMA-Empfang des folgenden Paketes vorbereitet wird. In diesem Framing-Error Int kann man dann noch schauen, ob das empfangene Byte auch tatsächlich 0 war. Kommt das folgende Paket in erwarteter Länge gibt es am Ende des DMAs die Verarbeitung ansonsten passiert einfach nichts, das Paket ist dann verloren (da nicht gültig). Dreh- und Angelpunkt ist immer der nächste Break-Interrupt, der rettet alles wieder. Damit wird das Interface sehr robust gegen Störungen aller Art. Selbst nach einem Trennen der Verbindung fängt sich das System anhand der Sync-Marke sofort wieder. Der Overhead für dieses Prinzip ist sehr gering. Man braucht kaum Zwangspausen zwischen den Paketen und alles findet in Interrupts statt, das ist ein zusätzlicher Interrupt pro Seite. Auf dem Interface selbst hat man nur das Break (im Prinzip 2 Bytes Länge und etwas Zeit für Verarbeitung und Aufsetzen des DMAs)
:
Bearbeitet durch User
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.