From 8ca3f0fb7c856e5b767d36bc56db883309e29fbf Mon Sep 17 00:00:00 2001 From: Stefan Kerkmann Date: Mon, 23 Jan 2023 22:24:21 +0100 Subject: [PATCH] [Bug] rp2040: fix timer wrap deadlock in ws2812 vendor driver (#19652) Co-authored-by: Sergey Vlasov --- .../drivers/vendor/RP/RP2040/ws2812_vendor.c | 14 ++++++++------ platforms/chibios/vendors/RP/RP2040.mk | 2 ++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/platforms/chibios/drivers/vendor/RP/RP2040/ws2812_vendor.c b/platforms/chibios/drivers/vendor/RP/RP2040/ws2812_vendor.c index bc03213f3be..a46b0991954 100644 --- a/platforms/chibios/drivers/vendor/RP/RP2040/ws2812_vendor.c +++ b/platforms/chibios/drivers/vendor/RP/RP2040/ws2812_vendor.c @@ -1,10 +1,13 @@ // Copyright 2022 Stefan Kerkmann (@KarlK90) // SPDX-License-Identifier: GPL-2.0-or-later -#include "quantum.h" #include "ws2812.h" -#include "hardware/pio.h" +#include "hardware/timer.h" #include "hardware/clocks.h" +// Keep this exact include order otherwise we run into naming conflicts between +// pico-sdk and rp2040.h which we don't control. +#include "quantum.h" +#include "hardware/pio.h" #if !defined(MCU_RP) # error PIO Driver is only available for Raspberry Pi 2040 MCUs! @@ -132,7 +135,7 @@ static uint32_t RP_DMA_MODE_WS2812; static int STATE_MACHINE = -1; static SEMAPHORE_DECL(TRANSFER_COUNTER, 1); -static rtcnt_t LAST_TRANSFER; +static absolute_time_t LAST_TRANSFER; /** * @brief Convert RGBW value into WS2812 compatible 32-bit data word. @@ -161,7 +164,7 @@ static void ws2812_dma_callback(void* p, uint32_t ct) { // Convert from ns to us time_to_completion /= 1000; - LAST_TRANSFER = chSysGetRealtimeCounterX() + time_to_completion + WS2812_TRST_US; + update_us_since_boot(&LAST_TRANSFER, time_us_64() + time_to_completion + WS2812_TRST_US); osalSysLockFromISR(); chSemSignalI(&TRANSFER_COUNTER); @@ -256,8 +259,7 @@ static inline void sync_ws2812_transfer(void) { } // Busy wait until last transfer has finished - while (unlikely(!timer_expired32(chSysGetRealtimeCounterX(), LAST_TRANSFER))) { - } + busy_wait_until(LAST_TRANSFER); } void ws2812_setleds(LED_TYPE* ledarray, uint16_t leds) { diff --git a/platforms/chibios/vendors/RP/RP2040.mk b/platforms/chibios/vendors/RP/RP2040.mk index 4360512c050..94f023d72b7 100644 --- a/platforms/chibios/vendors/RP/RP2040.mk +++ b/platforms/chibios/vendors/RP/RP2040.mk @@ -25,6 +25,7 @@ PICOSDKROOT := $(TOP_DIR)/lib/pico-sdk PICOSDKSRC = $(PICOSDKROOT)/src/rp2_common/hardware_clocks/clocks.c \ $(PICOSDKROOT)/src/rp2_common/hardware_pll/pll.c \ $(PICOSDKROOT)/src/rp2_common/hardware_pio/pio.c \ + $(PICOSDKROOT)/src/rp2_common/hardware_timer/timer.c \ $(PICOSDKROOT)/src/rp2_common/hardware_flash/flash.c \ $(PICOSDKROOT)/src/rp2_common/hardware_gpio/gpio.c \ $(PICOSDKROOT)/src/rp2_common/hardware_claim/claim.c \ @@ -44,6 +45,7 @@ PICOSDKINC = $(CHIBIOS)//os/various/pico_bindings/dumb/include \ $(PICOSDKROOT)/src/rp2_common/hardware_pll/include \ $(PICOSDKROOT)/src/rp2_common/hardware_pio/include \ $(PICOSDKROOT)/src/rp2_common/hardware_sync/include \ + $(PICOSDKROOT)/src/rp2_common/hardware_timer/include \ $(PICOSDKROOT)/src/rp2_common/hardware_resets/include \ $(PICOSDKROOT)/src/rp2_common/hardware_watchdog/include \ $(PICOSDKROOT)/src/rp2_common/hardware_xosc/include \