Restructure repo so the root contains project folders. This allows adding more Pico projects (e.g., another_project/) alongside color_switcher/ in the same repository. All internal paths are relative and unchanged — cd into color_switcher/ to build/flash.
3.4 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project
Raspberry Pi Pico firmware that sends commands over UART to a host computer. Written entirely in C using the Pico SDK (RP2040 / Cortex-M0+).
Build System
All builds run inside Docker — no local toolchain required.
docker compose build— build the container image (first time / after Dockerfile changes)docker compose run --rm pico-build bash build.sh— compile the firmware, output lands inbuild/docker compose run --rm pico-build bash— interactive shell for debugging./flash.sh— flash the.uf2to a Pico in BOOTSEL mode (host-side only, not Docker)docker compose run --rm pico-build bash build.sh && ./flash.sh— build + flash in one command
The build uses CMake with the Pico SDK's ARM cross-compilation toolchain. The final artifact is a .uf2 file in build/. Flashing must run on the host macOS because it copies to /Volumes/RPI-RP2 (the Pico's USB mass storage mount).
Repository layout
color_switcher/
├── cmake/ # all build-system files
│ ├── CMakeLists.txt # thin orchestrator, drives build phases in order
│ ├── pico_sdk_import.cmake # Pico SDK bootstrap (copied from SDK)
│ └── cmake_config/
│ ├── project_config.cmake # project-wide vars (name, version, languages)
│ ├── mcu_config.cmake # MCU helpers: mcu_init / mcu_sdk_config / mcu_link_target
│ └── sources_config.cmake # source glob + include dir list
├── src/
│ ├── STD_TYPES/inc/ # shared fixed-width types, status enums, macros
│ ├── MCU_UART/{inc,prg,cfg}/ # hardware UART peripheral abstraction
│ ├── MCU_USB/{inc,prg,cfg}/ # USB-CDC (virtual serial port) abstraction
│ ├── HAL_COM/{inc,prg,cfg}/ # transport-agnostic comm layer (dispatches to UART/USB)
│ ├── APP_CLSW/{inc,prg,cfg}/ # color switcher application logic
│ └── SYS_ECU/prg/ # top-level app orchestrator (main entry)
├── build.sh # out-of-source build wrapper
├── Dockerfile / docker-compose.yml # containerized build env
Component file convention
Each component uses three subfolders:
inc/— public API headers (safe for any other component to#include)prg/— private header (*_priv.h) + implementation (*_prg.c)cfg/— configuration header and definitions (*_cfg.h/*_cfg.c)
CMake build phases
The top-level cmake/CMakeLists.txt runs in a strict order dictated by the Pico SDK:
include(project_config)— defines variablesinclude(mcu_config)— defines helper macros (no side effects)mcu_init()— includespico_sdk_import.cmake(must be beforeproject())project(...)mcu_sdk_config()— callspico_sdk_init()include(sources_config)— setsPROJECT_SOURCESandPROJECT_INCLUDE_DIRSadd_executable(...)mcu_link_target(...)—target_link_libraries, stdio routing, UF2 output
PROJECT_ROOT_DIR is computed in the top-level CMakeLists.txt as the parent of cmake/ and used everywhere that refers to paths outside the build system (e.g. src/).
Conventions
- Always add descriptive comments to all code and config files
- Avoid magic numbers — use named constants in
config.h