aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Shawcroft <scott.shawcroft@gmail.com>2017-01-17 19:27:48 -0800
committerScott Shawcroft <scott.shawcroft@gmail.com>2017-01-17 19:27:48 -0800
commit1a8696891248bf7cffcadc7e0951c97b9bb84deb (patch)
tree5d5c237cdab40cedec4638914feb6d36886c35d7
parent42926c61596b017ebcf469ca5a7b6748b86df9b3 (diff)
atmel-samd: Fix neopixel timing by forcing the NVM cache to be deterministicly timed. Otherwise, bit order changes code timing. Fixes #740.8.3
-rw-r--r--atmel-samd/common-hal/neopixel_write/__init__.c21
1 files changed, 11 insertions, 10 deletions
diff --git a/atmel-samd/common-hal/neopixel_write/__init__.c b/atmel-samd/common-hal/neopixel_write/__init__.c
index f720c4518..bb396162d 100644
--- a/atmel-samd/common-hal/neopixel_write/__init__.c
+++ b/atmel-samd/common-hal/neopixel_write/__init__.c
@@ -40,6 +40,9 @@ void common_hal_neopixel_write(const nativeio_digitalinout_obj_t* digitalinout,
// Turn off interrupts of any kind during timing-sensitive code.
mp_hal_disable_all_interrupts();
+ // Make sure the NVM cache is consistently timed.
+ NVMCTRL->CTRLB.bit.READMODE = NVMCTRL_CTRLB_READMODE_DETERMINISTIC_Val;
+
uint32_t pin = digitalinout->pin->pin;
port = port_get_group_from_gpio_pin(pin);
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,
*set = pinMask;
asm("nop; nop;");
if(p & bitMask) {
- asm("nop; nop; nop; nop; nop; nop; nop; nop;"
- "nop; nop; nop; nop; nop;");
+ asm("nop; nop; nop; nop; nop; nop; nop;");
*clr = pinMask;
} else {
*clr = pinMask;
- asm("nop; nop; nop; nop; nop; nop; nop; nop;"
- "nop; nop; nop; nop; nop; nop; nop; nop;"
- "nop; nop;");
+ asm("nop; nop;");
}
if((bitMask >>= 1) != 0) {
- asm("nop; nop; nop; nop; nop; nop; nop; nop; nop;");
+ asm("nop; nop; nop; nop; nop;");
} else {
if(ptr >= end) break;
p = *ptr++;
@@ -76,13 +76,11 @@ void common_hal_neopixel_write(const nativeio_digitalinout_obj_t* digitalinout,
} else { // 400 KHz bitstream
for(;;) {
*set = pinMask;
- // 11 cycles high regardless
- asm("nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
+
+ asm("nop; nop; nop; nop; nop; nop; nop;");
if(p & bitMask) {
- // 27 cycles high
asm("nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop;"
- "nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop;");
*clr = pinMask;
} else {
@@ -106,6 +104,9 @@ void common_hal_neopixel_write(const nativeio_digitalinout_obj_t* digitalinout,
}
}
+ // Speed up! (But inconsistent timing.)
+ NVMCTRL->CTRLB.bit.READMODE = NVMCTRL_CTRLB_READMODE_NO_MISS_PENALTY_Val;
+
// Turn on interrupts after timing-sensitive code.
mp_hal_enable_all_interrupts();