pi_pico/cmake/cmake_config/mcu_config.cmake
Mohamed Salem b49c7f60bb Add WS2812B LED support via PIO with rainbow and color commands
MCU_PIO: generic PIO driver with config-driven program loading,
function-pointer init callbacks, blocking put, and DMA async put.
ws2812.pio written from scratch — 800 kHz, 10 cycles/bit, side-set.

HAL_LED: pixel buffer with intensity scaling, RGB byte order for
RP2040-Zero WS2812 variant. SetColor immediately pushes the strip.

APP_CLSW: rainbow HSV hue rotation on startup (auto-mode). Color
commands (red/green/blue/off/rainbow) stop the rainbow and set the
LED to a static color. Integer-only HSV-to-RGB conversion.

CMake: added hardware_pio link and pico_generate_pio_header for
ws2812.pio compilation. SYS_ECU init sequence updated.
2026-04-13 03:32:18 +02:00

107 lines
5.2 KiB
CMake

# ============================================================================
# mcu_config.cmake
# ----------------------------------------------------------------------------
# Encapsulates all Raspberry Pi Pico / RP2040 specific configuration.
# Depends on project_config.cmake having been included first (reads
# PROJECT_C_STANDARD).
#
# Because CMake forces a strict order (SDK bootstrap before project(),
# pico_sdk_init() after project(), linking after add_executable), this file
# exposes three macros/functions that the top-level CMakeLists.txt calls
# at the correct points in the build flow:
#
# mcu_init() - includes pico_sdk_import.cmake (pre-project)
# mcu_sdk_config() - runs pico_sdk_init() (post-project)
# mcu_link_target(target) - links SDK libs, configures stdio, emits UF2
# ============================================================================
# ----------------------------------------------------------------------------
# Step 1/3 - called BEFORE project() in the top-level CMakeLists.txt.
# Pulls in the Pico SDK bootstrap file so the ARM cross-compile toolchain
# (arm-none-eabi-gcc) is configured before CMake enables the project
# languages. Calling project() before this runs would cause CMake to detect
# the host compiler instead and produce a broken build.
# ----------------------------------------------------------------------------
macro(mcu_init)
# pico_sdk_import.cmake lives alongside the top-level CMakeLists.txt
# inside the cmake/ folder, so CMAKE_SOURCE_DIR (which points at cmake/
# when that file is the one being processed) is the right base path.
include(${CMAKE_SOURCE_DIR}/pico_sdk_import.cmake)
endmacro()
# ----------------------------------------------------------------------------
# Step 2/3 - called AFTER project() in the top-level CMakeLists.txt.
# Applies the C standard chosen in project_config.cmake and registers every
# Pico SDK library as a CMake target (pico_stdlib, hardware_uart,
# hardware_gpio, ...) so we can later pick only the ones we need.
# Note: pico_sdk_init() does NOT pull any libraries into the final binary
# by itself - it only makes them available as link targets.
# ----------------------------------------------------------------------------
macro(mcu_sdk_config)
set(CMAKE_C_STANDARD ${PROJECT_C_STANDARD})
set(CMAKE_C_STANDARD_REQUIRED ON)
pico_sdk_init()
endmacro()
# ----------------------------------------------------------------------------
# Step 3/3 - called AFTER add_executable() in the top-level CMakeLists.txt.
# Links only the Pico SDK libraries we actually use, routes stdio over
# USB-CDC so printf output is visible on the host serial monitor without
# any extra hardware, and emits the .uf2 file used for drag-and-drop
# flashing onto the Pico's mass-storage bootloader.
#
# Parameters:
# target - name of the executable target created with add_executable()
# ----------------------------------------------------------------------------
function(mcu_link_target target)
# Pick only the libraries we need:
# - pico_stdlib: core runtime, GPIO, clocks, basic init
# - hardware_uart: UART peripheral API (used by the MCU_UART driver)
# - hardware_dma: DMA controller API (used by MCU_UART + MCU_PIO async)
# - hardware_pio: PIO state machine API (used by MCU_PIO for WS2812 etc.)
target_link_libraries(${target} PRIVATE
pico_stdlib
hardware_uart
hardware_dma
hardware_pio
)
# Generate C header from PIO assembly programs. The generated header
# provides the compiled program struct (ws2812_program) and the
# ws2812_program_init() helper used by MCU_PIO_cfg.c. The header is
# placed in the build directory and automatically added to the
# target's include path.
pico_generate_pio_header(${target}
${PROJECT_ROOT_DIR}/src/MCU_PIO/pio/ws2812.pio)
# Route stdio over USB-CDC: the Pico will appear as a virtual serial
# port on the host when plugged in, so printf/getchar are visible in
# any serial monitor without needing a USB-to-UART adapter.
# 1 = enabled, 0 = disabled.
pico_enable_stdio_usb(${target} 1)
pico_enable_stdio_uart(${target} 0)
# Ask the SDK to generate the .uf2 (plus .hex, .bin, .map) alongside
# the .elf so the firmware can be flashed by dragging it onto the
# Pico's USB mass-storage device after holding BOOTSEL.
pico_add_extra_outputs(${target})
# Custom "flash" target: builds the firmware first (DEPENDS ensures
# the .uf2 is up to date), then runs flash.sh on the host to copy
# it to the Pico in BOOTSEL mode.
#
# Usage: cmake --build build --target flash
#
# NOTE: This target only works when cmake runs on the HOST macOS
# (not inside Docker), because it needs access to /Volumes/RPI-RP2.
# When running inside Docker, the target will fail with a clear error
# from flash.sh ("not found" or "/Volumes/RPI-RP2 not accessible").
add_custom_target(flash
COMMAND bash ${PROJECT_ROOT_DIR}/flash.sh
DEPENDS ${target}
WORKING_DIRECTORY ${PROJECT_ROOT_DIR}
COMMENT "Flashing firmware to Pico via USB mass storage"
VERBATIM
)
endfunction()