WS2812 driver with STM32H7, DMA and PWM

ChibiOS public support forum for topics related to the STMicroelectronics STM32 family of micro-controllers.

Moderators: barthess, RoccoMarco

User avatar
stertingen
Posts: 21
Joined: Mon Jan 13, 2020 10:55 pm
Has thanked: 7 times
Been thanked: 7 times

WS2812 driver with STM32H7, DMA and PWM

Postby stertingen » Sun Apr 05, 2020 2:20 pm

Hello there,

I'm struggling to port a PWM-based WS2812 LED driver (viewtopic.php?f=8&t=2601&start=10, https://github.com/joewa/WS2812-LED-Driver_ChibiOS) to STM32H750.

Data line is on Port D12 with AF2, I use timer 4, channel 0 (1 in data sheet. DMA stream is set to DMA_ID_ANY, the channel is not set, instead I call dmaSetRequestSource(STM32_DMAMUX1_TIM4_UP). PWM frequency is set to STM32_TIMCLK1.

I'm able to set a color to the WS2812 led once, when there's no sleep between ws2812_init() and ws2812_write_led(). Multiple calls to ws2812_write_led do not change the color; it seems that new color values are not correctly DMA'd to TIM4->CCR[0], but the DMA transmission complete callback (TCIE) is triggered regularly. The transmission error interrupt (TEIE, DMEIE) is not called.

ChibiOS checks and assertions are enabled.

The modified driver code is attached.
ws2812.zip
(6.66 KiB) Downloaded 86 times


Thanks for your help.

User avatar
Giovanni
Site Admin
Posts: 13807
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 934 times
Been thanked: 796 times
Contact:

Re: WS2812 driver with STM32H7, DMA and PWM

Postby Giovanni » Sun Apr 05, 2020 2:29 pm

Hi,

I cannot go into details of your code but you should consider that TIM4 has a 16 bits counter, it cannot count up to 800000 (am I reading it right?).

Giovanni

User avatar
stertingen
Posts: 21
Joined: Mon Jan 13, 2020 10:55 pm
Has thanked: 7 times
Been thanked: 7 times

Re: WS2812 driver with STM32H7, DMA and PWM

Postby stertingen » Sun Apr 05, 2020 2:48 pm

Giovanni wrote:Hi,

I cannot go into details of your code but you should consider that TIM4 has a 16 bits counter, it cannot count up to 800000 (am I reading it right?).

Giovanni


It does not need to. The period currently is 250 timer ticks. (STM32_TIMCLK1 / 800000). Also the PWM signal itself seems to work correctly; the PWM signals for the first frame buffer run are emitted correctly.

New signals written into the frame buffer later do not have an effect on the WS2812 LED. (Due to the lack of an oscilloscope in quarantaine, I'm unable to verify the PWM signal.)

User avatar
Giovanni
Site Admin
Posts: 13807
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 934 times
Been thanked: 796 times
Contact:

Re: WS2812 driver with STM32H7, DMA and PWM

Postby Giovanni » Sun Apr 05, 2020 4:34 pm

I am prisoner as well... no instrumentation at home.

Giovanni

rew
Posts: 375
Joined: Sat Jul 19, 2014 12:59 pm
Has thanked: 2 times
Been thanked: 13 times

Re: WS2812 driver with STM32H7, DMA and PWM

Postby rew » Sun Apr 05, 2020 6:48 pm

I have written code for WS2812 driving.....

I start a timer to go around at 3*800kHz. Then at wraparound/reset, I trigger a DMA to the output port from a memory location where I've stored: "a one" (all ones binary). The DMA controller is configured to not increment the memory address. So max 32bits required. Then at 1/3 of the max value, I trigger a second DMA channel. This one holds the data. And then at 2/3rd another non-incrementing DMA happens that finishes the WS2812 bit with a zero.

You can do 8 WS2812 strings at once. this way with an 8-bit DMA to 8 bits of an IO port. Or you can do 16 strings.

If you need only one, the memory area where you store the data becomes a bit sparse. Anyway, then the "one" DMA needs to have only the data-bit that is involved set. And you DMA to the port-set-register. The zero does something similar but with the reset register. For the data, I think you'll have to invert the data and use the port-reset register. (the output will always be high when the data is supposed to come... )

read-modifiy-write of the port data register becomes "forbidden". That will give odd effects.

If you have just a few leds that you need to give new data a few times per second... It pays to just write it yourself.

Code: Select all

for (i=0;i<24;i++) {
    palSetPad (MYPORT, MYBIT);
    ws_delay();
    palWritePad (MYPORT, MYBIT, data&0x1);
    data >>= 1;
    ws_delay ();
    palClearPad (MYPORT, MYBIT);
    ws_delay ();
}

Add a ws_delay, maybe better use a macro. for (j=0;j<15;j++) __asm__ ("nop"); will probably be about right (for a 216MHz clock).

User avatar
stertingen
Posts: 21
Joined: Mon Jan 13, 2020 10:55 pm
Has thanked: 7 times
Been thanked: 7 times

Re: WS2812 driver with STM32H7, DMA and PWM

Postby stertingen » Sun Apr 05, 2020 7:23 pm

rew wrote:I have written code for WS2812 driving.....

I start a timer to go around at 3*800kHz. Then at wraparound/reset, I trigger a DMA to the output port from a memory location where I've stored: "a one" (all ones binary). The DMA controller is configured to not increment the memory address. So max 32bits required. Then at 1/3 of the max value, I trigger a second DMA channel. This one holds the data. And then at 2/3rd another non-incrementing DMA happens that finishes the WS2812 bit with a zero.

You can do 8 WS2812 strings at once. this way with an 8-bit DMA to 8 bits of an IO port. Or you can do 16 strings.

If you need only one, the memory area where you store the data becomes a bit sparse. Anyway, then the "one" DMA needs to have only the data-bit that is involved set. And you DMA to the port-set-register. The zero does something similar but with the reset register. For the data, I think you'll have to invert the data and use the port-reset register. (the output will always be high when the data is supposed to come... )

read-modifiy-write of the port data register becomes "forbidden". That will give odd effects.

If you have just a few leds that you need to give new data a few times per second... It pays to just write it yourself.

Code: Select all

for (i=0;i<24;i++) {
    palSetPad (MYPORT, MYBIT);
    ws_delay();
    palWritePad (MYPORT, MYBIT, data&0x1);
    data >>= 1;
    ws_delay ();
    palClearPad (MYPORT, MYBIT);
    ws_delay ();
}

Add a ws_delay, maybe better use a macro. for (j=0;j<15;j++) __asm__ ("nop"); will probably be about right (for a 216MHz clock).


I'll try that, thanks. Do you have a code example?

User avatar
stertingen
Posts: 21
Joined: Mon Jan 13, 2020 10:55 pm
Has thanked: 7 times
Been thanked: 7 times

Re: WS2812 driver with STM32H7, DMA and PWM

Postby stertingen » Sun Apr 05, 2020 11:08 pm

I managed to get it working by adding a ws2812_flush() function.

In this function all DMA interrupts are cleared using dmaStreamClearInterrupt() and a new DMA transaction is startet using dmaStreamEnable().

The STM32_DMA_CR_CIRC flag was removed from dmaStreamSetMode().
Attachments
ws2812.zip
(6.58 KiB) Downloaded 91 times

User avatar
stertingen
Posts: 21
Joined: Mon Jan 13, 2020 10:55 pm
Has thanked: 7 times
Been thanked: 7 times

Re: WS2812 driver with STM32H7, DMA and PWM

Postby stertingen » Tue Apr 07, 2020 9:47 pm

Looks like the fault was at the WS2812B LED. The driver I used was suitable for revision v3 and prior; the manufacturer changed in revision v4 and later the needed reset time between two frames from 50us to 280us.

Adding the flush function worked because I called it every 1ms; now I've added a few reset frames.

cmirabile
Posts: 3
Joined: Tue Feb 13, 2018 5:39 pm
Been thanked: 2 times

Re: WS2812 driver with STM32H7, DMA and PWM

Postby cmirabile » Wed Sep 22, 2021 6:22 pm

stertingen wrote:Looks like the fault was at the WS2812B LED. The driver I used was suitable for revision v3 and prior; the manufacturer changed in revision v4 and later the needed reset time between two frames from 50us to 280us.

Adding the flush function worked because I called it every 1ms; now I've added a few reset frames.

Hi,
with the code on my STM32H750 cpu i only see 8 bits transmitted.
Did you experimented similar problem?

Thanks


Return to “STM32 Support”

Who is online

Users browsing this forum: Bing [Bot] and 5 guests