Hallo zusammen,
ich versuche einen LED-Streifen mit WS2812LEDs zum Laufen zu bekommen.
Dabei nutze ich die light_ws2812_ARM Bibliothek.
Ich bin den Anweisungen in der README-Datei gefolgt und die Anpassungen
auf dem Mikrocontroller haben soweit funktioniert.
Allerdings leuchtet der Streifen nicht in der von mir gewünschten Farbe.
Durch verschiedene Einstellungen an F_CPU und anschließende Messung mit
einem Oszi vermute ich, dass dies mit den wait states zusammenhängt.
Wie kann ich die wait states auf 0 setzen?
Folgendes hat nicht funktioniert:
1.) Set FLASH access time in clocks
Chip_FMC_SetFLASHAccess( FLASHTIM_50MHZ_CPU )
2.) Place the function that writes the data into the main RAM region
__RAMFUNC(RAM) void ws2812_sendarray(uint8_t *ledarray,int length);
Oder hatte jemand schon ein ähnliches Problem?
Marvin0807 schrieb:> Wie kann ich die wait states auf 0 setzen?
Bei der STM32L0 und STM32F0 Serie ist das standardmäßig bereits
deaktiviert.
SET_BIT(FLASH->ACR, FLASH_ACR_LATENCY); // 1 Wait state
CLEAR_BIT(FLASH->ACR, FLASH_ACR_LATENCY); // 0 Wait states
Der Flash Speicher fällt aber aus, denn du mit mehr als 24 MHz ohne
Wait-State taktest.
Welchen Mikrocontroller verwendest du denn?
Ich hatte mal einen M0, bei dem mußte man die Waitstates hochsetzen,
falls er mit 48 statt 32 MHz betrieben hat.
Stand ab Revision 1 dann auch im Handbuch.
Meistens sind die CPUs aber schnell genug. Daher vermute ich, dass der
Programmierer nicht genau weiss, was er tut.
PittyJ schrieb:> Meistens sind die CPUs aber schnell genug.
Klar, aber die Wait States sind für die Peripherals, das Zeugs was an
der superschnellen CPU hängt.
Jörg W. schrieb:> Nein, die sind für den Flash.
Der in der CPU wohnt, der direkt an die ALU getackert ist???
Ist der Speicher ist extern über einen BUS aun die CPU gekoppelt!
Doch, z.B. beim STM32F0 oder auch G0 muss man ab > 24MHz 1ws und > 48MHz
2ws konfigurieren.
Mit dem CubeMX oder dem alten Excel-Makro Tool ("AN4055 Clock
configuration tool for STM32F0xx microcontrollers") wird auch schon der
Startup-Code entsprechend generiert, so dass die WS korrekt konfiguriert
werden.
auweia schrieb im Beitrag #6270957:
> Wer nicht voellig geistig behindert ist, schaut einfach im> Referenzmanual des Controllers im Abschnitt "Flash" nach.
Wenn ich es gefunden hätte, würde ich hier nicht fragen..
Ich verwende den LPC11C24.
In einem deiner vielen Threads zu der WS2812 Ansteuerung hatte ich
schonmal geschrieben das der LPC die auch gut per SPI treiben kann, da
entfällt die taktabhängige Zyklenzählerei.
Marvin S. schrieb:> Wenn ich es gefunden hätte, würde ich hier nicht fragen..
Guckst Du UM10398 Kapitel 3.12:
http://www.keil.com/dd/docs/datashts/nxp/lpc11xx/lpc111x_lpc11cxx_um.pdf
Du setzt die Waitstates natürlich, BEVOR Du die Frequenz mittels PLL
raufsetzt.
Was auch noch schiefgehen kann, ist die PLL umzukonfigurieren, während
der Chip schon von der PLL läuft. Oder die PLL konfigurieren und
aufzuschalten, ohne zu warten, bis sie überhaupt eingeschwungen ist.
Ich habe beim LPC11C24 die Erfahrung gemacht, dass es auch eine Rolle
spielt wie und wo der Code der delay() Routine am Ende im Flash steht.
Das hat sicher mit den Caching-Stategien zu tun die es das auch gibt.
Bei mir äußerte sich das so, dass die Zeiten des Delays sich bei
manchmal nach Codeänderungen völlig verändert haben obwohl an der
Routine selbst nichts gemacht wurde. Ich habe mir dann so geholfen:
1
// Microsecond delay loop-
2
voidDelayuS(uint32_tuS)
3
{
4
uint32_tCyclestoLoops;
5
6
CyclestoLoops=SystemCoreClock<<1;
7
if(CyclestoLoops>=2000000)
8
{
9
CyclestoLoops/=1000000;
10
CyclestoLoops*=uS;
11
}
12
else
13
{
14
CyclestoLoops*=uS;
15
CyclestoLoops/=1000000;
16
}
17
18
if(CyclestoLoops<=100)
19
return;
20
21
CyclestoLoops-=320;// cycle count for entry/exit should be measured
22
CyclestoLoops/=8;//
23
24
if(!CyclestoLoops)
25
return;
26
27
// Delay loop for Cortex M3 thumb2
28
// das align 4 ist extrem wichtig, sonst
29
// sind Unterschiede im faktor 2 möglich jenachdem
30
// wie der Code erzeugt wird
31
__asmvolatile
32
(
33
// Load loop count to register
34
" mov r3, %[loops]\n"
35
" .align 4\n"
36
"loop: sub r3,#1 \n"
37
" bne loop \n\n"
38
39
:// No output registers
40
:[loops]"r"(CyclestoLoops)// Input registers
41
:"r3"// clobbered registers
42
);
43
}
Entscheidend war das .align 4\n im Assemblercode. Das schaffte dann
Reproduzierbare Ergebnisse.
Grundsätzlich sollte man - wie schon oben erwähnt - grundsätzlich
überdenken ob man die ws2812 nicht per SPI ansteuern möchte.
Ich finde dieses Bitbanging ist eine absolute Krücke die es eigentlich
zu vermeiden gilt.
temp schrieb:> if (CyclestoLoops <= 100)> return;>> CyclestoLoops -= 320; // cycle count for entry/exit should be measured
Ich würde die 100 oben durch 320 ersetzen. Falls 100 < CyclestoLoops <
320, wird das sonst wegen wrap-around eine sehr lange Delay-Loop.
Nop schrieb:> Guckst Du UM10398 Kapitel 3.12:> http://www.keil.com/dd/docs/datashts/nxp/lpc11xx/lpc111x_lpc11cxx_um.pdf
Genau das habe ich ja mit der unter 1.) aufgeführten Anweisung gemacht.
Nur dass dies der originale Aufruf war, der die Frequenz auf 50MHz
setzt.
So wie du auch geschrieben hast, wird zuerst die eben beschriebene
Anweisung ausgeführt und dann mittels PLL auf 4* 12MHz erhöht.
An die Lösung mit SPI habe ich mich schon letztes Mal gemacht, nachdem
ich davon gehört habe. Da hatte ich ein wenig Probleme durch eine zu
große Lücke zwischen der Übertragung von aufeinanderfolgenden Bytes. Das
ganze beruht auf dem Beispiel von LPCOpen. Nichtsdestotrotz hätte ich
gerne die Bibliothek hier zum Laufen gebracht..
Die Anwedung dieser Delay-Funktion verstehe ich nicht ganz um ehrlich zu
sein. Aber vielen Dank für das Bereitstellen des Quellcodes!
Marvin S. schrieb:> Da hatte ich ein wenig Probleme durch eine zu> große Lücke zwischen der Übertragung von aufeinanderfolgenden Bytes. Das> ganze beruht auf dem Beispiel von LPCOpen.
LPCOpen baut da eventuell zuviel Sicherheit ein, oder arbeitet mit
Interrupts? Ein WS Bit muss in 3 SPI Bits gesendet werden, macht 24 Bit.
Die kann man in 2x12 Bit @ 2,4 MHz verschicken. Beim Senden Pollen ob
das Statusregister ready sagt, dann einfach die Daten ins DR schreiben.
Nop schrieb:>> if (CyclestoLoops <= 100)>> return;>>>> CyclestoLoops -= 320; // cycle count for entry/exit should be measured>> Ich würde die 100 oben durch 320 ersetzen. Falls 100 < CyclestoLoops <> 320, wird das sonst wegen wrap-around eine sehr lange Delay-Loop.
Da gebe ich dir völlig Recht.
Markus M. schrieb:> Grundsätzlich sollte man - wie schon oben erwähnt - grundsätzlich> überdenken ob man die ws2812 nicht per SPI ansteuern möchte.>> Ich finde dieses Bitbanging ist eine absolute Krücke die es eigentlich> zu vermeiden gilt.
Oder nimm ein Bluepill Board und schieb die Daten per DMA raus, das hab
ich auch schon mal für 8 Kanäle gleichzeitig gemacht.
Johannes S. schrieb:> LPCOpen baut da eventuell zuviel Sicherheit ein, oder arbeitet mit> Interrupts?
Es kann zwischen einem Polling- und einem Interrupt-Modus gewählt
werden. So wie ich das sehe wird also in dem von mir gewählten Modus
nicht mit Interrupts gearbeitet. Das Verhalten wurde auch schon hier
beschrieben
https://community.nxp.com/thread/487020. Ich werde nun so wie du
beschrieben hast versuchen direkt in das DR zu schreiben.
Zu dem anderen hätte ich aber trotzdem noch eine Frage.
Die entscheidenende Funktion in der ws_light Bibliothek sieht wie folgt
aus:
> Markus M. schrieb:> Oder nimm ein Bluepill Board und schieb die Daten per DMA raus, das hab> ich auch schon mal für 8 Kanäle gleichzeitig gemacht.
Ich brauch den Controller aktuell wegen einer anderen Funktionalität,
aber ich werde es im Hinterkopf behalten:)