From d67c0699c9704c7f405ea982e78049f2a521cf44 Mon Sep 17 00:00:00 2001 From: Stephen Waits Date: Tue, 7 Apr 2026 11:47:32 -0600 Subject: [PATCH] fix: prevent RMT peripheral drop on V4, log WS2812 errors The Rmt struct was being dropped after extracting channel0, which likely disabled the RMT peripheral. Use ManuallyDrop to keep it alive. Also log WS2812 transmit errors instead of silently discarding them. --- firmware/src/board/heltec_v4.rs | 17 ++++++++++++----- firmware/src/driver/ws2812.rs | 4 +++- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/firmware/src/board/heltec_v4.rs b/firmware/src/board/heltec_v4.rs index 5603bea2..ae52f316 100644 --- a/firmware/src/board/heltec_v4.rs +++ b/firmware/src/board/heltec_v4.rs @@ -77,11 +77,18 @@ impl LoRaBoard for Board { let i2c = mcu::init_i2c(p.I2C0, p.GPIO17, p.GPIO18); let display = Some(DisplayParts { i2c }); - // WS2812B RGB LED on GPIO38 via RMT channel 0 - let rmt = Rmt::new(p.RMT, Rate::from_mhz(80)) - .expect("RMT init") - .into_async(); - let led_channel = rmt.channel0 + // WS2812B RGB LED on GPIO38 via RMT channel 0. + // Wrap in ManuallyDrop so the Rmt peripheral isn't disabled when + // the struct is dropped after we take channel0. + let rmt = core::mem::ManuallyDrop::new( + Rmt::new(p.RMT, Rate::from_mhz(80)) + .expect("RMT init") + .into_async(), + ); + // SAFETY: we're reading channel0 out of the ManuallyDrop wrapper. + // The Rmt won't be dropped, so the peripheral stays enabled. + let channel0 = unsafe { core::ptr::read(&raw const rmt.channel0) }; + let led_channel = channel0 .configure_tx( p.GPIO38, TxChannelConfig::default() diff --git a/firmware/src/driver/ws2812.rs b/firmware/src/driver/ws2812.rs index 46dbb58f..840c2a2f 100644 --- a/firmware/src/driver/ws2812.rs +++ b/firmware/src/driver/ws2812.rs @@ -43,6 +43,8 @@ impl Ws2812 { impl RgbLed for Ws2812 { async fn set_rgb(&mut self, r: u8, g: u8, b: u8) { let data = Self::encode(r, g, b); - let _ = self.channel.transmit(&data).await; + if let Err(e) = self.channel.transmit(&data).await { + defmt::warn!("WS2812 transmit error: {}", e); + } } }