From 81c9d8c5062c3c36eb8ff03391cc74eb9792b84c Mon Sep 17 00:00:00 2001 From: Awawa <69086569+awawa-dev@users.noreply.github.com> Date: Mon, 20 Apr 2026 20:28:34 +0200 Subject: [PATCH 01/11] Add support for RP2350 --- .github/workflows/push-master.yml | 86 +++++++++++++++++++------------ CMakeLists.txt | 20 +++++-- sdk/config/FreeRTOSConfig.h | 17 +++++- sdk/freertos | 2 +- sdk/pico | 2 +- 5 files changed, 87 insertions(+), 40 deletions(-) diff --git a/.github/workflows/push-master.yml b/.github/workflows/push-master.yml index 7b917a8..de25362 100644 --- a/.github/workflows/push-master.yml +++ b/.github/workflows/push-master.yml @@ -19,7 +19,7 @@ jobs: - name: Install GNU Arm Embedded Toolchain uses: carlosperate/arm-none-eabi-gcc-action@v1 with: - release: '12.2.Rel1' + release: '15.2.Rel1' - name: Build packages shell: bash @@ -30,27 +30,35 @@ jobs: cmake --build . --config Release - uses: actions/upload-artifact@v7.0.0 - name: Upload artifacts (commit) - if: (startsWith(github.event.ref, 'refs/tags') != true) + name: Upload artifacts (release) with: + name: firmware-release-generic-rp2040 path: | firmware/*.uf2 + - name: Build packages for generic rp2350 + shell: bash + run: | + cd build + rm -rf * + rm -rf ../firmware/* + cmake -DTARGET_BOARD=pico2 -DCMAKE_BUILD_TYPE=Release .. + cmake --build . + zip -j ../firmware/firmware_generic_rp2350.zip ../firmware/* + - uses: actions/upload-artifact@v7.0.0 - name: Upload artifacts (release) - if: startsWith(github.ref, 'refs/tags/') + name: Upload artifacts (release generic rp2350) with: - name: firmware-release-generic + name: firmware-release-generic-rp2350 path: | - firmware/*.uf2 + firmware/*.zip - - name: Build packages for Adafruit Feather RP2040 Scorpio (release-only) - if: startsWith(github.ref, 'refs/tags/') + - name: Build packages for Adafruit Feather RP2040 Scorpio shell: bash run: | cd build - rm *.* - rm ../firmware/* + rm -rf * + rm -rf ../firmware/* echo "Neopixel is using GPIO16(OUTPUT_DATA_PIN) on output 0." > ../firmware/Firmwares_for_Adafruit_Feather_RP2040_Scorpio.txt echo "SPI is using spi0 interface pins: GPIO19(OUTPUT_SPI_DATA_PIN) and GPIO18(OUTPUT_SPI_CLOCK_PIN) on output 3 and 2 respectively." >> ../firmware/Firmwares_for_Adafruit_Feather_RP2040_Scorpio.txt cmake -DOVERRIDE_BOOT_WORKAROUND=ON -DOVERRIDE_DATA_PIN=16 -DOVERRIDE_SPI_DATA_PIN=19 -DOVERRIDE_SPI_CLOCK_PIN=18 -DCMAKE_BUILD_TYPE=Release .. @@ -59,19 +67,17 @@ jobs: - uses: actions/upload-artifact@v7.0.0 name: Upload artifacts (release Adafruit_Feather) - if: startsWith(github.ref, 'refs/tags/') with: name: firmware-release-adafruit-scorpio path: | firmware/*.zip - - name: Build packages for Adafruit ItsyBitsy RP2040 (release-only) - if: startsWith(github.ref, 'refs/tags/') + - name: Build packages for Adafruit ItsyBitsy RP2040 shell: bash run: | cd build - rm *.* - rm ../firmware/* + rm -rf * + rm -rf ../firmware/* echo "Neopixel is using GPIO14(OUTPUT_DATA_PIN) on output 5." > ../firmware/Firmwares_for_Adafruit_ItsyBitsy_2040.txt cmake -DOVERRIDE_BOOT_WORKAROUND=ON -DOVERRIDE_DATA_PIN=14 -DCMAKE_BUILD_TYPE=Release .. cmake --build . @@ -79,20 +85,18 @@ jobs: zip -j ../firmware/Adafruit_ItsyBitsy_2040.zip ../firmware/* - uses: actions/upload-artifact@v7.0.0 - name: Upload artifacts (release Adafruit_ItsyBitsy) - if: startsWith(github.ref, 'refs/tags/') + name: Upload artifacts (release Adafruit_ItsyBitsy_2040) with: - name: firmware-release-adafruit-itsybitsy + name: firmware-release-adafruit-itsybitsy-2040 path: | firmware/*.zip - - name: Build packages for Pimoroni Plasma Stick 2040 W (release-only) - if: startsWith(github.ref, 'refs/tags/') + - name: Build packages for Pimoroni Plasma Stick 2040 W shell: bash run: | cd build - rm *.* - rm ../firmware/* + rm -rf * + rm -rf ../firmware/* echo "Neopixel is using GPIO15(OUTPUT_DATA_PIN) on output PIXELS." > ../firmware/Firmwares_for_Pimoroni_Plasma_Stick_2040_W.txt cmake -DOVERRIDE_DATA_PIN=15 -DCMAKE_BUILD_TYPE=Release .. cmake --build . @@ -100,20 +104,18 @@ jobs: zip -j ../firmware/Pimoroni_Plasma_Stick_2040_W.zip ../firmware/* - uses: actions/upload-artifact@v7.0.0 - name: Upload artifacts (release Pimoroni_Plasma_Stick_W) - if: startsWith(github.ref, 'refs/tags/') + name: Upload artifacts (release Pimoroni_Plasma_Stick_2040_W) with: - name: firmware-release-pimoroni-plasma-stick + name: firmware-release-pimoroni-plasma-stick-2040-w path: | firmware/*.zip - - name: Build packages for Pimoroni Plasma 2040 (release-only) - if: startsWith(github.ref, 'refs/tags/') + - name: Build packages for Pimoroni Plasma 2040 shell: bash run: | cd build - rm *.* - rm ../firmware/* + rm -rf * + rm -rf ../firmware/* echo "Neopixel is using GPIO15(OUTPUT_DATA_PIN) on output DA." > ../firmware/Firmwares_for_Pimoroni_Plasma_2040.txt echo "SPI is using spi1 interface pins: GPIO15(OUTPUT_SPI_DATA_PIN) and GPIO14(OUTPUT_SPI_CLOCK_PIN) on output DA and CL respectively." >> ../firmware/Firmwares_for_Pimoroni_Plasma_2040.txt cmake -DOVERRIDE_DATA_PIN=15 -DOVERRIDE_SPI_INTERFACE=spi1 -DOVERRIDE_SPI_DATA_PIN=15 -DOVERRIDE_SPI_CLOCK_PIN=14 -DCMAKE_BUILD_TYPE=Release .. @@ -121,10 +123,28 @@ jobs: zip -j ../firmware/Pimoroni_Plasma_2040.zip ../firmware/* - uses: actions/upload-artifact@v7.0.0 - name: Upload artifacts (release Pimoroni_Plasma) - if: startsWith(github.ref, 'refs/tags/') + name: Upload artifacts (release Pimoroni_Plasma_2040) + with: + name: firmware-release-pimoroni-plasma-2040 + path: | + firmware/*.zip + + - name: Build packages for Pimoroni Plasma 2350 + shell: bash + run: | + cd build + rm -rf * + rm -rf ../firmware/* + echo "Neopixel is using GPIO15(OUTPUT_DATA_PIN) on output DA." > ../firmware/Firmwares_for_Pimoroni_Plasma_2350.txt + echo "SPI is using spi1 interface pins: GPIO15(OUTPUT_SPI_DATA_PIN) and GPIO14(OUTPUT_SPI_CLOCK_PIN) on output DA and CL respectively." >> ../firmware/Firmwares_for_Pimoroni_Plasma_2350.txt + cmake -DTARGET_BOARD=pico2 -DOVERRIDE_DATA_PIN=15 -DOVERRIDE_SPI_INTERFACE=spi1 -DOVERRIDE_SPI_DATA_PIN=15 -DOVERRIDE_SPI_CLOCK_PIN=14 -DCMAKE_BUILD_TYPE=Release .. + cmake --build . + zip -j ../firmware/Pimoroni_Plasma_2350.zip ../firmware/* + + - uses: actions/upload-artifact@v7.0.0 + name: Upload artifacts (release Pimoroni_Plasma_2350) with: - name: firmware-release-pimoroni-plasma + name: firmware-release-pimoroni-plasma-rp2350 path: | firmware/*.zip diff --git a/CMakeLists.txt b/CMakeLists.txt index a6e0ad2..3aedd7a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,12 +33,26 @@ add_definitions ( -DPICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE=0 ) # initialize the SDK based on PICO_SDK_PATH # note: this must happen before project() set(PICO_SDK_PATH ${CMAKE_CURRENT_SOURCE_DIR}/sdk/pico) -set(FREERTOS_KERNEL_PATH ${CMAKE_CURRENT_SOURCE_DIR}/sdk/freertos) +# FreeRTOS config +add_library(freertos_config INTERFACE) +target_include_directories(freertos_config INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/sdk/config ) +set(FREERTOS_KERNEL_PATH "${CMAKE_CURRENT_SOURCE_DIR}/sdk/freertos") + +# Target: 'pico' (RP2040) or 'pico2' (RP2350) +set(TARGET_BOARD "pico" CACHE STRING "Target board: pico or pico2") +set(PICO_BOARD ${TARGET_BOARD}) include(${PICO_SDK_PATH}/external/pico_sdk_import.cmake) + +if (PICO_RP2350) + set(FREERTOS_PORT "GCC_ARM_CM33_NTZ" CACHE STRING "") +else() + set(FREERTOS_PORT "GCC_ARM_CM0" CACHE STRING "") +endif() + include(${FREERTOS_KERNEL_PATH}/portable/ThirdParty/GCC/RP2040/FreeRTOS_Kernel_import.cmake) -project(HyperSerialPico C CXX ASM) +project("HyperSerialPico_${PICO_CHIP}" C CXX ASM) set(CMAKE_C_STANDARD 11) set(CMAKE_CXX_STANDARD 17) @@ -53,8 +67,8 @@ ENDIF(CMAKE_COMPILER_IS_GNUCC) pico_sdk_init() # generic HyperSerialPico settings -set(HyperSerialPicoCompanionLibs FreeRTOS-Kernel FreeRTOS-Kernel-Heap1 pico_stdlib pico_multicore hardware_pio hardware_dma hardware_spi) set(HyperSerialPicoCompanionIncludes ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/sdk/config) +set(HyperSerialPicoCompanionLibs FreeRTOS-Kernel freertos_config FreeRTOS-Kernel-Heap4 pico_stdlib pico_multicore hardware_pio hardware_dma hardware_spi) file(MAKE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/generated) file(MAKE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/firmware) diff --git a/sdk/config/FreeRTOSConfig.h b/sdk/config/FreeRTOSConfig.h index 64902fc..6254710 100644 --- a/sdk/config/FreeRTOSConfig.h +++ b/sdk/config/FreeRTOSConfig.h @@ -47,7 +47,20 @@ #define configUSE_TICK_HOOK 0 #define configTICK_RATE_HZ ( ( TickType_t ) 1000 ) #define configMAX_PRIORITIES 32 -#define configMINIMAL_STACK_SIZE ( configSTACK_DEPTH_TYPE ) 256 +#ifdef __ARM_ARCH_8M_MAIN__ + #define configMINIMAL_STACK_SIZE ( ( configSTACK_DEPTH_TYPE ) 512 ) + #define configENABLE_FPU 0 + #define configENABLE_MPU 0 + #define configENABLE_TRUSTZONE 0 + #define configRUN_FREERTOS_SECURE_ONLY 1 + #define configPRIO_BITS 3 + #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x07 + #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 0x05 + #define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << ( 8 - configPRIO_BITS ) ) + #define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << ( 8 - configPRIO_BITS ) ) +#else + #define configMINIMAL_STACK_SIZE ( ( configSTACK_DEPTH_TYPE ) 256 ) +#endif #define configUSE_16_BIT_TICKS 0 #define configIDLE_SHOULD_YIELD 1 @@ -103,7 +116,7 @@ /* SMP port only */ #define configNUM_CORES 1 -#define configTICK_CORE 1 +#define configTICK_CORE 0 #define configRUN_MULTIPLE_PRIORITIES 1 /* RP2040 specific */ diff --git a/sdk/freertos b/sdk/freertos index 570ade4..9b777ae 160000 --- a/sdk/freertos +++ b/sdk/freertos @@ -1 +1 @@ -Subproject commit 570ade4001e50adbf06a074582ea993af562e0e1 +Subproject commit 9b777ae5c5b8e9e456065a00294d1e5f5f9facf5 diff --git a/sdk/pico b/sdk/pico index f396d05..a1438df 160000 --- a/sdk/pico +++ b/sdk/pico @@ -1 +1 @@ -Subproject commit f396d05f8252d4670d4ea05c8b7ac938ef0cd381 +Subproject commit a1438dff1d38bd9c65dbd693f0e5db4b9ae91779 From 58ba76d293d0fefe7409c2fb9a82ec65e4f1aeff Mon Sep 17 00:00:00 2001 From: Awawa <69086569+awawa-dev@users.noreply.github.com> Date: Tue, 21 Apr 2026 00:04:29 +0200 Subject: [PATCH 02/11] Increase stack --- sdk/config/FreeRTOSConfig.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/config/FreeRTOSConfig.h b/sdk/config/FreeRTOSConfig.h index 6254710..9c7eaab 100644 --- a/sdk/config/FreeRTOSConfig.h +++ b/sdk/config/FreeRTOSConfig.h @@ -48,7 +48,7 @@ #define configTICK_RATE_HZ ( ( TickType_t ) 1000 ) #define configMAX_PRIORITIES 32 #ifdef __ARM_ARCH_8M_MAIN__ - #define configMINIMAL_STACK_SIZE ( ( configSTACK_DEPTH_TYPE ) 512 ) + #define configMINIMAL_STACK_SIZE ( ( configSTACK_DEPTH_TYPE ) 2048 ) #define configENABLE_FPU 0 #define configENABLE_MPU 0 #define configENABLE_TRUSTZONE 0 @@ -59,7 +59,7 @@ #define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << ( 8 - configPRIO_BITS ) ) #define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << ( 8 - configPRIO_BITS ) ) #else - #define configMINIMAL_STACK_SIZE ( ( configSTACK_DEPTH_TYPE ) 256 ) + #define configMINIMAL_STACK_SIZE ( ( configSTACK_DEPTH_TYPE ) 512 ) #endif #define configUSE_16_BIT_TICKS 0 From 0263e8dc3f762fffce56ac005b7ceb1a3c740281 Mon Sep 17 00:00:00 2001 From: Awawa <69086569+awawa-dev@users.noreply.github.com> Date: Tue, 21 Apr 2026 04:02:49 +0200 Subject: [PATCH 03/11] Improved stability --- .github/workflows/push-master.yml | 70 +++++++++++++++++-------------- include/main.h | 5 +-- include/statistics.h | 23 ++++++++-- source/main.cpp | 5 +++ 4 files changed, 64 insertions(+), 39 deletions(-) diff --git a/.github/workflows/push-master.yml b/.github/workflows/push-master.yml index de25362..7502297 100644 --- a/.github/workflows/push-master.yml +++ b/.github/workflows/push-master.yml @@ -9,7 +9,7 @@ jobs: ########################### HyperSerialPico: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v6.0.2 @@ -19,7 +19,7 @@ jobs: - name: Install GNU Arm Embedded Toolchain uses: carlosperate/arm-none-eabi-gcc-action@v1 with: - release: '15.2.Rel1' + release: '14.2.Rel1' - name: Build packages shell: bash @@ -32,11 +32,11 @@ jobs: - uses: actions/upload-artifact@v7.0.0 name: Upload artifacts (release) with: - name: firmware-release-generic-rp2040 + name: firmware-release-generic-RP2040 path: | firmware/*.uf2 - - name: Build packages for generic rp2350 + - name: Build packages for generic RP2350 shell: bash run: | cd build @@ -44,12 +44,13 @@ jobs: rm -rf ../firmware/* cmake -DTARGET_BOARD=pico2 -DCMAKE_BUILD_TYPE=Release .. cmake --build . - zip -j ../firmware/firmware_generic_rp2350.zip ../firmware/* + zip -j ../firmware/firmware_generic_RP2350.zip ../firmware/* - uses: actions/upload-artifact@v7.0.0 - name: Upload artifacts (release generic rp2350) + name: Upload artifacts (release generic RP2350) with: - name: firmware-release-generic-rp2350 + name: firmware-release-generic-RP2350 + archive: false path: | firmware/*.zip @@ -59,16 +60,17 @@ jobs: cd build rm -rf * rm -rf ../firmware/* - echo "Neopixel is using GPIO16(OUTPUT_DATA_PIN) on output 0." > ../firmware/Firmwares_for_Adafruit_Feather_RP2040_Scorpio.txt - echo "SPI is using spi0 interface pins: GPIO19(OUTPUT_SPI_DATA_PIN) and GPIO18(OUTPUT_SPI_CLOCK_PIN) on output 3 and 2 respectively." >> ../firmware/Firmwares_for_Adafruit_Feather_RP2040_Scorpio.txt + echo "Neopixel is using GPIO16(OUTPUT_DATA_PIN) on output 0." > ../firmware/Pinout_for_Adafruit_Feather_RP2040_Scorpio.txt + echo "SPI is using spi0 interface pins: GPIO19(OUTPUT_SPI_DATA_PIN) and GPIO18(OUTPUT_SPI_CLOCK_PIN) on output 3 and 2 respectively." >> ../firmware/Pinout_for_Adafruit_Feather_RP2040_Scorpio.txt cmake -DOVERRIDE_BOOT_WORKAROUND=ON -DOVERRIDE_DATA_PIN=16 -DOVERRIDE_SPI_DATA_PIN=19 -DOVERRIDE_SPI_CLOCK_PIN=18 -DCMAKE_BUILD_TYPE=Release .. cmake --build . zip -j ../firmware/Adafruit_Feather_RP2040_Scorpio.zip ../firmware/* - uses: actions/upload-artifact@v7.0.0 - name: Upload artifacts (release Adafruit_Feather) + name: Upload artifacts (release for Adafruit_Feather_RP2040) with: - name: firmware-release-adafruit-scorpio + name: firmware-release-adafruit-scorpio-RP2040 + archive: false path: | firmware/*.zip @@ -78,35 +80,37 @@ jobs: cd build rm -rf * rm -rf ../firmware/* - echo "Neopixel is using GPIO14(OUTPUT_DATA_PIN) on output 5." > ../firmware/Firmwares_for_Adafruit_ItsyBitsy_2040.txt + echo "Neopixel is using GPIO14(OUTPUT_DATA_PIN) on output 5." > ../firmware/Pinout_for_Adafruit_ItsyBitsy_RP2040.txt cmake -DOVERRIDE_BOOT_WORKAROUND=ON -DOVERRIDE_DATA_PIN=14 -DCMAKE_BUILD_TYPE=Release .. cmake --build . rm ../firmware/*_Spi.uf2 - zip -j ../firmware/Adafruit_ItsyBitsy_2040.zip ../firmware/* + zip -j ../firmware/Adafruit_ItsyBitsy_RP2040.zip ../firmware/* - uses: actions/upload-artifact@v7.0.0 - name: Upload artifacts (release Adafruit_ItsyBitsy_2040) + name: Upload artifacts (release for Adafruit_ItsyBitsy_RP2040) with: - name: firmware-release-adafruit-itsybitsy-2040 + name: firmware-release-adafruit-itsybitsy-RP2040 + archive: false path: | firmware/*.zip - - name: Build packages for Pimoroni Plasma Stick 2040 W + - name: Build packages for Pimoroni Plasma Stick RP2040 W shell: bash run: | cd build rm -rf * rm -rf ../firmware/* - echo "Neopixel is using GPIO15(OUTPUT_DATA_PIN) on output PIXELS." > ../firmware/Firmwares_for_Pimoroni_Plasma_Stick_2040_W.txt + echo "Neopixel is using GPIO15(OUTPUT_DATA_PIN) on output PIXELS." > ../firmware/Pinout_for_Pimoroni_Plasma_Stick_RP2040_W.txt cmake -DOVERRIDE_DATA_PIN=15 -DCMAKE_BUILD_TYPE=Release .. cmake --build . rm ../firmware/*_Spi.uf2 - zip -j ../firmware/Pimoroni_Plasma_Stick_2040_W.zip ../firmware/* + zip -j ../firmware/Pimoroni_Plasma_Stick_RP2040_W.zip ../firmware/* - uses: actions/upload-artifact@v7.0.0 - name: Upload artifacts (release Pimoroni_Plasma_Stick_2040_W) + name: Upload artifacts (release for Pimoroni_Plasma_Stick_RP2040_W) with: - name: firmware-release-pimoroni-plasma-stick-2040-w + name: firmware-release-pimoroni-plasma-stick-RP2040-W + archive: false path: | firmware/*.zip @@ -116,35 +120,37 @@ jobs: cd build rm -rf * rm -rf ../firmware/* - echo "Neopixel is using GPIO15(OUTPUT_DATA_PIN) on output DA." > ../firmware/Firmwares_for_Pimoroni_Plasma_2040.txt - echo "SPI is using spi1 interface pins: GPIO15(OUTPUT_SPI_DATA_PIN) and GPIO14(OUTPUT_SPI_CLOCK_PIN) on output DA and CL respectively." >> ../firmware/Firmwares_for_Pimoroni_Plasma_2040.txt + echo "Neopixel is using GPIO15(OUTPUT_DATA_PIN) on output DA." > ../firmware/Pinout_for_Pimoroni_Plasma_RP2040.txt + echo "SPI is using spi1 interface pins: GPIO15(OUTPUT_SPI_DATA_PIN) and GPIO14(OUTPUT_SPI_CLOCK_PIN) on output DA and CL respectively." >> ../firmware/Pinout_for_Pimoroni_Plasma_RP2040.txt cmake -DOVERRIDE_DATA_PIN=15 -DOVERRIDE_SPI_INTERFACE=spi1 -DOVERRIDE_SPI_DATA_PIN=15 -DOVERRIDE_SPI_CLOCK_PIN=14 -DCMAKE_BUILD_TYPE=Release .. cmake --build . - zip -j ../firmware/Pimoroni_Plasma_2040.zip ../firmware/* + zip -j ../firmware/Pimoroni_Plasma_RP2040.zip ../firmware/* - uses: actions/upload-artifact@v7.0.0 - name: Upload artifacts (release Pimoroni_Plasma_2040) + name: Upload artifacts (release for Pimoroni_Plasma_RP2040) with: - name: firmware-release-pimoroni-plasma-2040 + name: firmware-release-pimoroni-plasma-RP2040 + archive: false path: | firmware/*.zip - - name: Build packages for Pimoroni Plasma 2350 + - name: Build packages for Pimoroni Plasma RP2350 shell: bash run: | cd build rm -rf * rm -rf ../firmware/* - echo "Neopixel is using GPIO15(OUTPUT_DATA_PIN) on output DA." > ../firmware/Firmwares_for_Pimoroni_Plasma_2350.txt - echo "SPI is using spi1 interface pins: GPIO15(OUTPUT_SPI_DATA_PIN) and GPIO14(OUTPUT_SPI_CLOCK_PIN) on output DA and CL respectively." >> ../firmware/Firmwares_for_Pimoroni_Plasma_2350.txt + echo "Neopixel is using GPIO15(OUTPUT_DATA_PIN) on output DA." > ../firmware/Pinout_for_Pimoroni_Plasma_RP2350.txt + echo "SPI is using spi1 interface pins: GPIO15(OUTPUT_SPI_DATA_PIN) and GPIO14(OUTPUT_SPI_CLOCK_PIN) on output DA and CL respectively." >> ../firmware/Pinout_for_Pimoroni_Plasma_RP2350.txt cmake -DTARGET_BOARD=pico2 -DOVERRIDE_DATA_PIN=15 -DOVERRIDE_SPI_INTERFACE=spi1 -DOVERRIDE_SPI_DATA_PIN=15 -DOVERRIDE_SPI_CLOCK_PIN=14 -DCMAKE_BUILD_TYPE=Release .. cmake --build . - zip -j ../firmware/Pimoroni_Plasma_2350.zip ../firmware/* + zip -j ../firmware/Pimoroni_Plasma_RP2350.zip ../firmware/* - uses: actions/upload-artifact@v7.0.0 - name: Upload artifacts (release Pimoroni_Plasma_2350) + name: Upload artifacts (release for Pimoroni_Plasma_RP2350) with: - name: firmware-release-pimoroni-plasma-rp2350 + name: firmware-release-pimoroni-plasma-RP2350 + archive: false path: | firmware/*.zip @@ -156,7 +162,7 @@ jobs: name: Publish Releases if: startsWith(github.event.ref, 'refs/tags') needs: [HyperSerialPico] - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 permissions: contents: write steps: diff --git a/include/main.h b/include/main.h index 3f0fca6..cc7e087 100644 --- a/include/main.h +++ b/include/main.h @@ -151,10 +151,7 @@ void processData() } else if (frameState.getCount() == 0x2aa2 && (input == 0x15 || input == 0x35)) { - statistics.print(currentTime, base.processDataHandle, base.processSerialHandle); - - if (input == 0x15) - printf(HELLO_MESSAGE); + statistics.print(currentTime, &base.receiverSemaphore, input == 0x15); frameState.setRegroup(true); diff --git a/include/statistics.h b/include/statistics.h index 8629179..189b0d0 100644 --- a/include/statistics.h +++ b/include/statistics.h @@ -28,6 +28,8 @@ #ifndef STATISTICS_H #define STATISTICS_H +#include + // statistics (stats sent only when there is no communication) class { @@ -38,8 +40,11 @@ class uint16_t finalGoodFrames = 0; uint16_t finalShowFrames = 0; uint16_t finalTotalFrames = 0; + std::atomic welcomeMessage = false; public: + std::atomic printLogs = false; + /** * @brief Get the start time of the current period * @@ -113,15 +118,22 @@ class * @param curTime * @param taskHandle */ - void print(unsigned long curTime, TaskHandle_t taskHandle1, TaskHandle_t taskHandle2) + void print(unsigned long curTime, semaphore_t* receiverSemaphore, bool isWelcome) { - char output[128]; - startTime = curTime; goodFrames = 0; totalFrames = 0; showFrames = 0; + welcomeMessage.store(isWelcome); + printLogs.store(true); + sem_release(receiverSemaphore); + } + + void printToSerial(TaskHandle_t taskHandle1, TaskHandle_t taskHandle2) + { + char output[128]; + snprintf(output, sizeof(output), "HyperHDR frames: %u (FPS), receiv.: %u, good: %u, incompl.: %u, mem1: %i, mem2: %i, heap: %zu\r\n", finalShowFrames, finalTotalFrames,finalGoodFrames,(finalTotalFrames - finalGoodFrames), (taskHandle1 != nullptr) ? uxTaskGetStackHighWaterMark(taskHandle1) : 0, @@ -132,6 +144,11 @@ class #if defined(NEOPIXEL_RGBW) calibrationConfig.printCalibration(); #endif + + if (welcomeMessage.exchange(false)) + { + printf(HELLO_MESSAGE); + } } /** diff --git a/source/main.cpp b/source/main.cpp index ada0f73..45221f9 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -153,6 +153,11 @@ static void core0( void *pvParameters ) } }while(wanted == received); + if (statistics.printLogs.exchange(false)) + { + statistics.printToSerial(base.processDataHandle, base.processSerialHandle); + } + sem_release(&base.serialSemaphore); } } From 02c737ab7d98952dc9e5ec25071f48ac1eda8f28 Mon Sep 17 00:00:00 2001 From: Awawa <69086569+awawa-dev@users.noreply.github.com> Date: Tue, 21 Apr 2026 22:06:06 +0200 Subject: [PATCH 04/11] Target: pimoroni_plasma2350 --- .github/workflows/push-master.yml | 2 +- include/calibration.h | 5 ++--- include/statistics.h | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/push-master.yml b/.github/workflows/push-master.yml index 7502297..f2dc2db 100644 --- a/.github/workflows/push-master.yml +++ b/.github/workflows/push-master.yml @@ -142,7 +142,7 @@ jobs: rm -rf ../firmware/* echo "Neopixel is using GPIO15(OUTPUT_DATA_PIN) on output DA." > ../firmware/Pinout_for_Pimoroni_Plasma_RP2350.txt echo "SPI is using spi1 interface pins: GPIO15(OUTPUT_SPI_DATA_PIN) and GPIO14(OUTPUT_SPI_CLOCK_PIN) on output DA and CL respectively." >> ../firmware/Pinout_for_Pimoroni_Plasma_RP2350.txt - cmake -DTARGET_BOARD=pico2 -DOVERRIDE_DATA_PIN=15 -DOVERRIDE_SPI_INTERFACE=spi1 -DOVERRIDE_SPI_DATA_PIN=15 -DOVERRIDE_SPI_CLOCK_PIN=14 -DCMAKE_BUILD_TYPE=Release .. + cmake -DTARGET_BOARD=pimoroni_plasma2350 -DOVERRIDE_DATA_PIN=15 -DOVERRIDE_SPI_INTERFACE=spi1 -DOVERRIDE_SPI_DATA_PIN=15 -DOVERRIDE_SPI_CLOCK_PIN=14 -DCMAKE_BUILD_TYPE=Release .. cmake --build . zip -j ../firmware/Pimoroni_Plasma_RP2350.zip ../firmware/* diff --git a/include/calibration.h b/include/calibration.h index cd7cf50..8d7b4a9 100644 --- a/include/calibration.h +++ b/include/calibration.h @@ -125,10 +125,9 @@ class CalibrationConfig * @brief print RGBW calibration parameters when no data is received * */ - void printCalibration() + void printCalibration(char* output, size_t outputSize) { - char output[128]; - snprintf(output, sizeof(output),"RGBW => Gain: %i/255, red: %i, green: %i, blue: %i\r\n", gain, red, green, blue); + snprintf(output, outputSize,"RGBW => Gain: %i/255, red: %i, green: %i, blue: %i\r\n", gain, red, green, blue); printf(output); } } calibrationConfig; diff --git a/include/statistics.h b/include/statistics.h index 189b0d0..2c0ecc9 100644 --- a/include/statistics.h +++ b/include/statistics.h @@ -142,7 +142,7 @@ class printf(output); #if defined(NEOPIXEL_RGBW) - calibrationConfig.printCalibration(); + calibrationConfig.printCalibration(output, sizeof(output)); #endif if (welcomeMessage.exchange(false)) From 9c0b84bffe02d91da7b3d7c2e52c52400d2c5016 Mon Sep 17 00:00:00 2001 From: Awawa <69086569+awawa-dev@users.noreply.github.com> Date: Wed, 22 Apr 2026 01:30:37 +0200 Subject: [PATCH 05/11] Fix semaphore communication conflict --- include/base.h | 2 +- include/calibration.h | 7 ++++--- include/main.h | 2 +- include/statistics.h | 10 +++++----- source/main.cpp | 24 +++++++++++++++++++++--- 5 files changed, 32 insertions(+), 13 deletions(-) diff --git a/include/base.h b/include/base.h index 9857b64..41330a9 100644 --- a/include/base.h +++ b/include/base.h @@ -47,7 +47,7 @@ class Base TaskHandle_t processSerialHandle = nullptr; // semaphore to synchronize them semaphore_t serialSemaphore; - semaphore_t receiverSemaphore; + SemaphoreHandle_t receiverSemaphore; // current queue position volatile int queueCurrent = 0; // queue end position diff --git a/include/calibration.h b/include/calibration.h index 8d7b4a9..0ce8ae3 100644 --- a/include/calibration.h +++ b/include/calibration.h @@ -125,10 +125,11 @@ class CalibrationConfig * @brief print RGBW calibration parameters when no data is received * */ - void printCalibration(char* output, size_t outputSize) + template + void printCalibration(char (&output)[N]) { - snprintf(output, outputSize,"RGBW => Gain: %i/255, red: %i, green: %i, blue: %i\r\n", gain, red, green, blue); - printf(output); + snprintf(output, N, "RGBW => Gain: %i/255, red: %i, green: %i, blue: %i\r\n", gain, red, green, blue); + fputs(output, stdout); } } calibrationConfig; diff --git a/include/main.h b/include/main.h index cc7e087..b993404 100644 --- a/include/main.h +++ b/include/main.h @@ -151,7 +151,7 @@ void processData() } else if (frameState.getCount() == 0x2aa2 && (input == 0x15 || input == 0x35)) { - statistics.print(currentTime, &base.receiverSemaphore, input == 0x15); + statistics.print(currentTime, input == 0x15); frameState.setRegroup(true); diff --git a/include/statistics.h b/include/statistics.h index 2c0ecc9..533c044 100644 --- a/include/statistics.h +++ b/include/statistics.h @@ -118,7 +118,7 @@ class * @param curTime * @param taskHandle */ - void print(unsigned long curTime, semaphore_t* receiverSemaphore, bool isWelcome) + void print(unsigned long curTime, bool isWelcome) { startTime = curTime; goodFrames = 0; @@ -127,7 +127,7 @@ class welcomeMessage.store(isWelcome); printLogs.store(true); - sem_release(receiverSemaphore); + multicore_fifo_push_blocking(0xFF); } void printToSerial(TaskHandle_t taskHandle1, TaskHandle_t taskHandle2) @@ -139,15 +139,15 @@ class (taskHandle1 != nullptr) ? uxTaskGetStackHighWaterMark(taskHandle1) : 0, (taskHandle2 != nullptr) ? uxTaskGetStackHighWaterMark(taskHandle2) : 0, xPortGetFreeHeapSize()); - printf(output); + fputs(output, stdout); #if defined(NEOPIXEL_RGBW) - calibrationConfig.printCalibration(output, sizeof(output)); + calibrationConfig.printCalibration(output); #endif if (welcomeMessage.exchange(false)) { - printf(HELLO_MESSAGE); + fputs(HELLO_MESSAGE, stdout); } } diff --git a/source/main.cpp b/source/main.cpp index 45221f9..dff21ec 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -30,6 +30,9 @@ #include "FreeRTOS.h" #include "task.h" +#include "pico/multicore.h" +#include "hardware/irq.h" +#include "semphr.h" #include #include #include "pico/stdio/driver.h" @@ -140,7 +143,7 @@ static void core0( void *pvParameters ) { for( ;; ) { - if (sem_acquire_timeout_us(&base.receiverSemaphore, portMAX_DELAY)) + if (xSemaphoreTake(base.receiverSemaphore, portMAX_DELAY) == pdTRUE) { int wanted, received; do @@ -156,6 +159,8 @@ static void core0( void *pvParameters ) if (statistics.printLogs.exchange(false)) { statistics.printToSerial(base.processDataHandle, base.processSerialHandle); + stdio_flush(); + vTaskDelay(pdMS_TO_TICKS(2)); } sem_release(&base.serialSemaphore); @@ -165,7 +170,16 @@ static void core0( void *pvParameters ) static void serialEvent(void *) { - sem_release(&base.receiverSemaphore); + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + xSemaphoreGiveFromISR(base.receiverSemaphore, &xHigherPriorityTaskWoken); + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); +} + +void on_fifo_irq() +{ + multicore_fifo_drain(); + + serialEvent(nullptr); } int main(void) @@ -174,7 +188,11 @@ int main(void) sem_init(&base.serialSemaphore, 0, 1); - sem_init(&base.receiverSemaphore, 0, 1); + base.receiverSemaphore = xSemaphoreCreateBinary(); + + multicore_fifo_clear_irq(); + irq_set_exclusive_handler(SIO_IRQ_FIFO, on_fifo_irq); + irq_set_enabled(SIO_IRQ_FIFO, true); multicore_launch_core1(core1); From ed74f651b329b85fd126b4c4ef81bdb0747bbd33 Mon Sep 17 00:00:00 2001 From: Awawa <69086569+awawa-dev@users.noreply.github.com> Date: Wed, 22 Apr 2026 14:13:23 +0200 Subject: [PATCH 06/11] Increase buffers --- CMakeLists.txt | 7 +++++++ source/main.cpp | 6 +++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3aedd7a..74c0f22 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -128,6 +128,13 @@ macro(HyperSerialPicoTarget HyperSerialPicoTargetName) if (BOOT_WORKAROUND) target_compile_definitions(${HyperSerialPicoTargetName} PUBLIC -DBOOT_WORKAROUND -DPICO_XOSC_STARTUP_DELAY_MULTIPLIER=64) endif() + + target_compile_definitions(${HyperSerialPicoTargetName} PRIVATE + CFG_TUD_CDC_RX_BUFSIZE=8192 + CFG_TUD_CDC_EP_BUFSIZE=2048 + CFG_TUD_CDC_TX_BUFSIZE=512 + ) + target_include_directories(${HyperSerialPicoTargetName} PRIVATE ${HyperSerialPicoCompanionIncludes}) target_link_libraries(${HyperSerialPicoTargetName} ${HyperSerialPicoCompanionLibs}) pico_add_extra_outputs(${HyperSerialPicoTargetName}) diff --git a/source/main.cpp b/source/main.cpp index dff21ec..5368e54 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -126,6 +126,10 @@ #define yield() busy_wait_us(100) #define millis xTaskGetTickCount +#if !defined(SIO_IRQ_FIFO) && defined(PICO_RP2040) + #define SIO_IRQ_FIFO SIO_IRQ_PROC0 +#endif + #include "main.h" static void core1() @@ -160,7 +164,7 @@ static void core0( void *pvParameters ) { statistics.printToSerial(base.processDataHandle, base.processSerialHandle); stdio_flush(); - vTaskDelay(pdMS_TO_TICKS(2)); + vTaskDelay(pdMS_TO_TICKS(5)); } sem_release(&base.serialSemaphore); From 6657de1c5b6374b40211344c8d44ec345ea50b5e Mon Sep 17 00:00:00 2001 From: Awawa <69086569+awawa-dev@users.noreply.github.com> Date: Wed, 22 Apr 2026 15:01:55 +0200 Subject: [PATCH 07/11] Fix communication --- source/main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/main.cpp b/source/main.cpp index 5368e54..49b1098 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -163,8 +163,6 @@ static void core0( void *pvParameters ) if (statistics.printLogs.exchange(false)) { statistics.printToSerial(base.processDataHandle, base.processSerialHandle); - stdio_flush(); - vTaskDelay(pdMS_TO_TICKS(5)); } sem_release(&base.serialSemaphore); @@ -181,7 +179,9 @@ static void serialEvent(void *) void on_fifo_irq() { - multicore_fifo_drain(); + while (multicore_fifo_rvalid()) { + multicore_fifo_pop_blocking(); + } serialEvent(nullptr); } From 88b794b307233259fb70be7576c4972d428b9fe4 Mon Sep 17 00:00:00 2001 From: Awawa <69086569+awawa-dev@users.noreply.github.com> Date: Wed, 22 Apr 2026 19:10:44 +0200 Subject: [PATCH 08/11] Fix for bare metal core1 --- .github/workflows/push-master.yml | 2 ++ CMakeLists.txt | 2 +- include/base.h | 1 - include/calibration.h | 2 +- include/main.h | 3 --- include/statistics.h | 11 +++++----- source/main.cpp | 34 ++++++++++++++++++++----------- 7 files changed, 31 insertions(+), 24 deletions(-) diff --git a/.github/workflows/push-master.yml b/.github/workflows/push-master.yml index f2dc2db..01aeec0 100644 --- a/.github/workflows/push-master.yml +++ b/.github/workflows/push-master.yml @@ -84,6 +84,7 @@ jobs: cmake -DOVERRIDE_BOOT_WORKAROUND=ON -DOVERRIDE_DATA_PIN=14 -DCMAKE_BUILD_TYPE=Release .. cmake --build . rm ../firmware/*_Spi.uf2 + rm ../firmware/*_ws2801.uf2 zip -j ../firmware/Adafruit_ItsyBitsy_RP2040.zip ../firmware/* - uses: actions/upload-artifact@v7.0.0 @@ -104,6 +105,7 @@ jobs: cmake -DOVERRIDE_DATA_PIN=15 -DCMAKE_BUILD_TYPE=Release .. cmake --build . rm ../firmware/*_Spi.uf2 + rm ../firmware/*_ws2801.uf2 zip -j ../firmware/Pimoroni_Plasma_Stick_RP2040_W.zip ../firmware/* - uses: actions/upload-artifact@v7.0.0 diff --git a/CMakeLists.txt b/CMakeLists.txt index 74c0f22..fbf49fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,7 +68,7 @@ pico_sdk_init() # generic HyperSerialPico settings set(HyperSerialPicoCompanionIncludes ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/sdk/config) -set(HyperSerialPicoCompanionLibs FreeRTOS-Kernel freertos_config FreeRTOS-Kernel-Heap4 pico_stdlib pico_multicore hardware_pio hardware_dma hardware_spi) +set(HyperSerialPicoCompanionLibs FreeRTOS-Kernel freertos_config FreeRTOS-Kernel-Heap1 pico_stdlib pico_multicore hardware_pio hardware_dma hardware_spi) file(MAKE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/generated) file(MAKE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/firmware) diff --git a/include/base.h b/include/base.h index 41330a9..b4a90b0 100644 --- a/include/base.h +++ b/include/base.h @@ -46,7 +46,6 @@ class Base TaskHandle_t processDataHandle = nullptr; TaskHandle_t processSerialHandle = nullptr; // semaphore to synchronize them - semaphore_t serialSemaphore; SemaphoreHandle_t receiverSemaphore; // current queue position volatile int queueCurrent = 0; diff --git a/include/calibration.h b/include/calibration.h index 0ce8ae3..5d334c7 100644 --- a/include/calibration.h +++ b/include/calibration.h @@ -129,7 +129,7 @@ class CalibrationConfig void printCalibration(char (&output)[N]) { snprintf(output, N, "RGBW => Gain: %i/255, red: %i, green: %i, blue: %i\r\n", gain, red, green, blue); - fputs(output, stdout); + tud_cdc_write_str(output); } } calibrationConfig; diff --git a/include/main.h b/include/main.h index b993404..3409581 100644 --- a/include/main.h +++ b/include/main.h @@ -73,7 +73,6 @@ void processData() if (base.queueCurrent >= MAX_BUFFER) { base.queueCurrent = 0; - yield(); } switch (frameState.getState()) @@ -294,8 +293,6 @@ void processData() currentTime = millis(); deltaTime = currentTime - statistics.getStartTime(); updateMainStatistics(currentTime, deltaTime, true); - - yield(); } frameState.setState(AwaProtocol::HEADER_A); diff --git a/include/statistics.h b/include/statistics.h index 533c044..2ede349 100644 --- a/include/statistics.h +++ b/include/statistics.h @@ -130,16 +130,15 @@ class multicore_fifo_push_blocking(0xFF); } - void printToSerial(TaskHandle_t taskHandle1, TaskHandle_t taskHandle2) + void printToSerial(TaskHandle_t taskHandleCore0) { char output[128]; - snprintf(output, sizeof(output), "HyperHDR frames: %u (FPS), receiv.: %u, good: %u, incompl.: %u, mem1: %i, mem2: %i, heap: %zu\r\n", + snprintf(output, sizeof(output), "HyperHDR frames: %u (FPS), receiv.: %u, good: %u, incompl.: %u, core0: %i, heap: %zu\r\n", finalShowFrames, finalTotalFrames,finalGoodFrames,(finalTotalFrames - finalGoodFrames), - (taskHandle1 != nullptr) ? uxTaskGetStackHighWaterMark(taskHandle1) : 0, - (taskHandle2 != nullptr) ? uxTaskGetStackHighWaterMark(taskHandle2) : 0, + (taskHandleCore0 != nullptr) ? uxTaskGetStackHighWaterMark(taskHandleCore0) : 0, xPortGetFreeHeapSize()); - fputs(output, stdout); + tud_cdc_write_str(output); #if defined(NEOPIXEL_RGBW) calibrationConfig.printCalibration(output); @@ -147,7 +146,7 @@ class if (welcomeMessage.exchange(false)) { - fputs(HELLO_MESSAGE, stdout); + tud_cdc_write_str(HELLO_MESSAGE); } } diff --git a/source/main.cpp b/source/main.cpp index 49b1098..d96a83b 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -30,6 +30,7 @@ #include "FreeRTOS.h" #include "task.h" +#include "tusb.h" #include "pico/multicore.h" #include "hardware/irq.h" #include "semphr.h" @@ -136,10 +137,8 @@ static void core1() { for( ;; ) { - if (sem_acquire_timeout_us(&base.serialSemaphore, portMAX_DELAY)) - { - processData(); - } + [[maybe_unused]] auto val = multicore_fifo_pop_blocking(); + processData(); } } @@ -153,7 +152,11 @@ static void core0( void *pvParameters ) do { wanted = std::min(MAX_BUFFER - base.queueEnd, MAX_BUFFER - 1); - received = stdio_usb.in_chars((char*)(&(base.buffer[base.queueEnd])), wanted); + + if (stdio_usb_connected() && tud_cdc_available()) { + received = (int)tud_cdc_read(const_cast(&(base.buffer[base.queueEnd])), (uint32_t)wanted); + } + if (received > 0) { base.queueEnd = (base.queueEnd + received) % (MAX_BUFFER); @@ -162,19 +165,28 @@ static void core0( void *pvParameters ) if (statistics.printLogs.exchange(false)) { - statistics.printToSerial(base.processDataHandle, base.processSerialHandle); + statistics.printToSerial(base.processSerialHandle); + tud_cdc_write_flush(); + vTaskDelay(pdMS_TO_TICKS(5)); } - sem_release(&base.serialSemaphore); + multicore_fifo_push_blocking(0xAA); } } } static void serialEvent(void *) { - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - xSemaphoreGiveFromISR(base.receiverSemaphore, &xHigherPriorityTaskWoken); - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + if (xPortIsInsideInterrupt()) + { + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + xSemaphoreGiveFromISR(base.receiverSemaphore, &xHigherPriorityTaskWoken); + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + } + else + { + xSemaphoreGive(base.receiverSemaphore); + } } void on_fifo_irq() @@ -190,8 +202,6 @@ int main(void) { stdio_init_all(); - sem_init(&base.serialSemaphore, 0, 1); - base.receiverSemaphore = xSemaphoreCreateBinary(); multicore_fifo_clear_irq(); From 54bf8774616c17cbeb3575686cff763648099c36 Mon Sep 17 00:00:00 2001 From: Awawa <69086569+awawa-dev@users.noreply.github.com> Date: Mon, 27 Apr 2026 17:44:32 +0200 Subject: [PATCH 09/11] Removed stdio_usb, use only tinyUSB --- CMakeLists.txt | 15 +++---- include/base.h | 2 - include/main.h | 12 ++++-- include/statistics.h | 36 ++++++++-------- sdk/config/tusb_config.h | 41 ++++++++++++++++++ source/main.cpp | 89 +++++++++++----------------------------- 6 files changed, 101 insertions(+), 94 deletions(-) create mode 100644 sdk/config/tusb_config.h diff --git a/CMakeLists.txt b/CMakeLists.txt index fbf49fd..2c5c6e8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,8 +67,8 @@ ENDIF(CMAKE_COMPILER_IS_GNUCC) pico_sdk_init() # generic HyperSerialPico settings -set(HyperSerialPicoCompanionIncludes ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/sdk/config) -set(HyperSerialPicoCompanionLibs FreeRTOS-Kernel freertos_config FreeRTOS-Kernel-Heap1 pico_stdlib pico_multicore hardware_pio hardware_dma hardware_spi) +set(HyperSerialPicoCompanionIncludes ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/sdk/config ${PICO_SDK_PATH}/src/rp2_common/pico_stdio_usb/include ${PICO_SDK_PATH}/src/common/pico_usb_reset_interface_headers/include) +set(HyperSerialPicoCompanionLibs FreeRTOS-Kernel freertos_config FreeRTOS-Kernel-Heap1 tinyusb_board tinyusb_device pico_stdlib pico_multicore hardware_pio hardware_dma hardware_spi) file(MAKE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/generated) file(MAKE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/firmware) @@ -128,17 +128,14 @@ macro(HyperSerialPicoTarget HyperSerialPicoTargetName) if (BOOT_WORKAROUND) target_compile_definitions(${HyperSerialPicoTargetName} PUBLIC -DBOOT_WORKAROUND -DPICO_XOSC_STARTUP_DELAY_MULTIPLIER=64) endif() - - target_compile_definitions(${HyperSerialPicoTargetName} PRIVATE - CFG_TUD_CDC_RX_BUFSIZE=8192 - CFG_TUD_CDC_EP_BUFSIZE=2048 - CFG_TUD_CDC_TX_BUFSIZE=512 - ) + + target_compile_definitions(${HyperSerialPicoTargetName} PRIVATE -DPICO_STDIO_USB_USE_DEFAULT_DESCRIPTORS=1) + target_sources(${HyperSerialPicoTargetName} PRIVATE ${PICO_SDK_PATH}/src/rp2_common/pico_stdio_usb/stdio_usb_descriptors.c) target_include_directories(${HyperSerialPicoTargetName} PRIVATE ${HyperSerialPicoCompanionIncludes}) target_link_libraries(${HyperSerialPicoTargetName} ${HyperSerialPicoCompanionLibs}) pico_add_extra_outputs(${HyperSerialPicoTargetName}) - pico_enable_stdio_usb(${HyperSerialPicoTargetName} 1) + pico_enable_stdio_usb(${HyperSerialPicoTargetName} 0) pico_enable_stdio_uart(${HyperSerialPicoTargetName} 0) pico_generate_pio_header(${HyperSerialPicoTargetName} ${CMAKE_CURRENT_SOURCE_DIR}/pio/neopixel.pio OUTPUT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/generated) pico_generate_pio_header(${HyperSerialPicoTargetName} ${CMAKE_CURRENT_SOURCE_DIR}/pio/neopixel_ws2812b.pio OUTPUT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/generated) diff --git a/include/base.h b/include/base.h index b4a90b0..e48b41e 100644 --- a/include/base.h +++ b/include/base.h @@ -45,8 +45,6 @@ class Base // handle to tasks TaskHandle_t processDataHandle = nullptr; TaskHandle_t processSerialHandle = nullptr; - // semaphore to synchronize them - SemaphoreHandle_t receiverSemaphore; // current queue position volatile int queueCurrent = 0; // queue end position diff --git a/include/main.h b/include/main.h index 3409581..c18bf73 100644 --- a/include/main.h +++ b/include/main.h @@ -154,10 +154,16 @@ void processData() frameState.setRegroup(true); - delay(10); - currentTime = millis(); - statistics.reset(currentTime); + if (input == 0x15) + { + statistics.reset(currentTime); + } + else + { + statistics.lightReset(currentTime, true); + } + frameState.setState(AwaProtocol::HEADER_A); } else diff --git a/include/statistics.h b/include/statistics.h index 2ede349..8d756f2 100644 --- a/include/statistics.h +++ b/include/statistics.h @@ -37,13 +37,16 @@ class uint16_t goodFrames = 0; uint16_t showFrames = 0; uint16_t totalFrames = 0; - uint16_t finalGoodFrames = 0; - uint16_t finalShowFrames = 0; - uint16_t finalTotalFrames = 0; - std::atomic welcomeMessage = false; + + volatile struct { + uint16_t finalGoodFrames = 0; + uint16_t finalShowFrames = 0; + uint16_t finalTotalFrames = 0; + bool welcomeMessage = false; + } outputStatistics; public: - std::atomic printLogs = false; + std::atomic printLogs = false; /** * @brief Get the start time of the current period @@ -101,9 +104,9 @@ class { if (totalFrames > 0) { - finalShowFrames = showFrames; - finalGoodFrames = std::min(goodFrames, totalFrames); - finalTotalFrames = totalFrames; + outputStatistics.finalShowFrames = showFrames; + outputStatistics.finalGoodFrames = std::min(goodFrames, totalFrames); + outputStatistics.finalTotalFrames = totalFrames; } startTime = currentTime; @@ -124,10 +127,10 @@ class goodFrames = 0; totalFrames = 0; showFrames = 0; - - welcomeMessage.store(isWelcome); + + outputStatistics.welcomeMessage = isWelcome; + printLogs.store(true); - multicore_fifo_push_blocking(0xFF); } void printToSerial(TaskHandle_t taskHandleCore0) @@ -135,7 +138,8 @@ class char output[128]; snprintf(output, sizeof(output), "HyperHDR frames: %u (FPS), receiv.: %u, good: %u, incompl.: %u, core0: %i, heap: %zu\r\n", - finalShowFrames, finalTotalFrames,finalGoodFrames,(finalTotalFrames - finalGoodFrames), + outputStatistics.finalShowFrames, outputStatistics.finalTotalFrames, outputStatistics.finalGoodFrames, + (outputStatistics.finalTotalFrames - outputStatistics.finalGoodFrames), (taskHandleCore0 != nullptr) ? uxTaskGetStackHighWaterMark(taskHandleCore0) : 0, xPortGetFreeHeapSize()); tud_cdc_write_str(output); @@ -144,7 +148,7 @@ class calibrationConfig.printCalibration(output); #endif - if (welcomeMessage.exchange(false)) + if (outputStatistics.welcomeMessage) { tud_cdc_write_str(HELLO_MESSAGE); } @@ -158,9 +162,9 @@ class { startTime = currentTime; - finalShowFrames = 0; - finalGoodFrames = 0; - finalTotalFrames = 0; + outputStatistics.finalShowFrames = 0; + outputStatistics.finalGoodFrames = 0; + outputStatistics.finalTotalFrames = 0; goodFrames = 0; totalFrames = 0; diff --git a/sdk/config/tusb_config.h b/sdk/config/tusb_config.h new file mode 100644 index 0000000..7627157 --- /dev/null +++ b/sdk/config/tusb_config.h @@ -0,0 +1,41 @@ +#ifndef _TUSB_CONFIG_H_ +#define _TUSB_CONFIG_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// ----------------------------------------------------------------------------- +// COMMON CONFIGURATION +// ----------------------------------------------------------------------------- +#define CFG_TUSB_MCU OPT_MCU_RP2040 + +#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_FULL_SPEED) +#ifndef BOARD_TUD_RHPORT + #define BOARD_TUD_RHPORT 0 +#endif + +#define CFG_TUD_ENDPOINT0_SIZE 64 + +// ----------------------------------------------------------------------------- +// DEVICE CLASSES CONFIGURATION +// ----------------------------------------------------------------------------- +#define CFG_TUD_ENABLED 1 +#define CFG_TUD_CDC 1 +#define CFG_TUD_MSC 0 +#define CFG_TUD_HID 0 +#define CFG_TUD_MIDI 0 +#define CFG_TUD_VENDOR 0 + +// ----------------------------------------------------------------------------- +// CDC CONFIGURATION +// ----------------------------------------------------------------------------- +#define CFG_TUD_CDC_RX_BUFSIZE 8192 +#define CFG_TUD_CDC_EP_BUFSIZE 4096 +#define CFG_TUD_CDC_TX_BUFSIZE 768 + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_CONFIG_H_ */ \ No newline at end of file diff --git a/source/main.cpp b/source/main.cpp index d96a83b..516d98b 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -25,11 +25,9 @@ * SOFTWARE. */ -#define TUD_OPT_HIGH_SPEED - - #include "FreeRTOS.h" #include "task.h" +#include "tusb_config.h" #include "tusb.h" #include "pico/multicore.h" #include "hardware/irq.h" @@ -39,7 +37,6 @@ #include "pico/stdio/driver.h" #include "pico/stdlib.h" #include "pico/stdio.h" -#include "pico/stdio_usb.h" #include "pico/multicore.h" #include "pico/sem.h" #include "leds.h" @@ -127,10 +124,6 @@ #define yield() busy_wait_us(100) #define millis xTaskGetTickCount -#if !defined(SIO_IRQ_FIFO) && defined(PICO_RP2040) - #define SIO_IRQ_FIFO SIO_IRQ_PROC0 -#endif - #include "main.h" static void core1() @@ -142,76 +135,44 @@ static void core1() } } -static void core0( void *pvParameters ) -{ - for( ;; ) - { - if (xSemaphoreTake(base.receiverSemaphore, portMAX_DELAY) == pdTRUE) +void core0(void *pvParameters) { + tusb_init(); + while (1) { + tud_task(); + if (tud_cdc_connected()) { - int wanted, received; - do - { - wanted = std::min(MAX_BUFFER - base.queueEnd, MAX_BUFFER - 1); + // receive + if (tud_cdc_available()) { + int wanted, received; + do + { + wanted = std::min(MAX_BUFFER - base.queueEnd, MAX_BUFFER - 1); - if (stdio_usb_connected() && tud_cdc_available()) { - received = (int)tud_cdc_read(const_cast(&(base.buffer[base.queueEnd])), (uint32_t)wanted); - } + if (tud_cdc_connected() && tud_cdc_available()) { + received = (int)tud_cdc_read(const_cast(&(base.buffer[base.queueEnd])), (uint32_t)wanted); + } - if (received > 0) - { - base.queueEnd = (base.queueEnd + received) % (MAX_BUFFER); - } - }while(wanted == received); + if (received > 0) + { + base.queueEnd = (base.queueEnd + received) % (MAX_BUFFER); + } + }while(wanted == received); - if (statistics.printLogs.exchange(false)) - { + multicore_fifo_push_blocking(0xAA); + } + // send + else if (statistics.printLogs.exchange(false)) { statistics.printToSerial(base.processSerialHandle); tud_cdc_write_flush(); - vTaskDelay(pdMS_TO_TICKS(5)); } - - multicore_fifo_push_blocking(0xAA); - } - } -} - -static void serialEvent(void *) -{ - if (xPortIsInsideInterrupt()) - { - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - xSemaphoreGiveFromISR(base.receiverSemaphore, &xHigherPriorityTaskWoken); - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); - } - else - { - xSemaphoreGive(base.receiverSemaphore); + } } } -void on_fifo_irq() -{ - while (multicore_fifo_rvalid()) { - multicore_fifo_pop_blocking(); - } - - serialEvent(nullptr); -} - int main(void) { - stdio_init_all(); - - base.receiverSemaphore = xSemaphoreCreateBinary(); - - multicore_fifo_clear_irq(); - irq_set_exclusive_handler(SIO_IRQ_FIFO, on_fifo_irq); - irq_set_enabled(SIO_IRQ_FIFO, true); - multicore_launch_core1(core1); - stdio_set_chars_available_callback(serialEvent, nullptr); - xTaskCreate(core0, "HyperSerialPico:core0", configMINIMAL_STACK_SIZE * 2, From 5fdd05f77808ad80c76d6118a0206dd90bbd640e Mon Sep 17 00:00:00 2001 From: Awawa <69086569+awawa-dev@users.noreply.github.com> Date: Tue, 28 Apr 2026 18:21:28 +0200 Subject: [PATCH 10/11] Make tusb_config.h configurable --- sdk/config/tusb_config.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/sdk/config/tusb_config.h b/sdk/config/tusb_config.h index 7627157..643553b 100644 --- a/sdk/config/tusb_config.h +++ b/sdk/config/tusb_config.h @@ -30,9 +30,15 @@ // ----------------------------------------------------------------------------- // CDC CONFIGURATION // ----------------------------------------------------------------------------- -#define CFG_TUD_CDC_RX_BUFSIZE 8192 -#define CFG_TUD_CDC_EP_BUFSIZE 4096 -#define CFG_TUD_CDC_TX_BUFSIZE 768 +#ifndef CFG_TUD_CDC_RX_BUFSIZE + #define CFG_TUD_CDC_RX_BUFSIZE 8192 +#endif +#ifndef CFG_TUD_CDC_EP_BUFSIZE + #define CFG_TUD_CDC_EP_BUFSIZE 4096 +#endif +#ifndef CFG_TUD_CDC_TX_BUFSIZE + #define CFG_TUD_CDC_TX_BUFSIZE 768 +#endif #ifdef __cplusplus } From 80d405b108b074e4f763401bbc6b03ec522db491 Mon Sep 17 00:00:00 2001 From: Awawa <69086569+awawa-dev@users.noreply.github.com> Date: Fri, 8 May 2026 13:15:39 +0200 Subject: [PATCH 11/11] Fix PicoLada rendering library --- include/leds.h | 63 +++++++++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/include/leds.h b/include/leds.h index bb58f32..3e92162 100644 --- a/include/leds.h +++ b/include/leds.h @@ -77,7 +77,7 @@ #include #include -struct ColorGrb32 +struct __attribute__((packed)) ColorGrb32 { uint8_t notUsed; uint8_t B; @@ -99,7 +99,7 @@ struct ColorGrb32 }; }; -struct ColorGrb +struct __attribute__((packed)) ColorGrb { uint8_t B; uint8_t R; @@ -116,7 +116,7 @@ struct ColorGrb }; }; -struct ColorGrbw +struct __attribute__((packed)) ColorGrbw { uint8_t W; uint8_t B; @@ -138,7 +138,7 @@ struct ColorGrbw }; }; -struct ColorDotstartBgr +struct __attribute__((packed)) ColorDotstartBgr { uint8_t Brightness; uint8_t B; @@ -155,7 +155,7 @@ struct ColorDotstartBgr }; }; -struct ColorRgb +struct __attribute__((packed)) ColorRgb { uint8_t R; uint8_t G; @@ -202,7 +202,7 @@ class LedDriver dma = reinterpret_cast(calloc(dmaSize, 1)); } - ~LedDriver() + virtual ~LedDriver() { free(buffer); free(dma); @@ -234,22 +234,27 @@ class DmaClient lastRenderTime = 0; }; - ~DmaClient() + virtual ~DmaClient() { - for(int i = 0; i < 10 && isDmaBusy; i++) + for(int i = 0; i < 100 && isDmaBusy; i++) busy_wait_us(500); dma_channel_abort(PICO_DMA_CHANNEL); dma_channel_set_irq0_enabled(PICO_DMA_CHANNEL, false); - irq_set_enabled(DMA_IRQ_0, false); + irq_remove_handler(DMA_IRQ_0, dmaFinishReceiver); dma_channel_unclaim(PICO_DMA_CHANNEL); }; - void dmaConfigure(PIO _selectedPIO, uint _sm) + void dmaConfigure() { - selectedPIO = _selectedPIO; - stateIndex = _sm; + selectedPIO = pio0; + int sm = pio_claim_unused_sm(selectedPIO, false); + if (sm < 0) { + selectedPIO = pio1; + sm = pio_claim_unused_sm(selectedPIO, true); + } + stateIndex = (uint)sm; }; void initDmaPio(uint dataLenDword32) @@ -275,7 +280,7 @@ class DmaClient void assignDmaIrq() { - irq_set_exclusive_handler(DMA_IRQ_0, dmaFinishReceiver); + irq_add_shared_handler(DMA_IRQ_0, dmaFinishReceiver, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY); dma_channel_set_irq0_enabled(PICO_DMA_CHANNEL, true); irq_set_enabled(DMA_IRQ_0, true); }; @@ -284,7 +289,7 @@ class DmaClient bool isReadyBlocking() { - int wait = 200; + int wait = 2000; while(isDmaBusy && wait-- > 0) busy_wait_us(50); @@ -315,6 +320,9 @@ class Neopixel : public LedDriver, public DmaClient uint64_t resetTime; + uint programAddress; + const pio_program_t* pioProgram; + friend class NeopixelParallel; public: @@ -322,15 +330,14 @@ class Neopixel : public LedDriver, public DmaClient LedDriver(_ledsNumber, _pin, _dmaSize) { pio_sm_config smConfig; - uint programAddress; - dmaConfigure(pio0, 0); + dmaConfigure(); resetTime = _resetTime; if (lanes >= 1) { - programAddress = (timingType == NeopixelSubtype::ws2812b) ? - pio_add_program(selectedPIO, &neopixel_ws2812b_parallel_program) : pio_add_program(selectedPIO, &neopixel_parallel_program); + pioProgram = (timingType == NeopixelSubtype::ws2812b) ? &neopixel_ws2812b_parallel_program : &neopixel_parallel_program; + programAddress = pio_add_program(selectedPIO, pioProgram); for(uint i=_pin; i<_pin + lanes; i++){ pio_gpio_init(selectedPIO, i); @@ -340,12 +347,11 @@ class Neopixel : public LedDriver, public DmaClient neopixel_ws2812b_parallel_program_get_default_config(programAddress) : neopixel_parallel_program_get_default_config(programAddress); sm_config_set_out_pins(&smConfig, _pin, lanes); - sm_config_set_set_pins(&smConfig, _pin, lanes); } else { - programAddress = (timingType == NeopixelSubtype::ws2812b) ? - pio_add_program(selectedPIO, &neopixel_ws2812b_program) : pio_add_program(selectedPIO, &neopixel_program); + pioProgram = (timingType == NeopixelSubtype::ws2812b) ? &neopixel_ws2812b_program : &neopixel_program; + programAddress = pio_add_program(selectedPIO, pioProgram); pio_gpio_init(selectedPIO, _pin); @@ -366,6 +372,15 @@ class Neopixel : public LedDriver, public DmaClient initDmaPio(dmaSize / 4); } + virtual ~Neopixel() + { + pio_sm_set_enabled(selectedPIO, stateIndex, false); + pio_sm_clear_fifos(selectedPIO, stateIndex); + pio_sm_unclaim(selectedPIO, stateIndex); + + pio_remove_program(selectedPIO, pioProgram, programAddress); + } + uint8_t* getBufferMemory() { return buffer; @@ -440,7 +455,7 @@ class NeopixelParallel buffer = muxer->getBufferMemory(); } - ~NeopixelParallel() + virtual ~NeopixelParallel() { if (instances > 0) instances--; @@ -514,7 +529,7 @@ class Dotstar : public LedDriver, public DmaClient Dotstar(uint64_t _resetTime, int _ledsNumber, spi_inst_t* _spi, uint32_t _datapin, uint32_t _clockpin, int _dmaSize): LedDriver(_ledsNumber, _datapin, _clockpin, _dmaSize) { - dmaConfigure(pio0, 0); + dmaConfigure(); resetTime = _resetTime; spi_init(_spi, 10000000); @@ -583,7 +598,7 @@ class Ws2801 : public LedDriver, public DmaClient Ws2801(uint64_t _resetTime, int _ledsNumber, spi_inst_t* _spi, uint32_t _datapin, uint32_t _clockpin, int _dmaSize): LedDriver(_ledsNumber, _datapin, _clockpin, _dmaSize) { - dmaConfigure(pio0, 0); + dmaConfigure(); resetTime = _resetTime; spi_init(_spi, 1000000);