Forum: Mikrocontroller und Digitale Elektronik Erfahrungen XMega und DMA-Timing (192A3)


von Markus M. (adrock)


Lesenswert?

Hi,

ich kämpfe immernoch mit meinem Xmega 192A3 und dem DMA :-)

Ich möchte in relativ kurzen Abständen das CCABUF Registers des Timers 
neu setzen, um das PWM-Tastverhältnis zu ändern.

Der Timer läuft mit einer Frequenz von 800 KHz, der Controller mit 32 
MHz.

Um auch während der DMA neue Daten berechnen zu können, nutze ich den 
Double-Buffering Modus mit CH0 + CH1.

Momentan triggere ich den DMA-Transfer eines neuen Wertes in das CCABUF 
Register gleichzeitig mit dem Compare-Match TCC0_CCA.

Der höchste Compare-Wert den ich habe ist 0x19 bei einer Periodenlänge 
von 0x27. D.h. der DMA-Controller hätte eigentlich 14 Taktzyklen Zeit, 
um den neuen Wert in den CCABUF zu schreiben.

Wenn die CPU ansonsten nix macht und einfach in einer Endlosschelife 
läuft sieht das auch alles sehr gut aus und funktioniert problemlos.

Unter besonderen Bedingungen (in diesem Fall wenn gerade eine 
Interrupt-Routine mit RETI beendet wird) scheint er es aber nicht 
rechtzeitig zu schaffen bevor der Counter neu geladen wird und der 
vorherige Wert wird erneut verwendet.

Darum nun die Frage:

Ist irgendwo das Timing des DMA-Controllers etwas genauer spezifiziert? 
Also wieviel Zyklen er worst case benötigt um eine Aktion von z.B. SRAM 
-> I/O bei einem Trigger durch I/O abzuschliessen? Bzw. WANN er 
überhaupt an die Reihe kommt...

Ich kann es mir nur so erklären, dass durch den RETI die CPU mehr Zyklen 
abbekommt und der DMA warten muss...

Nichtsdestotrotz werde ich wohl meinen Trigger so umbauen, dass der neue 
Wert in den Buffer im Anfang eines neuen PWM-Zyklus geladen wird, DAS 
soltle der faule DMA-Controller dann wohl schaffen...

Grüße
Markus

von Markus M. (adrock)


Lesenswert?

...achja, jetzt weiss ich wieder, warum ich es so machen musste...

Wenn man den DMA-Transfer auf einen Überlauf des Timers triggern würde, 
müsste man entweder den Counter oder das Periodenregister beschreiben, 
damit der Transfertrigger dann zurückgesetzt wird.

Und das tue ich ja nicht... ich beschreibe ja nur CCA(BUf)...

Irgendwie eine etwas dumme Konstruktion so... wie soll man damit das PWM 
vernünftig steuern? Das geht ja garnicht, was wäre wenn man z.B. von 
max. (CCA == PER) auf min. (CCA == 0) wechseln möchte... da hätte der 
DMA-Controller genau einen Zyklus Zeit... gut, das mag vielleicht 
funktionieren wenn man den Timer mit einem hohen Prescaler betreibt...

Grüße
Markus

von Markus M. (adrock)


Lesenswert?

Hmmm... es würde wohl mit dem Event-System gehen... ich muss über den 
Timerüberlauf ein Event generieren, welches dann den DMA-Controller dazu 
bringt ein Byte in das CCABUF zu schreiben...

Achja... einfach kann ja jeder :-)

Grüße
Markus

von Basti M. (counterfeiter)


Lesenswert?

Das Event System hat auch einen Takt Verzögerung...

Die Frage ist wie so oft: was zur Hölle hast du vor? ;)

von Markus M. (adrock)


Lesenswert?

...ich verwende das ganze Konstrukt um ein serielles Protokoll per DMA 
und PWM zu generieren. Um genau zu sein das Protokoll zur Ansteuerung 
der WS2812 LEDs.

Das kann man zwar auch mit anderen Mechanismen machen, aber ich möchte 
ja so wenig CPU-Zeit wie möglich verbrauchen.

