diff options
| author | Scott Shawcroft <scott.shawcroft@gmail.com> | 2017-01-17 19:27:48 -0800 |
|---|---|---|
| committer | Scott Shawcroft <scott.shawcroft@gmail.com> | 2017-01-17 19:27:48 -0800 |
| commit | 1a8696891248bf7cffcadc7e0951c97b9bb84deb (patch) | |
| tree | 5d5c237cdab40cedec4638914feb6d36886c35d7 | |
| parent | 42926c61596b017ebcf469ca5a7b6748b86df9b3 (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__.c | 21 |
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(); |
