RIOT icon indicating copy to clipboard operation
RIOT copied to clipboard

drivers/ws281x: Bit banging STM32 support

Open Lennart-Lutz opened this issue 1 year ago • 4 comments

Contribution description

This pull request adds support for driving ws281x LEDs on STM32 microcontrollers operating at 84, 100, and 180 MHz clock frequencies. That's the case for almost all STM32F4 microcontrollers, except 405/415 and 407/417. The implementation uses the bit banging approach by exploiting NOPs. (Don't be afraid of all the lines I've changed. Most of them are NOPs.)

The following parts of the RIOT are involved:

  • drivers/ws281x
  • drivers/include

You can test my changes with the test application provided in tests/ws281x and using a STM32 board like the "nucleo-f411re" or any other Nucleo with a STM32 that operates at 84, 100, and 180 MHz.

Testing procedure

This implementation was tested with the test application provided in tests/ws281x using a "weact-f401cc", "nucleo-f411re" and "nucleo-f446re" board. Each time I did a visual inspection of the LEDs. In addition to that, I also checked the timings with a "Saleae Logic Analyzer" at 500MS/s. Since every board I mentioned above has a different CPU speed, I confirmed that my implementation works for all mentioned clock frequencies.

Lennart-Lutz avatar Jan 26 '24 18:01 Lennart-Lutz

Thanks for you pull request and sorry for the long delay.

This PR has been opened just shortly after https://github.com/RIOT-OS/RIOT/pull/19891 was merged. I think it might be, that you have been unaware of https://github.com/RIOT-OS/RIOT/pull/19891.

For https://github.com/RIOT-OS/RIOT/pull/19891 to work on STM32 MCUs the periph_timer_poll extension is needed. I do believe that this would be the better approach, as this API extension would be useful not only for ws281x bit-banging, but other bit-banging as well.

In addition I have made some unpleasant experiences with counting CPU cycles for timing, as this can vary a lot between different MCUs. E.g. the Cortex M7 has this dual issue feature that may allow the CPU to perform two instructions in a single CPU cycle. However, it is difficult to find out documentation that clearly specifies which instructions get executed simultaneously and which not. Specifically, would to nops qualify for this to be executed in one CPU cycles, or not? Also whether the instruction cache is hot or not has a huge impact. Hence, I believe that using a timer for timing is less fragile.

In conclusion, I would prefer if ws281x bit-banging would be implemented using the timer.

Also note: https://github.com/RIOT-OS/RIOT/pull/20218 would be even another approach that would work for STM32. (Ab)using SPI with DMA for the bit-banging would allow the CPU to either attend other tasks, or to conserve power. That would only work for STM32 MCUs with DMA, though.

maribu avatar Apr 30 '24 11:04 maribu

Would https://github.com/RIOT-OS/RIOT/pull/20646 be a viable alternative for you?

maribu avatar May 02 '24 21:05 maribu

Hi,

yes at this time i was unaware of https://github.com/RIOT-OS/RIOT/pull/19891 and it seems like the better option.

Lennart-Lutz avatar Aug 07 '24 12:08 Lennart-Lutz

Hi,

I haven't looked in my PR for a while. I sadly was unable to reliably control one family of ws281x LEDs with that PR.

It might be a hardware issue with that 5x5 LED matrix I was testing against.

It might be that the alternative I suggested doesn't meet the timing requirements good enough for consistently controlling the ws281x LEDs. Or I just didn't get the implementation right yet. Or I messed up the PCB desing of LED matrix tested against.

I sadly do not have time to dig deeper into it as of now ☹️

maribu avatar Aug 07 '24 12:08 maribu