Habe es mit dem Eventsystem jetzt hinbekommen den DMA-Transfer nach 
jedem Timerüberlauf zu triggern. Ein paar kleine Unstimmigkeiten sind 
noch zu beheben, aber ich denke so wird es funktionieren.

Den DMA Double-Buffer Modus haben sie aber echt mies dokumentiert :-( 
Z.B. ist garnicht erwähnt, dass man den Repeat-Mode zwingend aktivieren 
muss, und zwar jeweils für den DMA-Kanal der als nächstes an der Reihe 
ist.

Grüße
Markus

von Basti M. (counterfeiter)


Lesenswert?

Hm, klingt ziemlich umständlich...

Wie man die WS2812 LEDs mit sehr sehr geringer CPU Last ansteuert habe 
ich ja schon mal im Sammelbestellthread geschrieben:

1 Byte über USART im SPI Mode sind genau 2 Bit Farbdaten für WS2812. Das 
passt mit dem Timing sehr gut zusammen. Also einfach mit einer lookup 
table zwei Bit in 1 Byte wandeln und in einen Buffer schreiben (der muss 
natürlich um den Faktor 4 größer sein) und anschließend einfach mit DMA 
diesen Buffer versenden. In USART SPI lässt sich der Sendetakt ja sehr 
genau einstellen, damit erhält man spitzen Ergebnisse.

CPU freundlicher geht es meiner Meinung nach nicht ;)

Grüße

Basti

von Markus M. (adrock)


Lesenswert?

Hi,

das mit dem USART geht auch, stimmt schon. Fällt mir jetzt gerade nicht 
ein, warum ich das verworfen hatte :-) Ich glaube mir gefiel einfach, 
dass ich das Tastverhältnis "frei" einstellen kann bei PWM und die 
Routine zum erzeugen der Daten ist auch einfacher (Bit -> Byte). Spart 
zumindest ein paar Taktzyklen :-)

Aber DMA double buffering müsste man trotzdem machen, oder bereitest Du 
den Ausgabestrom für alle LEDs komplett vorher vor? Das kostet dann 
aber Speicher bei vielen LEDs.

Meine Ausgabe läuft jetzt, das eigentliche Ärgernis sind nicht die 
eigenen Fehler sondern die Unzulänglichkeiten sowohl in der Atmel Doku 
als auch vom Debugger (Debuggen von Interrupts funktioniert nur 
sporadisch...).

CPU-Belastung liegt so bei < 30% zur Vorbereitung der DMA-Daten 
jeweils... je größer der DMA-Buffer ist, umso mehr Daten können im Stück 
vorbereitet werden und desto effizienter...

Werde für die Nachwelt den Source demnächst hier irgendwo mal 
hinstellen...

Grüße
Markus

von Fabian F. (folfy)


Angehängte Dateien:

Lesenswert?

Hallo,

Für denn Fall dass auch andere über diesen Thread stolpert, teile ich 
hier gleich meine Erfahrungen:

Ich hatte ebenfalls ein xMega-Projekt (xmega64a4u), das eigentlich noch 
auf den einfacheren WS2801 zugeschnitten war.
Dort habe ich bereits Funktionen wie DMA-Datenausgabe auf SPI, 
Gamma-Korrektur, und 2-8x Oversampling (für bessere Farbauflösung und 
feinere Helligkeitsregelung) eingebaut.
Das Projekt ist derzeit noch in Arbeit, aber wer es sich trotzdem 
ansehen möchte, findet es unter https://github.com/folfy/tinylight/.

Nun bin ich auch vor der Aufgabe gestanden, das ganze für den WS2812 zu 
portieren.
Da ich kein einzige Taktzyklus der CPU dafür verschwenden wollte, habe 
ich auch auf einen Ansatz mit Timer gesetzt, der jedoch ausschließlich 
die Peripherie dafür nutzt:
- Datenausgabe auf ungenutztem SPI-Port
Per Event-System:
- Flanke am Clock startet den Timer für die Ausgabe eines WS2812-Bits
- Flanken am Daten-Pin triggert einen DMA-Channel, der alternierend den 
Zeit-Wert für "1" und "0" in das entsprechende Compare-Register des 
Timers schiebt

