Contributing¶
Workflow¶
- Branch from
main:<your-name>/<short-description>(e.g.dhairya/vcu-can-heartbeat). - Open a PR; every change needs a review and a green presubmit before merge.
No direct pushes to
main. - Presubmit runs
bazel test //...(builds all firmware, runs host tests) andbazel run //tools/format:check. Run both locally before pushing.
Formatting¶
rewrites every tracked C/C++ file with the hermetic clang-format. Generated
code under boards/*/Core/ is excluded — never hand-format (or hand-edit) it.
Documentation¶
Docs live next to the code they describe: drop a README.md (or any
.md) in the directory it documents. CI builds the whole tree into a site
with MkDocs (mkdocs.yml) and publishes it to GitHub Pages on
every merge to main; README.md renders as that directory's index page.
You can also embed docs in source files — a comment block starting with
/** md (until **/) or lines starting with // md (until // end md)
is extracted as a page next to the file.
Preview locally:
PRs that touch docs run mkdocs build --strict, so broken links between
pages fail presubmit. Links to code files (BUILD files, configs) don't
exist on the site — use a full GitHub URL for those.
Adding a new board¶
Copy the layout of boards/VCU:
- Create the CubeMX project (
<name>.ioc) at the board root with "Generate peripheral initialization as a pair of .c/.h files per peripheral" enabled, targeting a Makefile toolchain. Generated code lands inCore/. - Hand-written bring-up (
main.cpp, clock config, LHAL adapter wiring) goes inBoard/. Application logic goes inApp/as a plaincc_librarydepending only on//drivers/lhal, so it runs in host tests and sims too (the per-family platform in//platformsselects a toolchain with the MCU flags baked in when cross-compiling). - Add a
BUILD.bazelcallingfirmware_project(see boards/VCU/BUILD.bazel) plus the linker script and startup file for your chip. - Add a
post_cubemx.shlike the VCU's.
Regenerating CubeMX code safely¶
Core/ is 100% CubeMX-owned; Board/ is 100% ours. That split is what makes
"Generate Code" safe:
- Edit the
.iocin CubeMX and generate. - Run the board's
post_cubemx.sh(deletes the generatedmain.c; our entry point isBoard/main.cpp). - If you changed the clock tree in CubeMX, mirror it by hand in
Board/main.cpp(ConfigureSystemClock()) — clock config is the one thing owned in both places. - Build and diff: only
Core/files should have changed.
Season policy¶
main is always the current car. Years live in git, not in directory names:
- Tag milestones:
season/2027/comp-michigan,season/2027/final. - When work on the next car starts, cut a
season/<year>maintenance branch from the final tag. Fixes for the running old car land there and are cherry-picked tomainif still relevant. - When hardware is scrapped, delete its
boards/directory onmain— history and the season branch keep it.