Forum: Mikrocontroller und Digitale Elektronik Frage zu HAL_UART_Transmit_IT


von Donald (tick1234)


Lesenswert?

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?

von Nachdenklicher (Gast)


Lesenswert?

Steht alles auf Seite 42 der Dokumentation.

von Donald (tick1234)


Lesenswert?

Nachdenklicher schrieb:
> Dokumentation

welcher?

von Bauform B. (bauformb)


Lesenswert?

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.

von STK500-Besitzer (Gast)


Lesenswert?

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.

von Nachdenklicher (Gast)


Lesenswert?

Donald schrieb:
> welcher?

Na in der zu der nicht näher bezeichneten Bibliothek für einen nicht 
näher bezeichneten Prozessor.

von Donald (tick1234)


Lesenswert?

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.

von STK500-Besitzer (Gast)


Lesenswert?

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.

von Donald (tick1234)


Lesenswert?

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.

von weiter weg (Gast)


Lesenswert?

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.

von Harry L. (mysth)


Angehängte Dateien:

Lesenswert?

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.

von STK500-Besitzer (Gast)


Lesenswert?

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.

von STK500-Besitzer (Gast)


Lesenswert?

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.

von Donald (tick1234)


Lesenswert?

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.

von J. S. (jojos)


Lesenswert?

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.

von Donald (tick1234)


Lesenswert?

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.

von STK500-Besitzer (Gast)


Lesenswert?

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

von Johnny B. (johnnyb)


Lesenswert?

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
von Donald (tick1234)


Lesenswert?

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.

von Donald (tick1234)


Lesenswert?

Johnny B. schrieb:
> Ja das geht problemlos, mache ich auch immer so.

super danke, ja geht

von W.S. (Gast)


Lesenswert?

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.

von W.S. (Gast)


Lesenswert?

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.

von STK500-Besitzer (Gast)


Lesenswert?

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.

von STK500-Besitzer (Gast)


Lesenswert?

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.

von Bauform B. (bauformb)


Lesenswert?

W.S. schrieb:
> Ach, ein Interrupt-Handler mit einem Argument?

Bist du gerade genauso frustiert wie ich?

von STK500-Besitzer (Gast)


Lesenswert?

Bauform B. schrieb:
> Bist du gerade genauso frustiert wie ich?

nee, er ist das dauerhaft.

Wo ist das Problem?

von J. S. (jojos)


Lesenswert?

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.

von Donald (tick1234)


Lesenswert?

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

von Harry L. (mysth)


Lesenswert?

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.

von Donald (tick1234)


Lesenswert?

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
von Guest (Gast)


Lesenswert?

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

von Donald (tick1234)


Lesenswert?

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.

von J. S. (jojos)


Lesenswert?

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
von Donald (tick1234)


Lesenswert?

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.

von Guest (Gast)


Lesenswert?

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.

von STK500-Besitzer (Gast)


Lesenswert?

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