Wie ihr auch schon bemerkt habt, ist der xmega-DMA ist nicht gerade gut 
für zeitkritische Ereignisse geeignet. Lt. Datenblatt hat die CPU 
absolute Priorität, dementsprechend kann es schon mal dauern, bis der 
DMA zum Zug kommt. Ich wollte mich damit nicht zufrieden geben, und habe 
erst mal den Core von 32 auf 48MHz übertaktet.
Damit bekam ich dann schon halbwegs vertretbare Latenzzeiten, wie man 
dem angehängten Oszillogramm entnehmen kann (Dunkelblau = Trigger, 
Hellblau = DMA-Transaktion abgeschlossen).
Meinen Messungen zufolge braucht der DMA damit (in meinem Szenario) 
zwischen 0,25 bis 1,1 µs (~11-53 Cycles).
Damit liegt die Schwankungsbreite mit 0,85µs auch schon unter der 
Periodendauer von 1µs@1MHz (um noch etwas mehr Performance aus den LEDs 
zu holen, ggü. original 800kHz).
Und ja, man hätte die Daten bei 32MHz auch einfach langsamer übertragen 
können, aber wer will das schon?

Schlussendlich habe ich dann mit ein paar Tricks, wie Nutztung des Timer 
CC-Register Double-Bufferings und leicht verzögertem Start des Timers 
am Ende des Bytes, eine stabile HW-Echtzeitausgabe mit 1MHz 
hinbekommen ;)

Das ganze wird voraussichtlich in ein paar Wochen dann auch unter 
WS2812 Ansteuerung auffindbar sein!

Grüße
Fabian

von Dieter F. (Gast)


Lesenswert?

Fabian F. schrieb:
> Wie ihr auch schon bemerkt habt, ist der xmega-DMA ist nicht gerade gut
> für zeitkritische Ereignisse geeignet.

Ist mir wohl entgangen ...

Fabian F. schrieb:
> Lt. Datenblatt hat die CPU
> absolute Priorität, dementsprechend kann es schon mal dauern, bis der
> DMA zum Zug kommt.

Ja, da muss man die CPU halt ruhig halten.

Fabian F. schrieb:
> Ich wollte mich damit nicht zufrieden geben, und habe
> erst mal den Core von 32 auf 48MHz übertaktet.

Hat die CPU dann weniger Priorität?

Fabian F. schrieb:
> Meinen Messungen zufolge braucht der DMA damit (in meinem Szenario)
> zwischen 0,25 bis 1,1 µs (~11-53 Cycles).

Wie sieht denn Dein Szenario aus?

Fabian F. schrieb:
> Und ja, man hätte die Daten bei 32MHz auch einfach langsamer übertragen
> können, aber wer will das schon?

Wenn es ausreicht, wieso dann nicht?

Fabian F. schrieb:
> Schlussendlich habe ich dann mit ein paar Tricks, wie Nutztung des Timer
> CC-Register Double-Bufferings und leicht verzögertem Start des Timers
> am Ende des Bytes, eine stabile HW-Echtzeitausgabe mit 1MHz
> hinbekommen ;)

Kannst Du die auch bitte verraten?

von Fabian F. (folfy)


Lesenswert?

Dieter F. schrieb:
> Fabian F. schrieb:
>> Wie ihr auch schon bemerkt habt, ist der xmega-DMA ist nicht gerade gut
>> für zeitkritische Ereignisse geeignet.
>
> Ist mir wohl entgangen ...
>
> Fabian F. schrieb:
>> Lt. Datenblatt hat die CPU
>> absolute Priorität, dementsprechend kann es schon mal dauern, bis der
>> DMA zum Zug kommt.
>
> Ja, da muss man die CPU halt ruhig halten.

Wie der Ersteller des Threads schon erkannt hat, sind die Interrupts mit 
den PUSH/POPs eines der großen Probleme - die während des ganzen 
Transfers ruhig halten ist eher ein Schuss ins Knie ;)

80 LEDs x 24bit (RGB) x 50Hz x 4 (Oversampling) = 0,384 Mbit/s
-> Wäre bei einer Datenrate von 1Mbit also etwa 40% der Zeit!

>
> Fabian F. schrieb:
>> Ich wollte mich damit nicht zufrieden geben, und habe
>> erst mal den Core von 32 auf 48MHz übertaktet.
>
> Hat die CPU dann weniger Priorität?
>

Nein, aber der DMA hat mehr "Zeit", also in Clock-Zyklen gesprochen.
Die Problem-Ursache lässt sich nicht wirklich beheben:
Mehrere CPU<>Datenbus-Zugriffe ohne Pause blockieren den DMA, bis sie 
fertig sind. Es gibt keinen Round-Robin-Mode, Optionen zur 
Umpriorisierungen o.ä.

> Fabian F. schrieb:
>> Meinen Messungen zufolge braucht der DMA damit (in meinem Szenario)
>> zwischen 0,25 bis 1,1 µs (~11-53 Cycles).
>
> Wie sieht denn Dein Szenario aus?
>
Siehe github-Projekt: Daten kommen z.B. vom PC->Prismatik via 
onchip-USB, dann Gammakorrektur incl. Oversampling auf 9-11bit, 
Buffer geht via DMA zum SPI; 1000x4 ADC Samples pro sec für 
Messungen, IR, Bluetooth, NRF24L01 Funk und andere Features..

> Fabian F. schrieb:
>> Und ja, man hätte die Daten bei 32MHz auch einfach langsamer übertragen
>> können, aber wer will das schon?
>
> Wenn es ausreicht, wieso dann nicht?
>
Bei längeren Streifen kommt es dann mit Oversampling zu sichtbarem 
Flackern...

> Fabian F. schrieb:
>> Schlussendlich habe ich dann mit ein paar Tricks, wie Nutztung des Timer
>> CC-Register Double-Bufferings und leicht verzögertem Start des Timers
>> am Ende des Bytes, eine stabile HW-Echtzeitausgabe mit 1MHz
>> hinbekommen ;)
>
> Kannst Du die auch bitte verraten?

Das lässt sich ohne Grafik und Code nicht so verständlich erklären 
(folgt dann eben im Wiki wenn ich die Dokumentation für das Projekt 
fertig hab), aber ich versuch es:
- Eine Flanke auf SPI-Data triggert "sofort" (ohne Verzögerung) einen 
DMA-Transfer des Timer-Werts in das Puffer-Register des 
Capture/Compare-Channels.
- Die fallende Flanke des SPI-Clock (also am Ende des Zyklus, der neue 
Daten-Wert wird bereits auf SPI-Data gelegt) startet den Timer.
Da der DMA (inkl. Event-System ohne Verzögerung) >10 Cycles braucht, 
kann dies zusätzlich noch (per Event-System) leicht verzögert werden.
Der CC-Wert des Buffer-Registers wird dabei geladen, und die Daten 
werden quasi um 1 ganzen Daten-Zyklus verzögert ausgegben.

Damit bekommt man ein Zeifenster für den DMA, das nur minimal kleiner 
als ein Zyklus (hier 1µs / 48 Core-Cyles) ist.

: Bearbeitet durch User
von Dieter F. (Gast)


Lesenswert?

Fabian F. schrieb:
> Siehe github-Projekt: Daten kommen z.B. vom PC->Prismatik via
> onchip-USB, dann Gammakorrektur incl. Oversampling auf 9-11bit,
> Buffer geht via DMA zum SPI; 1000x4 ADC Samples pro sec für
> Messungen, IR, Bluetooth, NRF24L01 Funk und andere Features..

Ambitioniert ...

Fabian F. schrieb:
> Eine Flanke auf SPI-Data triggert "sofort" (ohne Verzögerung) einen
> DMA-Transfer des Timer-Werts in das Puffer-Register des
> Capture/Compare-Channels

"sofort" geht nicht - soweit mir bekannt - aber ich lasse mich gerne 
belehren.

Ich frage mich (und Dich), warum Du den ganzen "aufwändigen Kram" auf 
dem ATXMega verarbeiten willst. Du legst Dir damit doch selbst 
"Fallstricke", in welche Du immer wieder gerätst. Wenn Du sowieso einen 
PC zur Steuerung nutzt, dann lass den doch alle Berechnungen etc. 
durchführen. Funk, IR etc. kann auch ein "untergeordneter" Prozessor 
ausführen, welcher dann nur noch Netto-Daten per SPI (wenn Zeit ist) an 
den ATXMega sendet.

Interrupts sind bei zeitkritischen DMA-Prozessen kontra-produktiv. Wenn 
die mit Prolog und Epilog abgearbeitet werden verlierst Du jede Menge 
Zeit (Takte) und der DMA-Prozess wird unkontrolliert unterbrochen.

Ich würde immer eine komplette "Versorgung" des Stripes per DMA (ohne 
Unterbrechung etc.) "abhusten" und dann in der Zwangs-Pause die 
Kommunikation mit USB und dem Sklaven durchführen. In diesem Fall ist 
serialisieren - denke ich - besser den parallelisieren.

von Fabian F. (folfy)


Lesenswert?

Dieter F. schrieb:
> Fabian F. schrieb:
>> Siehe github-Projekt: Daten kommen z.B. vom PC->Prismatik via
>> onchip-USB, dann Gammakorrektur incl. Oversampling auf 9-11bit,
>> Buffer geht via DMA zum SPI; 1000x4 ADC Samples pro sec für
>> Messungen, IR, Bluetooth, NRF24L01 Funk und andere Features..
>
> Ambitioniert ...
>

Freizeitprojekt von mir und einem Freund als wir noch viel Zeit 
hatten...
Jetzt ist es zusätzlich ein FH-Projekt, womit dann halt die Erweiterung 
WS2812 und Umsetzung der damaligen NRF24L01-Idee kam. :P

> Fabian F. schrieb:
>> Eine Flanke auf SPI-Data triggert "sofort" (ohne Verzögerung) einen
>> DMA-Transfer des Timer-Werts in das Puffer-Register des
>> Capture/Compare-Channels
>
> "sofort" geht nicht - soweit mir bekannt - aber ich lasse mich gerne
> belehren.
>
Richtig, daher die Anführungszeichen, hätte allerdings ohne 
zusätzliche Verzögerung heißen sollen, hab ich übersehen (Event-Sys 
braucht glaub ich 2 Cycles vom Input bis getriggert wird).

> Ich frage mich (und Dich), warum Du den ganzen "aufwändigen Kram" auf
> dem ATXMega verarbeiten willst. Du legst Dir damit doch selbst
> "Fallstricke", in welche Du immer wieder gerätst. Wenn Du sowieso einen
> PC zur Steuerung nutzt, dann lass den doch alle Berechnungen etc.
> durchführen. Funk, IR etc. kann auch ein "untergeordneter" Prozessor
> ausführen, welcher dann nur noch Netto-Daten per SPI (wenn Zeit ist) an
> den ATXMega sendet.

Ganz einfach, weil der Controller einige Modi auch Standalone kann (war 
wie gesagt nur ein Beispiel).
Das Smartphone (Android) als Fernbedienung via BT müsste sonst z.B. auch 
konstant die Daten produzieren&aufbereiten, anstelle einfache Kommandos 
zu schicken (Akku...).
Das Board haben wir hardwareseitig minimal gehalten, um es klein und 
unauffällig zu machen (~3x5cm). Damals gab es auch keinen WS2811/2812.
Einen zusätzlichen ATtiny als Protokoll-Konverter (wesentlich billiger 
als einen xMega) kann man Notfalls immer in ein paar Stunden bauen und 
als Adapter zwischenschalten.

>
> Interrupts sind bei zeitkritischen DMA-Prozessen kontra-produktiv. Wenn
> die mit Prolog und Epilog abgearbeitet werden verlierst Du jede Menge
> Zeit (Takte) und der DMA-Prozess wird unkontrolliert unterbrochen.

Im Falle der xMega-Serie, ja leider (insbesondere unter Nutzung des ASF, 
da dort Interrupts immer den max. Overhead haben).

