Skip to content

MECSEM/firmware

Repository files navigation

MECSEM Firmware

Firmware for the MECSEM controller stack. Each board is an independent RP2350 (Pico-SDK 2.2.0) target sharing a common library (mecsem-std/) and a protobuf-based message protocol (ext/mecsem_protobuf).

Safety notice. This firmware drives kV-level electronics and a vacuum system (turbo + roughing pump + isolation valve). Do not flash it onto hardware without the corresponding hardware and interlock review.

Boards

Directory Target board Role in the stack USB
lv-controller/ LV controller Roughing/turbo pump state machine, isolation-valve sequencing, Pirani gauge, HYVFD turbo control Dual CDC (mscf+console)
hv-controller/ HV controller ±5 kV inverter enables, six 5 kV amp setpoints, scintillator bias, raster scan, PMT readout, MSCF bridge to cathode controller Dual CDC + UART link to cathode controller
hv-inverter/ HV inverter (×2 variants) Buck control + arc detection for the negative 5 kV inverter and the positive scintillator bias Dual CDC
cathode-controller/ Cathode controller Battery-powered cathode/filament current loop and battery monitor UART MSCF only (USB disabled)
beam-align/ Beam alignment (×2 stages) Two independent ±0.5 A current sources for primary/secondary beam alignment magnetics Dual CDC

The cathode controller is battery-powered and isolated; it speaks MSCF (MECSEM communications format, see below) over UART to the HV controller, which bridges those messages to the host over USB.

Repository layout

firmware/
├── lv-controller/        # Per-board firmware distros (each has main.cpp,
├── hv-controller/        # Pinout.hpp, StateVariables.cpp, lib_config.hpp,
├── hv-inverter/          # CMakeLists.txt, and a board header)
├── cathode-controller/
├── beam-align/
├── mecsem-std/           # Shared library (scheduler, drivers, MSCF, state vars)
├── ext/                  # Submodules: pico-sdk, tinyusb, nanopb, fmt,
│                         #             mecsem_protobuf, openocd
│                         # plus mecsem-tinyusb.patch (see ext/tinyusb)
├── flash.sh              # ./flash.sh path/to/firmware.elf  (CMSIS-DAP via openocd)
├── start-openocd.sh      # Launch openocd for gdb attach
├── mecsem-openocd        # Wrapper that invokes ext/openocd/src/openocd
├── format.sh             # clang-format the tree (skips ext/ and build/)
└── cloc.sh               # SCC line-count report

Prerequisites

  • arm-none-eabi-gcc capable of C++23 (the CMake config sets CMAKE_CXX_STANDARD 23).
  • CMake >= 3.13 (per the per-board cmake_minimum_required).
  • Python 3 (Pico-SDK build scripts).
  • picotool — pulled in transitively by the Pico-SDK build.
  • clang-format if you intend to run format.sh.
  • openocd — a Raspberry Pi fork is vendored at ext/openocd and used by mecsem-openocd. Build it once: cd ext/openocd && ./bootstrap && ./configure && make.

Cloning

The build pulls in submodules, initialize with: git submodule update --init --recursive

Pinned submodule versions:

Submodule Version
ext/pico-sdk 2.2.0
ext/tinyusb 0.20.0 (patched, see below)
ext/nanopb 0.4.9.1
ext/fmt 12.1.0
ext/mecsem_protobuf tracks main
ext/openocd Raspberry Pi fork, sdk-2.2.0

Patched TinyUSB

ext/mecsem-tinyusb.patch factors tud_task_ext's inner switch into a new tud_task_iter(timeout_ms) so USBTask can timeslice it inside the cooperative scheduler. The patch is not auto-applied by CMake; apply it once after git submodule update:

cd ext/tinyusb
git apply ../mecsem-tinyusb.patch

See mecsem-std/Tasks/USB/README.md for details on what the patch changes and why.

Build & flash

Each board lives in its own CMake project. To build, e.g., the LV controller:

cd lv-controller
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j

The output ELF is lv-controller/build/lv-controller-firmware.elf (and .uf2/.bin/.hex/.map). Other boards follow the same pattern; the produced binary is named <board>-firmware.<ext>.

Flash via CMSIS-DAP (e.g., a Picoprobe):

./flash.sh lv-controller/build/lv-controller-firmware.elf

For interactive debugging:

./start-openocd.sh        # leaves openocd listening on :3333 / :4444
arm-none-eabi-gdb lv-controller/build/lv-controller-firmware.elf -ex 'target extended-remote :3333'

Debug builds (-DCMAKE_BUILD_TYPE=Debug) enable MECSEM_DEBUG_ENABLED, which turns on MECSEM_ASSERT and disables LTO/whole-program optimization.

Build variants

Two boards support per-build variants via a CMake-level define:

  • hv-inverter: define MECSEM_HV_INVERTER_SCINT to build the positive scintillator-bias variant (PID 0xABD0, product hv-scint-inverter); otherwise it builds the negative 5 kV inverter (PID 0xABCF, product hv-inverter).
  • beam-align: define MECSEM_BEAM_ALIGN_STAGE2 for the secondary stage (PID 0xABD2, beam-align-s2); otherwise it builds the primary stage (PID 0xABD1, beam-align-s1).

Pass the define via -DCMAKE_CXX_FLAGS=-DMECSEM_HV_INVERTER_SCINT or set it in the board's lib_config.hpp before configuring.

USB enumeration

USB-enabled boards expose two CDC ACM interfaces under VID 0xFEFE, manufacturer string "MECSEM":

Interface Index Descriptor name Purpose
CDC 0 0 mscf Binary protocol (nanopb + COBS framing + CRC32C); see mecsem-std/Interface/MSCFInterface.hpp
CDC 1 1 console Human-readable command shell (SerialTTY)

Per-board PIDs and product strings are in each board's lib_config.hpp (see the build-variants table above).

Code style

See .clang-format. Conventions:

  • Globals: g_camelCase
  • Constants: kPascalCase
  • State variables: SCREAMING_SNAKE_CASE (registered via MECSEM_DECL_STATE_VAR / MECSEM_IMPL_STATE_VAR — see mecsem-std/State/StateVariable.hpp)

Run ./format.sh from the repo root to format all in-tree C/C++ sources.

About

Board firmware & standard library

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors