---
name: beyond-synaptics-firmware-build
description: How to build+package+flash the Beyond MCU firmware headlessly (no Microchip Studio) — runbook + gotchas
metadata: 
  node_type: memory
  type: reference
  originSessionId: 5600518d-ea58-44ca-8950-24c360b5c0d4
---

The Beyond MCU firmware (`../beyond_synaptics`, ATSAMG55/FreeRTOS) builds **fully headless** — do NOT install Microchip Studio. Full runbook: **`beyond_synaptics/docs/Build_And_Flash.md`** (committed on the `doze-warm-sleep` branch). Key facts so future sessions don't rediscover the half-day of debugging:

- **Toolchain**: arm-none-eabi-gcc 12.2 (`winget install Arm.ArmGnuToolchain`, lands at `C:\Program Files (x86)\Arm GNU Toolchain arm-none-eabi\12.2 mpacbti-rel1\bin`, NOT on PATH) + ninja (`winget install Ninja-build.Ninja`) + `pip install crc`. CMake/Ninja files live on the `build-cmake` branch.
- **Build Release (`-O3`), never Debug** — Debug fails to link (`circular_buffer_get` undefined: non-static `inline` in `tundra_uart.h` not inlined at `-Og`). Studio also ships `-O3`.
- **CMakeLists fixes** the `build-cmake` branch needs vs current `main`: project include dirs (`src/Devices`, `src/Drivers`, `src/config`, `src/crash_handler`) must come BEFORE the ASF/CMSIS dirs (samg55 CMSIS `adc.h` shadows `src/Drivers/adc.h` → cascade of unknown-type/implicit-decl errors); source-list drift `adc_driver.c`→`adc.c`, add `tundra_uart.c`. Authoritative source list = the `.cproj` `<Compile Include>` entries.
- **Package**: `usb_fw_packager_cli.py` raw .hex → AppImage (embeds len@0x400 + CRC32 the bootloader checks on boot) → `utility_fw_packager_cli.py` → `.beyondfw`. Use absolute paths (packager mangles leading `../`).
- **Flash**: `quick-beyond-updater/bs_hmd_tools.py` (`load_beyondfw_file`/`enter_hmd_bootloader`/`update_hmd_firmware`). HID app=`35BD:0101`, bootloader=`35BD:4004`. Flashing AppImage leaves bootloader intact → always recoverable.
- **FLASH QUIRK — always retry**: attempt 1 reliably fails mid-write ~addr `0x404Axx` `code 46` (transient HID); retry direct-to-bootloader (`35BD:4004`) succeeds. Working driver: `beyond_synaptics/dist/reflash_doze.py`.
- HID command codes are densely packed in `usbhid_interface.h`; doze added `'H'`(0x48)/`'h'`(0x68). FPU+libm present (`powf` ok in tasks; `printf`=`iprintf`, no float formatting).

Brandon has full firmware build/flash/debug authority (Bigscreen Beyond dev). See [[fan-kickstart-approach]], [[hmd-bench-rig]].