>
> Ich würde immer eine komplette "Versorgung" des Stripes per DMA (ohne
> Unterbrechung etc.) "abhusten" und dann in der Zwangs-Pause die
> Kommunikation mit USB und dem Sklaven durchführen. In diesem Fall ist
> serialisieren - denke ich - besser den parallelisieren.

Die Sendezeit um die allgemein benötigte Rechenzeit kürzen zu müssen, 
geht auch auf Kosten der LED-Datenrate.
Nachdem allgemein mehr zu tun ist (s.o.), wäre das wesentlich langsam 
(andere Probleme mal außer acht).

: Bearbeitet durch User
von Dieter F. (Gast)


Lesenswert?

Fabian F. schrieb:
> Das Smartphone (Android) als Fernbedienung via BT müsste sonst z.B. auch
> konstant die Daten produzieren&aufbereiten, anstelle einfache Kommandos
> zu schicken (Akku...).

Das Smartphone dürfte um ein vielfaches leistungsfähiger sein wie der 
ATXMega.

Fabian F. schrieb:
> insbesondere unter Nutzung des ASF,
> da dort Interrupts immer den max. Overhead haben

?Da sorgt sorgt doch der Compiler (GCC) für - und nicht ASF - oder?

Fabian F. schrieb:
> Die Sendezeit um die allgemein benötigte Rechenzeit kürzen zu müssen,
> geht auch auf Kosten der LED-Datenrate.
> Nachdem allgemein mehr zu tun ist (s.o.), wäre das wesentlich langsam
> (andere Probleme mal außer acht).

Da habe ich ein syntaktisch / semantisches Verständnisproblem :-(

Wenn ich mir die minimale/maximale Spezifikation des WS2812-Protokolls 
so anschaue wirst Du bei 32 MHz (Standard) wohl kaum großartige 
Interrupts während der "Versorgung" der LED ausführen können - oder 
täusche ich mich da?

Also bleiben Dir ohnehin nur die "Anzeige-Pausen".

Alternativ kannst Du natürlich eine deutlich schnellere CPU mit ggf. 
entkoppeltem DMA (ich kenne keine - aber ich habe auch nicht weiter 
rumgeschaut) nutzen.

von Basti (Gast)


Lesenswert?

Ich versteh nicht ganz, warum man das Protokoll nicht per SPI 
simuliert?? (wie alle anderen -> wahrscheinlich deswegen?)
Geht doch alles total bequem... und SPI hat einen Buffer und einen 
Takt... da macht es auch nichts, dass der DMA mal 20 CPU Takte später 
agiert...

Das Byte empfangen und anschließend mit einer Lookup auf 4 Byte 
aufzuweiten geht sehr schnell -> 1024 WS2812 LEDs kann ich flackerfrei 
bedienen.

Was soll das Oversampling bringen? Mit 1024 WS2812 bei 800 kHz ist man 
doch schon auf 25 Frames limitiert... wie klein soll die LED-Kette denn 
werden?

Hmm... klingt akademisch, aber wenig nach Praxis...

von Dieter F. (Gast)


Lesenswert?

Basti schrieb:
> Ich versteh nicht ganz, warum man das Protokoll nicht per SPI
> simuliert??

Hmm - das verstehe ich nicht (doof wie ich nun mal bin).

Du hast Dir das WS2812-Protokoll angeschaut - und auch bemerkt, dass da 
0 und 1 verschiedene Takt-/Impuls-Zeiten haben?

von Dieter F. (Gast)


Lesenswert?

Basti schrieb:
> Das Byte empfangen und anschließend mit einer Lookup auf 4 Byte
> aufzuweiten geht sehr schnell -> 1024 WS2812 LEDs kann ich flackerfrei
> bedienen.

Poste doch bitte mal das Coding ...

von Markus M. (adrock)


Lesenswert?

Der WS2801 hat ein separates Clock-Signal und kann bis 25MHz clock. Mit 
diesem könnte man tatsächlich noch zusätzlich PWM machen.

Mit dem WS2812 kann man das vergessen, das hatten wir schon in einem 
anderen Thread festgestellt:

Beitrag "The secret of WS2812B"

Die PWM-Frequenz der WS2812 beträgt ca. 400Hz und ist asynchron zum 
Datensignal. Somit entstehen hässliche Flackereffekte.

Ansonsten habe ich das ganze auf dem STM32 auch mit SPI gemacht 
(allerdings jeweils ein Byte auf drei Bytes umgesetzt, das Timing ist ja 
doch relativ gutmütig).

von Basti (Gast)


Lesenswert?

@Dieter ganz einfach... eine Flanke sind 4 Bit, also zwei high zwei low 
oder eins high zwei low... fertig! Scheint sogar mit 3 Bit zu 
funktionieren... (siehe markus)

WS2801 is genauso schäbig wie WS2812... Bei Untersuchungen hat sich 
gezeigt das sich der Clock durch die Weiterleitung zuschnürt. Mit 3,6 
MHz ist nach 250 LEDs schluss. Dann ist der Clock nur noch High. Wir 
haben aus nem kleinen Logikgatter nen Reapeter gebaut, der den Clock 
wieder aufzieht... aber nur Workaround... interessanter weise kommt man 
bei einer Extremwertberechnung auf ca. 800 kHz bei 25 FPS optimale SPI 
Frequenz... also kein Stück besser als WS2812 ;)

