8000 atmel-samd: Fix neopixel timing by forcing the NVM cache to be determ… · pcurry/circuitpython@1a86968 · GitHub
[go: up one dir, main page]

Skip to content

Commit 1a86968

Browse files
committed
atmel-samd: Fix neopixel timing by forcing the NVM cache to be deterministicly timed. Otherwise, bit order changes code timing. Fixes adafruit#74
1 parent 42926c6 commit 1a86968

File tree

1 file changed

+11
-10
lines changed

1 file changed

+11
-10
lines changed

atmel-samd/common-hal/neopixel_write/__init__.c

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ void common_hal_neopixel_write(const nativeio_digitalinout_obj_t* digitalinout,
4040
// Turn off interrupts of any kind during timing-sensitive code.
4141
mp_hal_disable_all_interrupts();
4242

43+
// Make sure the NVM cache is consistently timed.
44+
NVMCTRL->CTRLB.bit.READMODE = NVMCTRL_CTRLB_READMODE_DETERMINISTIC_Val;
45+
4346
uint32_t pin = digitalinout->pin->pin;
4447
port = port_get_group_from_gpio_pin(pin);
4548
pinMask = (1UL << (pin % 32)); // From port_pin_set_output_level ASF code.
@@ -56,17 +59,14 @@ void common_hal_neopixel_write(const nativeio_digitalinout_obj_t* digitalinout,
5659
*set = pinMask;
5760
asm("nop; nop;");
5861
if(p & bitMask) {
59-
asm("nop; nop; nop; nop; nop; nop; nop; nop;"
60-
"nop; nop; nop; nop; nop;");
62+
asm("nop; nop; nop; nop; nop; nop; nop;");
6163
*clr = pinMask;
6264
} else {
6365
*clr = pinMask;
64-
asm("nop; nop; nop; nop; nop; nop; nop; nop;"
65-
"nop; nop; nop; nop; nop; nop; nop; nop;"
66-
"nop; nop;");
66+
asm("nop; nop;");
6767
}
6868
if((bitMask >>= 1) != 0) {
69-
asm("nop; nop; nop; nop; nop; nop; nop; nop; nop;");
69+
asm("nop; nop; nop; nop; nop;");
7070
} else {
7171
if(ptr >= end) break;
7272
p = *ptr++;
@@ -76,12 +76,10 @@ void common_hal_neopixel_write(const nativeio_digitalinout_obj_t* digitalinout,
7676
} else { // 400 KHz bitstream
7777
for(;;) {
7878
*set = pinMask;
79-
// 11 cycles high regardless
80-
asm("nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
79+
80+
asm("nop; nop; nop; nop; nop; nop; nop;");
8181
if(p & bitMask) {
82-
// 27 cycles high
8382
asm("nop; nop; nop; nop; nop; nop; nop; nop;"
84-
"nop; nop; nop; nop; nop; nop; nop; nop;"
8583
"nop; nop; nop; nop; nop; nop; nop; nop;"
8684
"nop; nop; nop;");
8785
*clr = pinMask;
@@ -106,6 +104,9 @@ void common_hal_neopixel_write(const nativeio_digitalinout_obj_t* digitalinout,
106104
}
107105
}
108106

107+
// Speed up! (But inconsistent timing.)
108+
NVMCTRL->CTRLB.bit.READMODE = NVMCTRL_CTRLB_READMODE_NO_MISS_PENALTY_Val;
109+
109110
// Turn on interrupts after timing-sensitive code.
110111
mp_hal_enable_all_interrupts();
111112

0 commit comments

Comments
 (0)
0