# AGENTS.md ## Repository Overview `PlantCtrl` is a mixed-discipline repo: two embedded Rust firmware targets, a shared crate, KiCad hardware, and a Hugo site. Top-level layout: - `Software/MainBoard/rust`: main firmware (`plant-ctrl2`) for ESP32-C6 controller board. - `Software/CAN_Sensor`: sensor firmware (`bms`) for CH32V203C8T6 (CAN sensor / BMS board). - `Software/Shared/canapi`: shared crate for CAN protocol/serialization — consumed by both firmware targets. - `Hardware`: KiCad PCB designs and 3D case files. - `DataSheets`: reference material; treat as source data, not generated output. - `website`: Hugo site (Blowfish theme via git submodule at `website/themes/blowfish`). - `bin`: helper scripts and dev tooling. ## Critical Constraints - **No Cargo workspace** — each project has its own `Cargo.toml` and `Cargo.lock`. Run checks with `--manifest-path`. - **Both firmware targets require `nightly` toolchain** (`rust-toolchain.toml`). Main board uses `build-std = ["alloc", "core"]` in `.cargo/config.toml`. - **`no_std`/`no_main`** — both firmware crates are bare-metal. Do not introduce `std`-only dependencies. - **Main board clippy rules** (`src/main.rs`): `#![deny(clippy::mem_forget, clippy::unwrap_used, clippy::expect_used, clippy::panic)]`. Do not add `#[allow(...)]` without explicit user request. - **mcutie** (`src/mcutie_3_0_0/`): vendored sub-crate with `#![deny(unreachable_pub)]` and `#![warn(missing_docs)]`. - **Flash layout** (main board `partitions.csv`): 16 MB total — `ota_0` (3968K), `ota_1` (3968K), `storage` (8M LittleFS), `nvs` (16K), `otadata` (8K), `phy_init` (4K). - **CH32V203C8T6 memory** (`CAN_Sensor/memory.x`): 64 KB flash, 20 KB RAM. Tight budget — avoid allocations. - **ESP IDF config** (`sdkconfig.defaults`): `CONFIG_ESP_MAIN_TASK_STACK_SIZE=50000`, `CONFIG_FREERTOS_HZ=1000`, `CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE=y`. ## Firmware Build & Flash ### Main Board (ESP32-C6) ``` # Quick check (no build): cargo check --manifest-path Software/MainBoard/rust/Cargo.toml # Full build + flash + monitor: bash Software/MainBoard/rust/flash.sh # Build only (no flash): cargo build --release --manifest-path Software/MainBoard/rust/Cargo.toml # Build OTA image without flashing: bash Software/MainBoard/rust/image_build.sh # Erase OTA data partition (recover from bad flash): bash Software/MainBoard/rust/erase_ota.sh ``` `flash.sh` rebuilds the webpack frontend (`src_webpack/`) then flashes via `espflash` at 921600 baud. The frontend is bundled into the firmware binary — do not run `npm` separately unless modifying `src_webpack/`. ### Sensor Board (CH32V203C8T6) ``` cargo check --manifest-path Software/CAN_Sensor/Cargo.toml cargo build --release --manifest-path Software/CAN_Sensor/Cargo.toml # Flash: wchisp flash Software/CAN_Sensor/target/riscv32imc-unknown-none-elf/release/bms ``` Runner is preconfigured in `.cargo/config.toml` as `wchisp flash`. Debug via `openocd` + `gdb` (scripts in `CAN_Sensor/bin/`). See `CAN_Sensor/README.md` for MCU unlock steps. ### Shared Crate ``` cargo check --manifest-path Software/Shared/canapi/Cargo.toml ``` ### Cross-impact Any change to `canapi` (IDs, frame layout, serialization) must be checked against both firmware targets. The crate uses `bincode` for serialization. ## Architecture Notes - **Main board entry**: `Software/MainBoard/rust/src/main.rs` — `#[esp_rtos::main]` async entry, Embassy executor, ESP-HAL. - **HAL layer**: `src/hal/mod.rs` defines `PlantHal` trait; `esp.rs` and `v4_hal.rs` are concrete implementations. - **mcutie**: `src/mcutie_3_0_0/` is a vendored MQTT/HA client library. - **Webserver**: `src/webserver/` serves OTA, logs, static files over HTTP. Frontend in `src_webpack/`. - **Sensor entry**: `Software/CAN_Sensor/src/main.rs` — `#[embassy_executor::main]` async entry, CH32-HAL, CAN + USB CDC. - **Both targets**: Embassy executor, `heapless` for heapless data structures, `option-lock` for optional state. ## Website ``` cd website npm run dev # starts Hugo dev server with Blowfish theme ``` Theme is a git submodule. Do not edit `website/themes/` directly — make customizations in `assets/` or `config/` instead. ## Working Rules - Keep changes tightly scoped to the user request; this repo spans hardware, firmware, and website code. - Preserve existing file structure and naming unless the user explicitly asks for restructuring. - Avoid mass formatting or opportunistic cleanup in KiCad files, lockfiles, generated assets, or vendored dependencies. - Do not edit dependency directories (`website/themes`, `src_webpack/node_modules`) unless explicitly asked. - When touching firmware code, keep resource usage and target constraints in mind; avoid unnecessary allocations or feature creep. - Shared protocol or serialization changes must be checked for impact across both firmware targets. ## Validation - Use the narrowest relevant check first. - Embedded firmware may require target-specific toolchains or hardware-adjacent tooling. If you cannot run a meaningful validation step, say so explicitly and describe the likely prerequisite. ## Handoff Expectations - Summarize what changed, where it changed, and any validation performed. - Call out follow-up work when a change likely affects both firmware targets, hardware assumptions, or the website.