Skip to content

Commit 3c6b343

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 3c6b343

File tree

1 file changed

+29
-5
lines changed

1 file changed

+29
-5
lines changed

Adafruit_NeoPixel.cpp

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

4646
#include "Adafruit_NeoPixel.h"
4747

48+
#define barrier() __asm__ __volatile__ ("" ::: "memory")
49+
50+
#undef REPRODUCE_TEENSY_TIMING
51+
#ifdef REPRODUCE_TEENSY_TIMING
52+
#include "imxrt.h"
53+
#endif
54+
4855
#if defined(TARGET_LPC1768)
4956
#include <time.h>
5057
#endif
@@ -1912,16 +1919,32 @@ void Adafruit_NeoPixel::show(void) {
19121919
ARM_DEMCR |= ARM_DEMCR_TRCENA;
19131920
ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA;
19141921

1922+
#ifdef REPRODUCE_TEENSY_TIMING
1923+
// reproducer for the timing issue
1924+
{
1925+
static uint8_t ct;
1926+
1927+
//if (!(ct & 1)) {
1928+
if (true) {
1929+
asm("dsb");
1930+
asm("isb");
1931+
SCB_CACHE_ICIALLU = 0UL;
1932+
asm("dsb");
1933+
asm("isb");
1934+
}
1935+
ct++;
1936+
}
1937+
#endif
1938+
19151939
#if defined(NEO_KHZ400) // 800 KHz check needed only if 400 KHz support enabled
19161940
if (is800KHz) {
19171941
#endif
1918-
cyc = ARM_DWT_CYCCNT + CYCLES_800;
1942+
cyc = ARM_DWT_CYCCNT; // make sure it's initialised..
19191943
while (p < end) {
19201944
pix = *p++;
19211945
for (mask = 0x80; mask; mask >>= 1) {
1922-
while (ARM_DWT_CYCCNT - cyc < CYCLES_800)
1923-
;
19241946
cyc = ARM_DWT_CYCCNT;
1947+
barrier();
19251948
*set = msk;
19261949
if (pix & mask) {
19271950
while (ARM_DWT_CYCCNT - cyc < CYCLES_800_T1H)
@@ -1931,10 +1954,11 @@ void Adafruit_NeoPixel::show(void) {
19311954
;
19321955
}
19331956
*clr = msk;
1957+
barrier();
1958+
while (ARM_DWT_CYCCNT - cyc < CYCLES_800)
1959+
;
19341960
}
19351961
}
1936-
while (ARM_DWT_CYCCNT - cyc < CYCLES_800)
1937-
;
19381962
#if defined(NEO_KHZ400)
19391963
} else { // 400 kHz bitstream
19401964
cyc = ARM_DWT_CYCCNT + CYCLES_400;

0 commit comments

Comments
 (0)