Skip to content

Commit 840121e

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 840121e

File tree

1 file changed

+27
-5
lines changed

1 file changed

+27
-5
lines changed

Adafruit_NeoPixel.cpp

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

4646
#include "Adafruit_NeoPixel.h"
4747

48+
#undef REPRODUCE_TEENSY_TIMING
49+
#ifdef REPRODUCE_TEENSY_TIMING
50+
#include "imxrt.h"
51+
#endif
52+
4853
#if defined(TARGET_LPC1768)
4954
#include <time.h>
5055
#endif
@@ -1912,16 +1917,32 @@ void Adafruit_NeoPixel::show(void) {
19121917
ARM_DEMCR |= ARM_DEMCR_TRCENA;
19131918
ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA;
19141919

1920+
#ifdef REPRODUCE_TEENSY_TIMING
1921+
// reproducer for the timing issue
1922+
{
1923+
static uint8_t ct;
1924+
1925+
//if (!(ct & 1)) {
1926+
if (true) {
1927+
asm("dsb");
1928+
asm("isb");
1929+
SCB_CACHE_ICIALLU = 0UL;
1930+
asm("dsb");
1931+
asm("isb");
1932+
}
1933+
ct++;
1934+
}
1935+
#endif
1936+
19151937
#if defined(NEO_KHZ400) // 800 KHz check needed only if 400 KHz support enabled
19161938
if (is800KHz) {
19171939
#endif
1918-
cyc = ARM_DWT_CYCCNT + CYCLES_800;
1940+
cyc = ARM_DWT_CYCCNT; // make sure it's initialised..
19191941
while (p < end) {
19201942
pix = *p++;
19211943
for (mask = 0x80; mask; mask >>= 1) {
1922-
while (ARM_DWT_CYCCNT - cyc < CYCLES_800)
1923-
;
19241944
cyc = ARM_DWT_CYCCNT;
1945+
barrier();
19251946
*set = msk;
19261947
if (pix & mask) {
19271948
while (ARM_DWT_CYCCNT - cyc < CYCLES_800_T1H)
@@ -1931,10 +1952,11 @@ void Adafruit_NeoPixel::show(void) {
19311952
;
19321953
}
19331954
*clr = msk;
1955+
barrier();
1956+
while (ARM_DWT_CYCCNT - cyc < CYCLES_800)
1957+
;
19341958
}
19351959
}
1936-
while (ARM_DWT_CYCCNT - cyc < CYCLES_800)
1937-
;
19381960
#if defined(NEO_KHZ400)
19391961
} else { // 400 kHz bitstream
19401962
cyc = ARM_DWT_CYCCNT + CYCLES_400;

0 commit comments

Comments
 (0)