Forum: Mikrocontroller und Digitale Elektronik Suche fertigen Ringpuffer für USART-Receive über DMA auf XMega


von Nicolas G. (Gast)


Lesenswert?

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.

von Detlef K. (adenin)


Lesenswert?


von Falk B. (falk)


Lesenswert?

@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

von Moby (Gast)


Lesenswert?

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.

von Nicolas G. (Gast)


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

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

von Nicolas G. (Gast)


Lesenswert?

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

von Falk B. (falk)


Lesenswert?

Kann sein, keine Ahnung.

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.