pi_pico/cmake/cmake_config/mcu_config.cmake
Mohamed Salem f50e877ffc Implement MCU_UART driver with blocking and non-blocking TX
Full hardware UART driver with config-driven per-instance setup.
Non-blocking SendBuffer supports DMA (zero-CPU) and ISR (FIFO-fill)
modes selectable per instance in MCU_UART_cfg.h. Both modes and
blocking SendBufferBlocking invoke a configurable TX-complete
callback (STD_NULL to ignore). All public functions take a u8
instance parameter. Config uses struct-of-arrays pattern for
runtime state, designated-initializer array for per-instance
settings, and value enums in the public header for parity/data
bits/stop bits/async mode. Added hardware_dma to CMake link list.
2026-04-12 19:36:41 +02:00

97 lines
4.7 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 non-blocking TX)
target_link_libraries(${target} PRIVATE
pico_stdlib
hardware_uart
hardware_dma
)
# 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()