Hallo zusammen, ich habe ein kleines Problem mit dem USART-DMA-Modus. Dazu erstmal der Init-Code: UART_HandleTypeDef g_UsART3_Handle; DMA_HandleTypeDef g_hdma_usart3_rx; DMA_HandleTypeDef g_hdma_usart3_tx; g_UsART3_Handle.Instance = USART3; g_UsART3_Handle.Init.BaudRate = 19200; g_UsART3_Handle.Init.WordLength = UART_WORDLENGTH_8B; g_UsART3_Handle.Init.StopBits = UART_STOPBITS_1; g_UsART3_Handle.Init.Parity = UART_PARITY_NONE; g_UsART3_Handle.Init.Mode = UART_MODE_TX_RX; g_UsART3_Handle.Init.HwFlowCtl = UART_HWCONTROL_NONE; g_UsART3_Handle.Init.OverSampling = UART_OVERSAMPLING_16; HAL_UART_Init(&g_UsART3_Handle); g_hdma_usart3_rx.Instance = DMA1_Stream1; g_hdma_usart3_rx.Init.Channel = DMA_CHANNEL_4; g_hdma_usart3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; g_hdma_usart3_rx.Init.PeriphInc = DMA_PINC_DISABLE; g_hdma_usart3_rx.Init.MemInc = DMA_MINC_ENABLE; g_hdma_usart3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; g_hdma_usart3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; g_hdma_usart3_rx.Init.Mode = DMA_CIRCULAR; g_hdma_usart3_rx.Init.Priority = DMA_PRIORITY_LOW; g_hdma_usart3_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; HAL_DMA_Init(&g_hdma_usart3_rx); __HAL_LINKDMA(&g_UsART3_Handle,hdmarx,g_hdma_usart3_rx); HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn); HAL_UART_Receive_DMA(&g_UsART3_Handle, &g_usartRX, g_usartRXlen); Im DMA Full-Callback sollen dann die Daten abgefragt werden. Das funktioniert auch soweit. Das Problem ist nun, dass ich Daten-Frames mit einer definierten Länge übertragen möchte (Frame-Layout damit die Daten leichter zu verarbeiten sind). Es kann jedoch vorkommen, dass durch ein Übertragungsfehler Bytes verloren gehen und somit der DMA aus dem tritt kommt. D.h. im DMA stehen die Daten-Bytes nicht mehr an der richtigen Stelle. Die Frage ist nun, wie ich den DMA-Stream "Löschen" bzw zurücksetzen kann, damit dieser bei einem fehlerhaften Frame wieder die Daten an die richtige Stelle schreibt. Danke schon mal für hilfreiche Ideen.
Servus, du bist echt wie ein einarmiger Bandit. Kein Affe weiß was du mit DMA willst. mfg
In ihre definierte Packet soll auch einen CRC checksum implementiert sein. Damit kan jedes Packet ueberprueft werden. Wen Falsch, soll das neu gesendet werden. Zweitens sollen sie eine time_out für die DMA forsehen. Damit weisst du wen da ein Zeichen fehlt, den ende DMA-transfer kommt nur nach das alle Zeichen von ein Packet enpfangen sind.
Keine DMA ist mit einer Prophetschaltung ausgerüstet, die weiss, wann nun ein fehlerhafter Frame ankommt. DMA bedeutet ja extra, das es nicht über die CPU läuft und deswegen auch nicht geprüft wird. Du solltest also eher die gute alte USART_RX_Complete ISR benutzen, die dir einen Buffer füllt und prüft, ob das alles so sein kann. Wenns die Prüfung besteht, gibts eine OK Flagge, wenn nicht, Fehlerchen ausgeben und neuen Frame anfordern. Und wenns besonders fix gehen soll, kannst du ja den CCRam benutzen, immerhin sind da ungenutzte 64kByte (beim F407 zumindest).
Mahlzeit zusammen,
@aSma:
Danke für deine konstruktive Kritik. Es scheint so, als ob zwei "Affen"
doch wissen, was ich mit dem DMA machen möchte.
@Jan H., @Matthias Sch.:
Die "Prophetschaltung", wie sie Matthias Sch. so schön bezeichnet hat,
habe ich bereits implementiert und diese funktioniert auch zuverlässig.
Vllt habe ich das Problem nicht genug umschrieben:
Wenn ein Fehler auftritt wird dies von der Prophetschaltung (der Name
sollte Markenrechtlicht lizenziert werden...) erkannt.
Zur Erklärung:
Ein Frame soll bspw aus 4 Datenbytes (x -> S.u.) bestehen. Es kann nun
vorkommen, dass beim Senden eines Frames nicht 4 sondern nur 3
Datenbytes ankommen (Frame 1)
Frame 1: [X X X]
Hier wird dann natürlich der DMA-Full-Callback nicht ausgelöst.
Wird nun ein zweites Datenbyt mit der korrekten Länge(4) gesendet (Frame
2) kommt es zu einem "Überlauf" des DMAs, wodurch alle folgenden Frames
(mit Korrekter länge) als Falsch erkannt werden
Frame 2: [Y Y Y Y]
Bsp: Beim Senden des ersten Bytes steht wird der DMA folgender maßen
befüllt:
DMA[X X X 0]
1 2 3 4
DMA Byte 4 bleibt also leer.
Beim Senden des ersten Bytes des 2ten Frames geschieht nun folgendes:
Frame2[Y Y Y Y->] DMA[->Y X X X] 0->
1 2 3 4
Byte 4 des DMA wird weitergeschoben und der Callback ausgelöst. Im
Callback wird jetzt erkannt, dass die Daten fehlerhaft sind, da es sich
nicht um ein Vollständiges Frame handelt.
Nach dem Callback stehen jedoch die verbleibenden 3 Bytes des 2ten
Frames im DMA und das Spiel beginnt von vorn.
DMA[Y Y Y 0]
Ich möchte nun, wenn von der Prophetschaltun© ein Fehler erkannt wird,
den DMA vollständig löschen bzw. zurücksetzten, damit der DMA wieder
"Synchron" läuft.
Wie kann ich dies ohne einen neuen Init des USARTs umsetzen.
Grüße
Servus, Nico schrieb: > Ich möchte nun, wenn von der Prophetschaltun© ein Fehler erkannt wird, > den DMA vollständig löschen bzw. zurücksetzten, damit der DMA wieder > "Synchron" läuft. > Wie kann ich dies ohne einen neuen Init des USARTs umsetzen. Was du brauchst ist ein Protokoll. Mit header und terminator. Bei der Auswertung siehst du was fehlt. Daten senden ist einfach, aber gesendete Daten zu empfangen dagegen nicht. Hat man einen großen Buffer (FIFO), dann muss muss man irgendwie feststellen, ob die Daten schon geschrieben sind. Dazu gibt es irgendwo eine AppNote von st mit z.B. einen Timer. Bei einen festen Buffer hat man mit Überlauf zu kämpfen oder man muss einen timeout erstellen, falls zu wenig Daten angekommen sind.
1 | Nico schrieb im Beitrag #4544123: |
2 | > g_hdma_usart3_rx.Init.Mode = DMA_CIRCULAR; |
Das Problem ist hier, dass sobald der Buffer voll ist, erst dann wird ein Interrupt ausgefühlt. Man kann auch per Protokoll überprüfen, was fehlt und diese Daten anfordern. Leider kenne deine Libraray nicht gut, da ich mit der Standart Lib arbeite. Mein Vorschlag wäre:
1 | g_hdma_usart3_rx.Init.Mode = DMA_Mode_Normal; |
2 | |
3 | //Pseudo Code, DMA Channel muss erst ausgemacht werden,
|
4 | //damit neue Bufferlänge Wirkung hat!
|
5 | DMA_UART_RX(uint8_t num2read) |
6 | {
|
7 | DMA_Cmd(ChannelRx, DISABLE); |
8 | DMA_SetCurrDataCounter(x,x,num2read); |
9 | DMA_Cmd(ChannelRx, ENABLE); |
10 | }
|
Sry, aber ich denke kaum jemand nutzt die HAL? Bibliothek. mfg
Für mich stellt sich die Frage, ob sich für die paar Bytes der ganze DMA Aufwand überhaupt lohnt. Das ist doch mit einer ISR viel leichter und schneller gelöst. Wären das 1000 oder 10000 Bytes, sähe das evtl. anders aus, obwohl ich mit ADC und I2S in der ISR Behandlung gute Erfahrungen gemacht habe und immer genügend Rechenleistung in Reserve hatte (bei Audio mit 48kHz Samplerate). Auch ein Restart der DMA im Fehlerfall birgt immer das Risiko, falsch auf einen Frame einzurasten oder ein Byte zu verpassen. Bin auch kein HALer sondern StdLibler und kann deswegen auch nicht beurteilen, ob evtl. die HAL das Problem ist.
Matthias S. schrieb: > Für mich stellt sich die Frage, ob sich für die paar Bytes der ganze DMA > Aufwand überhaupt lohnt. Ein klares JA, aber nur wenn man den Vorteil der DMA auch einsetz (ISR). Beim pollen nutze ich es auch immer, da der Code sich stark minimiert. Matthias S. schrieb: > Auch ein Restart der DMA im Fehlerfall birgt immer das Risiko, falsch > auf einen Frame einzurasten oder ein Byte zu verpassen. Bei einen konstanten Buffer ist das größte Problem ein overflow. Nehmen wir an beim Initialisieren des UART sendet der Tx ein paar sinnlose bytes. Dann werden die Daten gesendet [header]data[terminator]+paar bytes. Genau diese Aufgabe gilt es jetzt zu lösen. Fährt man die gleiche Schiene, dann muss der overflow erkannt werden und einen restart der Daten anfordern. Andere Möglichkeit wäre ein FIFO zu implementieren mit einen großzügigen Buffer. Oder auch wie zuvor geschrieben, einen Timer erstellen der guckt, fertig oder nicht mit der Übertragung? Man kann es auch ohne DMA lösen, aber mit sehr viel Mehrcode. Matthias S. schrieb: > Bin auch kein HALer sondern StdLibler und kann deswegen auch nicht > beurteilen, ob evtl. die HAL das Problem ist. Willkommen im Club. :)
aSma>> schrieb: > Man kann es auch ohne DMA lösen, aber mit sehr viel Mehrcode. Wieso das? Eine simple RX complete ISR ist doch kein Mehrcode. Alleine die Fehlerbehandlung der DMA ist grösser als die ganze ISR.
Nico schrieb: > ich habe ein kleines Problem mit dem USART-DMA-Modus. Das sehe ich anders: Du hast Probleme mit dem Durchsteigen durch dein eigenes Vorhaben, kurzum falsch angedacht. Wozu soll bitte sehr denn ein DMA-Betrieb für sowas wie einen USART gut sein? Glaubst du, damit besser oder schneller zu werden? Allein wenn ich mir deine Initialisierungsorgie anschaue, bezweifle ich dies. Als nächstes frag ich mich, was du denn tun willst, wenn gerade dann, wenn dein DMA-Puffer voll ist und die DMA fertig ist, weitere Zeichen hereingerauscht kommen? Ignorieren? Ungewollt verlieren? Nee, bei USART's macht man das anders: Zeichenempfang in einen Ringpuffer und Zeichenausgabe aus einem Ringpuffer. Beides natürlich per Interrupt, so daß die eigentlichen Programmschichten, die den gewünschen Algorithmus praktizieren, lediglich mit Puffern zu tun haben, aus denen und in die man zeichenweise den I/O-Strom fließen läßt. Dieses puffernde Verhalten eines guten seriellen Treibers kann man per DMA eben niemals nachbilden, denn dazu ist CPU-"Intelligenz" vonnöten. Und es möge hier keiner behaupten, daß das zugehörige Interruptprogramm aufwendig oder umfänglich sei. Das ist Quatsch. W.S.
Nico schrieb: > Die Frage ist nun, wie ich den DMA-Stream "Löschen" bzw zurücksetzen > kann, damit dieser bei einem fehlerhaften Frame wieder die Daten an die > richtige Stelle schreibt. Der f4 kann IIRC einen Timeout-Interrupt auslösen. Timeout auf z.b. 5 Zeichen festlegen. Wenn der Timeout anschlägt bevor der DMA fertig ist dann hats wo ein Zeichen gefressen. Modbus-RTU macht Telegram-Erkennung per Timeout, ist sicher nicht die schlechteste Geschichte. Wenn Mist ankommen kann dann braucht man so oder so einen zeitbasierten Watchdog, weil ein Protokoll-Parser ganz gleich welcher Art sich dauerhaft verhaspeln kann.
W.S. schrieb: > Dieses puffernde > Verhalten eines guten seriellen Treibers kann man per DMA eben niemals > nachbilden, denn dazu ist CPU-"Intelligenz" vonnöten. Um die Intelligenz muss sich der Programmierer kümmern. Prizipiell kann man schon die DMA nehmen, wenn man genau weiß wieviele Bytes man empfängt. Eine Möglichkeit um overflow zu entgehen, könnte der Half-Transfer Interrupt genutz werden. Beispielsweise: Man will 20bytes empfangen. Den Buffer setzt man auf 40 Bytes. Mit ein wenig Phantasie lässt sich schon was machen. W.S. schrieb: > Und es möge hier keiner behaupten, daß das zugehörige Interruptprogramm > aufwendig oder umfänglich sei. Das ist Quatsch. Wenn man halt die Möglichkeit hat die CPU zu entlassen, warum sollte man es nicht auch anstreben? Es gibt viele Wege nach ROM. Man muss nur den richtigen aussuchen. Über das Mittelmeer, wie die Asylanten dauert einfach zu lange. Ich nehme das Flugzeug.
aSma>> schrieb: > Wenn man halt die Möglichkeit hat die CPU zu entlassen, warum sollte man > es nicht auch anstreben? Ich muss aber bei einem F4XX nicht die CPU entlasten, um 4 Bytes vom USART zu empfangen. Das ist sicher optimieren an der falschen Stelle, abgesehen von der, wie wir ja sehen, Fehleranfälligkeit. Eine DMA ist sicher prima, wenn ich genau weiss, wieviel und wohin es gehen soll. Beim Mehrkanal ADC gibt es ja sogar nur diese Option. Aber nicht für 4 Bytes über die serielle.
aSma>> schrieb: > Um die Intelligenz muss sich der Programmierer kümmern. Prizipiell kann > man schon die DMA nehmen, wenn man genau weiß wieviele Bytes man > empfängt. Eben genau diese Annahme ist der Knackpunkt. Sie ist nämlich IMMER falsch. Bei jeder seriellen Verbindung muß man damit rechnen, daß selbige unvollständig ist oder gestört oder sonstwas. Die Kommunikation findet nämlich immer mit einem anderen Ding statt, welches schlichtweg unabhängigig ist vom eigenen Programm. Folglich darf man niemals damit rechnen, an irgend einer Stelle im eigenen Programm (oder zu einem bestimmten Zeitpunkt) genau soundso viele Bytes zu empfangen. auf solche Annahmen darf man sein Programm niemals aufbauen, sonst erleidet man Schiffbruch. Also ist es schlichtweg sinnlos, eine DMA auf eine bestimmte Anzahl Bytes für einen bestimmten Puffer zu programmieren und dann quasi blind losrennen zu lassen. Stattdessen muß man eben die Zeichen in der o.g. Interrupt-Routine empfangen und in einen hinreichend großen Ringpuffer packen. Die Grundroutine hingegen muß allzeit prüfen, ob was angekommen ist, muß es abholen und parsen und in einen weiteren (nicht-Ring-)Puffer schreiben. Wenn das aktuelle Zeichen nicht dem entspricht, was man an dieser Stelle erwartet, dann muß man eben das Bieherige verwerfen und nach der nächsten Synchronisier-Gelegenheit Ausschau halten. Also wieder auf Zeichen warten, auf Synchronisier-Zeichen oder -Zeichenfolge warten und dann weitermachen. All dies geht immer einzelzeichenweise und niemals blockweise aus oben genannten Gründen. W.S.
Matthias S. schrieb: > Ich muss aber bei einem F4XX nicht die CPU entlasten, um 4 Bytes vom > USART zu empfangen. Das ist sicher optimieren an der falschen Stelle, > abgesehen von der, wie wir ja sehen, Fehleranfälligkeit. > Eine DMA ist sicher prima, wenn ich genau weiss, wieviel und wohin es > gehen soll. Beim Mehrkanal ADC gibt es ja sogar nur diese Option. > > Aber nicht für 4 Bytes über die serielle. Ja, gut nehmen wir an, dass man super lange Leitung hat und baud von 9600 ausgesetzt ist und kriegt 4096 bytes. Der TE hat nichts darüber erzählt. Er wollte nur wissen wie man den DMA counter rücksetzt. W.S. schrieb: > Eben genau diese Annahme ist der Knackpunkt. Sie ist nämlich IMMER > falsch. Bei jeder seriellen Verbindung muß man damit rechnen, daß > selbige unvollständig ist oder gestört oder sonstwas. Die Kommunikation > findet nämlich immer mit einem anderen Ding statt, welches schlichtweg > unabhängigig ist vom eigenen Programm. Genau das ist die Annahme von AVR Programmierer. Man muss mal auch den horizont erweitern können! Bei Störung, Fehler, Verzögerung etc. kann man immer tätig werden. Ich verstehe schon, wenn man einmal ein Konzept ausgearbeitet hat, dann kann man dieses auch weiter nutzen. Ich habe gleich mit stm32 angefangen zu programmieren, deshalb bin ich vielleicht mehr offen für alles. Mein Beispiel zuvor mit Halb transfer Interrupt war vielleicht unglücklich gewählt. Aber die Ideologie ist nicht verkehrt, wenn man mit ein wenig Gehirnschmalz sich ein echtes FIFO mit DMA basteln will. Wobei der M3 Cortex kein echtes Fifo bestizt, vielleicht der F4? Habe ich schon vergessen. W.S. schrieb: > Also ist es schlichtweg sinnlos, eine DMA auf eine bestimmte Anzahl > Bytes für einen bestimmten Puffer zu programmieren und dann quasi blind > losrennen zu lassen. Stattdessen muß man eben die Zeichen in der o.g. > Interrupt-Routine empfangen und in einen hinreichend großen Ringpuffer > packen. Kommt immer wieder auf den Einsatzort an! Nehmen wir mal das Beispiel: Ich möchte eine Echtzeit von 1ms mit 5Mbaud erstellen. Es sollen dabei 256bytes übertragen werden. Ich würde dabei nie auf die Idee kommen normalen Interrupt zu nehmen, sondern ich würde DMA einfach pollen. Ist doch kein Problem. Ein timeout programmieren, falls was schiefgegangen ist und basta. Zum Beispiel als Kommunikationschnittstelle mit den PC. Ist mein Regler erstellt worden, dann kommt UART eh wieder weg. mfg
aSma>> schrieb: > Ja, gut nehmen wir an, dass man super lange Leitung hat und baud von > 9600 ausgesetzt ist und kriegt 4096 bytes. Der TE hat nichts darüber > erzählt. Ich verstehe von deinem Satz nur die Hälfte, aber die 4 Bytes hat der TE doch genannt: Nico schrieb: > Ein Frame soll bspw aus 4 Datenbytes (x -> S.u.) bestehen. Es kann nun > vorkommen, dass beim Senden eines Frames nicht 4 sondern nur 3 > Datenbytes ankommen (Frame 1) W.S. schrieb: > Also ist es schlichtweg sinnlos, eine DMA auf eine bestimmte Anzahl > Bytes für einen bestimmten Puffer zu programmieren und dann quasi blind > losrennen zu lassen. Zustimmung.
Hallo zusammen, danke nochmals für eure anregungen. Allerdings geht die Dikusion hier an der eigentlichen Frage vorbei. Mir ging es lediglich darum zu erfahren, ob und wie ich den DMA zurücksetzen bzw. löschen kann. Habe dazu jetzt auch ein ansatz. Sollte dieser funktionieren werde ich meine Lößung posten. Ein letzter Satz zur Sinhaftigkeit der Nutzung eines DMA zur übertragung einer festen Frame-länge: Angenommen bei 100000 übertragungen treten 10 Fehler auf. In diesem Fall muss der µC 10x den Fehler (wie auch immer) behandeln. Bei den restlichen 99990 übertragungen hat der µC keine zusätzliche Arbeit und das Datenframe kann direkt verarbeitet werden. Lohnt sich aus meiner Sicht also auf jeden Fall. Grüße
Ps. Außerdem die alten bewährten Methoden (auf Terminierendes zeichen im rxIr zu warten)werden irgendwann ja langweilig ;)
Nico schrieb: > Mir ging es lediglich darum zu erfahren, ob und wie ich den DMA > zurücksetzen bzw. löschen kann. Habe dazu jetzt auch ein ansatz. Sollte > dieser funktionieren werde ich meine Lößung posten. Siehe: aSma>> schrieb: > Datum: 14.04.2016 14:58 Nico schrieb: > Außerdem die alten bewährten Methoden (auf Terminierendes zeichen im > rxIr zu warten)werden irgendwann ja langweilig ;) Hauptsache du hast nur einen Bruchteil von der Diskussion wahrgenommen. mfg
>Bei den >restlichen 99990 übertragungen hat der µC keine zusätzliche Arbeit stimmt nicht. Der Frame muss immer auf Korrektheit geprüft werden. Das geht norm. nicht ganz ohne CPU. Und eine DMA muss auch nicht "ausser Tritt" kommen, wenn ein Übertragungsfehler (auf der Übertragunsstrecke) aufgetreten ist. Lediglich der gesamte Frame enthält dann Fehler (was ja später kontrolliert wird). Wenn man schon nach jeder einzelnen Teilübertragung eine Fehler-Überprüfung machen wollte, wäre die Nutzung von DMA unnötig und umständlich.
Nico schrieb: > Ein letzter Satz zur Sinhaftigkeit der Nutzung eines DMA zur übertragung > einer festen Frame-länge: > Angenommen bei 100000 übertragungen treten 10 Fehler auf. In diesem Fall > muss der µC 10x den Fehler (wie auch immer) behandeln. Bei den > restlichen 99990 übertragungen hat der µC keine zusätzliche Arbeit und > das Datenframe kann direkt verarbeitet werden. Lohnt sich aus meiner > Sicht also auf jeden Fall. Ich verstehe dein Argument nicht. Also, du hast per DMA 99990 fehlerfreie Übertragungen gemacht, nun steht der Kram im RAM und dann? Was dann? Braucht es zur weiteren Verarbeitung keine CPU? Nee, die CPU-Leistung ist immer gefordert, weil es ja keinerlei Vorteile bringt, die Daten erstmal vom UART in den RAM zu befördern und sich dabei zu denken "hach, was hab ich jetzt die CPU entlastet". Anschließend muß die CPU den Kram aus dem RAM holen anstatt aus dem Empfangsregister des UART und weiterverarbeiten - wo ist da der Entlastungseffekt? Ich seh da eher das Gegenteil: du mußt dich nicht nur um den UART kümmern, sondern obendrein noch um die DMA. Oder setzt die sich selbst auf? W.S.
>Anschließend muß die CPU den Kram aus dem RAM holen anstatt aus dem >Empfangsregister des UART und weiterverarbeiten - wo ist da der >Entlastungseffekt? Mit DMA kann die CPU Daten "in einem Rutsch" in den DMA-Puffer schreiben oder daraus lesen. Ohne DMA müsste die CPU ggfs bereits nach jedem Byte, Wort usw (je nach FIFO-Tiefe) tätig werden; was ein riessen Unterschied ist. Allerdings ist es oft so, dass -je nach Architektur- bei aktiver DMA der CPU Cyclen "gestohlen" werden.
MCUA schrieb: > Mit DMA kann die CPU Daten "in einem Rutsch" in den DMA-Puffer schreiben > oder daraus lesen. Ohne DMA müsste die CPU ggfs bereits nach jedem Byte, > Wort usw (je nach FIFO-Tiefe) tätig werden; was ein riessen Unterschied > ist. Du schreibst wirr. Entweder die CPU bewegt die Daten oder die DMA. Aber verarbeitet werden sie immer nur per CPU. Und nochwas: selbst bei 115000 Baud kommen die Byte mit nur so etwa 10 kHz hereingerauscht. Das ist grottenlangsam im Vergleich zu dem, was ein heutiger µC so drauf hat. Das Begrenzende ist tatsächlich das Weiterverarbeiten und nicht der Empfang nebs Puffern. W.S.
Hi Nico, Nico schrieb: > Die Frage ist nun, wie ich den DMA-Stream "Löschen" bzw zurücksetzen > kann, damit dieser bei einem fehlerhaften Frame wieder die Daten an die > richtige Stelle schreibt. ich habe gerade die gleiche Aufgabe. Für's Senden ist DMA wirklich problemlos. Beim Empfangen kommst Du dann eigentlich nicht um ein Timeout herum (HAL_UART_DMAStop). Wenn Du Daten zyklisch bekommen würdest und mit der Latenz von einem Packet leben könntest, dann könntest Du auf den Timer verzichten und müsstest die empfangenen Daten nur prüfen und defekte entsprechen verwerfen. mfg Torsten
>Du schreibst wirr. Wer hat denn das hier >Anschließend muß die CPU den Kram aus dem RAM holen anstatt aus dem >Empfangsregister des UART und weiterverarbeiten - wo ist da der >Entlastungseffekt? geschrieben? >Entweder die CPU bewegt die Daten oder die DMA. Muss nicht. Es kann sein, dass die CPU zuerst (an einem(!)) Daten zum DMA-Puffer schreibt, und der transferiert es dann weiter (dann ohne CPU). Ausserdem düfte jedem hier klar sein, dass CPU Und DMA Daten bewegen. Scheinbar kennst du die Vorteile (*) von DMA nicht, sonst hättest du das so nicht geschrieben. (*)theoretische und praktische unterscheiden sich, wie schon erwähnt
>Das Begrenzende ist tatsächlich das >Weiterverarbeiten und nicht der Empfang nebs Puffern. Doch. Bei höheren Bitraten wäre das Begrenzende definitv die CPU(-Last), weil die nach jedem Byte/Wort tätig werden müsste.
W.S. schrieb: > Das Begrenzende ist tatsächlich das > Weiterverarbeiten und nicht der Empfang nebs Puffern. ISR ist nicht gratis. Für jedes Zeichen ISR enter/leave machen summiert sich, MCU braucht u.U. auch mehr Strom bzw. muss jedesmal aus Sleep aufwachen. Bei DMA-Empfang gibts nur einen ISR-Aufruf bei Ende und/oder Timeout. Torsten R. schrieb: > Wenn Du Daten zyklisch bekommen würdest und mit der Latenz von einem > Packet leben könntest, dann könntest Du auf den Timer verzichten und > müsstest die empfangenen Daten nur prüfen und defekte entsprechen > verwerfen. Timeout-Interrupt (RTOF) des UARTS verwenden (so vorhanden).
Robert S. schrieb: > Timeout-Interrupt (RTOF) des UARTS verwenden (so vorhanden). Super Tipp :-) :
1 | RTOEN:Receivertimeoutenable |
2 | ...
|
3 | 1: Receiver timeout feature enabled. |
4 | |
5 | When this feature is enabled, the RTOF flag in the USARTx_ISR register is set if the RX line is idle (no reception) for the duration programmed in the RTOR (receiver timeout register). |
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.
