Skip to content

Commit 8309f7e

Browse files
author
Volker Eckert
committed
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.
1 parent aa798ff commit 8309f7e

File tree

1 file changed

+28
-5
lines changed

1 file changed

+28
-5
lines changed

Adafruit_NeoPixel.cpp

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@
4545

4646
#include "Adafruit_NeoPixel.h"
4747

48+
#undef REPRODUCE_TEENSY_TIMING
49+
#define barrier() __asm__ __volatile__ ("" ::: "memory")
50+
#ifdef REPRODUCE_TEENSY_TIMING
51+
#include "imxrt.h"
52+
#endif
53+
4854
#if defined(TARGET_LPC1768)
4955
#include <time.h>
5056
#endif
@@ -1912,16 +1918,32 @@ void Adafruit_NeoPixel::show(void) {
19121918
ARM_DEMCR |= ARM_DEMCR_TRCENA;
19131919
ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA;
19141920

1921+
#ifdef REPRODUCE_TEENSY_TIMING
1922+
// reproducer for the timing issue
1923+
{
1924+
static uint8_t ct;
1925+
1926+
//if (!(ct & 1)) {
1927+
if (true) {
1928+
asm("dsb");
1929+
asm("isb");
1930+
SCB_CACHE_ICIALLU = 0UL;
1931+
asm("dsb");
1932+
asm("isb");
1933+
}
1934+
ct++;
1935+
}
1936+
#endif
1937+
19151938
#if defined(NEO_KHZ400) // 800 KHz check needed only if 400 KHz support enabled
19161939
if (is800KHz) {
19171940
#endif
1918-
cyc = ARM_DWT_CYCCNT + CYCLES_800;
1941+
cyc = ARM_DWT_CYCCNT; // make sure it's initialised..
19191942
while (p < end) {
19201943
pix = *p++;
19211944
for (mask = 0x80; mask; mask >>= 1) {
1922-
while (ARM_DWT_CYCCNT - cyc < CYCLES_800)
1923-
;
19241945
cyc = ARM_DWT_CYCCNT;
1946+
barrier();
19251947
*set = msk;
19261948
if (pix & mask) {
19271949
while (ARM_DWT_CYCCNT - cyc < CYCLES_800_T1H)
@@ -1931,10 +1953,11 @@ void Adafruit_NeoPixel::show(void) {
19311953
;
19321954
}
19331955
*clr = msk;
1956+
barrier();
1957+
while (ARM_DWT_CYCCNT - cyc < CYCLES_800)
1958+
;
19341959
}
19351960
}
1936-
while (ARM_DWT_CYCCNT - cyc < CYCLES_800)
1937-
;
19381961
#if defined(NEO_KHZ400)
19391962
} else { // 400 kHz bitstream
19401963
cyc = ARM_DWT_CYCCNT + CYCLES_400;

0 commit comments

Comments
 (0)