VG Basti

von Dieter F. (Gast)


Lesenswert?

Basti schrieb:
> Dieter ganz einfach... eine Flanke sind 4 Bit, also zwei high zwei low
> oder eins high zwei low... fertig! Scheint sogar mit 3 Bit zu
> funktionieren... (siehe markus)

Na, wenn es so einfach ist kannst Du ja auch das funktionierende Coding 
einstellen (für 1024 LED) - oder?

von Basti (Gast)


Lesenswert?

@Dieter geht leider nicht, kommerzielles Projekt gewesen...

Vorgehen:
UART in SPI Mode 3,6 MHz Speed
MOSI invertieren = LED Data
Eingangsbyte mit 32 Bit x 256 Lookup verarbeiten
TX Buffer per DMA an UART/SPI senden

... fertig...
Brauch nur recht viel RAM für einen kleinen XMega...

von Dieter F. (Gast)


Lesenswert?

Basti schrieb:
> @Dieter geht leider nicht, kommerzielles Projekt gewesen...

Blubb... :-)

von Fabian F. (folfy)


Lesenswert?

Dieter F. schrieb:
> Fabian F. schrieb:
>> insbesondere unter Nutzung des ASF,
>> da dort Interrupts immer den max. Overhead haben
>
> ?Da sorgt sorgt doch der Compiler (GCC) für - und nicht ASF - oder?
Normal ja, bei ASF-Libs werden die ISRs aber grundsätzlich dynamisch 
gelinkt (publish-subscribe), daher muss der Compiler immer vom 
Worst-Case ausgehen, sprich alle fixed und call-used register 
sichern&wiederherstellen.

> Wenn ich mir die minimale/maximale Spezifikation des WS2812-Protokolls
> so anschaue wirst Du bei 32 MHz (Standard) wohl kaum großartige
> Interrupts während der "Versorgung" der LED ausführen können - oder
> täusche ich mich da?
Nein, lange ISRs sind kein Problem, solange darin nicht dutzende I/O 
oder Speicherzugriffe (wirklich pausenlos) direkt nacheinander erfolgen, 
was sehr ungewöhnlich wäre (vom Register-Backup eben abgesehen).

> Alternativ kannst Du natürlich eine deutlich schnellere CPU mit ggf.
> entkoppeltem DMA (ich kenne keine - aber ich habe auch nicht weiter
> rumgeschaut) nutzen.
Ich habe schon öfters auf ARM entwickelt, dort ist gewöhnlich die 
Peripherie auf mehrere Busse aufgeteilt, und die Bus-Matrix ist simultan 
Multi-Master fähig (manche haben sogar Multi-Bank/Port RAM).
Und bevor jemand was sagt, ich mag den xMega trotzdem gern, ich kann mit 
seinen schwächen leben ;)

