# 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 in `build/` - `docker compose run --rm pico-build bash` — interactive shell for debugging - `./flash.sh` — flash the `.uf2` to 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: 1. `include(project_config)` — defines variables 2. `include(mcu_config)` — defines helper macros (no side effects) 3. `mcu_init()` — includes `pico_sdk_import.cmake` (must be before `project()`) 4. `project(...)` 5. `mcu_sdk_config()` — calls `pico_sdk_init()` 6. `include(sources_config)` — sets `PROJECT_SOURCES` and `PROJECT_INCLUDE_DIRS` 7. `add_executable(...)` 8. `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`