Hallo Leute, hat schon irgendwer einen Ringpuffer gebaut, der über USART Daten empfängt und per DMA in den Puffer schreibt? Oder denke ich gar zu kompliziert? Meine Idee war erst wie folgt: Ich erstelle einen Puffer. Sagen wir mal 100 Bytes. Dann konfiguriere ich einen DMA-Kanal so, dass er byteweise vom USART.DATA-Register inkrementell in den Puffer schreibt. Am Anfang sage ich dem DMA, dass er 100 Bytes transferieren darf. Wenn jetzt Bytes über den USART rein kommen, dann transferiert der DMA diese automatisch nach und nach in den Puffer. Ich hab's zwar bisher so noch nicht ausprobiert, sollte aber klappen. Das Problem ist jetzt, dass ich in der Zeit, in der so nach und nach die Bytes eintrudeln, nicht weiß wie weit der Puffer schon gefüllt ist. Das heißt ich bekomme erst einen Interrupt vom DMA ausgelöst, wenn die 100 Bytes komplett voll sind. Da die Befehle, die rein kommen, aber meistens nur wenige Bytes lang sind, ist das recht unpraktisch. Jetzt könnte ich ja den Puffer klein genug machen, sodass der Interrupt öfter ausgelöst wird, aber da stellt sich mir dann die Frage, ob ich den DMA überhaupt noch brauche. Das heißt da könnte ich gleich auf den Received-Interrupt vom USART reagieren und DMA ganz lassen. Was meint ihr? Ich frage deswegen, weil ich nicht das Rad neu erfinden möchte und ich bisher nur eine fertige Ringpuffer-Implementierung in die andere Richtung gefunden habe. Also Puffer -> DMA -> Usart transmit. In die Richtung macht es auch viel mehr Sinn, finde ich.
Ringpuffer gibts fertig bei ebay: http://www.ebay.de/itm/Vibrationsdaempfer-Ringpuffer-Set-3-Stueck-passend-fuer-Stihl-MS260-026-/251481979382 SCNR ;)
@Nicolas G. (ntq) >Ich erstelle einen Puffer. Sagen wir mal 100 Bytes. >Dann konfiguriere ich einen DMA-Kanal so, dass er byteweise vom >USART.DATA-Register inkrementell in den Puffer schreibt. Am Anfang sage >ich dem DMA, dass er 100 Bytes transferieren darf. Zuviel. Nimm lieber 10x10 oder so. >Das Problem ist jetzt, dass ich in der Zeit, in der so nach und nach die >Bytes eintrudeln, nicht weiß wie weit der Puffer schon gefüllt ist. Das >heißt ich bekomme erst einen Interrupt vom DMA ausgelöst, wenn die 100 >Bytes komplett voll sind. Jo. Aber danach kannst du dem DMA sagen, wieviel Bytes er bis zum nächsten Interrupt schreiben darf. Das kann man aus der Anzahl Bytes im FIFO berechnen. >Da die Befehle, die rein kommen, aber meistens nur wenige Bytes lang >sind, ist das recht unpraktisch. Jetzt könnte ich ja den Puffer klein >genug machen, sodass der Interrupt öfter ausgelöst wird, Den Puffer nicht, aber die DMA-Größe. >aber da stellt >sich mir dann die Frage, ob ich den DMA überhaupt noch brauche. Das >heißt da könnte ich gleich auf den Received-Interrupt vom USART >reagieren und DMA ganz lassen. Sicher. DMA braucht man nur, wenn man höchste Baudraten mit maximaler Perfomance verarbeiten muss. Im "Handbetrieb" per Interrupt und CPU schaufelt so ein AVR immer noch eine beachtliche Menge. Schau dir die diversen DMX512 Projekte an, dort werden 250kbaud gefahren und bei gescheiter Programmierung ist immer nocht massig CPU-Leistung verfügbar. >Was meint ihr? >Ich frage deswegen, weil ich nicht das Rad neu erfinden möchte und ich >bisher nur eine fertige Ringpuffer-Implementierung in die andere >Richtung gefunden habe. Also Puffer -> DMA -> Usart transmit. In die >Richtung macht es auch viel mehr Sinn, finde ich. Jo. RX geht aber auch. Siehe oben. MFG Falk
Die Verwendung des normalen Usart Receive Interrupts ist meist besser als die entsprechende DMA Variante (im Gegensatz zum Transmit). Man spart den Pufferspeicher, ggf. Aufwand zur Extraktion gesuchter Daten daraus, vor allem aber kann man im Usart-Interrupt gleich in "Echtzeit" auf gesuchte Daten reagieren bzw. diese sofort verwerfen.
Falk Brunner schrieb: >>Das Problem ist jetzt, dass ich in der Zeit, in der so nach und nach die >>Bytes eintrudeln, nicht weiß wie weit der Puffer schon gefüllt ist. Das >>heißt ich bekomme erst einen Interrupt vom DMA ausgelöst, wenn die 100 >>Bytes komplett voll sind. > > Jo. Aber danach kannst du dem DMA sagen, wieviel Bytes er bis zum > nächsten Interrupt schreiben darf. Das kann man aus der Anzahl Bytes im > FIFO berechnen. > >>Da die Befehle, die rein kommen, aber meistens nur wenige Bytes lang >>sind, ist das recht unpraktisch. Jetzt könnte ich ja den Puffer klein >>genug machen, sodass der Interrupt öfter ausgelöst wird, > > Den Puffer nicht, aber die DMA-Größe. Achso, logisch. Ich könnte den Puffer bei 100 Bytes lassen, aber dem DMA sagen, dass er immer nur 10 Bytes oder weniger übertragen soll. Dann bekomme ich alle 10 Bytes einen Interrupt und kann dann den writeIndex aktualisieren, sodass die receiveBuffer-Methode beim nächsten Aufruf weiß, dass was neues drin ist. Klar. So mach ich es. Ich muss dann nur mein Protokoll auf der PC-Seite etwas anpassen, sodass ein Datenchunk immer genau 10 Bytes oder ein Vielfaches davon groß sein muss, auch wenn mal nur weniger übertragen werden müsste. Das reicht mir aber vollkommen.
@ Nicolas G. (ntq) >Klar. So mach ich es. Ich muss dann nur mein Protokoll auf der PC-Seite >etwas anpassen, sodass ein Datenchunk immer genau 10 Bytes oder ein >Vielfaches davon groß sein muss, auch wenn mal nur weniger übertragen >werden müsste. Nein, das musst du nicht. Der RX DMA kann beliebig "dumm" die Daten in den FIFO schreiben. Nur deine Auswertung muss halt ab und annmal schauen, wieviele Daten im FIFO sind und dann etnsprechend reagieren.
Falk Brunner schrieb: > Nur deine Auswertung muss halt ab und annmal > schauen, wieviele Daten im FIFO sind und dann etnsprechend reagieren. Woran sehe ich weit ein bestimmter DMA-Kanal bereits geschrieben hat? Ändert sich DMA.CHx.DESTADDR während eines Schreibvorgangs? Das hab ich noch nie ausprobiert? Sorry, falls ich mich jetzt etwas dumm anstelle. :/
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.