Basti schrieb:
> Ich versteh nicht ganz, warum man das Protokoll nicht per SPI
> simuliert?? (wie alle anderen -> wahrscheinlich deswegen?)
Du hast dir die Antwort selber gegeben:
Basti schrieb:
> Brauch nur recht viel RAM für einen kleinen XMega...
Zur Info, Buffer alleine wären bei mir 300LEDs*3bytes*4 = 3,6kB
High-Speed USB-Endpoints brauchen auch viel, und die bereits vorhandene 
Hardware hat nun mal nur 4kB.

Basti schrieb:
> Was soll das Oversampling bringen? Mit 1024 WS2812 bei 800 kHz ist man
> doch schon auf 25 Frames limitiert... wie klein soll die LED-Kette denn
> werden?
>
> Hmm... klingt akademisch, aber wenig nach Praxis...
Wer braucht/hat bitte 1024 LEDs an einem Stück, das sind grob 
60A@5V=300Watt?
Dafür braucht man ja noch ein Dutzend zusätzlicher Versorgungsleitungen 
damit am Ende überhaupt noch was leuchten kann...

Nein, also damals hab ich 300 LEDs (5m bei 60LEDs/m) als Systemgrenze 
eingeplant, womit noch 2xOS möglich ist (>50Hz effektiv).
Das Projekt ist aus der "Praxis" entstanden, und als Ambilight&Moodlamp 
hinten am Fernseher montiert.

Markus M. schrieb:
> Der WS2801 hat ein separates Clock-Signal und kann bis 25MHz
> clock. Mit
> diesem könnte man tatsächlich noch zusätzlich PWM machen.
>
> Mit dem WS2812 kann man das vergessen, das hatten wir schon in einem
> anderen Thread festgestellt:
>
> Beitrag "The secret of WS2812B"
>
> Die PWM-Frequenz der WS2812 beträgt ca. 400Hz und ist asynchron zum
> Datensignal. Somit entstehen hässliche Flackereffekte.
>
> Ansonsten habe ich das ganze auf dem STM32 auch mit SPI gemacht
> (allerdings jeweils ein Byte auf drei Bytes umgesetzt, das Timing ist ja
> doch relativ gutmütig).

Ähm, ja, da muss ich dir jetzt irgendwie recht geben :-(
Ich hab bis jetzt die WS2801 mit 4xOS (10bit) im Einsatz, ohne Problem. 
Nachdem beide 400Hz PWM-Frequenz haben sollen, und ich mit den 800kHz 
die selbe Framerate wie bisher fahren kann, habe ich mit solch einen 
eigenartigen Verhalten überhaupt nicht mehr gerechnet (gerade erst 
getestet)...


Sorry dass es so lang wurde, hab versucht mich kurz zu halten... :-/

: Bearbeitet durch User
von Basti (Gast)


Lesenswert?

Ich bleibe dabei. Bevor man eine DMA aktiviert, sollte man sich Gedanken 
über das passende Ausgabeinterface machen.
Wollte gerade den XMegaE ins Spiel bringen. Mit der zusätzlichen Logik 
am Ausgabeport kann man wohl auch wunderbar WS2812 betreiben, der hat 
nur leider kein USB.

1024 LEDs sind doch nicht viel ;) Kommt auf die Anwendung an. Manche 
bauen es hinter den Fernseher und manche wollen, dass es der Fernseher 
selbst ist.

Hier mal mein Beispiel von passendem Interface (Parallel Interface) + 
DMA auf einem CortexM4! Ja, und auch hier wird CPU-Load gegen 
RAM--Verbrauch eingetauscht. Die Entscheidung muss man all zu oft 
treffen...
https://sebastianfoerster86.wordpress.com/2014/06/02/2048-pixel-rgb-led-matrix-basic/

Zum RAM-Verbrauch auf dem XMega:

Durch die freie CPU musst die auch nicht gleich die kompletten 3,4 kB im 
Speicher ablegen, dass geht auch Stückweise, wenn du RAM sparen willst!

VG
Basti

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.