Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-enable interrupts in between writing LED data for ARM M0. #751

Merged
merged 2 commits into from Apr 6, 2019

Conversation

Projects
None yet
2 participants
@ademuri
Copy link
Contributor

commented Mar 11, 2019

This adds support for FASTLED_ALLOW_INTERRUPTS to ARM M0-based platforms
(e.g. SAMD21).

This fixes the clock getting off when using more than ~30 LEDs, since
Arduino uses an interrupt to increment the millis clock.

This also fixes the breakage in NRF51 support introduced by dba8825.

@focalintent

This comment has been minimized.

Copy link
Member

commented Mar 11, 2019

The problem with allowing interrupts without a corresponding definition of SEI_CHK is that if there’s an interrupt that runs too long, the leds will reset and the next bit of data getting written out will go to the first led, not the n’th. (There’s a reason why I never had that as an option in the code)

@ademuri

This comment has been minimized.

Copy link
Contributor Author

commented Mar 11, 2019

Ah, I misread what SEI_CHK/CLI_CHK does - to confirm, it returns 0 if too much time has elapsed (and so the LEDs have latched the already-written data), so that the entire data stream is written from the beginning. Is that right?

@ademuri ademuri force-pushed the candykingdom:interrupts branch 2 times, most recently from 5050deb to 7ef5d34 Mar 12, 2019

@ademuri

This comment has been minimized.

Copy link
Contributor Author

commented Mar 12, 2019

Ok, I gave this another go. I made a compromise so that all of the M0 platforms will work with this change - I checked whether SysTick advanced by the equivalent of more than 45uSecs. This will occasionally fail - if an interrupt takes more than 1ms, and SysTick ends up being close to where it was before (i.e. the interrupt takes very close to whole ms). I'm not positive, but I suspect this is especially rare, since several interrupts would have to be service (the arduino millis must be serviced so that SysTick resets, and a long interrupt).

I did try to use millis() to check for this case, but because of the registers allocated we can't call any functions here.

This approach adds support for all of the M0 platforms, and doesn't depend on any other timers (which may interfere with others' code). If you're concerned about the edge cases (or think they're more than edge cases), that's OK too, I can try the timer approach (which would require adding support for individual platforms).

This also preserves the existing nrf51 behavior, and if other platforms add timer support, will preferentially use that.

Re-enable interrupts in between writing LED data for ARM M0.
This adds support for FASTLED_ALLOW_INTERRUPTS to ARM M0-based platforms
(e.g. SAMD21).

This fixes the clock getting off when using more than ~30 LEDs, since
Arduino uses an interrupt to increment the millis clock.

This uses SysTick->VAL to determine whether more than 45uSecs have
elapsed while interrupts were enabled. This isn't as correct as using a
dedicated timer, but it does work on all ARM M0 platforms.

@ademuri ademuri force-pushed the candykingdom:interrupts branch from 7ef5d34 to 9e1a219 Mar 15, 2019

@ademuri

This comment has been minimized.

Copy link
Contributor Author

commented Mar 15, 2019

Updated the logic and tested this.

Here's how I tested: I have a (custom) SAMD21-based board, running a fork of the Adafruit board definitions (only the variant is changed). I connected 150 WS2812 LEDs to the board and loaded the ColorPalette example (and modified it to only use the default rainbow palette). With this setup, the last LED seems to cycle as smoothly as the first LED. There are no glitches (before I fixed the math, it would 'glitch' as expected where later parts of the strand would stop lighting for a split second).

I also tried to simulate a long interrupt by adding a sleep (manually implemented with a for loop) to SysTick_DefaultHandler. This reduced the number of LEDs that lit up successfully, which I think suggests that the bailout logic is working.

@focalintent focalintent merged commit 403464a into FastLED:master Apr 6, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.