From 840121e36926c797ca948d003aae8c4dc2e04e42 Mon Sep 17 00:00:00 2001 From: Volker Eckert Date: Thu, 3 Oct 2024 19:22:25 +0100 Subject: [PATCH] cope with I$ miss on teensy if the instruction cache is completely flushed *even before* the counter is read, under specific situations (presumably when relevant parts of show() are on different cache lines), the first bit would not be sent (but discarded), often leading to a change in colour. prevent compiler optimisation across counter reads, order the delays so that they are easier to reason about. --- Adafruit_NeoPixel.cpp | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/Adafruit_NeoPixel.cpp b/Adafruit_NeoPixel.cpp index 39f0b11..848edd8 100644 --- a/Adafruit_NeoPixel.cpp +++ b/Adafruit_NeoPixel.cpp @@ -45,6 +45,11 @@ #include "Adafruit_NeoPixel.h" +#undef REPRODUCE_TEENSY_TIMING +#ifdef REPRODUCE_TEENSY_TIMING +#include "imxrt.h" +#endif + #if defined(TARGET_LPC1768) #include #endif @@ -1912,16 +1917,32 @@ void Adafruit_NeoPixel::show(void) { ARM_DEMCR |= ARM_DEMCR_TRCENA; ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA; +#ifdef REPRODUCE_TEENSY_TIMING + // reproducer for the timing issue + { + static uint8_t ct; + + //if (!(ct & 1)) { + if (true) { + asm("dsb"); + asm("isb"); + SCB_CACHE_ICIALLU = 0UL; + asm("dsb"); + asm("isb"); + } + ct++; + } +#endif + #if defined(NEO_KHZ400) // 800 KHz check needed only if 400 KHz support enabled if (is800KHz) { #endif - cyc = ARM_DWT_CYCCNT + CYCLES_800; + cyc = ARM_DWT_CYCCNT; // make sure it's initialised.. while (p < end) { pix = *p++; for (mask = 0x80; mask; mask >>= 1) { - while (ARM_DWT_CYCCNT - cyc < CYCLES_800) - ; cyc = ARM_DWT_CYCCNT; + barrier(); *set = msk; if (pix & mask) { while (ARM_DWT_CYCCNT - cyc < CYCLES_800_T1H) @@ -1931,10 +1952,11 @@ void Adafruit_NeoPixel::show(void) { ; } *clr = msk; + barrier(); + while (ARM_DWT_CYCCNT - cyc < CYCLES_800) + ; } } - while (ARM_DWT_CYCCNT - cyc < CYCLES_800) - ; #if defined(NEO_KHZ400) } else { // 400 kHz bitstream cyc = ARM_DWT_CYCCNT + CYCLES_400;