hallo, ich habe einen stm32f103 und möchte gerne den DMA als FIFO einsetzen. der DMA funktioniert soweit, aber wie kann ich daraus einen FIFO machen?
Peter schrieb: > DMA funktioniert soweit, aber wie kann ich daraus einen FIFO machen? Hmmm, was meinst Du damit? Du willst verschiedene Anforderungen (Transferanforderungen, Kopiere Speicher von A nach B) FIFO (first in First out) in den DMA reinstecken? Dann brauchst Du eine linked list in die Du die Anforderungen auf der einen Seite reinsteckst und auf der anderen Seite wieder rausholst (ist in SW zu lösen) und dann den Inhalt der jeweils elektierten Elements in die DMA reinschiebst. Oder doch was anderes? rgds
ne ich möchte die bytes welche ich über die usart empfange im fifo zwischenspeichern und später auslesen
Peter schrieb: > ne ich möchte die bytes welche ich über die usart empfange im fifo > zwischenspeichern und später auslesen Die Zeichen der USART kommen, wenn die FIFI enabled wird, automatisch in die FIFO. Die löst normalerweise bei einer einstellbaren Schwellwertmarke (z.B. halbe Füllung) einen Interrupt oder DMA aus. Wie Du dann weitermachst ist klar: entweder mit DMA die Zeichen aus der FIFO in einen Transferbuffer (Ringpuffer) übertragen lassen wobei Du den DMA dann immer richtig nachführen musst (Wohin das letzte Zeichen gegangen ist dorthin+1 muss der nächste DMA gehen). Oder Du machst das mit Interrupt und überträgst den FIFO-Inhalt normal in den Ringpuffer. Das Nachführen der Zieladresse ist auch in diesem Fall nötig. Empfehlung: FIFO Verständnis vertiefen, DMA Verständnis vertiefen. Weitere Fragen? rgds
ich würde halt gerne das FIFO in gewissen zeitabständen auslesen, also über timer interrupt gesteuert. da ich unterschiedlich viele Bytes pro telegramm empfangen möchte und ich somit keinen interrupt bei halber Füllung oder so auslösen kann
Peter schrieb: > ich würde halt gerne das FIFO in gewissen zeitabständen auslesen, also > über timer interrupt gesteuert. da ich unterschiedlich viele Bytes pro > telegramm empfangen möchte und ich somit keinen interrupt bei halber > Füllung oder so auslösen kann Aber Du kannst Doch einen Interrupt vom Timer auslösen lassen und dann einfach aus der Fifio rauslesen bis die leer ist. Wo ist das Problem? Und wie soll das mit dem DMA in Verbindung zu bringen sein? rgds
Peter schrieb: > der dma muss ja als fifo arbeiten. der stm32f10x hat ja sonst kein fifo Das nennt sich Puffer und nicht FIFO!
FIFO ist doch nur die Zugriffsart auf einen Puffer, oder sehe ich da was Falsch? Der DMA Puffer muss als FIFO funktionieren, sond kämen ja alle Daten durcheinander.
ich will eben die schnittstelle übern timerinterrupt einlesen und damit ich höhere übertragungsraten machen kann und nicht immer im timer interrupt hängen möchte sollen die bytes im dma zwischengespeichert werden. also ich schaue im timer interrupt ob daten im dma sind und lese die dann aus
Peter schrieb: > ich will eben die schnittstelle übern timerinterrupt einlesen und damit > ich höhere übertragungsraten machen kann und nicht immer im timer > interrupt hängen möchte sollen die bytes im dma zwischengespeichert > werden. also ich schaue im timer interrupt ob daten im dma sind und lese > die dann aus Hallo Peter, bitte belies Dich UNBEDINGT über die Funktionsweise des DMA und der FIFO. a) FIFO ist ein Speicher/eine Registerkette die einen Eingang und einen Ausgang hat und die FirstInFirstOut betrieben wird - daher der Name. b)DMA ist eine Controller der in der Lage ist auf eine Anforderung oder ein Startsignal hin automatisch Speicherbereiche zu kopieren. Im DMA-Controller hast Du Register um den automatischen Speichertransfer einzustellen (woher, wohin, wie lange, automatische Inkrementierung, ...). Da kannst Du NICHTS zwischenspeichern. In der FIFO der Schnittstelle - siehe oben - landen bei entspechender Einstellung die empfangenen Daten automatisch. Das ist wie in Rohr in das man Bälle reinsteckt: der Ball der zuerst reinkam kommt zuerst wieder raus (wenn man ihr rauslässt). rgds
Peter schrieb: > Und wie kann ich das fifo beim stm 32 f 10x programmieren? RTFM Wenn Du die Peripheral Lib verwendest ist das relativ einfach. Siehe auch dort. rgds
6A66 schrieb: > RTFM > Wenn Du die Peripheral Lib verwendest ist das relativ einfach. Siehe > auch dort. also in der Ref manual kann ich nix von einem FIFO für den USART finden
Peter schrieb: > also in der Ref manual kann ich nix von einem FIFO für den USART finden Hallo Peter, wenn der Baustein keinen FIFO an der USART hat, bleibt Dir nur die SW-Implementierung dieser FIFO (meist als Ringpuffer, ist keine Weltraumphysik aber auch nicht trivial: Zwei Pointer, einer ist nächstes Ausgabeelement und einer ist letztes Eingabelement). Dann kannst Du auch mit dem DMA (bei entsprechnder Programmierung) die Daten in Deinen Puffer übertragen lassen. rgds
6A66 schrieb: > wenn der Baustein keinen FIFO an der USART hat, bleibt Dir nur die > SW-Implementierung dieser FIFO (meist als Ringpuffer, ist keine > Weltraumphysik aber auch nicht trivial: Zwei Pointer, einer ist nächstes > Ausgabeelement und einer ist letztes Eingabelement). Dann kannst Du auch > mit dem DMA (bei entsprechnder Programmierung) die Daten in Deinen > Puffer übertragen lassen. ja genau, und genau das möchte ich mit dem DMA machen, was aber nicht funktioniert. mit der zeit bekomm ich nämlich nen fehle das er im HardFault_Handler fest hängt
Peter schrieb: > ja genau, und genau das möchte ich mit dem DMA machen, was aber nicht > funktioniert. mit der zeit bekomm ich nämlich nen fehle das er im > HardFault_Handler fest hängt Hallo Peter, Peter schrieb: > ich habe einen stm32f103 und möchte gerne den DMA als FIFO einsetzen. > der DMA funktioniert soweit, aber wie kann ich daraus einen FIFO machen? Zwischen dem was Du ursprünglich sagtest und dem was Du jetzt sagst sind aber große Unterschiede - sei's drum. Bei Fehlern hilft da nur: systematisches Debugging. Ein allgemeines Rezept zur Umsetzung von Ringpufferen gib's nicht. Vielleicht hilft es ja, dass Du Dein Konzept einmal versuchst auf's Papier zu bringen und darlegts. Dann müssen wir hier nicht raten. rgds
Von der DMA erhältst du ja eine der beiden Zeiger (letztes Eingabelement) und den anderen (nächstes Ausgabeelement) musst du ja sowieso in deiner Ausgabefunktion haben.
also ich rufe im timer interrupt eine Funktion auf mit folgendem Inhalt: if(DMA1_Channel5->CNDTR != USART1_BUFFER_GROESSE) { bWritePtrUsart1DMA = USART1_BUFFER_GROESSE - DMA1_Channel5->CNDTR; while((bWritePtrUsart1DMA != bReadPtrUsart1DMA)) { read_buffer1[bWritePtr1++] = USART1_DMA_RxBuffer[bReadPtrUsart1DMA++]; if(bWritePtr1 > USART1_BUFFER_GROESSE) { bWritePtr1 = 0; bReadPtrUsart1DMA = 0; } } DMA_SetCurrDataCounter(DMA1_Channel5, USART1_BUFFER_GROESSE); } hierbei schau ich mit der if bedingung ob zeichen im dma stehen, wenn ja lese ich die zeichen aus dem dma in ein array (read_buffer1). in einer weiteren Funktion die die Telegramme auswertet vergleiche ich den bWritePtr1 mit einem bReadPtr1, um zu sehen ob neue zeichen in read_buffer1 sind
Peter schrieb: > if(DMA1_Channel5->CNDTR != USART1_BUFFER_GROESSE) > { > bWritePtrUsart1DMA = USART1_BUFFER_GROESSE - DMA1_Channel5->CNDTR; > while((bWritePtrUsart1DMA != bReadPtrUsart1DMA)) > { > read_buffer1[bWritePtr1++] = > USART1_DMA_RxBuffer[bReadPtrUsart1DMA++]; > if(bWritePtr1 > USART1_BUFFER_GROESSE) > { > bWritePtr1 = 0; > bReadPtrUsart1DMA = 0; > } > } > DMA_SetCurrDataCounter(DMA1_Channel5, USART1_BUFFER_GROESSE); > } Hallo Peter, das ist jetzt aber kein Konzept sondern nur ein Codeschnipsel. Da müsste ich jetzt mal annehmen: USART1_BUFFER_GROESSE = die maximale Buffergröße für den USART Buffer. Wenn dem so ist würde deine erste if-Bedingung if(DMA1_Channel5->CNDTR != USART1_BUFFER_GROESSE) mitnichten das machen was Du wünschst: hierbei schau ich mit der if bedingung ob zeichen im dma stehen. Denn in CNDTR steht nach Datenblatt "Number of Data to be transferred" und die wird nach jedem Transfer geringer. rgds
6A66 schrieb: > Denn in CNDTR steht nach Datenblatt "Number of Data to be transferred" > und die wird nach jedem Transfer geringer. ja, und wenn der CNDTR ungleich der maximalen Buffer größe ist dann befinden sich ja zeichen im dma, die lese ich dann alle ein und setze den CNDTR zurück auf die maximale buffer größe
Peter schrieb: > ja, und wenn der CNDTR ungleich der maximalen Buffer größe ist dann > befinden sich ja zeichen im dma, die lese ich dann alle ein und setze > den CNDTR zurück auf die maximale buffer größe Und woher soll man das wissen? rgds
Peter schrieb: > woher soll man was wissen? Sorry, war gerade gedanklich in anderem Thread. Wenn ich Deinen Code richtig verstehe (Alles Annahmen da Du ja bisher nicht mehr zu Variablen sagst und auch vom Code nicht mehr zeigst) versuchst Du nachdem der DMA Transfer den Wert(die Werte) in den "USART1_DMA_RxBuffer" eingetragen hat diese in eine zweiten Puffer "read_buffer1" umzukopieren. Warum bearbeitest Du nicht den DMA_RxBuffer direkt? Wie kommt beim Überlauf "bWritePtr1 > USART1_BUFFER_GROESSE" die korrekten daten in den DMA? Ich schlage vor - um uns hier nicht weiter im Trüben fischen zu lassen - Dir DEIN Konzept selbst mal aufzuzeichnen und zu analysieren und uns dran teilhaben zu lassen bevor wir hier Codeschnipsel mit der Glaskugel analysieren. rgds
6A66 schrieb: > Peter schrieb: >> woher soll man was wissen? > > Sorry, war gerade gedanklich in anderem Thread. > > Wenn ich Deinen Code richtig verstehe (Alles Annahmen da Du ja bisher > nicht mehr zu Variablen sagst und auch vom Code nicht mehr zeigst) > versuchst Du nachdem der DMA Transfer den Wert(die Werte) in den > "USART1_DMA_RxBuffer" eingetragen hat diese in eine zweiten Puffer > "read_buffer1" umzukopieren. Warum bearbeitest Du nicht den DMA_RxBuffer > direkt? > Wie kommt beim Überlauf "bWritePtr1 > USART1_BUFFER_GROESSE" die > korrekten daten in den DMA? > > Ich schlage vor - um uns hier nicht weiter im Trüben fischen zu lassen - > Dir DEIN Konzept selbst mal aufzuzeichnen und zu analysieren und uns > dran teilhaben zu lassen bevor wir hier Codeschnipsel mit der Glaskugel > analysieren. > > rgds meine Auswertung arbeitet mit dem read_buffer1, sowie der Interrupt. also man kann die Schnittstelle per Interrupt oder per DMA arbeiten lassen, muss halt in der Software ein define entsprechend setzen. deswegen kopiere ich den DMA Buffer in den anderen um. > Wie kommt beim Überlauf "bWritePtr1 > USART1_BUFFER_GROESSE" die > korrekten daten in den DMA? Das wäre nicht gegangen, aber ich hätte einen Fehler verhindert. dieser Code Teile habe ich aber inzwischen auskommentiert. ich schau jetzt regelmäßig den Write und Read Pointer an und wenn diese gleich sind, weis ich das alle empfangenen bytes ausgewertet sind und ich kann sie ohne Datenverlust zu 0 setzen. das war vorher mein problem das die Pointer irgendwann mal außerhalb des buffers standen und dann ging gar nichts mehr. Also die Kommunikation über DMA läuft jetzt so ab, das die Schnittstelle die empfanenen Bytes in den DMA schreibt und über den Timer interrupt schaue ich alle 5ms nach ob Zeichen im DMA stehen und wenn ja kopiere ich diese in den anderen Buffer. wenn keine zeichen im DMA stehen und die zwei Pointer (Read/Write) gleich sind, dann setze ich diese zu 0. Ich muss halt momentan gewährleisten das der DMA die größe der maximalen Telegramlänge hat. Ob ein großer DMA irgendwelche andere negative folgen hat weis ich noch nicht, vlt kannst du mir da nochmal helfen? danke
Peter schrieb: > Schnittstelle > die empfanenen Bytes in den DMA schreibt Die Schnittstelle schreibt garnichts! Der DMA-Controller schreibt die Daten in den Puffer! Nochmals: Der DMA Controller ist nichts anderes als ein kleiner "Prozessor" dem man sagt er solle auf Anforderung N Bytes von A nach B (Puffer) kopieren! Peter schrieb: > ob Zeichen im DMA stehen Es stehen keine Zeichen Im DMA sondern höchstens im Puffer den der DMA bedient.
ja entschuldigung für die falsche ausdrucksweise, aber du weist ja was ich meine
Hallo Peter, warum machst Du das überhaupt mit DMA. Ich denke mal dass das mit Interrupt einfacher ist. Jedesmal wenn ein Zeichen ankommt dieses in den Puffer kopieren. Wenn Telegrammende erkannt (z.B. CRLF oder NULL) ein Signal absetzen und Verabreitung beginnen. Wenn Du unbekannte Länge hast musst Du ja den DMA immer auf maximale Telegrammlänge aufziehen und dann trotzdem hinterherlaufen und prüfen ob das Ende erreicht ist. rgds
der stm32 hat ja noch andere dinge zu tun als die schnittstelle. bei hohen baudraten würde er ja viel in dem schnittstelleninterrupt hängen. mit dem DMA wird quasi das empfangen ausgelagert und nur hin und wieder geschaut, ob der dma was empfangen hat und diese zeichen dann ausgewertet.
Peter schrieb: > der stm32 hat ja noch andere dinge zu tun als die schnittstelle. bei > hohen baudraten würde er ja viel in dem schnittstelleninterrupt hängen. Also: 110kbaud ist alle 8us ein bit, ist alle 80..100us ein Zeichen. Das ist ja noch langsam. Bei einer Interuptroutine die nur ein Zeichen umkopiert kommt man bei 64MHz sicher bei 1..2us hin. Sind 1-2%. rgds
Also empfangen ich kann mit einem STM8 (8-bitter mit 16MHz) mit "normaler" ISR mit 187,5k problemlos. Und in der ISR habe ich eine State-Machine drin um ein Protokoll zu erkennen, nicht nur ein einfaches "Zeichenkopiere". Ansonsten läuft ein kleines Menü im Display, LED-Anzeige, ... .. wie gesagt problemlos!
6A66 schrieb: > Also: 110kbaud ist alle 8us ein bit, ist alle 80..100us ein Zeichen. Das > ist ja noch langsam. Bei einer Interuptroutine die nur ein Zeichen > umkopiert kommt man bei 64MHz sicher bei 1..2us hin. Sind 1-2%. Das soll jetzt nicht heißen dass DMA nicht nützlich ist. Im Gegenteil. Ich habe damit schon - unabhängig von der CPU die dann eben ganz andere Aufgaben macht - über die angeschlossene Peripherie nette Dinge nach Aussen erledigt. rgds
ich empfang ja nicht nur ein zeichen sondern zwischen 8 bytes und 260 bytes. da ist es doch sinnvoll wenn der dma es empfängt und ich nachher nur noch kopieren muss
Peter schrieb: > ich empfang ja nicht nur ein zeichen sondern zwischen 8 bytes und 260 > bytes. da ist es doch sinnvoll wenn der dma es empfängt und ich nachher > nur noch kopieren muss Mach es wie Du es für sinnvoll erachtest. rgds
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.