From 88dbb8f0693bef775e3d1fb4c6b0ba21416c3c60 Mon Sep 17 00:00:00 2001 From: zouhaitao Date: Wed, 8 Jul 2026 11:56:23 +0800 Subject: [PATCH] fix: prevent SPI write collision and hanging by introducing 20-NOP buffer offset and timeout-protected loops in WS2812_Write24Bit --- App/main.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/App/main.c b/App/main.c index 02058d4..2631821 100644 --- a/App/main.c +++ b/App/main.c @@ -150,6 +150,7 @@ void WS2812_Write24Bit(u8 g, u8 r, u8 b) { u8 xdata buf[15]; u8 i; + u16 timeout; WS2812_EncodeByte5(g, &buf[0]); WS2812_EncodeByte5(r, &buf[5]); @@ -165,20 +166,27 @@ void WS2812_Write24Bit(u8 g, u8 r, u8 b) SPSTAT = 0xC0; // Clear flags SPDAT = buf[0]; // Goes to shift register immediately - // Wait at least 1 SPI clock cycle (8 system cycles) to avoid WCOL - _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); + // Wait about 20 system cycles (halfway through transmission) to avoid WCOL + _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); + _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); + _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); + _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); SPDAT = buf[1]; // Goes to transmit buffer for (i = 2; i < 15; i++) { - while (!(SPSTAT & 0x80)); // Wait for buf[i-2] to finish, buf[i-1] moves to shifter + timeout = 2000; + while (!(SPSTAT & 0x80) && --timeout); // Wait with timeout SPSTAT = 0xC0; - SPDAT = buf[i]; // Write buf[i] to transmit buffer (zero gap!) + SPDAT = buf[i]; // Write buf[i] to transmit buffer } - while (!(SPSTAT & 0x80)); // Wait for buf[13] to finish, buf[14] moves to shifter + timeout = 2000; + while (!(SPSTAT & 0x80) && --timeout); // Wait for buf[13] SPSTAT = 0xC0; - while (!(SPSTAT & 0x80)); // Wait for buf[14] to finish + + timeout = 2000; + while (!(SPSTAT & 0x80) && --timeout); // Wait for buf[14] SPSTAT = 0xC0; SPCTL = 0x90; // Disable SPI