From 776985ab342e8a58d3678f96bcf879dcc9b0f8d1 Mon Sep 17 00:00:00 2001 From: Kun-Yi Chen Date: Wed, 24 Sep 2025 12:29:23 +0800 Subject: [PATCH 1/3] refactor(usb): enlarge string buffer and remove hardcoded limit Increased _desc_str size from 32 to 64 to allow longer USB string descriptors. Replaced the fixed limit (31) with a value derived from the buffer size for clarity and maintainability. --- src/usb_descriptors.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/usb_descriptors.c b/src/usb_descriptors.c index 7adec8d35..5b385ec53 100644 --- a/src/usb_descriptors.c +++ b/src/usb_descriptors.c @@ -142,7 +142,7 @@ char const* string_desc_arr [] = "CDC-ACM UART Interface", // 6: Interface descriptor for CDC }; -static uint16_t _desc_str[32]; +static uint16_t _desc_str[64]; // Invoked when received GET STRING DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete @@ -166,7 +166,8 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) // Cap at max char chr_count = strlen(str); - if ( chr_count > 31 ) chr_count = 31; + if ( chr_count > (sizeof(_desc_str)/sizeof(_desc_str[0]) - 1) ) + chr_count = sizeof(_desc_str)/sizeof(_desc_str[0]) - 1; for(uint8_t i=0; i Date: Tue, 23 Sep 2025 23:23:21 +0800 Subject: [PATCH 2/3] add board support: waveshare rp2040 zero --- CMakeLists.txt | 16 +++++++++- README.md | 15 ++++++++++ include/board_pico_zero_config.h | 50 ++++++++++++++++++++++++++++++++ src/probe_config.h | 10 +++++-- 4 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 include/board_pico_zero_config.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d20c37dca..2cfb138a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,16 +52,30 @@ target_compile_definitions (debugprobe PRIVATE option (DEBUG_ON_PICO "Compile firmware for the Pico instead of Debug Probe" OFF) if (DEBUG_ON_PICO) target_compile_definitions (debugprobe PRIVATE - DEBUG_ON_PICO=1 + DEBUG_ON_PICO=1 ) if (PICO_BOARD STREQUAL "pico") set_target_properties(debugprobe PROPERTIES OUTPUT_NAME "debugprobe_on_pico" ) + target_compile_definitions (debugprobe PRIVATE + PICO_BOARD_PICO=1 + ) + elseif (PICO_BOARD STREQUAL "pico2") set_target_properties(debugprobe PROPERTIES OUTPUT_NAME "debugprobe_on_pico2" ) + target_compile_definitions (debugprobe PRIVATE + PICO_BOARD_PICO2=1 + ) + elseif (PICO_BOARD STREQUAL "waveshare_rp2040_zero") + set_target_properties(debugprobe PROPERTIES + OUTPUT_NAME "debugprobe_on_zero" + ) + target_compile_definitions (debugprobe PRIVATE + PICO_BOARD_PICO_ZERO=1 + ) else () message(SEND_ERROR "Unsupported board ${PICO_BOARD}") endif () diff --git a/README.md b/README.md index bfdb82120..69dc42364 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,21 @@ cd build-pico2 cmake -DDEBUG_ON_PICO=1 -DPICO_BOARD=pico2 -DPICO_PLATFORM=rp2350 ../ ``` +# Building for Waveshare RP2040 Zero + +To build for the Waveshare RP2040 Zero, configure CMake with the DEBUG_ON_PICO option and set the target board: + +- Requires Pico SDK v2.0.0 or newer (PICO_SDK_PATH must be set). +- The output file will be named debugprobe_on_zero.uf2 (default build produces debugprobe.uf2). + +``` +git submodule sync +git submodule update --init --recursive +mkdir build-zero +cd build-zero +cmake .. -DDEBUG_ON_PICO=1 -DPICO_BOARD=waveshare_rp2040_zero +``` + # TODO - AutoBaud selection, as PIO is a capable frequency counter - Possibly include RTT support diff --git a/include/board_pico_zero_config.h b/include/board_pico_zero_config.h new file mode 100644 index 000000000..6fe5f7bea --- /dev/null +++ b/include/board_pico_zero_config.h @@ -0,0 +1,50 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 KUNYI CHEN + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +#pragma once +#ifndef BOARD_PICO_ZERO_H_ +#define BOARD_PICO_ZERO_H_ + +#define PROBE_IO_RAW +#define PROBE_CDC_UART + +// PIO config +#define PROBE_SM 0 +#define PROBE_PIN_OFFSET 2 +#define PROBE_PIN_SWCLK (PROBE_PIN_OFFSET + 0) // 2 +#define PROBE_PIN_SWDIO (PROBE_PIN_OFFSET + 1) // 3 +// Target reset config +#if false +#define PROBE_PIN_RESET 1 +#endif + +// UART config +#define PROBE_UART_TX 4 +#define PROBE_UART_RX 5 +#define PROBE_UART_INTERFACE uart1 +#define PROBE_UART_BAUDRATE 115200 + +#define PROBE_PRODUCT_STRING "DebugProbe on Pico Zero (CMSIS-DAP/SWD)" + +#endif diff --git a/src/probe_config.h b/src/probe_config.h index 5c5e14909..bdb07ad12 100644 --- a/src/probe_config.h +++ b/src/probe_config.h @@ -65,8 +65,14 @@ do { \ // TODO tie this up with PICO_BOARD defines in the main SDK -#ifdef DEBUG_ON_PICO -#include "board_pico_config.h" +#ifdef DEBUG_ON_PICO + #if (PICO_BOARD_PICO) + #include "board_pico_config.h" + #elif (PICO_BOARD_PICO2) + #include "board_pico_config.h" + #elif (PICO_BOARD_PICO_ZERO) + #include "board_pico_zero_config.h" + #endif #else #include "board_debug_probe_config.h" #endif From a805e6a209f3dae9efe1a248226b6f728327b233 Mon Sep 17 00:00:00 2001 From: Kun-Yi Chen Date: Wed, 24 Sep 2025 19:31:37 +0800 Subject: [PATCH 3/3] add ws2812 led driver code --- CMakeLists.txt | 4 ++ include/DAP_config.h | 12 ++++ include/board_pico_zero_config.h | 16 ++++++ src/main.c | 31 +++++++++-- src/ws2812.c | 96 ++++++++++++++++++++++++++++++++ src/ws2812.h | 37 ++++++++++++ src/ws2812.pio | 89 +++++++++++++++++++++++++++++ 7 files changed, 281 insertions(+), 4 deletions(-) create mode 100644 src/ws2812.c create mode 100644 src/ws2812.h create mode 100644 src/ws2812.pio diff --git a/CMakeLists.txt b/CMakeLists.txt index 2cfb138a5..0a3504ec6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,7 @@ target_compile_options(debugprobe PRIVATE -Wall) pico_generate_pio_header(debugprobe ${CMAKE_CURRENT_LIST_DIR}/src/probe.pio) pico_generate_pio_header(debugprobe ${CMAKE_CURRENT_LIST_DIR}/src/probe_oen.pio) +pico_generate_pio_header(debugprobe ${CMAKE_CURRENT_LIST_DIR}/src/ws2812.pio) target_include_directories(debugprobe PRIVATE src) @@ -76,6 +77,9 @@ if (DEBUG_ON_PICO) target_compile_definitions (debugprobe PRIVATE PICO_BOARD_PICO_ZERO=1 ) + target_sources(debugprobe PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/src/ws2812.c + ) else () message(SEND_ERROR "Unsupported board ${PICO_BOARD}") endif () diff --git a/include/DAP_config.h b/include/DAP_config.h index 88c11d9c4..a4cb73716 100755 --- a/include/DAP_config.h +++ b/include/DAP_config.h @@ -48,7 +48,11 @@ This information includes: #include #include "cmsis_compiler.h" + #include "probe_config.h" +#ifdef PROBE_WS2812_LED +#include "ws2812.h" +#endif #include "probe.h" /// Processor Clock of the Cortex-M MCU used in the Debug Unit. @@ -505,6 +509,10 @@ It is recommended to provide the following LEDs for status indication: __STATIC_INLINE void LED_CONNECTED_OUT (uint32_t bit) { #ifdef PROBE_DAP_CONNECTED_LED gpio_put(PROBE_DAP_CONNECTED_LED, bit); +#else + #ifdef PROBE_WS2812_DAP_CONNECTED + PROBE_WS2812_DAP_CONNECTED(bit); + #endif #endif } @@ -516,6 +524,10 @@ __STATIC_INLINE void LED_CONNECTED_OUT (uint32_t bit) { __STATIC_INLINE void LED_RUNNING_OUT (uint32_t bit) { #ifdef PROBE_DAP_RUNNING_LED gpio_put(PROBE_DAP_RUNNING_LED, bit); +#else + #ifdef PROBE_WS2812_DAP_RUNNING + PROBE_WS2812_DAP_RUNNING(bit); + #endif #endif } diff --git a/include/board_pico_zero_config.h b/include/board_pico_zero_config.h index 6fe5f7bea..bbec3cb99 100644 --- a/include/board_pico_zero_config.h +++ b/include/board_pico_zero_config.h @@ -34,6 +34,7 @@ #define PROBE_PIN_OFFSET 2 #define PROBE_PIN_SWCLK (PROBE_PIN_OFFSET + 0) // 2 #define PROBE_PIN_SWDIO (PROBE_PIN_OFFSET + 1) // 3 + // Target reset config #if false #define PROBE_PIN_RESET 1 @@ -45,6 +46,21 @@ #define PROBE_UART_INTERFACE uart1 #define PROBE_UART_BAUDRATE 115200 +/* LED config - some or all of these can be omitted if not used */ +#define PROBE_WS2812_LED +#define SM_WS2812 0 +#define WS2812_PIN 16 +#define PROBE_WS2812_USB_CONNECTED put_blueLED +#define PROBE_WS2812_DAP_CONNECTED put_greenLED +#define PROBE_WS2812_DAP_RUNNING put_redLED +/* +#define PROBE_USB_CONNECTED_LED 2 +#define PROBE_DAP_CONNECTED_LED 15 +#define PROBE_DAP_RUNNING_LED 16 +#define PROBE_UART_RX_LED 7 +#define PROBE_UART_TX_LED 8 +*/ + #define PROBE_PRODUCT_STRING "DebugProbe on Pico Zero (CMSIS-DAP/SWD)" #endif diff --git a/src/main.c b/src/main.c index 72cfd549d..8347c9954 100644 --- a/src/main.c +++ b/src/main.c @@ -45,6 +45,7 @@ #include "tusb_edpt_handler.h" #include "DAP.h" #include "hardware/structs/usb.h" +#include "ws2812.h" // UART0 for debugprobe debug // UART1 for debugprobe to target device @@ -54,14 +55,27 @@ static uint8_t RxDataBuffer[CFG_TUD_HID_EP_BUFSIZE]; #define THREADED 1 -#define UART_TASK_PRIO (tskIDLE_PRIORITY + 3) -#define TUD_TASK_PRIO (tskIDLE_PRIORITY + 2) -#define DAP_TASK_PRIO (tskIDLE_PRIORITY + 1) +#define UART_TASK_PRIO (tskIDLE_PRIORITY + 4) +#define TUD_TASK_PRIO (tskIDLE_PRIORITY + 3) +#define DAP_TASK_PRIO (tskIDLE_PRIORITY + 2) +#define LED_TASK_PRIO (tskIDLE_PRIORITY + 1) -TaskHandle_t dap_taskhandle, tud_taskhandle, mon_taskhandle; +TaskHandle_t dap_taskhandle, tud_taskhandle, mon_taskhandle, led_taskhandle; static int was_configured; +void led_thread(void *ptr) +{ + TickType_t wake; + + ws2812_init(); + wake = xTaskGetTickCount(); + do { + refresh_led(); + xTaskDelayUntil(&wake, pdMS_TO_TICKS(20)); + } while (true); +} + void dev_mon(void *ptr) { uint32_t sof[3]; @@ -106,7 +120,12 @@ void usb_thread(void *ptr) gpio_put(PROBE_USB_CONNECTED_LED, 1); else gpio_put(PROBE_USB_CONNECTED_LED, 0); +#else +#ifdef PROBE_WS2812_USB_CONNECTED + PROBE_WS2812_USB_CONNECTED(tud_ready()); +#endif #endif + // If suspended or disconnected, delay for 1ms (20 ticks) if (tud_suspended() || !tud_connected()) xTaskDelayUntil(&wake, 20); @@ -139,6 +158,10 @@ int main(void) { xTaskCreate(usb_thread, "TUD", configMINIMAL_STACK_SIZE, NULL, TUD_TASK_PRIO, &tud_taskhandle); #if PICO_RP2040 xTaskCreate(dev_mon, "WDOG", configMINIMAL_STACK_SIZE, NULL, TUD_TASK_PRIO, &mon_taskhandle); +#endif +#ifdef PROBE_WS2812_LED + // #pragma message("WS2812 support enabled") + xTaskCreate(led_thread, "LED", configMINIMAL_STACK_SIZE, NULL, LED_TASK_PRIO, &led_taskhandle); #endif vTaskStartScheduler(); } diff --git a/src/ws2812.c b/src/ws2812.c new file mode 100644 index 000000000..150fabec2 --- /dev/null +++ b/src/ws2812.c @@ -0,0 +1,96 @@ +#include +#include + +#include +#include +#include + +#include "probe_config.h" +#include "ws2812.pio.h" + +#define RED_MASK 0x01 +#define GREEN_MASK 0x02 +#define BLUE_MASK 0x04 +struct _ws2812 { + uint initted; + uint offset; + uint led; +}; + +static struct _ws2812 ws2812 = {0}; + +#ifndef SM_WS2812 +#define SM_WS2812 2 +#endif + +#ifndef WS2812_PIN +#define WS2812_PIN 16 +#endif + +static inline void put_pixel(uint32_t pixel_grb) { + pio_sm_put_blocking(pio1, SM_WS2812, pixel_grb << 8u); +} + +void put_rgb(uint8_t red, uint8_t green, uint8_t blue) +{ + uint32_t mask = (green << 16) | (red << 8) | (blue << 0); + put_pixel(mask); +} + +void refresh_led(void) +{ + uint val = 0; + if (ws2812.led & RED_MASK) + val |= 10 << 8; + if (ws2812.led & GREEN_MASK) + val |= 10 << 16; + if (ws2812.led & BLUE_MASK) + val |= 10; + + put_pixel(val); +} + +void put_redLED(bool on) +{ + if (on) + ws2812.led |= RED_MASK; + else + ws2812.led &= ~RED_MASK; +} + +void put_greenLED(bool on) +{ + if (on) + ws2812.led |= GREEN_MASK; + else + ws2812.led &= ~GREEN_MASK; +} + +void put_blueLED(bool on) +{ + if (on) + ws2812.led |= BLUE_MASK; + else + ws2812.led &= ~BLUE_MASK; +} + +void ws2812_init(void) +{ + if (ws2812.initted) + return; + + ws2812.initted = 1; + ws2812.led = 0; + ws2812.offset = pio_add_program(pio1, &ws2812_program); + ws2812_program_init(pio1, SM_WS2812, ws2812.offset, WS2812_PIN, 800000, false); +} + +void ws2812_deinit(void) +{ + if (!ws2812.initted) + return; + + pio_sm_set_enabled(pio1, SM_WS2812, 0); + pio_remove_program(pio1, &ws2812_program, ws2812.offset); + ws2812.initted = 0; +} diff --git a/src/ws2812.h b/src/ws2812.h new file mode 100644 index 000000000..56b782927 --- /dev/null +++ b/src/ws2812.h @@ -0,0 +1,37 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 KUNYI CHEN + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#pragma once +#ifndef WS2812_H_ +#define WS2812_H_ + +void put_redLED(bool on); +void put_greenLED(bool on); +void put_blueLED(bool on); +void refresh_led(void); +void ws2812_init(void); +void ws2812_deinit(void); + +#endif diff --git a/src/ws2812.pio b/src/ws2812.pio new file mode 100644 index 000000000..1ce9030ac --- /dev/null +++ b/src/ws2812.pio @@ -0,0 +1,89 @@ +; +; Copyright (c) 2020 Raspberry Pi (Trading) Ltd. +; +; SPDX-License-Identifier: BSD-3-Clause +; +.pio_version 0 // only requires PIO version 0 + +.program ws2812 +.side_set 1 + +; The following constants are selected for broad compatibility with WS2812, +; WS2812B, and SK6812 LEDs. Other constants may support higher bandwidths for +; specific LEDs, such as (7,10,8) for WS2812B LEDs. + +.define public T1 2 +.define public T2 5 +.define public T3 3 + +.lang_opt python sideset_init = pico.PIO.OUT_HIGH +.lang_opt python out_init = pico.PIO.OUT_HIGH +.lang_opt python out_shiftdir = 1 + +.wrap_target +bitloop: + out x, 1 side 0 [T3 - 1] ; Side-set still takes place when instruction stalls + jmp !x do_zero side 1 [T1 - 1] ; Branch on the bit we shifted out. Positive pulse +do_one: + jmp bitloop side 1 [T2 - 1] ; Continue driving high, for a long pulse +do_zero: + nop side 0 [T2 - 1] ; Or drive low, for a short pulse +.wrap + +% c-sdk { +#include "hardware/clocks.h" + +static inline void ws2812_program_init(PIO pio, uint sm, uint offset, uint pin, float freq, bool rgbw) { + + pio_gpio_init(pio, pin); + pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true); + + pio_sm_config c = ws2812_program_get_default_config(offset); + sm_config_set_sideset_pins(&c, pin); + sm_config_set_out_shift(&c, false, true, rgbw ? 32 : 24); + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); + + int cycles_per_bit = ws2812_T1 + ws2812_T2 + ws2812_T3; + float div = clock_get_hz(clk_sys) / (freq * cycles_per_bit); + sm_config_set_clkdiv(&c, div); + + pio_sm_init(pio, sm, offset, &c); + pio_sm_set_enabled(pio, sm, true); +} +%} + +.program ws2812_parallel + +.define public T1 3 +.define public T2 3 +.define public T3 4 + +.wrap_target + out x, 32 + mov pins, !null [T1-1] + mov pins, x [T2-1] + mov pins, null [T3-2] +.wrap + +% c-sdk { +#include "hardware/clocks.h" + +static inline void ws2812_parallel_program_init(PIO pio, uint sm, uint offset, uint pin_base, uint pin_count, float freq) { + for(uint i=pin_base; i