Wenn ich eine grössere Datenmenge mit HAL_UART_Transmit_IT sende, generiert das HAL intern etliche interrupts um die SFR des USARTs (oder dessen FIFO bereich) nach jedem byte/datengruppe neu zu laden? Oder wie funktioniert dies ohne DMA? Anders formuliert: generiert HAL_UART_Transmit_IT mehr CPU last als HAL_UART_Transmit_DMA bei transmittlängen über 50bytes?
Wir wissen natürlich nicht, was HAL innen drin anstellt. Rein von der Hardware her muss es ohne DMA für jedes gesendete Zeichen einen Interrupt geben (natürlich könnte man auch pollen). Die meisten (alle?) STM32-UARTs haben nämlich kein FIFO. Wenn man genau einen Block mit DMA sendet, kostet das genau einen Interrupt am Schluss. Und manchmal kann man sogar auf den verzichten.
Bauform B. schrieb: > Wir wissen natürlich nicht, was HAL innen drin anstellt Kann man aber nachgucken, weil der Quellcode offenliegt. Donald schrieb: > welcher? Die zu den HAL- und LL-Treibern. Die Dokumente unterscheiden sich teilweise von einer zur anderen Controllerfamilie. DMA ist übrigens kein Hexenwerk.
Donald schrieb: > welcher? Na in der zu der nicht näher bezeichneten Bibliothek für einen nicht näher bezeichneten Prozessor.
Nachdenklicher schrieb: > Na in der zu der nicht näher bezeichneten Bibliothek für einen nicht > näher bezeichneten Prozessor. Ach so einfach irgendwo auf seite 42, danke das war sehr hilfreich. Nun es get um das STM32 HAL generell, aber bitte uC STM32F103C6, Bibliothek des aktuellen CubeIDE.
Donald schrieb: > Nun es get um das STM32 HAL generell, aber bitte uC STM32F103C6, > Bibliothek des aktuellen CubeIDE. https://www.st.com/resource/en/user_manual/dm00154093-description-of-stm32f1-hal-and-lowlayer-drivers-stmicroelectronics.pdf Die Lib gilt für die ganze STM32F1-Familie; also auch die Docu.
STK500-Besitzer schrieb: > Donald schrieb: >> Nun es get um das STM32 HAL generell, aber bitte uC STM32F103C6, >> Bibliothek des aktuellen CubeIDE. > > https://www.st.com/resource/en/user_manual/dm00154093-description-of-stm32f1-hal-and-lowlayer-drivers-stmicroelectronics.pdf > > Die Lib gilt für die ganze STM32F1-Familie; also auch die Docu. Danke und darin steht lediglich, dass die transmit_IT funktion non blocking ist. Und Seite 42 ist natürlich super hilfreich. Die Info bezüglich TO Frage fehlt. STK500-Besitzer schrieb: > DMA ist übrigens kein Hexenwerk. Nun FIFO wäre besser, das den DMA nicht auslasent würde. Aber eigentlich müsste gem folgender Begründung: Bauform B. schrieb: > Rein von der > Hardware her muss es ohne DMA für jedes gesendete Zeichen einen > Interrupt geben (natürlich könnte man auch pollen). Die meisten (alle?) > STM32-UARTs haben nämlich kein FIFO. es so sein wie Bauform B. beschrieben hat. Dass das HAL intern interrupts macht und daher die CPU auslastet. Wenns ohne CPU last und ohne DMA gehen würde wäre dies natürlich der beste weg. Nutzt evtl. die IT funktion intern DMA? Also intern für jedes Zeichen zu interrupten wäre ja bescheuert und nacht die ganze Funktion discouraged.
Donald schrieb: > Wenns ohne CPU last und > ohne DMA gehen würde wäre dies natürlich der beste weg. Das geht auf jeden Fall. Ich habe aus HAL-Allergie-Gründen den Transfer in der LL (Low-Level) Version umgesetzt. Das funktioniert ganz prächtig. Braucht zum Starten ca. 10-15usec für einen Transfer-Block (bei einem F103) der beliebig lang ist und verursacht (wenn man es zulässt) genau einen Interrupt am Ende des Transfers (zum Löschen des Transfer Complete Flags). In der Zwischenzeit kann man unbelastet beliebig andere Dinge tun. Der einzige "Nachteil" - für mich ist es keiner, ist dass man den Transfer nicht so auf dem Silbertablett geliefert bekommt wie mit HAL.
Donald schrieb: > Dass das HAL intern > interrupts macht und daher die CPU auslastet. Mit dem UART wirst du bei den üblichen Baudraten die CPU nicht merklich belasten. Donald schrieb: > Nutzt evtl. die IT funktion intern DMA? Nein! Ich hab dir im Anhang funktionierenden Code für den UART angehängt.
Donald schrieb: > Nun FIFO wäre besser, das den DMA nicht auslasent würde. Aber eigentlich > müsste gem folgender Begründung: Wie groß müsste das FIFO sein? Wieso hat sich DMA für "prozessorschonenden" Datenverkehr derart etabliert? Wenn man eine variabele Menge an Empfangsdaten hat, und man möglichst schnell reagieren will, ist DMA leider ungeeignet. Deswegen verwende ich da id IT-Methode. Für den Versand ist es ideal. Man darf halt nicht gleichzeitig, schreibend auf den Sendepuffer zugreifen.
Donald schrieb: > generiert HAL_UART_Transmit_IT mehr CPU last als > HAL_UART_Transmit_DMA bei transmittlängen über 50bytes? Donald schrieb: > Die Info bezüglich TO Frage fehlt. Weil Du mich in dem Zusammenhang erwähnst: Ja. Für jedes Zeichen ein Interrupt. DMA liefert ein bis zwei: Jeweils eins bei der Hälfte und eins am Ende der Übertragung.
STK500-Besitzer schrieb: > Wenn man eine variabele Menge an Empfangsdaten hat, und man möglichst > schnell reagieren will, ist DMA leider ungeeignet. Deswegen verwende ich > da id IT-Methode. Ja empfangen IT, senden in dem Fall mit DMA. Ich hoffe das geht mit dem gleichen USART? Als discouraged sehe ich lediglich die Transmit_IT. Also ich möchte empfang IT und senden DMA mit USART1. Noch was anderes: Habe gerade in die HAL geschaut. Es giebt void HAL_UART_IRQHandler(UART_HandleTypeDef *huart); Dieses scheint die Hal internen interrupts zu machen und erhöht den pointer entsprechend. Nur was ich gerade nicht gefunden habe: Diese funktion scheint nicht in der Vektor Tabelle registriert noch sonnst irgendwo aufgerufen zu werden o_O. STK500-Besitzer schrieb: > DMA liefert ein bis zwei: > Jeweils eins bei der Hälfte und eins am Ende der Übertragung. Genau dann einfach jeweils in der ISR die entsprechende hälfte des Buffers laden.
Der Tilen Majerle hat sehr ausführlich aufgedröselt wie Senden/Empfangen mit DMA und variabler Länge mit den HAL Funktionen realisiert werden kann. https://github.com/MaJerle/stm32-usart-uart-dma-rx-tx Im Repo ist in projects reichlich Beispielcode.
Donald schrieb: > Nur was ich gerade nicht gefunden habe: Diese funktion scheint nicht in > der Vektor Tabelle registriert noch sonnst irgendwo aufgerufen zu werden > o_O. Hat sich erledigt. Wenn die entsprechenden interrupts aktiviert werden generiert der cube den code im generellen interupt file.
Donald schrieb: > Genau dann einfach jeweils in der ISR die entsprechende hälfte des > Buffers laden. Wozu? Ein Mal dei gewünschte Anzahl in den Transmitbuffer laden und auf das Ende-Interrupt warten. Dann kannst du den Puffer wieder füllen und die gewünschte Anzahl per DMA verschicken. Du kannst natürlich auch deinen Puffer so groß wählen, dass du da mehrere "Nachrichten" zum Versand reinschreiben kannst. Dann versetzt du nur den Pointer von dem die Zeichen per DMA übertragen werden sollen (und setzt die zu versendende Anzahl) und startest die Übertragung. Man kann auch einen Ringpuffer einstellen (hab ich bisher nicht verwendet).
Donald schrieb: > Ja empfangen IT, senden in dem Fall mit DMA. Ja das geht problemlos, mache ich auch immer so. Mit der HAL hatte ich diesbezüglich überhaupt keine Probleme, lief immer einwandfrei und die Performance für meine Zwecke völlig ausreichend.
:
Bearbeitet durch User
STK500-Besitzer schrieb: > Man kann auch einen Ringpuffer einstellen (hab ich bisher nicht > verwendet). gnau das war meine idee um idle zeit des busses zu vermeiden, daher immer hälfte nachfüllen. Da der uC uS benötigt bis er gestackt hat und endlich in der ISR ist und den neuen DMA gestartet hat.
STK500-Besitzer schrieb: > Wie groß müsste das FIFO sein? > Wieso hat sich DMA für "prozessorschonenden" Datenverkehr derart > etabliert? Eigentlich ist es ganz einfach: der UART-Kernel erzeugt einen Interrupt, sobald das Senderegister leer ist. Das ist aber nicht das Schieberegister, wo das zu sendende Byte herausgeschoben wird, sondern das 'davor'. Folglich hast du im Grunde genau SOVIEL Zeit zum Nachfüllen des TX, wie das Senden eines Bytes braucht. Bist du langsamer, dann gibt es auf der TX-Leitung eben Wartezeiten, bis das nächste Byte zum Senden kommt und beim RX gäbe es einen Überlauf-Fehler. Bei 115kBaud wäre jetzt ein Bit 8.7µs lang (wenn mich mein Taschenrechner nicht trügt) und daraus ergeben sich dann 87µs für ein Byte (8 Bit vom Byte und je 1 Start- und Stopbit). Jetzt ist es an dir, mal zu rechnen, wie schnell du bei einem Interrupt aus dem Knick kommst. Sowas hängt an dem Krempel, den deine HAL intern da noch macht. Und DMA hat sich eigentlich NICHT wirklich für langsame Interfaces wie UART etabliert. Das ist nur eine Marotte von ST. Der Grund ist, daß DMA lediglich Daten schaufeln kann - und zwar Datenmengen, die ZUVOR genau bekannt sind. Aber bei einem Lowlevel-Treiber für einen UART ist dem Treiber eben NICHT bekannt, wieviele Bytes er senden soll oder wieviele Bytes in der nächsten Zeit über RX hereinrauschen. Das ist eben das Prinzip bei einem Universellen Asynchronen Empfänger und Transmitter. Der Treiber sollte deshalb beide Datenströme per Ringpuffer zwischenpuffern, um eben die Zugriffe der übrigen Firmware auf den seriellen Kanal vom Sende- und Empfangsgeschehen zu entkoppeln. Aber einen derartigen Ansatz hat das Zeug von ST eben nicht. Vorrangig für ST ist eben die Kundenbindung. Und wenn ich mir die Herangehensweisen der Leute anschaue, dann sehe ich viel zu oft "jetzt will ich 5 Zeichen vom UART empfangen". So, als ob man die Gegenstelle an der seriellen Strippe kommandieren könnte "senden sie genau JETZT 5 Zeichen". W.S.
Donald schrieb: > Noch was anderes: Habe gerade in die HAL geschaut. Es giebt > void HAL_UART_IRQHandler(UART_HandleTypeDef *huart); > > Dieses scheint die Hal internen interrupts zu machen und erhöht den > pointer entsprechend. Ach, ein Interrupt-Handler mit einem Argument? Hast du dir eigentlich mal klargemacht, was ein Interrupt überhaupt ist und wie und wann er zustande kommt? W.S.
W.S. schrieb: > Und DMA hat sich eigentlich NICHT wirklich für langsame Interfaces wie > UART etabliert. Das ist nur eine Marotte von ST. Der Grund ist, daß DMA > lediglich Daten schaufeln kann - und zwar Datenmengen, die ZUVOR genau > bekannt sind. Aber bei einem Lowlevel-Treiber für einen UART ist dem > Treiber eben NICHT bekannt, wieviele Bytes er senden soll oder wieviele > Bytes in der nächsten Zeit über RX hereinrauschen. Das ist eben das > Prinzip bei einem Universellen Asynchronen Empfänger und Transmitter. > Der Treiber sollte deshalb beide Datenströme per Ringpuffer > zwischenpuffern, um eben die Zugriffe der übrigen Firmware auf den > seriellen Kanal vom Sende- und Empfangsgeschehen zu entkoppeln. Und mal wieder ST-Bashing von W.S. (und mal nicht über die HAL gemeckert? Krank?). Wenn man eine Applikation entwickelt, weiß man in der Regel, wieviele Byte man versenden will: Die Menge hängt mit dem Protokoll zusammen (siehe z.B. Modbus-RTU). Die schreibt man in einen Puffer mit genügend Platz und lässt den DMA-Controller den Rest erledigen ("Fire and Forget"). Um irgendwelche FIFOs einer Schnittstelle kümmert sich dann auch die DMA-Mimik (in Hardware). Warum muss man sich eigentlich über Sachen auffregen, die das Leben vereinfachen? DMA nimmt dem Controller Arbeit ab. Er kann dann was anderes machen und muss nicht auf Interrupts oder blockierend auf die Übertragung warten.
W.S. schrieb: > Ach, ein Interrupt-Handler mit einem Argument? Ja, weil er für alle UART-Schnittstellen verwendet wird. Ein Handler für alle.
W.S. schrieb: > Ach, ein Interrupt-Handler mit einem Argument? Bist du gerade genauso frustiert wie ich?
Bauform B. schrieb: > Bist du gerade genauso frustiert wie ich? nee, er ist das dauerhaft. Wo ist das Problem?
das UART und DMA sich nicht ausschliessen wird in dem von mir verlinkten Artikel ja beschrieben. Nur da müsste man ja fremden Code lesen und verstehen. Und T. Majerle ist kein Dummer, der hatte lange eine eigene Website und gute Beispiele geliefert. So gut, das ST ihn gleich eingekauft hat wie es aussieht.
W.S. schrieb: > Ach, ein Interrupt-Handler mit einem Argument? Och gott, diese ist die welche die relevante tätigkeit macht und dann von der ISR her aufgeruffen wird. Wieso denkst du ich sei so bescheuert und denke der Interrupt vektor zeige auf die funktion...
Donald schrieb: > Wieso denkst du ich sei so bescheuert und denke der Interrupt vektor > zeige auf die funktion... Weil W.S. die Struktur und Funktionsweise der HAL nicht einmal ansatzweise verstanden hat, und sich hartnäckig weigert, das zu verstehen. Kommentare von dem Herrn sollte man einfach ignorieren. Der ist in den 80/90er des le. Jahrtausend kleben geblieben, und hat seitdem auch nichts mehr dazu gelernt.
STK500-Besitzer schrieb: > Und mal wieder ST-Bashing Ach so, als hätte ST nicht auch etwas bashing verdient. HAL wo kein HAL ist, target dass nicht gewechselt werden kann. Dann praktisch keine FIFOs sondern nur einige DMA kanäle um transistoren zu sparen. Verfügbarkeit ist auch top. (obwohl da sind andere auch nicht besser.) Der TouchGFX ist auch der burner :P Dazu kommen gravierende Mängel in richtung sicherheit: siehe zb. Trezor hack Lahmes startup. Poweglitch resistenz generell (nebst dem safety register).
:
Bearbeitet durch User
Donald schrieb: > Dann praktisch keine FIFOs sondern nur einige DMA kanäle um transistoren > zu sparen. Weil DMA und FIFO ja auch das gleiche tun......
Guest schrieb: > und FIFO ja auch das gleiche tun das gleiche tun aber es nicht gleich ausführen. (Mal abgesehen, dass der DMA eher beschränkt ist und nicht direkt ein fifo machen kann, nur stupide circular, aber nicht speicherzugriffe selbst erkennen und entprechende fifostandsadressen in ein SFR damit ein wirkliches fifo mit minimaler CPU last realisiert werden kann). Anyway DMA nutzung führt zu DMA, Mem etc. Auslastung, fifo läuft komplett unabhängig und ist daher DMA überlegen.
Dann nimm die H7, die haben auch FIFOs. Was die Sache allerdings nicht einfacher macht. Zumindest beim SPI. Ich hoffe ich werfe das jetzt nicht durcheinander.
:
Bearbeitet durch User
Donald schrieb: > Ach so, als hätte ST nicht auch etwas bashing verdient. Ach und ganz vergessen: Die TO funktion HAL_UART_Transmit_IT ist discouraged, und der DMA in jeglicher hinsicht unterlegen. Schade dass diese überhaupt vorhanden ist und im beschrieb nicht über den Mangel des Fifos hingewiesen wird und er intern für jedes byte stupide ruminterrupted.
Donald schrieb: > Anyway DMA nutzung führt zu DMA, Mem etc. Auslastung, fifo läuft > komplett unabhängig und ist daher DMA überlegen. Das ist für die meisten Anwendungen absolut egal und die Peripherie wo es interessant ist hat entweder eine größere FIFO oder einen eigene seperate DMA, siehe CAN, Ethernet, SDMMC, USB usw.
Donald schrieb: > Ach so, als hätte ST nicht auch etwas bashing verdient. HAL wo kein HAL > ist, target dass nicht gewechselt werden kann. > Dann praktisch keine FIFOs sondern nur einige DMA kanäle um transistoren > zu sparen. > Verfügbarkeit ist auch top. (obwohl da sind andere auch nicht besser.) > Der TouchGFX ist auch der burner :P > > Dazu kommen gravierende Mängel in richtung sicherheit: siehe zb. Trezor > hack > Lahmes startup. Poweglitch resistenz generell (nebst dem safety > register). Finde dich damit ab, oder nimm einen anderen (von einem anderen Hersteller)!
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.