adafruit / Adafruit_NeoPixel

Arduino library for controlling single-wire LED pixels (NeoPixel, WS2812, etc.)
GNU Lesser General Public License v3.0
3.1k stars 1.27k forks source link

DWT based pixel programming on nRF52 blocks I2S with easyDMA and digitalWrite command #234

Open Protonerd opened 4 years ago

Protonerd commented 4 years ago

I use the Adafruit Feather BLE, with the nRF52 chipset, together with an I2S amp from Adafruit. I have a Sketch running I2S with easyDMA and neopixels with this library. If I leave the decision to the library to choose either PWM easyDMA to drive the Pixels or bit banging with DWT, all works fine except that after a time there is a memory overflow I try to track down. If I tweak the code to force the DWT bit banging, I observe the following:

Is there any obvious reason why DWT mode blocks I2S and seemingly digitalWrite commands?

Thanks in advance for any suggestion and great library!

hathach commented 4 years ago

Neopixel is time sensitive, dwt method need to call call enter critical section which prevent any isr with priority > 1 to run. Effectively only Softdevice can preempt the dwt. However it should have no impact on I2S and/or other code after the DWT complete its work. Other than that I also have no clues, dwt is essentially bit banging the neopixel data pin and should have no impact on other module

Protonerd commented 4 years ago

Thank you hathach for the quick feedback. In fact I tried commenting out going into critical section, with same result. One thing I'm curious about is how the code decides whether there is enough memory available for easyDMA PWM to drive the pixels. If I use easyDMA, my sketch works for a while with both sound and light, then both stop. Previously I though that it was becuase of a memory overflow (heap and stack growing into each other), but there is a change it is caused simply by the driver changing into DWT mode. How does the library detect if enough memory is available?

hathach commented 4 years ago

the library will fallback to DWT method when there is

https://github.com/adafruit/Adafruit_NeoPixel/blob/master/Adafruit_NeoPixel.cpp#L1441 The memory used by library is determined by number of neopixel (16*pixel + 4)

https://github.com/adafruit/Adafruit_NeoPixel/blob/master/Adafruit_NeoPixel.cpp#L1404

if you are short in memory, you could try to enable debug mode = 1, and use these debug function to know how much memory left at a specific location (possible before neopixel malloc) https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/master/cores/nRF5/utility/debug.h#L63

DWT is very troublesome and will likely to be preempted by BLE, and have funky effect if you try to display something in an active ble transmitting. If your problem is lacking of memory since 832 has limited SRAM, I can help you to tune it up to use to guarantee an PWM neopixel, it is better than DWT, DWT is really the last resource that we hope it could work !!!

Protonerd commented 3 years ago

Since I learned and got so much from you guys at Adafruit (and excellent boards to top it!), at least I would like to give back a bit (at a time, as we have implemented a few more frequently asked libraries for the nRF52 platform. Well not because we wanted but because they were not available. Tech support from Nordic is a joke of the worse type)

I implemented a light weight library for bit banging neopixel support if you are interested: [https://github.com/Protonerd/nrf52-neopixel] It is proven on application level as well as with a digital analyser to find the sweet spot in the timing which is fast and yet robust. Feel free to replace the non-working DWT based approach with this one if you think others might not have sufficient memory for the PWM based one.

ladyada commented 3 years ago

thanks! @hathach will review when there is some free time :)

hathach commented 3 years ago

@Protonerd thank you for your willingness, I just take a quick look at the code. It is similar to DWT, last time I checked DWT work just fine. You cannot __disable_irq() with freeRTOS, it also could cause issue when doing BLE timing as well.