claude claude-code-guide Explore general-purpose gsd-advisor-researcher gsd-ai-researcher gsd-assumptions-analyzer gsd-code-fixer gsd-code-reviewer gsd-codebase-mapper gsd-debug-session-manager gsd-debugger gsd-doc-classifier gsd-doc-synthesizer gsd-doc-verifier gsd-doc-writer gsd-domain-researcher gsd-eval-auditor gsd-eval-planner gsd-executor gsd-framework-selector gsd-integration-checker gsd-intel-updater gsd-nyquist-auditor gsd-pattern-mapper gsd-phase-researcher gsd-plan-checker gsd-planner gsd-project-researcher gsd-research-synthesizer gsd-roadmapper gsd-security-auditor gsd-ui-auditor gsd-ui-checker gsd-ui-researcher gsd-user-profiler gsd-verifier Plan statusline-setup

- claude: Catch-all for any task that doesn't fit a more specific agent. FleetView's default when no agent name is typed. (Tools: *)

- claude-code-guide: Use this agent when the user asks questions ("Can Claude...", "Does Claude...", "How do I...") about: (1) Claude Code (the CLI tool) - features, hooks, slash commands, MCP servers, settings, IDE integrations, keyboard shortcuts; (2) Claude Agent SDK - building custom agents; (3) Claude API (formerly Anthropic API) - API usage, tool use, Anthropic SDK usage. **IMPORTANT:** Before spawning a new agent, check if there is already a running or recently completed claude-code-guide agent that you can continue via SendMessage. (Tools: Glob, Grep, Read, WebFetch, WebSearch)

- Explore: Read-only search agent for broad fan-out searches — when answering means sweeping many files, directories, or naming conventions and you only need the conclusion, not the file dumps. It reads excerpts rather than whole files, so it locates code; it doesn't review or audit it. Specify search breadth: "medium" for moderate exploration, "very thorough" for multiple locations and naming conventions. (Tools: All tools except Agent, ExitPlanMode, Edit, Write, NotebookEdit)

- general-purpose: General-purpose agent for researching complex questions, searching for code, and executing multi-step tasks. When you are searching for a keyword or file and are not confident that you will find the right match in the first few tries use this agent to perform the search for you. (Tools: *)

- gsd-advisor-researcher: Researches a single gray area decision and returns a structured comparison table with rationale. Spawned by discuss-phase advisor mode. (Tools: Read, Bash, Grep, Glob, WebSearch, WebFetch, mcp__context7__*)

- gsd-ai-researcher: Researches a chosen AI framework's official docs to produce implementation-ready guidance — best practices, syntax, core patterns, and pitfalls distilled for the specific use case. Writes the Framework Quick Reference and Implementation Guidance sections of AI-SPEC.md. Spawned by /gsd:ai-integration-phase orchestrator. (Tools: Read, Write, Bash, Grep, Glob, WebFetch, WebSearch, mcp__context7__*)

- gsd-assumptions-analyzer: Deeply analyzes codebase for a phase and returns structured assumptions with evidence. Spawned by discuss-phase assumptions mode. (Tools: Read, Bash, Grep, Glob)

- gsd-code-fixer: Applies fixes to code review findings from REVIEW.md. Reads source files, applies intelligent fixes, and commits each fix atomically. Spawned by /gsd:code-review --fix. (Tools: Read, Edit, Write, Bash, Grep, Glob)

- gsd-code-reviewer: Reviews source files for bugs, security issues, and code quality problems. Produces structured REVIEW.md with severity-classified findings. Spawned by /gsd:code-review. (Tools: Read, Write, Bash, Grep, Glob)

- gsd-codebase-mapper: Explores codebase and writes structured analysis documents. Spawned by map-codebase with a focus area (tech, arch, quality, concerns). Writes documents directly to reduce orchestrator context load. (Tools: Read, Bash, Grep, Glob, Write)

- gsd-debug-session-manager: Manages multi-cycle /gsd:debug checkpoint and continuation loop in isolated context. Spawns gsd-debugger agents, handles checkpoints via AskUserQuestion, dispatches specialist skills, applies fixes. Returns compact summary to main context. Spawned by /gsd:debug command. (Tools: Read, Write, Bash, Grep, Glob, Agent, AskUserQuestion)

- gsd-debugger: Investigates bugs using scientific method, manages debug sessions, handles checkpoints. Spawned by /gsd:debug orchestrator. (Tools: Read, Write, Edit, Bash, Grep, Glob, WebSearch)

- gsd-doc-classifier: Classifies a single planning document as ADR, PRD, SPEC, DOC, or UNKNOWN. Extracts title, scope summary, and cross-references. Spawned in parallel by /gsd:ingest-docs. Writes a JSON classification file and returns a one-line confirmation. (Tools: Read, Write, Grep, Glob)

- gsd-doc-synthesizer: Synthesizes classified planning docs into a single consolidated context. Applies precedence rules, detects cross-ref cycles, enforces LOCKED-vs-LOCKED hard-blocks, and writes INGEST-CONFLICTS.md with three buckets (auto-resolved, competing-variants, unresolved-blockers). Spawned by /gsd:ingest-docs. (Tools: Read, Write, Grep, Glob, Bash)

- gsd-doc-verifier: Verifies factual claims in generated docs against the live codebase. Returns structured JSON per doc. (Tools: Read, Write, Bash, Grep, Glob)

- gsd-doc-writer: Writes and updates project documentation. Spawned with a doc_assignment block specifying doc type, mode (create/update/supplement), and project context. (Tools: Read, Bash, Grep, Glob, Write)

- gsd-domain-researcher: Researches the business domain and real-world application context of the AI system being built. Surfaces domain expert evaluation criteria, industry-specific failure modes, regulatory context, and what "good" looks like for practitioners in this field — before the eval-planner turns it into measurable rubrics. Spawned by /gsd:ai-integration-phase orchestrator. (Tools: Read, Write, Bash, Grep, Glob, WebSearch, WebFetch, mcp__context7__*)

- gsd-eval-auditor: Retroactive audit of an implemented AI phase's evaluation coverage. Checks implementation against the AI-SPEC.md evaluation plan. Scores each eval dimension as COVERED/PARTIAL/MISSING. Produces a scored EVAL-REVIEW.md with findings, gaps, and remediation guidance. Spawned by /gsd:eval-review orchestrator. (Tools: Read, Write, Bash, Grep, Glob)

- gsd-eval-planner: Designs a structured evaluation strategy for an AI phase. Identifies critical failure modes, selects eval dimensions with rubrics, recommends tooling, and specifies the reference dataset. Writes the Evaluation Strategy, Guardrails, and Production Monitoring sections of AI-SPEC.md. Spawned by /gsd:ai-integration-phase orchestrator. (Tools: Read, Write, Bash, Grep, Glob, AskUserQuestion)

- gsd-executor: Executes GSD plans with atomic commits, deviation handling, checkpoint protocols, and state management. Spawned by execute-phase orchestrator or execute-plan command. (Tools: Read, Write, Edit, Bash, Grep, Glob, mcp__context7__*)

- gsd-framework-selector: Presents an interactive decision matrix to surface the right AI/LLM framework for the user's specific use case. Produces a scored recommendation with rationale. Spawned by /gsd:ai-integration-phase and /gsd-select-framework orchestrators. (Tools: Read, Bash, Grep, Glob, WebSearch, AskUserQuestion)

- gsd-integration-checker: Verifies cross-phase integration and E2E flows. Checks that phases connect properly and user workflows complete end-to-end. (Tools: Read, Bash, Grep, Glob)

- gsd-intel-updater: Analyzes codebase and writes structured intel files to .planning/intel/. (Tools: Read, Write, Bash, Glob, Grep)

- gsd-nyquist-auditor: Fills Nyquist validation gaps by generating tests and verifying coverage for phase requirements (Tools: Read, Write, Edit, Bash, Glob, Grep)

- gsd-pattern-mapper: Analyzes codebase for existing patterns and produces PATTERNS.md mapping new files to closest analogs. Read-only codebase analysis spawned by /gsd:plan-phase orchestrator before planning. (Tools: Read, Bash, Glob, Grep, Write)

- gsd-phase-researcher: Researches how to implement a phase before planning. Produces RESEARCH.md consumed by gsd-planner. Spawned by /gsd:plan-phase orchestrator. (Tools: Read, Write, Bash, Grep, Glob, WebSearch, WebFetch, mcp__context7__*, mcp__firecrawl__*, mcp__exa__*)

- gsd-plan-checker: Verifies plans will achieve phase goal before execution. Goal-backward analysis of plan quality. Spawned by /gsd:plan-phase orchestrator. (Tools: Read, Bash, Glob, Grep)

- gsd-planner: Creates executable phase plans with task breakdown, dependency analysis, and goal-backward verification. Spawned by /gsd:plan-phase orchestrator. (Tools: Read, Write, Bash, Glob, Grep, WebFetch, mcp__context7__*)

- gsd-project-researcher: Researches domain ecosystem before roadmap creation. Produces files in .planning/research/ consumed during roadmap creation. Spawned by /gsd:new-project or /gsd:new-milestone orchestrators. (Tools: Read, Write, Bash, Grep, Glob, WebSearch, WebFetch, mcp__context7__*, mcp__firecrawl__*, mcp__exa__*)

- gsd-research-synthesizer: Synthesizes research outputs from parallel researcher agents into SUMMARY.md. Spawned by /gsd:new-project after 4 researcher agents complete. (Tools: Read, Write, Bash)

- gsd-roadmapper: Creates project roadmaps with phase breakdown, requirement mapping, success criteria derivation, and coverage validation. Spawned by /gsd:new-project orchestrator. (Tools: Read, Write, Bash, Glob, Grep)

- gsd-security-auditor: Verifies threat mitigations from PLAN.md threat model exist in implemented code. Produces SECURITY.md. Spawned by /gsd:secure-phase. (Tools: Read, Write, Edit, Bash, Glob, Grep)

- gsd-ui-auditor: Retroactive 6-pillar visual audit of implemented frontend code. Produces scored UI-REVIEW.md. Spawned by /gsd:ui-review orchestrator. (Tools: Read, Write, Bash, Grep, Glob)

- gsd-ui-checker: Validates UI-SPEC.md design contracts against 6 quality dimensions. Produces BLOCK/FLAG/PASS verdicts. Spawned by /gsd:ui-phase orchestrator. (Tools: Read, Bash, Glob, Grep)

- gsd-ui-researcher: Produces UI-SPEC.md design contract for frontend phases. Reads upstream artifacts, detects design system state, asks only unanswered questions. Spawned by /gsd:ui-phase orchestrator. (Tools: Read, Write, Bash, Grep, Glob, WebSearch, WebFetch, mcp__context7__*, mcp__firecrawl__*, mcp__exa__*)

- gsd-user-profiler: Analyzes extracted session messages across 8 behavioral dimensions to produce a scored developer profile with confidence levels and evidence. Spawned by profile orchestration workflows. (Tools: Read)

- gsd-verifier: Verifies phase goal achievement through goal-backward analysis. Checks codebase delivers what phase promised, not just that tasks completed. Creates VERIFICATION.md report. (Tools: Read, Write, Bash, Grep, Glob)

- Plan: Software architect agent for designing implementation plans. Use this when you need to plan the implementation strategy for a task. Returns step-by-step plans, identifies critical files, and considers architectural trade-offs. (Tools: All tools except Agent, ExitPlanMode, Edit, Write, NotebookEdit)

- statusline-setup: Use this agent to configure the user's Claude Code status line setting. (Tools: Read, Edit)


Baseline = **v0.3.18** (noted — even tighter than my v0.3.19 compare). CRC-vs-prebuilt-0.3.18 is a sharp idea: catches build divergence even with identical source. Doing the build-config comparison now + locating the prebuilt 0.3.18 for the CRC check.


Bash

cd C:/Users/decid/Documents/projects/beyond_synaptics && echo "===cproj + cmake + linker files===" && git ls-files | grep -iE "\.cproj$|CMakeLists|\.ld$|\.cmake$|toolchain|preset" && echo "" && echo "===prebuilt 0.3.18 binaries (repo + siblings)===" && (git ls-files | grep -iE "\.(hex|bin|beyondfw|appimage|elf)$"; ls ../quick-beyond-updater/*.beyondfw ../quick-beyond-updater/*.hex 2>/dev/null; ls dist/ 2>/dev/null) | head -40 && echo "" && echo "===v0.3.18..v0.3.19 source delta (completeness)===" && git diff --stat v0.3.18 v0.3.19 -- 'src/*.c' 'src/*.h' | tail -20

Locate build config + prebuilt 0.3.18 + baseline delta


Command running in background with ID: b1c7br8ir. Output is being written to: C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-sauna\d3fb9be1-d61d-4f88-b77c-2a2a282b11fd\tasks\b1c7br8ir.output. You will be notified when it completes. To check interim output, use Read on that file path.


proceed with next steps. hmd power cycled.


<task-notification>
<task-id>b1c7br8ir</task-id>
<tool-use-id>toolu_012CVyFKzH4oUUT1JUNBFAvx</tool-use-id>
<output-file>C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-sauna\d3fb9be1-d61d-4f88-b77c-2a2a282b11fd\tasks\b1c7br8ir.output</output-file>
<status>completed</status>
<summary>Background command "Locate build config + prebuilt 0.3.18 + baseline delta" completed (exit code 0)</summary>
</task-notification>


1	===cproj + cmake + linker files===
2	Beyond_Synaptics.cproj
3	CMakeLists.txt
4	CMakePresets.json
5	arm-gcc-toolchain.cmake
6	src/ASF/sam/utils/linker_scripts/samg/samg55j19/gcc/flash.ld
7	src/ASF/sam/utils/linker_scripts/samg/samg55j19/gcc/flash_bootloader.ld
8	src/ASF/sam/utils/linker_scripts/samg/samg55j19/gcc/flash_usb_bootloader.ld
9	utils.cmake
10
11	===prebuilt 0.3.18 binaries (repo + siblings)===
12	build/Beyond_Synaptics_22_10_05.hex
13	build/Beyond_Synaptics_22_10_06.hex
14	build/Beyond_Synaptics_22_10_07.hex
15	build/Beyond_Synaptics_AppImage_22_10_05.hex
16	build/Beyond_Synaptics_AppImage_22_10_06.hex
17	build/Beyond_Synaptics_AppImage_22_10_07.hex
18	build/Beyond_Synaptics_AppImage_23_01_30.hex
19	build/Beyond_Synaptics_AppImage_v020_22_12_08.hex
20	build/Beyond_Synaptics_AppImage_v0210_230515.hex
21	build/Beyond_Synaptics_AppImage_v0211_230607.hex
22	build/Beyond_Synaptics_AppImage_v0212_230705.hex
23	build/Beyond_Synaptics_AppImage_v0213_230721.hex
24	build/Beyond_Synaptics_AppImage_v021_23_01_31.hex
25	build/Beyond_Synaptics_AppImage_v022_23_02_02.hex
26	build/Beyond_Synaptics_AppImage_v023_23_02_23.hex
27	build/Beyond_Synaptics_AppImage_v024A_230316.hex
28	build/Beyond_Synaptics_AppImage_v024A_23_03_07.hex
29	build/Beyond_Synaptics_AppImage_v024_23_02_28.hex
30	build/Beyond_Synaptics_AppImage_v025_230331.hex
31	build/Beyond_Synaptics_AppImage_v025_230412.hex
32	build/Beyond_Synaptics_AppImage_v026_230412.hex
33	build/Beyond_Synaptics_AppImage_v027_230420.hex
34	build/Beyond_Synaptics_AppImage_v028_230509.hex
35	build/Beyond_Synaptics_AppImage_v029_230509.hex
36	build/Beyond_Synaptics_FullImage_v020_22_12_08.hex
37	build/Beyond_Synaptics_FullImage_v0210_230515.hex
38	build/Beyond_Synaptics_FullImage_v0211_230607.hex
39	build/Beyond_Synaptics_FullImage_v0212_230705.hex
40	build/Beyond_Synaptics_FullImage_v0213_230721.hex
41	build/Beyond_Synaptics_FullImage_v024A_230316.hex
42	build/Beyond_Synaptics_FullImage_v025_230331.hex
43	build/Beyond_Synaptics_FullImage_v025_230412.hex
44	build/Beyond_Synaptics_FullImage_v026_230412.hex
45	build/Beyond_Synaptics_FullImage_v027_230420.hex
46	build/Beyond_Synaptics_FullImage_v028_230509.hex
47	build/Beyond_Synaptics_FullImage_v029_230509.hex
48	build/stack_checking/Beyond_AppImage_v99215_231005.hex
49	build/stack_checking/Beyond_FullImage_v99215_231005.hex
50	build/stack_checking/latest.beyondfw
51	build/v0.2.13/Beyond_AppImage_v0213_230913.hex
52
53	===v0.3.18..v0.3.19 source delta (completeness)===
54	 src/sw_ver.h           |  2 +-
55	 src/test_and_debug.c   | 21 +++++++++++++++++++++
56	 src/test_and_debug.h   |  1 +
57	 src/usbhid_interface.c | 13 +++++++++++++
58	 4 files changed, 36 insertions(+), 1 deletion(-)
59

===cproj + cmake + linker files===
Beyond_Synaptics.cproj
CMakeLists.txt
CMakePresets.json
arm-gcc-toolchain.cmake
src/ASF/sam/utils/linker_scripts/samg/samg55j19/gcc/flash.ld
src/ASF/sam/utils/linker_scripts/samg/samg55j19/gcc/flash_bootloader.ld
src/ASF/sam/utils/linker_scripts/samg/samg55j19/gcc/flash_usb_bootloader.ld
utils.cmake

===prebuilt 0.3.18 binaries (repo + siblings)===
build/Beyond_Synaptics_22_10_05.hex
build/Beyond_Synaptics_22_10_06.hex
build/Beyond_Synaptics_22_10_07.hex
build/Beyond_Synaptics_AppImage_22_10_05.hex
build/Beyond_Synaptics_AppImage_22_10_06.hex
build/Beyond_Synaptics_AppImage_22_10_07.hex
build/Beyond_Synaptics_AppImage_23_01_30.hex
build/Beyond_Synaptics_AppImage_v020_22_12_08.hex
build/Beyond_Synaptics_AppImage_v0210_230515.hex
build/Beyond_Synaptics_AppImage_v0211_230607.hex
build/Beyond_Synaptics_AppImage_v0212_230705.hex
build/Beyond_Synaptics_AppImage_v0213_230721.hex
build/Beyond_Synaptics_AppImage_v021_23_01_31.hex
build/Beyond_Synaptics_AppImage_v022_23_02_02.hex
build/Beyond_Synaptics_AppImage_v023_23_02_23.hex
build/Beyond_Synaptics_AppImage_v024A_230316.hex
build/Beyond_Synaptics_AppImage_v024A_23_03_07.hex
build/Beyond_Synaptics_AppImage_v024_23_02_28.hex
build/Beyond_Synaptics_AppImage_v025_230331.hex
build/Beyond_Synaptics_AppImage_v025_230412.hex
build/Beyond_Synaptics_AppImage_v026_230412.hex
build/Beyond_Synaptics_AppImage_v027_230420.hex
build/Beyond_Synaptics_AppImage_v028_230509.hex
build/Beyond_Synaptics_AppImage_v029_230509.hex
build/Beyond_Synaptics_FullImage_v020_22_12_08.hex
build/Beyond_Synaptics_FullImage_v0210_230515.hex
build/Beyond_Synaptics_FullImage_v0211_230607.hex
build/Beyond_Synaptics_FullImage_v0212_230705.hex
build/Beyond_Synaptics_FullImage_v0213_230721.hex
build/Beyond_Synaptics_FullImage_v024A_230316.hex
build/Beyond_Synaptics_FullImage_v025_230331.hex
build/Beyond_Synaptics_FullImage_v025_230412.hex
build/Beyond_Synaptics_FullImage_v026_230412.hex
build/Beyond_Synaptics_FullImage_v027_230420.hex
build/Beyond_Synaptics_FullImage_v028_230509.hex
build/Beyond_Synaptics_FullImage_v029_230509.hex
build/stack_checking/Beyond_AppImage_v99215_231005.hex
build/stack_checking/Beyond_FullImage_v99215_231005.hex
build/stack_checking/latest.beyondfw
build/v0.2.13/Beyond_AppImage_v0213_230913.hex

===v0.3.18..v0.3.19 source delta (completeness)===
 src/sw_ver.h           |  2 +-
 src/test_and_debug.c   | 21 +++++++++++++++++++++
 src/test_and_debug.h   |  1 +
 src/usbhid_interface.c | 13 +++++++++++++
 4 files changed, 36 insertions(+), 1 deletion(-)


Prompt:
<task-notification>
<task-id>b1c7br8ir</task-id>
<tool-use-id>toolu_012CVyFKzH4oUUT1JUNBFAvx</tool-use-id>
<output-file>C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-sauna\d3fb9be1-d61d-4f88-b77c-2a2a282b11fd\tasks\b1c7br8ir.output</output-file>
<status>completed</status>
<summary>Background command "Locate build config + prebuilt 0.3.18 + baseline delta" completed (exit code 0)</summary>
</task-notification>


<task-notification>
<task-id>b5j4kgng0</task-id>
<tool-use-id>toolu_01C8ZbfdhNQkTKUwhpsPXZ5r</tool-use-id>
<output-file>C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-sauna\d3fb9be1-d61d-4f88-b77c-2a2a282b11fd\tasks\b5j4kgng0.output</output-file>
<status>completed</status>
<summary>Background command "Read 0.3.18 to 0.3.19 HID + debug delta" completed (exit code 0)</summary>
</task-notification>


**New lead — baseline is v0.3.18, and v0.3.18→v0.3.19 itself changed `usbhid_interface.c` (+13) and `test_and_debug.c` (+21), pre-doze.** Since the HMD jumped 0.3.18 → 0.4.3 directly, those 0.3.19 changes are *also* untested with addons and bundled into 0.4.3. A HID-handler change in 0.3.19 is a fresh suspect on the addon path. Let me read it.


cd C:/Users/decid/Documents/projects/beyond_synaptics && echo "===v0.3.18..v0.3.19 usbhid_interface.c===" && git diff v0.3.18 v0.3.19 -- src/usbhid_interface.c src/usbhid_interface.h && echo "" && echo "===v0.3.18..v0.3.19 test_and_debug===" && git diff v0.3.18 v0.3.19 -- src/test_and_debug.c src/test_and_debug.h && echo "" && echo "===commits v0.3.18..v0.3.19===" && git log --oneline v0.3.18..v0.3.19

Read 0.3.18 to 0.3.19 HID + debug delta


Command running in background with ID: b5j4kgng0. Output is being written to: C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-sauna\d3fb9be1-d61d-4f88-b77c-2a2a282b11fd\tasks\b5j4kgng0.output. You will be notified when it completes. To check interim output, use Read on that file path.


Prompt:
<task-notification>
<task-id>b5j4kgng0</task-id>
<tool-use-id>toolu_01C8ZbfdhNQkTKUwhpsPXZ5r</tool-use-id>
<output-file>C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-sauna\d3fb9be1-d61d-4f88-b77c-2a2a282b11fd\tasks\b5j4kgng0.output</output-file>
<status>completed</status>
<summary>Background command "Read 0.3.18 to 0.3.19 HID + debug delta" completed (exit code 0)</summary>
</task-notification>


1	===v0.3.18..v0.3.19 usbhid_interface.c===
2	diff --git a/src/usbhid_interface.c b/src/usbhid_interface.c
3	index 6a455cc..f2ff5c8 100644
4	--- a/src/usbhid_interface.c
5	+++ b/src/usbhid_interface.c
6	@@ -756,12 +756,25 @@ void usbhid_set_feature(uint8_t* report) {
7	 		newcolor.r = report[1];
8	 		newcolor.g = report[2];
9	 		newcolor.b = report[3];
10	+		uint8_t new_mode = report[4];
11	 		if(send_code_to_i2c_task_fromISR(I2C_CTRL_RGB_COLOR)) {
12	 			report_task_code = HID_REPORT_TASK_CODE_FOR_SUCCESS;
13	 		} else {
14	 			report_task_code = HID_REPORT_TASK_CODE_FOR_ERROR;
15	 			hid_error_reply = Hid_Busy_Error;
16	 		}
17	+		if(0 != new_mode)  {
18	+			xHigherPriorityTaskWoken = pdFALSE;
19	+			if(1 == new_mode) // force LED on
20	+				xTaskNotifyFromISR( get_led_task_handle(), LED_TASK_CODE_STATIC_COLOR, eSetBits, &xHigherPriorityTaskWoken );
21	+			if(2 == new_mode) // force LED into breathing animation
22	+				xTaskNotifyFromISR( get_led_task_handle(), LED_TASK_CODE_BREATHING, eSetBits, &xHigherPriorityTaskWoken );
23	+			if(3 == new_mode) // force LED into blinking
24	+				xTaskNotifyFromISR( get_led_task_handle(), LED_TASK_CODE_BLINKING, eSetBits, &xHigherPriorityTaskWoken );
25	+
26	+			portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
27	+		}
28	+
29	 		send_code_to_hid_task_fromISR(report_task_code);
30	 	}
31	 	if(report[0] == HID_CODE_FOR_PROX_SETTINGS) {
32
33	===v0.3.18..v0.3.19 test_and_debug===
34	diff --git a/src/test_and_debug.c b/src/test_and_debug.c
35	index ee3538c..108a91e 100644
36	--- a/src/test_and_debug.c
37	+++ b/src/test_and_debug.c
38	@@ -385,6 +385,7 @@ static void task_led(void* pvParameters) {
39	 	uint32_t led_state = LED_TASK_CODE_STATIC_COLOR;
40	 	uint8_t step = 0;
41	 	uint8_t brightdir = 0; // 0 = increasing, 1 = wait at full, 2 = decreasing, 3 = wait at off
42	+	// and in blinking mode: 0 = off, 1 = on
43
44	 	// xLedTaskHandle = xTaskGetCurrentTaskHandle();
45
46	@@ -420,6 +421,12 @@ static void task_led(void* pvParameters) {
47	 			led_state = LED_TASK_CODE_STATIC_COLOR;
48	 			rgb_led_set_dimming(MCU_I2C(), 0x80);
49	 		}
50	+		if((notify_val & LED_TASK_CODE_MODE_MASK) == LED_TASK_CODE_BLINKING) {
51	+			led_state = LED_TASK_CODE_BLINKING;
52	+			rgb_led_set_dimming(MCU_I2C(), 0x80);
53	+			step = 0;
54	+			brightdir = 1;
55	+		}
56
57	 		if(LED_TASK_CODE_BREATHING == led_state) {
58	 			if(brightdir == 0) {
59	@@ -453,6 +460,20 @@ static void task_led(void* pvParameters) {
60	 				}
61	 			}
62	 		}
63	+
64	+		if(LED_TASK_CODE_BLINKING == led_state) {
65	+			step++;
66	+			if (step >= 5) {
67	+				step = 0;
68	+				if(brightdir == 0) {
69	+					brightdir = 1;
70	+					rgb_led_set_dimming(MCU_I2C(), 0x80);
71	+				} else {
72	+					brightdir = 0;
73	+					rgb_led_set_dimming(MCU_I2C(), 0x00);
74	+				}
75	+			}
76	+		}
77	 	}
78	 }
79
80	diff --git a/src/test_and_debug.h b/src/test_and_debug.h
81	index cc83681..291d9af 100644
82	--- a/src/test_and_debug.h
83	+++ b/src/test_and_debug.h
84	@@ -24,6 +24,7 @@
85	 #define LED_TASK_CODE_MODE_MASK		(0x0E) // Bit 0 is init, bits 3:1 are mode
86	 #define LED_TASK_CODE_STATIC_COLOR	(0x02)
87	 #define LED_TASK_CODE_BREATHING		(0x04)
88	+#define LED_TASK_CODE_BLINKING		(0x08)
89
90	 #define FAN_UPDATE_DELAY		(10) // Fan updates PWM at 100Hz
91	 #define FAN_TASK_CODE_NEW_SPEED		(0x100) // Lowest byte is the new speed
92
93	===commits v0.3.18..v0.3.19===
94	b2c696a adds RGB LED animation override to the color change HID command
95	7917c44 Update config_editor_imgui.py
96

===v0.3.18..v0.3.19 usbhid_interface.c===
diff --git a/src/usbhid_interface.c b/src/usbhid_interface.c
index 6a455cc..f2ff5c8 100644
--- a/src/usbhid_interface.c
+++ b/src/usbhid_interface.c
@@ -756,12 +756,25 @@ void usbhid_set_feature(uint8_t* report) {
 		newcolor.r = report[1];
 		newcolor.g = report[2];
 		newcolor.b = report[3];
+		uint8_t new_mode = report[4];
 		if(send_code_to_i2c_task_fromISR(I2C_CTRL_RGB_COLOR)) {
 			report_task_code = HID_REPORT_TASK_CODE_FOR_SUCCESS;
 		} else {
 			report_task_code = HID_REPORT_TASK_CODE_FOR_ERROR;
 			hid_error_reply = Hid_Busy_Error;
 		}
+		if(0 != new_mode)  {
+			xHigherPriorityTaskWoken = pdFALSE;
+			if(1 == new_mode) // force LED on
+				xTaskNotifyFromISR( get_led_task_handle(), LED_TASK_CODE_STATIC_COLOR, eSetBits, &xHigherPriorityTaskWoken );
+			if(2 == new_mode) // force LED into breathing animation
+				xTaskNotifyFromISR( get_led_task_handle(), LED_TASK_CODE_BREATHING, eSetBits, &xHigherPriorityTaskWoken );
+			if(3 == new_mode) // force LED into blinking
+				xTaskNotifyFromISR( get_led_task_handle(), LED_TASK_CODE_BLINKING, eSetBits, &xHigherPriorityTaskWoken );
+
+			portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
+		}
+
 		send_code_to_hid_task_fromISR(report_task_code);
 	}
 	if(report[0] == HID_CODE_FOR_PROX_SETTINGS) {

===v0.3.18..v0.3.19 test_and_debug===
diff --git a/src/test_and_debug.c b/src/test_and_debug.c
index ee3538c..108a91e 100644
--- a/src/test_and_debug.c
+++ b/src/test_and_debug.c
@@ -385,6 +385,7 @@ static void task_led(void* pvParameters) {
 	uint32_t led_state = LED_TASK_CODE_STATIC_COLOR;
 	uint8_t step = 0;
 	uint8_t brightdir = 0; // 0 = increasing, 1 = wait at full, 2 = decreasing, 3 = wait at off
+	// and in blinking mode: 0 = off, 1 = on

 	// xLedTaskHandle = xTaskGetCurrentTaskHandle();

@@ -420,6 +421,12 @@ static void task_led(void* pvParameters) {
 			led_state = LED_TASK_CODE_STATIC_COLOR;
 			rgb_led_set_dimming(MCU_I2C(), 0x80);
 		}
+		if((notify_val & LED_TASK_CODE_MODE_MASK) == LED_TASK_CODE_BLINKING) {
+			led_state = LED_TASK_CODE_BLINKING;
+			rgb_led_set_dimming(MCU_I2C(), 0x80);
+			step = 0;
+			brightdir = 1;
+		}

 		if(LED_TASK_CODE_BREATHING == led_state) {
 			if(brightdir == 0) {
@@ -453,6 +460,20 @@ static void task_led(void* pvParameters) {
 				}
 			}
 		}
+
+		if(LED_TASK_CODE_BLINKING == led_state) {
+			step++;
+			if (step >= 5) {
+				step = 0;
+				if(brightdir == 0) {
+					brightdir = 1;
+					rgb_led_set_dimming(MCU_I2C(), 0x80);
+				} else {
+					brightdir = 0;
+					rgb_led_set_dimming(MCU_I2C(), 0x00);
+				}
+			}
+		}
 	}
 }

diff --git a/src/test_and_debug.h b/src/test_and_debug.h
index cc83681..291d9af 100644
--- a/src/test_and_debug.h
+++ b/src/test_and_debug.h
@@ -24,6 +24,7 @@
 #define LED_TASK_CODE_MODE_MASK		(0x0E) // Bit 0 is init, bits 3:1 are mode
 #define LED_TASK_CODE_STATIC_COLOR	(0x02)
 #define LED_TASK_CODE_BREATHING		(0x04)
+#define LED_TASK_CODE_BLINKING		(0x08)

 #define FAN_UPDATE_DELAY		(10) // Fan updates PWM at 100Hz
 #define FAN_TASK_CODE_NEW_SPEED		(0x100) // Lowest byte is the new speed

===commits v0.3.18..v0.3.19===
b2c696a adds RGB LED animation override to the color change HID command
7917c44 Update config_editor_imgui.py


v0.3.18→v0.3.19 eliminated: it's just an **RGB LED animation feature** (LED task + a `report[4]` mode byte on the `'L'`/0x4c command). LED-only, can't stop prox/HID. So the regression isn't there either.

That leaves the **build/toolchain** as the prime suspect (source is inert without the doze opcodes). Now the comparison you picked — CMake vs `.cproj`. Let me extract the decisive bits from both: source-file list, compiler flags/defines, FPU/float ABI, linker script + libs.


cd C:/Users/decid/Documents/projects/beyond_synaptics && echo "######## .cproj COMPILER FLAGS / DEFINES / FPU / LINKER ########" && grep -iE "OptimizationLevel|<armgcc|fpu|float-abi|mfloat|DefSymbols|<Value>|miscellaneous|LinkerScript|libraries|<ListValues>|garbage|gc-sections|nano|specs" Beyond_Synaptics.cproj | sed 's/^[[:space:]]*//' | head -80

Extract .cproj build flags/defines/linker


Command running in background with ID: bcp330021. Output is being written to: C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-sauna\d3fb9be1-d61d-4f88-b77c-2a2a282b11fd\tasks\bcp330021.output. You will be notified when it completes. To check interim output, use Read on that file path.


<task-notification>
<task-id>bcp330021</task-id>
<tool-use-id>toolu_0167LydVaPJ1hgBejCa7YypB</tool-use-id>
<output-file>C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-sauna\d3fb9be1-d61d-4f88-b77c-2a2a282b11fd\tasks\bcp330021.output</output-file>
<status>completed</status>
<summary>Background command "Extract .cproj build flags/defines/linker" completed (exit code 0)</summary>
</task-notification>


1	######## .cproj COMPILER FLAGS / DEFINES / FPU / LINKER ########
2	<configuration key="config.compiler.armgcc.fpu_used" value="yes" default="yes" content-id="Atmel.ASF" />
3	<file path="src/ASF/sam/utils/fpu/fpu.h" framework="" version="" source="sam/utils/fpu/fpu.h" changed="False" content-id="Atmel.ASF" />
4	<ArmGcc>
5	<armgcc.common.outputfiles.hex>True</armgcc.common.outputfiles.hex>
6	<armgcc.common.outputfiles.lss>True</armgcc.common.outputfiles.lss>
7	<armgcc.common.outputfiles.eep>True</armgcc.common.outputfiles.eep>
8	<armgcc.common.outputfiles.bin>True</armgcc.common.outputfiles.bin>
9	<armgcc.common.outputfiles.srec>True</armgcc.common.outputfiles.srec>
10	<armgcc.compiler.symbols.DefSymbols>
11	<ListValues>
12	<Value>NDEBUG</Value>
13	<Value>__SAMG55J19__</Value>
14	<Value>ARM_MATH_CM4=true</Value>
15	<Value>printf=iprintf</Value>
16	<Value>__FREERTOS__</Value>
17	<Value>scanf=iscanf</Value>
18	<Value>BOARD=SAMG55_XPLAINED_PRO</Value>
19	<Value>UDD_ENABLE</Value>
20	</armgcc.compiler.symbols.DefSymbols>
21	<armgcc.compiler.directories.IncludePaths>
22	<ListValues>
23	<Value>../src/ASF/common/services/clock</Value>
24	<Value>../src/ASF/sam/drivers/pmc</Value>
25	<Value>../src/ASF/sam/utils</Value>
26	<Value>../src/ASF/sam/utils/header_files</Value>
27	<Value>../src/ASF/sam/utils/preprocessor</Value>
28	<Value>../src/ASF/thirdparty/CMSIS/Include</Value>
29	<Value>../src/ASF/thirdparty/CMSIS/Lib/GCC</Value>
30	<Value>../src/ASF/sam/utils/fpu</Value>
31	<Value>../src/ASF/common/utils</Value>
32	<Value>../src/ASF/sam/utils/cmsis/samg/samg55/include</Value>
33	<Value>../src/ASF/sam/drivers/efc</Value>
34	<Value>../src/ASF/sam/drivers/supc</Value>
35	<Value>../src/ASF/thirdparty/freertos/freertos-10.0.0/Source/include</Value>
36	<Value>../src/ASF/thirdparty/freertos/freertos-10.0.0/Source/portable/GCC/ARM_CM4F</Value>
37	<Value>../src/ASF/common/utils/stdio/stdio_serial</Value>
38	<Value>../src/ASF/common/services/serial/sam_uart</Value>
39	<Value>../src/ASF/common/services/serial</Value>
40	<Value>../src/ASF/sam/drivers/flexcom</Value>
41	<Value>../src/ASF/common/services/sleepmgr</Value>
42	<Value>../src/ASF/sam/drivers/usart</Value>
43	<Value>../src/ASF/sam/boards/samg55_xplained_pro</Value>
44	<Value>../src/ASF/sam/boards</Value>
45	<Value>../src/ASF/common/boards</Value>
46	<Value>../src/ASF/common/services/ioport</Value>
47	<Value>../src</Value>
48	<Value>../src/config</Value>
49	<Value>../src/ASF/sam/drivers/matrix</Value>
50	<Value>../src/ASF/sam/drivers/pdc</Value>
51	<Value>../src/ASF/sam/drivers/pdc/pdc_uart_example</Value>
52	<Value>../src/ASF/sam/drivers/pdm</Value>
53	<Value>../src/ASF/sam/drivers/pio</Value>
54	<Value>../src/ASF/common/services/usb</Value>
55	<Value>../src/ASF/common/services/usb/class/cdc</Value>
56	<Value>../src/ASF/common/services/usb/class/cdc/device</Value>
57	<Value>../src/ASF/common/services/usb/udc</Value>
58	<Value>../src/ASF/sam/drivers/udp</Value>
59	<Value>../src/ASF/sam/drivers/adc</Value>
60	<armgcc.compiler.optimization.level>Optimize most (-O3)</armgcc.compiler.optimization.level>
61	<armgcc.compiler.optimization.OtherFlags>-fdata-sections</armgcc.compiler.optimization.OtherFlags>
62	<armgcc.compiler.optimization.PrepareFunctionsForGarbageCollection>True</armgcc.compiler.optimization.PrepareFunctionsForGarbageCollection>
63	<armgcc.compiler.warnings.AllWarnings>True</armgcc.compiler.warnings.AllWarnings>
64	<armgcc.compiler.miscellaneous.OtherFlags>-pipe -fno-strict-aliasing -Wall -Wstrict-prototypes -Wmissing-prototypes -Werror-implicit-function-declaration -Wpointer-arith -std=gnu99 -ffunction-sections -fdata-sections -Wchar-subscripts -Wcomment -Wformat=2 -Wimplicit-int -Wmain -Wparentheses -Wsequence-point -Wreturn-type -Wswitch -Wtrigraphs -Wunused -Wuninitialized -Wunknown-pragmas -Wfloat-equal -Wundef -Wshadow -Wbad-function-cast -Wwrite-strings -Wsign-compare -Waggregate-return -Wmissing-declarations -Wformat -Wmissing-format-attribute -Wno-deprecated-declarations -Wpacked -Wredundant-decls -Wnested-externs -Wlong-long -Wunreachable-code -Wcast-align --param max-inline-insns-single=500 -mfloat-abi=softfp -mfpu=fpv4-sp-d16</armgcc.compiler.miscellaneous.OtherFlags>
65	<armgcc.linker.libraries.Libraries>
66	<ListValues>
67	<Value>libarm_cortexM4lf_math_softfp</Value>
68	<Value>libm</Value>
69	</armgcc.linker.libraries.Libraries>
70	<armgcc.linker.libraries.LibrarySearchPaths>
71	<ListValues>
72	<Value>../src/ASF/thirdparty/CMSIS/Lib/GCC</Value>
73	</armgcc.linker.libraries.LibrarySearchPaths>
74	<armgcc.linker.optimization.GarbageCollectUnusedSections>True</armgcc.linker.optimization.GarbageCollectUnusedSections>
75	<armgcc.linker.miscellaneous.LinkerFlags>-Wl,--entry=Reset_Handler -Wl,--cref -mthumb -T../src/ASF/sam/utils/linker_scripts/samg/samg55j19/gcc/flash.ld</armgcc.linker.miscellaneous.LinkerFlags>
76	<armgcc.assembler.general.IncludePaths>
77	<ListValues>
78	<Value>../src/ASF/common/services/clock</Value>
79	<Value>../src/ASF/sam/drivers/pmc</Value>
80	<Value>../src/ASF/sam/utils</Value>
81	<Value>../src/ASF/sam/utils/header_files</Value>
82

######## .cproj COMPILER FLAGS / DEFINES / FPU / LINKER ########
<configuration key="config.compiler.armgcc.fpu_used" value="yes" default="yes" content-id="Atmel.ASF" />
<file path="src/ASF/sam/utils/fpu/fpu.h" framework="" version="" source="sam/utils/fpu/fpu.h" changed="False" content-id="Atmel.ASF" />
<ArmGcc>
<armgcc.common.outputfiles.hex>True</armgcc.common.outputfiles.hex>
<armgcc.common.outputfiles.lss>True</armgcc.common.outputfiles.lss>
<armgcc.common.outputfiles.eep>True</armgcc.common.outputfiles.eep>
<armgcc.common.outputfiles.bin>True</armgcc.common.outputfiles.bin>
<armgcc.common.outputfiles.srec>True</armgcc.common.outputfiles.srec>
<armgcc.compiler.symbols.DefSymbols>
<ListValues>
<Value>NDEBUG</Value>
<Value>__SAMG55J19__</Value>
<Value>ARM_MATH_CM4=true</Value>
<Value>printf=iprintf</Value>
<Value>__FREERTOS__</Value>
<Value>scanf=iscanf</Value>
<Value>BOARD=SAMG55_XPLAINED_PRO</Value>
<Value>UDD_ENABLE</Value>
</armgcc.compiler.symbols.DefSymbols>
<armgcc.compiler.directories.IncludePaths>
<ListValues>
<Value>../src/ASF/common/services/clock</Value>
<Value>../src/ASF/sam/drivers/pmc</Value>
<Value>../src/ASF/sam/utils</Value>
<Value>../src/ASF/sam/utils/header_files</Value>
<Value>../src/ASF/sam/utils/preprocessor</Value>
<Value>../src/ASF/thirdparty/CMSIS/Include</Value>
<Value>../src/ASF/thirdparty/CMSIS/Lib/GCC</Value>
<Value>../src/ASF/sam/utils/fpu</Value>
<Value>../src/ASF/common/utils</Value>
<Value>../src/ASF/sam/utils/cmsis/samg/samg55/include</Value>
<Value>../src/ASF/sam/drivers/efc</Value>
<Value>../src/ASF/sam/drivers/supc</Value>
<Value>../src/ASF/thirdparty/freertos/freertos-10.0.0/Source/include</Value>
<Value>../src/ASF/thirdparty/freertos/freertos-10.0.0/Source/portable/GCC/ARM_CM4F</Value>
<Value>../src/ASF/common/utils/stdio/stdio_serial</Value>
<Value>../src/ASF/common/services/serial/sam_uart</Value>
<Value>../src/ASF/common/services/serial</Value>
<Value>../src/ASF/sam/drivers/flexcom</Value>
<Value>../src/ASF/common/services/sleepmgr</Value>
<Value>../src/ASF/sam/drivers/usart</Value>
<Value>../src/ASF/sam/boards/samg55_xplained_pro</Value>
<Value>../src/ASF/sam/boards</Value>
<Value>../src/ASF/common/boards</Value>
<Value>../src/ASF/common/services/ioport</Value>
<Value>../src</Value>
<Value>../src/config</Value>
<Value>../src/ASF/sam/drivers/matrix</Value>
<Value>../src/ASF/sam/drivers/pdc</Value>
<Value>../src/ASF/sam/drivers/pdc/pdc_uart_example</Value>
<Value>../src/ASF/sam/drivers/pdm</Value>
<Value>../src/ASF/sam/drivers/pio</Value>
<Value>../src/ASF/common/services/usb</Value>
<Value>../src/ASF/common/services/usb/class/cdc</Value>
<Value>../src/ASF/common/services/usb/class/cdc/device</Value>
<Value>../src/ASF/common/services/usb/udc</Value>
<Value>../src/ASF/sam/drivers/udp</Value>
<Value>../src/ASF/sam/drivers/adc</Value>
<armgcc.compiler.optimization.level>Optimize most (-O3)</armgcc.compiler.optimization.level>
<armgcc.compiler.optimization.OtherFlags>-fdata-sections</armgcc.compiler.optimization.OtherFlags>
<armgcc.compiler.optimization.PrepareFunctionsForGarbageCollection>True</armgcc.compiler.optimization.PrepareFunctionsForGarbageCollection>
<armgcc.compiler.warnings.AllWarnings>True</armgcc.compiler.warnings.AllWarnings>
<armgcc.compiler.miscellaneous.OtherFlags>-pipe -fno-strict-aliasing -Wall -Wstrict-prototypes -Wmissing-prototypes -Werror-implicit-function-declaration -Wpointer-arith -std=gnu99 -ffunction-sections -fdata-sections -Wchar-subscripts -Wcomment -Wformat=2 -Wimplicit-int -Wmain -Wparentheses -Wsequence-point -Wreturn-type -Wswitch -Wtrigraphs -Wunused -Wuninitialized -Wunknown-pragmas -Wfloat-equal -Wundef -Wshadow -Wbad-function-cast -Wwrite-strings -Wsign-compare -Waggregate-return -Wmissing-declarations -Wformat -Wmissing-format-attribute -Wno-deprecated-declarations -Wpacked -Wredundant-decls -Wnested-externs -Wlong-long -Wunreachable-code -Wcast-align --param max-inline-insns-single=500 -mfloat-abi=softfp -mfpu=fpv4-sp-d16</armgcc.compiler.miscellaneous.OtherFlags>
<armgcc.linker.libraries.Libraries>
<ListValues>
<Value>libarm_cortexM4lf_math_softfp</Value>
<Value>libm</Value>
</armgcc.linker.libraries.Libraries>
<armgcc.linker.libraries.LibrarySearchPaths>
<ListValues>
<Value>../src/ASF/thirdparty/CMSIS/Lib/GCC</Value>
</armgcc.linker.libraries.LibrarySearchPaths>
<armgcc.linker.optimization.GarbageCollectUnusedSections>True</armgcc.linker.optimization.GarbageCollectUnusedSections>
<armgcc.linker.miscellaneous.LinkerFlags>-Wl,--entry=Reset_Handler -Wl,--cref -mthumb -T../src/ASF/sam/utils/linker_scripts/samg/samg55j19/gcc/flash.ld</armgcc.linker.miscellaneous.LinkerFlags>
<armgcc.assembler.general.IncludePaths>
<ListValues>
<Value>../src/ASF/common/services/clock</Value>
<Value>../src/ASF/sam/drivers/pmc</Value>
<Value>../src/ASF/sam/utils</Value>
<Value>../src/ASF/sam/utils/header_files</Value>


Prompt:
<task-notification>
<task-id>bcp330021</task-id>
<tool-use-id>toolu_0167LydVaPJ1hgBejCa7YypB</tool-use-id>
<output-file>C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-sauna\d3fb9be1-d61d-4f88-b77c-2a2a282b11fd\tasks\bcp330021.output</output-file>
<status>completed</status>
<summary>Background command "Extract .cproj build flags/defines/linker" completed (exit code 0)</summary>
</task-notification>


Studio (`.cproj`) known-good reference captured. Critical settings: **`-mfloat-abi=softfp -mfpu=fpv4-sp-d16`**, **`-fno-strict-aliasing`** under `-O3`, defines `printf=iprintf scanf=iscanf ARM_MATH_CM4=true UDD_ENABLE __FREERTOS__ NDEBUG`, libs `libarm_cortexM4lf_math_softfp + libm`, linker `flash.ld`. Now the CMake side — any mismatch here is a build-induced runtime risk.


1	cmake_minimum_required(VERSION 3.10)
2	project(beyond_synaptics C CXX ASM)
3
4	set(CMAKE_EXECUTABLE_SUFFIX ".elf")
5	set(CMAKE_C_COMPILER_TARGET thumbv7m-unknown-none-eabi)
6	set(CMAKE_CXX_COMPILER_TARGET thumbv7m-unknown-none-eabi)
7	set(CMAKE_C_STANDARD 11)
8	set(CMAKE_C_STANDARD_REQUIRED ON)
9
10	set(CPU_FLAGS -mthumb -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16)
11	# set(COMPILER_FLAGS -ffreestanding -ffunction-sections -fdata-sections -fsigned-char -fmessage-length=0 -fshort-enums)
12	set(COMPILER_FLAGS -pipe -fno-strict-aliasing -Wall -Wstrict-prototypes -Wmissing-prototypes
13	 -Werror-implicit-function-declaration -Wpointer-arith -std=gnu99
14	 -ffunction-sections -fdata-sections -Wchar-subscripts -Wcomment
15	 -Wformat=2 -Wimplicit-int -Wmain -Wparentheses -Wsequence-point
16	 -Wreturn-type -Wswitch -Wtrigraphs -Wunused -Wuninitialized -Wunknown-pragmas -Wno-expansion-to-defined
17	 -Wfloat-equal -Wundef -Wshadow -Wbad-function-cast -Wwrite-strings -Wsign-compare
18	 -Waggregate-return -Wmissing-declarations -Wformat -Wmissing-format-attribute
19	 -Wno-deprecated-declarations -Wpacked -Wredundant-decls -Wnested-externs -Wlong-long
20	 -Wunreachable-code -Wcast-align --param max-inline-insns-single=500
21	 -ffast-math -mlong-calls)
22
23
24	set(LINKER_FILE "${CMAKE_CURRENT_LIST_DIR}/src/ASF/sam/utils/linker_scripts/samg/samg55j19/gcc/flash_usb_bootloader.ld")
25
26	add_compile_options(${CPU_FLAGS} ${COMPILER_FLAGS})
27	add_link_options(${CPU_FLAGS})
28	add_definitions(-D__SAMG55G19__ -DARM_MATH_CM4=true -Dprintf=iprintf -D__FREERTOS__ -Dscanf=iscanf -DBOARD=USER_EXT_BOARD -DUDD_ENABLE -DNOTBOARD=SAMG55_XPLAINED_PRO -DUSER_BOARD_REVISION=4)
29
30	include(utils.cmake)
31
32	if("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
33	    include(../../../clang_utils.cmake)
34	    clang_utils_get_arm_gcc_sysroot(${ARM_GCC_C_COMPILER} ${CPU_FLAGS})
35	    clang_utils_get_arm_gcc_multilib_dir(${ARM_GCC_C_COMPILER} ${CPU_FLAGS})
36	    clang_utils_get_arm_gcc_lib_dir(${ARM_GCC_C_COMPILER} ${CPU_FLAGS})
37	    clang_utils_get_arm_gcc_crt(${ARM_GCC_SYSROOT} ${ARM_GCC_MULTIDIR} ${ARM_GCC_LIBGCC_DIR})
38	    string(APPEND CMAKE_EXE_LINKER_FLAGS
39	        " -nostdlib -L${ARM_GCC_SYSROOT}/lib/${ARM_GCC_MULTIDIR} -L${ARM_GCC_LIBGCC_DIR}")
40	    string(APPEND CMAKE_EXE_LINKER_FLAGS " -lgcc -lc_nano -lc")
41	elseif("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
42	    string(REGEX MATCH ".*\.specs.*" has_specs "${CMAKE_EXE_LINKER_FLAGS}")
43
44	    if(NOT has_specs)
45	        string(APPEND CMAKE_EXE_LINKER_FLAGS " --specs=nano.specs")
46	    endif()
47	endif()
48
49	string(REPLACE ";" " " _LINKER_CPU_FLAGS "${CPU_FLAGS}")
50
51	# subdirlist(include_dir_list ${CMAKE_CURRENT_LIST_DIR}/src)
52
53	add_executable(beyond_synaptics src/main.c)
54	target_include_directories(beyond_synaptics PRIVATE
55	src/
56	# Project source dirs must precede the ASF/CMSIS dirs: the samg55 CMSIS tree
57	# ships its own component/instance "adc.h" which otherwise shadows the
58	# project's src/Drivers/adc.h on a bare #include "adc.h".
59	src/Devices/
60	src/Drivers/
61	src/config/
62	src/crash_handler/
63	src/ASF/
64	src/ASF/common/
65	src/ASF/common/boards/
66	src/ASF/common/services/
67	src/ASF/common/services/clock/
68	src/ASF/common/services/clock/samg/
69	src/ASF/common/services/ioport/
70	src/ASF/common/services/ioport/sam/
71	src/ASF/common/services/serial/
72	src/ASF/common/services/serial/sam_uart/
73	src/ASF/common/services/sleepmgr/
74	src/ASF/common/services/sleepmgr/sam/
75	src/ASF/common/services/usb/
76	src/ASF/common/services/usb/class/
77	src/ASF/common/services/usb/class/audio/device
78	src/ASF/common/services/usb/class/audio
79	src/ASF/common/services/usb/class/hid
80	src/ASF/common/services/usb/class/hid/device
81	src/ASF/common/services/usb/class/composite
82	src/ASF/common/services/usb/class/hid/device/generic
83	src/ASF/common/services/usb/udc/
84	src/ASF/common/utils/
85	src/ASF/common/utils/interrupt/
86	src/ASF/common/utils/stdio/
87	src/ASF/common/utils/stdio/stdio_serial/
88	src/ASF/sam/
89	src/ASF/sam/boards/
90	src/ASF/sam/boards/displayboard
91	src/ASF/sam/boards/samg55_xplained_pro/
92	src/ASF/sam/drivers/
93	src/ASF/sam/drivers/adc/
94	src/ASF/sam/drivers/efc/
95	src/ASF/sam/drivers/flexcom/
96	src/ASF/sam/drivers/matrix/
97	src/ASF/sam/drivers/pdc/
98	src/ASF/sam/drivers/pdc/pdc_uart_example/
99	src/ASF/sam/drivers/pdm/
100	src/ASF/sam/drivers/pio/
101	src/ASF/sam/drivers/pmc/
102	src/ASF/sam/drivers/supc/
103	src/ASF/sam/drivers/udp/
104	src/ASF/sam/drivers/usart/
105	src/ASF/sam/utils/
106	src/ASF/sam/utils/cmsis/
107	src/ASF/sam/utils/cmsis/samg/
108	src/ASF/sam/utils/cmsis/samg/samg55/
109	src/ASF/sam/utils/cmsis/samg/samg55/include/
110	src/ASF/sam/utils/cmsis/samg/samg55/include/component/
111	src/ASF/sam/utils/cmsis/samg/samg55/include/instance/
112	src/ASF/sam/utils/cmsis/samg/samg55/include/pio/
113	src/ASF/sam/utils/cmsis/samg/samg55/source/
114	src/ASF/sam/utils/cmsis/samg/samg55/source/templates/
115	src/ASF/sam/utils/cmsis/samg/samg55/source/templates/gcc/
116	src/ASF/sam/utils/fpu/
117	src/ASF/sam/utils/header_files/
118	src/ASF/sam/utils/linker_scripts/
119	src/ASF/sam/utils/linker_scripts/samg/
120	src/ASF/sam/utils/linker_scripts/samg/samg55j19/
121	src/ASF/sam/utils/linker_scripts/samg/samg55j19/gcc/
122	src/ASF/sam/utils/make/
123	src/ASF/sam/utils/preprocessor/
124	src/ASF/sam/utils/syscalls/
125	src/ASF/sam/utils/syscalls/gcc/
126	src/ASF/thirdparty/
127	src/ASF/thirdparty/CMSIS/
128	src/ASF/thirdparty/CMSIS/Include/
129	src/ASF/thirdparty/CMSIS/Lib/
130	src/ASF/thirdparty/CMSIS/Lib/GCC/
131	src/ASF/thirdparty/freertos/
132	src/ASF/thirdparty/freertos/freertos-10.0.0/
133	src/ASF/thirdparty/freertos/freertos-10.0.0/Source/
134	src/ASF/thirdparty/freertos/freertos-10.0.0/Source/include/
135	src/ASF/thirdparty/freertos/freertos-10.0.0/Source/portable/
136	src/ASF/thirdparty/freertos/freertos-10.0.0/Source/portable/GCC/
137	src/ASF/thirdparty/freertos/freertos-10.0.0/Source/portable/GCC/ARM_CM4F/
138	src/ASF/thirdparty/freertos/freertos-10.0.0/Source/portable/MemMang/
139	src/config/
140	src/Devices
141	src/Drivers
142	src/crash_handler
143	)
144
145	target_sources(beyond_synaptics PRIVATE
146	src/ASF/common/services/usb/class/audio/device/udi_audio.c
147	src/ASF/common/services/usb/class/hid/device/udi_hid_desc.c
148	src/ASF/sam/boards/displayboard/displayboard_init.c
149	src/ASF/sam/drivers/adc/adc2.c
150	src/crash_handler/crash_handler.c
151	src/Devices/eyetrack_fpga.c
152	src/Devices/fan_motor_control.c
153	src/Devices/linkbox_hpd.c
154	src/Devices/oled_control.c
155	src/Devices/prox_control.c
156	src/Devices/prox_tmd2635.c
157	src/Devices/rgb_led.c
158	src/Devices/usb2517.c
159	src/Devices/usb3803.c
160	src/Devices/usbc_mux.c
161	src/Devices/vxr_interface.c
162	src/Devices/tundra_uart.c
163	src/Drivers/adc.c
164	src/Drivers/flash_mutex.c
165	src/Drivers/i2c.c
166	src/Drivers/pdm_mics.c
167	src/Drivers/power_control.c
168	src/Drivers/rtt_util.c
169	src/Drivers/signature.c
170	src/Drivers/temp_sense.c
171	src/eeprom_emulation.c
172	src/hw_test.c
173	src/sw_ver.c
174	src/ui_interface.c
175	src/usart_interface.c
176	src/usbhid_interface.c
177	src/video_proc.c
178	src/test_and_debug.c
179	src/ASF/common/services/usb/class/composite/udi_composite_desc.c
180	src/ASF/common/services/usb/class/hid/device/generic/udi_hid_generic.c
181	src/ASF/common/services/usb/class/hid/device/udi_hid.c
182	src/ASF/common/services/usb/udc/udc.c
183	src/ASF/sam/drivers/pio/pio_handler.c
184	src/ASF/sam/drivers/udp/udp_device.c
185	src/ASF/sam/drivers/matrix/matrix.c
186	src/ASF/sam/drivers/pdc/pdc.c
187	src/ASF/sam/drivers/pdm/pdm.c
188	src/ASF/sam/drivers/pio/pio.c
189	src/ASF/common/services/clock/samg/sysclk.c
190	src/ASF/common/services/serial/usart_serial.c
191	src/ASF/common/services/sleepmgr/sam/sleepmgr.c
192	src/ASF/common/utils/interrupt/interrupt_sam_nvic.c
193	src/ASF/common/utils/stdio/read.c
194	src/ASF/common/utils/stdio/write.c
195	src/ASF/sam/drivers/efc/efc.c
196	src/ASF/sam/drivers/flexcom/flexcom.c
197	src/ASF/sam/drivers/pmc/pmc.c
198	src/ASF/sam/drivers/pmc/sleep.c
199	src/ASF/sam/drivers/supc/supc.c
200	src/ASF/sam/drivers/usart/usart.c
201	src/ASF/sam/utils/cmsis/samg/samg55/source/templates/gcc/startup_samg55.c
202	src/ASF/sam/utils/cmsis/samg/samg55/source/templates/system_samg55.c
203	src/ASF/sam/utils/syscalls/gcc/syscalls.c
204	src/ASF/thirdparty/freertos/freertos-10.0.0/Source/croutine.c
205	src/ASF/thirdparty/freertos/freertos-10.0.0/Source/event_groups.c
206	src/ASF/thirdparty/freertos/freertos-10.0.0/Source/list.c
207	src/ASF/thirdparty/freertos/freertos-10.0.0/Source/portable/GCC/ARM_CM4F/port.c
208	src/ASF/thirdparty/freertos/freertos-10.0.0/Source/portable/MemMang/heap_3.c
209	src/ASF/thirdparty/freertos/freertos-10.0.0/Source/queue.c
210	src/ASF/thirdparty/freertos/freertos-10.0.0/Source/stream_buffer.c
211	src/ASF/thirdparty/freertos/freertos-10.0.0/Source/tasks.c
212	src/ASF/thirdparty/freertos/freertos-10.0.0/Source/timers.c
213	)
214
215	target_link_directories(beyond_synaptics PRIVATE src/ASF/thirdparty/CMSIS/Lib/GCC)
216	target_link_libraries(beyond_synaptics PRIVATE arm_cortexM4lf_math m)
217
218	target_link_options(beyond_synaptics PRIVATE -Wl,--gc-sections -Wl,-T ${LINKER_FILE})
219
220	firmware_size(beyond_synaptics sysv)
221	generate_object(beyond_synaptics .bin binary)
222
223	if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
224	     generate_object(beyond_synaptics .hex ihex)
225	endif()

cmake_minimum_required(VERSION 3.10)
project(beyond_synaptics C CXX ASM)

set(CMAKE_EXECUTABLE_SUFFIX ".elf")
set(CMAKE_C_COMPILER_TARGET thumbv7m-unknown-none-eabi)
set(CMAKE_CXX_COMPILER_TARGET thumbv7m-unknown-none-eabi)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)

set(CPU_FLAGS -mthumb -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16)
# set(COMPILER_FLAGS -ffreestanding -ffunction-sections -fdata-sections -fsigned-char -fmessage-length=0 -fshort-enums)
set(COMPILER_FLAGS -pipe -fno-strict-aliasing -Wall -Wstrict-prototypes -Wmissing-prototypes
 -Werror-implicit-function-declaration -Wpointer-arith -std=gnu99
 -ffunction-sections -fdata-sections -Wchar-subscripts -Wcomment
 -Wformat=2 -Wimplicit-int -Wmain -Wparentheses -Wsequence-point
 -Wreturn-type -Wswitch -Wtrigraphs -Wunused -Wuninitialized -Wunknown-pragmas -Wno-expansion-to-defined
 -Wfloat-equal -Wundef -Wshadow -Wbad-function-cast -Wwrite-strings -Wsign-compare
 -Waggregate-return -Wmissing-declarations -Wformat -Wmissing-format-attribute
 -Wno-deprecated-declarations -Wpacked -Wredundant-decls -Wnested-externs -Wlong-long
 -Wunreachable-code -Wcast-align --param max-inline-insns-single=500
 -ffast-math -mlong-calls)

set(LINKER_FILE "${CMAKE_CURRENT_LIST_DIR}/src/ASF/sam/utils/linker_scripts/samg/samg55j19/gcc/flash_usb_bootloader.ld")

add_compile_options(${CPU_FLAGS} ${COMPILER_FLAGS})
add_link_options(${CPU_FLAGS})
add_definitions(-D__SAMG55G19__ -DARM_MATH_CM4=true -Dprintf=iprintf -D__FREERTOS__ -Dscanf=iscanf -DBOARD=USER_EXT_BOARD -DUDD_ENABLE -DNOTBOARD=SAMG55_XPLAINED_PRO -DUSER_BOARD_REVISION=4)

include(utils.cmake)

if("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
    include(../../../clang_utils.cmake)
    clang_utils_get_arm_gcc_sysroot(${ARM_GCC_C_COMPILER} ${CPU_FLAGS})
    clang_utils_get_arm_gcc_multilib_dir(${ARM_GCC_C_COMPILER} ${CPU_FLAGS})
    clang_utils_get_arm_gcc_lib_dir(${ARM_GCC_C_COMPILER} ${CPU_FLAGS})
    clang_utils_get_arm_gcc_crt(${ARM_GCC_SYSROOT} ${ARM_GCC_MULTIDIR} ${ARM_GCC_LIBGCC_DIR})
    string(APPEND CMAKE_EXE_LINKER_FLAGS
        " -nostdlib -L${ARM_GCC_SYSROOT}/lib/${ARM_GCC_MULTIDIR} -L${ARM_GCC_LIBGCC_DIR}")
    string(APPEND CMAKE_EXE_LINKER_FLAGS " -lgcc -lc_nano -lc")
elseif("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
    string(REGEX MATCH ".*\.specs.*" has_specs "${CMAKE_EXE_LINKER_FLAGS}")

    if(NOT has_specs)
        string(APPEND CMAKE_EXE_LINKER_FLAGS " --specs=nano.specs")
    endif()
endif()

string(REPLACE ";" " " _LINKER_CPU_FLAGS "${CPU_FLAGS}")

# subdirlist(include_dir_list ${CMAKE_CURRENT_LIST_DIR}/src)

add_executable(beyond_synaptics src/main.c)
target_include_directories(beyond_synaptics PRIVATE
src/
# Project source dirs must precede the ASF/CMSIS dirs: the samg55 CMSIS tree
# ships its own component/instance "adc.h" which otherwise shadows the
# project's src/Drivers/adc.h on a bare #include "adc.h".
src/Devices/
src/Drivers/
src/config/
src/crash_handler/
src/ASF/
src/ASF/common/
src/ASF/common/boards/
src/ASF/common/services/
src/ASF/common/services/clock/
src/ASF/common/services/clock/samg/
src/ASF/common/services/ioport/
src/ASF/common/services/ioport/sam/
src/ASF/common/services/serial/
src/ASF/common/services/serial/sam_uart/
src/ASF/common/services/sleepmgr/
src/ASF/common/services/sleepmgr/sam/
src/ASF/common/services/usb/
src/ASF/common/services/usb/class/
src/ASF/common/services/usb/class/audio/device
src/ASF/common/services/usb/class/audio
src/ASF/common/services/usb/class/hid
src/ASF/common/services/usb/class/hid/device
src/ASF/common/services/usb/class/composite
src/ASF/common/services/usb/class/hid/device/generic
src/ASF/common/services/usb/udc/
src/ASF/common/utils/
src/ASF/common/utils/interrupt/
src/ASF/common/utils/stdio/
src/ASF/common/utils/stdio/stdio_serial/
src/ASF/sam/
src/ASF/sam/boards/
src/ASF/sam/boards/displayboard
src/ASF/sam/boards/samg55_xplained_pro/
src/ASF/sam/drivers/
src/ASF/sam/drivers/adc/
src/ASF/sam/drivers/efc/
src/ASF/sam/drivers/flexcom/
src/ASF/sam/drivers/matrix/
src/ASF/sam/drivers/pdc/
src/ASF/sam/drivers/pdc/pdc_uart_example/
src/ASF/sam/drivers/pdm/
src/ASF/sam/drivers/pio/
src/ASF/sam/drivers/pmc/
src/ASF/sam/drivers/supc/
src/ASF/sam/drivers/udp/
src/ASF/sam/drivers/usart/
src/ASF/sam/utils/
src/ASF/sam/utils/cmsis/
src/ASF/sam/utils/cmsis/samg/
src/ASF/sam/utils/cmsis/samg/samg55/
src/ASF/sam/utils/cmsis/samg/samg55/include/
src/ASF/sam/utils/cmsis/samg/samg55/include/component/
src/ASF/sam/utils/cmsis/samg/samg55/include/instance/
src/ASF/sam/utils/cmsis/samg/samg55/include/pio/
src/ASF/sam/utils/cmsis/samg/samg55/source/
src/ASF/sam/utils/cmsis/samg/samg55/source/templates/
src/ASF/sam/utils/cmsis/samg/samg55/source/templates/gcc/
src/ASF/sam/utils/fpu/
src/ASF/sam/utils/header_files/
src/ASF/sam/utils/linker_scripts/
src/ASF/sam/utils/linker_scripts/samg/
src/ASF/sam/utils/linker_scripts/samg/samg55j19/
src/ASF/sam/utils/linker_scripts/samg/samg55j19/gcc/
src/ASF/sam/utils/make/
src/ASF/sam/utils/preprocessor/
src/ASF/sam/utils/syscalls/
src/ASF/sam/utils/syscalls/gcc/
src/ASF/thirdparty/
src/ASF/thirdparty/CMSIS/
src/ASF/thirdparty/CMSIS/Include/
src/ASF/thirdparty/CMSIS/Lib/
src/ASF/thirdparty/CMSIS/Lib/GCC/
src/ASF/thirdparty/freertos/
src/ASF/thirdparty/freertos/freertos-10.0.0/
src/ASF/thirdparty/freertos/freertos-10.0.0/Source/
src/ASF/thirdparty/freertos/freertos-10.0.0/Source/include/
src/ASF/thirdparty/freertos/freertos-10.0.0/Source/portable/
src/ASF/thirdparty/freertos/freertos-10.0.0/Source/portable/GCC/
src/ASF/thirdparty/freertos/freertos-10.0.0/Source/portable/GCC/ARM_CM4F/
src/ASF/thirdparty/freertos/freertos-10.0.0/Source/portable/MemMang/
src/config/
src/Devices
src/Drivers
src/crash_handler
)

target_sources(beyond_synaptics PRIVATE
src/ASF/common/services/usb/class/audio/device/udi_audio.c
src/ASF/common/services/usb/class/hid/device/udi_hid_desc.c
src/ASF/sam/boards/displayboard/displayboard_init.c
src/ASF/sam/drivers/adc/adc2.c
src/crash_handler/crash_handler.c
src/Devices/eyetrack_fpga.c
src/Devices/fan_motor_control.c
src/Devices/linkbox_hpd.c
src/Devices/oled_control.c
src/Devices/prox_control.c
src/Devices/prox_tmd2635.c
src/Devices/rgb_led.c
src/Devices/usb2517.c
src/Devices/usb3803.c
src/Devices/usbc_mux.c
src/Devices/vxr_interface.c
src/Devices/tundra_uart.c
src/Drivers/adc.c
src/Drivers/flash_mutex.c
src/Drivers/i2c.c
src/Drivers/pdm_mics.c
src/Drivers/power_control.c
src/Drivers/rtt_util.c
src/Drivers/signature.c
src/Drivers/temp_sense.c
src/eeprom_emulation.c
src/hw_test.c
src/sw_ver.c
src/ui_interface.c
src/usart_interface.c
src/usbhid_interface.c
src/video_proc.c
src/test_and_debug.c
src/ASF/common/services/usb/class/composite/udi_composite_desc.c
src/ASF/common/services/usb/class/hid/device/generic/udi_hid_generic.c
src/ASF/common/services/usb/class/hid/device/udi_hid.c
src/ASF/common/services/usb/udc/udc.c
src/ASF/sam/drivers/pio/pio_handler.c
src/ASF/sam/drivers/udp/udp_device.c
src/ASF/sam/drivers/matrix/matrix.c
src/ASF/sam/drivers/pdc/pdc.c
src/ASF/sam/drivers/pdm/pdm.c
src/ASF/sam/drivers/pio/pio.c
src/ASF/common/services/clock/samg/sysclk.c
src/ASF/common/services/serial/usart_serial.c
src/ASF/common/services/sleepmgr/sam/sleepmgr.c
src/ASF/common/utils/interrupt/interrupt_sam_nvic.c
src/ASF/common/utils/stdio/read.c
src/ASF/common/utils/stdio/write.c
src/ASF/sam/drivers/efc/efc.c
src/ASF/sam/drivers/flexcom/flexcom.c
src/ASF/sam/drivers/pmc/pmc.c
src/ASF/sam/drivers/pmc/sleep.c
src/ASF/sam/drivers/supc/supc.c
src/ASF/sam/drivers/usart/usart.c
src/ASF/sam/utils/cmsis/samg/samg55/source/templates/gcc/startup_samg55.c
src/ASF/sam/utils/cmsis/samg/samg55/source/templates/system_samg55.c
src/ASF/sam/utils/syscalls/gcc/syscalls.c
src/ASF/thirdparty/freertos/freertos-10.0.0/Source/croutine.c
src/ASF/thirdparty/freertos/freertos-10.0.0/Source/event_groups.c
src/ASF/thirdparty/freertos/freertos-10.0.0/Source/list.c
src/ASF/thirdparty/freertos/freertos-10.0.0/Source/portable/GCC/ARM_CM4F/port.c
src/ASF/thirdparty/freertos/freertos-10.0.0/Source/portable/MemMang/heap_3.c
src/ASF/thirdparty/freertos/freertos-10.0.0/Source/queue.c
src/ASF/thirdparty/freertos/freertos-10.0.0/Source/stream_buffer.c
src/ASF/thirdparty/freertos/freertos-10.0.0/Source/tasks.c
src/ASF/thirdparty/freertos/freertos-10.0.0/Source/timers.c
)

target_link_directories(beyond_synaptics PRIVATE src/ASF/thirdparty/CMSIS/Lib/GCC)
target_link_libraries(beyond_synaptics PRIVATE arm_cortexM4lf_math m)

target_link_options(beyond_synaptics PRIVATE -Wl,--gc-sections -Wl,-T ${LINKER_FILE})

firmware_size(beyond_synaptics sysv)
generate_object(beyond_synaptics .bin binary)

if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
     generate_object(beyond_synaptics .hex ihex)
endif()


This is the payload. Several **concrete CMake-vs-Studio build divergences** that all-paths firmware would inherit:

| Setting | Studio `.cproj` (known-good) | CMake (0.4.3 flashed) |
|---|---|---|
| Float opt | *(none)* | **`-ffast-math`** added |
| Calls | *(none)* | **`-mlong-calls`** added |
| Part define | `__SAMG55J19__` | **`__SAMG55G19__`** (J→G) |
| Board | `BOARD=SAMG55_XPLAINED_PRO` | **`BOARD=USER_EXT_BOARD` + `USER_BOARD_REVISION=4`** |
| Linker script | `flash.ld` | **`flash_usb_bootloader.ld`** |
| C lib | full newlib | **`--specs=nano.specs` / `-lc_nano`** |

Some may be intentional for the AppImage/OTA path (linker, maybe board), but `__SAMG55G19__` looks like a **J→G typo** (chip is samg55**j19**), and `-ffast-math` is a risky unilateral add. Let me verify whether the part-define and board actually change compiled behavior (do headers branch on them?).


cd C:/Users/decid/Documents/projects/beyond_synaptics && echo "===does code branch on J19 vs G19?===" && grep -rnE "__SAMG55J19__|__SAMG55G19__|SAMG55J19|SAMG55G19" src/ --include=*.h --include=*.c | grep -ivE "linker_scripts" | head -20 && echo "" && echo "===USER_EXT_BOARD vs SAMG55_XPLAINED_PRO / USER_BOARD_REVISION usage===" && grep -rnE "USER_EXT_BOARD|SAMG55_XPLAINED_PRO|USER_BOARD_REVISION" src/ --include=*.h --include=*.c | grep -ivE "ASF/sam/boards/samg55_xplained_pro" | head -25

Check if part-define + board actually branch code


Command running in background with ID: bsm4l9o29. Output is being written to: C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-sauna\d3fb9be1-d61d-4f88-b77c-2a2a282b11fd\tasks\bsm4l9o29.output. You will be notified when it completes. To check interim output, use Read on that file path.


<task-notification>
<task-id>bsm4l9o29</task-id>
<tool-use-id>toolu_01NF68UCcqWT3XKEk1FpM1Jg</tool-use-id>
<output-file>C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-sauna\d3fb9be1-d61d-4f88-b77c-2a2a282b11fd\tasks\bsm4l9o29.output</output-file>
<status>completed</status>
<summary>Background command "Check if part-define + board actually branch code" completed (exit code 0)</summary>
</task-notification>


1	===does code branch on J19 vs G19?===
2	src/ASF/common/utils/parts.h:1462:		SAM_PART_IS_DEFINED(SAMG55G19) ||\
3	src/ASF/common/utils/parts.h:1464:		SAM_PART_IS_DEFINED(SAMG55J19) ||\
4	src/ASF/sam/utils/cmsis/samg/samg55/include/pio/samg55g19.h:35:#ifndef _SAMG55G19_PIO_
5	src/ASF/sam/utils/cmsis/samg/samg55/include/pio/samg55g19.h:36:#define _SAMG55G19_PIO_
6	src/ASF/sam/utils/cmsis/samg/samg55/include/pio/samg55g19.h:439:#endif /* _SAMG55G19_PIO_ */
7	src/ASF/sam/utils/cmsis/samg/samg55/include/pio/samg55j19.h:35:#ifndef _SAMG55J19_PIO_
8	src/ASF/sam/utils/cmsis/samg/samg55/include/pio/samg55j19.h:36:#define _SAMG55J19_PIO_
9	src/ASF/sam/utils/cmsis/samg/samg55/include/pio/samg55j19.h:492:#endif /* _SAMG55J19_PIO_ */
10	src/ASF/sam/utils/cmsis/samg/samg55/include/samg55.h:39:#elif defined (__SAMG55G19__)
11	src/ASF/sam/utils/cmsis/samg/samg55/include/samg55.h:43:#elif defined (__SAMG55J19__)
12	src/ASF/sam/utils/cmsis/samg/samg55/include/samg55g19.h:35:#ifndef _SAMG55G19_
13	src/ASF/sam/utils/cmsis/samg/samg55/include/samg55g19.h:36:#define _SAMG55G19_
14	src/ASF/sam/utils/cmsis/samg/samg55/include/samg55g19.h:38:/** \addtogroup SAMG55G19_definitions SAMG55G19 definitions
15	src/ASF/sam/utils/cmsis/samg/samg55/include/samg55g19.h:39:  This file defines all structures and symbols for SAMG55G19:
16	src/ASF/sam/utils/cmsis/samg/samg55/include/samg55g19.h:56:/*   CMSIS DEFINITIONS FOR SAMG55G19 */
17	src/ASF/sam/utils/cmsis/samg/samg55/include/samg55g19.h:58:/** \addtogroup SAMG55G19_cmsis CMSIS Definitions */
18	src/ASF/sam/utils/cmsis/samg/samg55/include/samg55g19.h:73:/******  SAMG55G19 specific Interrupt Numbers *********************************/
19	src/ASF/sam/utils/cmsis/samg/samg55/include/samg55g19.h:75: SUPC_IRQn            =  0, /**<  0 SAMG55G19 Supply Controller (SUPC) */
20	src/ASF/sam/utils/cmsis/samg/samg55/include/samg55g19.h:76:  RSTC_IRQn            =  1, /**<  1 SAMG55G19 Reset Controller (RSTC) */
21	src/ASF/sam/utils/cmsis/samg/samg55/include/samg55g19.h:77:  RTC_IRQn             =  2, /**<  2 SAMG55G19 Real Time Clock (RTC) */
22
23	===USER_EXT_BOARD vs SAMG55_XPLAINED_PRO / USER_BOARD_REVISION usage===
24	src/ASF/common/boards/board.h:133:#define SAMG55_XPLAINED_PRO        75  //!< SAMG55 Xplained Pro board.
25	src/ASF/common/boards/board.h:179:#define USER_EXT_BOARD              99  //!< User-reserved extension board (if any).
26	src/ASF/common/boards/board.h:228:#elif BOARD == SAMG55_XPLAINED_PRO
27	src/ASF/common/boards/board.h:417:#  elif EXT_BOARD == USER_EXT_BOARD
28	src/Devices/fan_motor_control.h:6:#if BOARD==SAMG55_XPLAINED_PRO
29	src/main.c:149:	#if BOARD == USER_EXT_BOARD
30	src/main.c:168:	#if BOARD == USER_EXT_BOARD
31	src/main.c:326:#if BOARD == USER_EXT_BOARD
32	src/usart_interface.c:158:#if BOARD == USER_EXT_BOARD
33

===does code branch on J19 vs G19?===
src/ASF/common/utils/parts.h:1462:		SAM_PART_IS_DEFINED(SAMG55G19) ||\
src/ASF/common/utils/parts.h:1464:		SAM_PART_IS_DEFINED(SAMG55J19) ||\
src/ASF/sam/utils/cmsis/samg/samg55/include/pio/samg55g19.h:35:#ifndef _SAMG55G19_PIO_
src/ASF/sam/utils/cmsis/samg/samg55/include/pio/samg55g19.h:36:#define _SAMG55G19_PIO_
src/ASF/sam/utils/cmsis/samg/samg55/include/pio/samg55g19.h:439:#endif /* _SAMG55G19_PIO_ */
src/ASF/sam/utils/cmsis/samg/samg55/include/pio/samg55j19.h:35:#ifndef _SAMG55J19_PIO_
src/ASF/sam/utils/cmsis/samg/samg55/include/pio/samg55j19.h:36:#define _SAMG55J19_PIO_
src/ASF/sam/utils/cmsis/samg/samg55/include/pio/samg55j19.h:492:#endif /* _SAMG55J19_PIO_ */
src/ASF/sam/utils/cmsis/samg/samg55/include/samg55.h:39:#elif defined (__SAMG55G19__)
src/ASF/sam/utils/cmsis/samg/samg55/include/samg55.h:43:#elif defined (__SAMG55J19__)
src/ASF/sam/utils/cmsis/samg/samg55/include/samg55g19.h:35:#ifndef _SAMG55G19_
src/ASF/sam/utils/cmsis/samg/samg55/include/samg55g19.h:36:#define _SAMG55G19_
src/ASF/sam/utils/cmsis/samg/samg55/include/samg55g19.h:38:/** \addtogroup SAMG55G19_definitions SAMG55G19 definitions
src/ASF/sam/utils/cmsis/samg/samg55/include/samg55g19.h:39:  This file defines all structures and symbols for SAMG55G19:
src/ASF/sam/utils/cmsis/samg/samg55/include/samg55g19.h:56:/*   CMSIS DEFINITIONS FOR SAMG55G19 */
src/ASF/sam/utils/cmsis/samg/samg55/include/samg55g19.h:58:/** \addtogroup SAMG55G19_cmsis CMSIS Definitions */
src/ASF/sam/utils/cmsis/samg/samg55/include/samg55g19.h:73:/******  SAMG55G19 specific Interrupt Numbers *********************************/
src/ASF/sam/utils/cmsis/samg/samg55/include/samg55g19.h:75: SUPC_IRQn            =  0, /**<  0 SAMG55G19 Supply Controller (SUPC) */
src/ASF/sam/utils/cmsis/samg/samg55/include/samg55g19.h:76:  RSTC_IRQn            =  1, /**<  1 SAMG55G19 Reset Controller (RSTC) */
src/ASF/sam/utils/cmsis/samg/samg55/include/samg55g19.h:77:  RTC_IRQn             =  2, /**<  2 SAMG55G19 Real Time Clock (RTC) */

===USER_EXT_BOARD vs SAMG55_XPLAINED_PRO / USER_BOARD_REVISION usage===
src/ASF/common/boards/board.h:133:#define SAMG55_XPLAINED_PRO        75  //!< SAMG55 Xplained Pro board.
src/ASF/common/boards/board.h:179:#define USER_EXT_BOARD              99  //!< User-reserved extension board (if any).
src/ASF/common/boards/board.h:228:#elif BOARD == SAMG55_XPLAINED_PRO
src/ASF/common/boards/board.h:417:#  elif EXT_BOARD == USER_EXT_BOARD
src/Devices/fan_motor_control.h:6:#if BOARD==SAMG55_XPLAINED_PRO
src/main.c:149:	#if BOARD == USER_EXT_BOARD
src/main.c:168:	#if BOARD == USER_EXT_BOARD
src/main.c:326:#if BOARD == USER_EXT_BOARD
src/usart_interface.c:158:#if BOARD == USER_EXT_BOARD


Prompt:
<task-notification>
<task-id>bsm4l9o29</task-id>
<tool-use-id>toolu_01NF68UCcqWT3XKEk1FpM1Jg</tool-use-id>
<output-file>C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-sauna\d3fb9be1-d61d-4f88-b77c-2a2a282b11fd\tasks\bsm4l9o29.output</output-file>
<status>completed</status>
<summary>Background command "Check if part-define + board actually branch code" completed (exit code 0)</summary>
</task-notification>


Decisive nuance on the board/define findings:

- **`__SAMG55G19__` vs `__SAMG55J19__`**: selects a different CMSIS device header (`samg55g19.h` vs `samg55j19.h`). Same die, different package (PIO line count). Since it *compiled*, code doesn't reference J19-only pin macros → likely compile-benign at runtime. Wrong, fix it, but probably not the wedge.
- **`BOARD=USER_EXT_BOARD`**: `main.c:149/168/326` and `usart_interface.c:158` gate the **real Beyond HW init** on `#if BOARD == USER_EXT_BOARD`. So CMake's `USER_EXT_BOARD` is **correct** — and the `.cproj`'s `SAMG55_XPLAINED_PRO` would *omit* that init. ⇒ **the in-repo `.cproj` is NOT the true production build config.** So I can't trust `.cproj` as the known-good baseline for the other flags.

That validates your CRC idea as the *reliable* baseline. The standout CMake-introduced deviation that isn't board-correctness is **`-ffast-math`** (sets FPU flush-to-zero/default-NaN globally at startup, changes all float behavior) plus `-mlong-calls` and newlib-**nano**. Let me locate the prebuilt 0.3.18 to compare against.


cd C:/Users/decid/Documents/projects && echo "===prebuilt 0.3.x / 318 binaries anywhere===" && (cd beyond_synaptics && git ls-files | grep -iE "build/.*(0?3[._]?1[0-9]|v03|0\.3)" ; ls build/*.hex build/*.beyondfw 2>/dev/null | grep -iE "3[._]?1[0-8]|v031|0\.3\.1" ) 2>/dev/null | head && echo "---ALL .beyondfw in beyond_synaptics + quick-beyond-updater---" && find beyond_synaptics quick-beyond-updater -iname "*.beyondfw" -o -iname "*318*" -o -iname "*0.3.18*" 2>/dev/null | head -20 && echo "---newest build/ hex (tail)---" && (cd beyond_synaptics && git ls-files | grep -E "^build/" | grep -iE "\.hex$|\.beyondfw$" | tail -25)

Locate prebuilt 0.3.18 binary


Command running in background with ID: bsiphdtm1. Output is being written to: C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-sauna\d3fb9be1-d61d-4f88-b77c-2a2a282b11fd\tasks\bsiphdtm1.output. You will be notified when it completes. To check interim output, use Read on that file path.


<task-notification>
<task-id>bsiphdtm1</task-id>
<tool-use-id>toolu_01JYSJjYHFnnaaqsBnTF8zXp</tool-use-id>
<output-file>C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-sauna\d3fb9be1-d61d-4f88-b77c-2a2a282b11fd\tasks\bsiphdtm1.output</output-file>
<status>completed</status>
<summary>Background command "Locate prebuilt 0.3.18 binary" completed (exit code 0)</summary>
</task-notification>


1	===prebuilt 0.3.x / 318 binaries anywhere===
2	build/Beyond_Synaptics_AppImage_v024A_230316.hex
3	build/Beyond_Synaptics_FullImage_v024A_230316.hex
4	build/stack_checking/Beyond_AppImage_v99215_231005.hex
5	build/stack_checking/Beyond_FullImage_v99215_231005.hex
6	build/v0.2.16/Beyond_AppImage_v0216_231010.hex
7	build/v0.2.16/Beyond_FullImage_v0216_231010.hex
8	build/v0.2.17/Beyond_AppImage_v0217_231013.hex
9	build/v0.2.17/Beyond_FullImage_v0217_231013.hex
10	build/v0.2.18/Beyond_AppImage_v0218_231014.hex
11	build/v0.2.18/Beyond_FullImage_v0218_231014.hex
12	---ALL .beyondfw in beyond_synaptics + quick-beyond-updater---
13	beyond_synaptics/build/stack_checking/latest.beyondfw
14	beyond_synaptics/build/v0.2.13/latest.beyondfw
15	beyond_synaptics/build/v0.2.14/latest.beyondfw
16	beyond_synaptics/build/v0.2.15/latest.beyondfw
17	beyond_synaptics/build/v0.2.16/latest.beyondfw
18	beyond_synaptics/build/v0.2.17/latest.beyondfw
19	beyond_synaptics/build/v0.2.18/latest.beyondfw
20	beyond_synaptics/build/v0.2.19/latest.beyondfw
21	beyond_synaptics/build/v0.2.20/latest.beyondfw
22	beyond_synaptics/build/v0.2.21/latest.beyondfw
23	beyond_synaptics/build/v0.2.22/latest.beyondfw
24	beyond_synaptics/build/v0.2.24/latest.beyondfw
25	beyond_synaptics/build/v0.2.25/latest.beyondfw
26	beyond_synaptics/build/v0.3.1/latest.beyondfw
27	beyond_synaptics/build/v0.3.2/latest.beyondfw
28	beyond_synaptics/build/v0.3.3/latest.beyondfw
29	beyond_synaptics/build/v0.3.5/latest.beyondfw
30	beyond_synaptics/build/v0.3.6/latest.beyondfw
31	beyond_synaptics/build/v0.3.7/latest.beyondfw
32	beyond_synaptics/build/v0.3.7D/latest.beyondfw
33	---newest build/ hex (tail)---
34	build/v0.3.2/latest.beyondfw
35	build/v0.3.3/Beyond_AppImage_v033_241113.hex
36	build/v0.3.3/Beyond_FullImage_v033_241113.hex
37	build/v0.3.3/latest.beyondfw
38	build/v0.3.5/Beyond_AppImage_v035_241219.hex
39	build/v0.3.5/Beyond_FullImage_v035_241219.hex
40	build/v0.3.5/latest.beyondfw
41	build/v0.3.6/Beyond_AppImage_v036_250128.hex
42	build/v0.3.6/Beyond_FullImage_v036_250128.hex
43	build/v0.3.6/latest.beyondfw
44	build/v0.3.7/Beyond_AppImage_v037_250202.hex
45	build/v0.3.7/Beyond_FullImage_v037_250202.hex
46	build/v0.3.7/latest.beyondfw
47	build/v0.3.7D/Beyond_AppImage_v037D_250219.hex
48	build/v0.3.7D/Beyond_FullImage_v037D_250219.hex
49	build/v0.3.7D/latest.beyondfw
50	build/v0.3.7E/Beyond_AppImage_v037E_250220.hex
51	build/v0.3.7E/Beyond_FullImage_v037E_250220.hex
52	build/v0.3.7E/latest.beyondfw
53	build/v0.3.8/Beyond_AppImage_v038_250227.hex
54	build/v0.3.8/Beyond_FullImage_v038_250227.hex
55	build/v0.3.8/latest.beyondfw
56	build/v0.3.9/Beyond_AppImage_v039_250328.hex
57	build/v0.3.9/Beyond_FullImage_v039_250328.hex
58	build/v0.3.9/latest.beyondfw
59

===prebuilt 0.3.x / 318 binaries anywhere===
build/Beyond_Synaptics_AppImage_v024A_230316.hex
build/Beyond_Synaptics_FullImage_v024A_230316.hex
build/stack_checking/Beyond_AppImage_v99215_231005.hex
build/stack_checking/Beyond_FullImage_v99215_231005.hex
build/v0.2.16/Beyond_AppImage_v0216_231010.hex
build/v0.2.16/Beyond_FullImage_v0216_231010.hex
build/v0.2.17/Beyond_AppImage_v0217_231013.hex
build/v0.2.17/Beyond_FullImage_v0217_231013.hex
build/v0.2.18/Beyond_AppImage_v0218_231014.hex
build/v0.2.18/Beyond_FullImage_v0218_231014.hex
---ALL .beyondfw in beyond_synaptics + quick-beyond-updater---
beyond_synaptics/build/stack_checking/latest.beyondfw
beyond_synaptics/build/v0.2.13/latest.beyondfw
beyond_synaptics/build/v0.2.14/latest.beyondfw
beyond_synaptics/build/v0.2.15/latest.beyondfw
beyond_synaptics/build/v0.2.16/latest.beyondfw
beyond_synaptics/build/v0.2.17/latest.beyondfw
beyond_synaptics/build/v0.2.18/latest.beyondfw
beyond_synaptics/build/v0.2.19/latest.beyondfw
beyond_synaptics/build/v0.2.20/latest.beyondfw
beyond_synaptics/build/v0.2.21/latest.beyondfw
beyond_synaptics/build/v0.2.22/latest.beyondfw
beyond_synaptics/build/v0.2.24/latest.beyondfw
beyond_synaptics/build/v0.2.25/latest.beyondfw
beyond_synaptics/build/v0.3.1/latest.beyondfw
beyond_synaptics/build/v0.3.2/latest.beyondfw
beyond_synaptics/build/v0.3.3/latest.beyondfw
beyond_synaptics/build/v0.3.5/latest.beyondfw
beyond_synaptics/build/v0.3.6/latest.beyondfw
beyond_synaptics/build/v0.3.7/latest.beyondfw
beyond_synaptics/build/v0.3.7D/latest.beyondfw
---newest build/ hex (tail)---
build/v0.3.2/latest.beyondfw
build/v0.3.3/Beyond_AppImage_v033_241113.hex
build/v0.3.3/Beyond_FullImage_v033_241113.hex
build/v0.3.3/latest.beyondfw
build/v0.3.5/Beyond_AppImage_v035_241219.hex
build/v0.3.5/Beyond_FullImage_v035_241219.hex
build/v0.3.5/latest.beyondfw
build/v0.3.6/Beyond_AppImage_v036_250128.hex
build/v0.3.6/Beyond_FullImage_v036_250128.hex
build/v0.3.6/latest.beyondfw
build/v0.3.7/Beyond_AppImage_v037_250202.hex
build/v0.3.7/Beyond_FullImage_v037_250202.hex
build/v0.3.7/latest.beyondfw
build/v0.3.7D/Beyond_AppImage_v037D_250219.hex
build/v0.3.7D/Beyond_FullImage_v037D_250219.hex
build/v0.3.7D/latest.beyondfw
build/v0.3.7E/Beyond_AppImage_v037E_250220.hex
build/v0.3.7E/Beyond_FullImage_v037E_250220.hex
build/v0.3.7E/latest.beyondfw
build/v0.3.8/Beyond_AppImage_v038_250227.hex
build/v0.3.8/Beyond_FullImage_v038_250227.hex
build/v0.3.8/latest.beyondfw
build/v0.3.9/Beyond_AppImage_v039_250328.hex
build/v0.3.9/Beyond_FullImage_v039_250328.hex
build/v0.3.9/latest.beyondfw


Prompt:
<task-notification>
<task-id>bsiphdtm1</task-id>
<tool-use-id>toolu_01JYSJjYHFnnaaqsBnTF8zXp</tool-use-id>
<output-file>C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-sauna\d3fb9be1-d61d-4f88-b77c-2a2a282b11fd\tasks\bsiphdtm1.output</output-file>
<status>completed</status>
<summary>Background command "Locate prebuilt 0.3.18 binary" completed (exit code 0)</summary>
</task-notification>


Prebuilt artifacts in the repo stop at **v0.3.9** (`build/v0.3.9/Beyond_AppImage_v039_250328.hex`) — no 0.3.18 prebuilt is committed. Those hex files ARE official Studio-built artifacts, so they're a usable in-repo baseline for your CRC/repro idea (build same source via CMake, diff against the official hex). If you have the real prebuilt 0.3.18 locally, even better.

Let me record the build-diff findings before we pick the experiment.


Edit

**DECISIVE NEXT EXPERIMENT (isolates build vs source):** build *pure v0.3.19 source* with the SAME CMake/arm-gcc toolchain, flash, test with addons. v0.3.19-via-CMake ALSO wedges ⇒ it's the BUILD/toolchain (not doze source). v0.3.19-via-CMake works but 0.4.3 wedges ⇒ it's the 0.4.x source delta (fan-kickstart prime suspect → bisect by reverting it). Headless build+flash code-46 retry quirk applies. Verify MCU liveness read-only via `get_hmd_fw_version` (QBU bs_hmd_tools). Don't power past a wedge — power-cycle first. Related: [[hmd-bench-rig]].

Also ELIMINATED: v0.3.18→v0.3.19 source delta (baseline was v0.3.18; HMD jumped straight 0.3.18→0.4.3). That delta is ONLY an RGB-LED-animation feature (commit b2c696a: `report[4]` mode byte on the 'L'/0x4c cmd + LED blinking task). LED-task only, can't gate prox/HID. Not the wedge.

**LEADING HYPOTHESIS = BUILD/TOOLCHAIN (source is inert).** The 0.4.3 flashed is the headless CMake/arm-gcc-12.2 build; known-good v0.3.18 was an official build. Compared `CMakeLists.txt` vs `Beyond_Synaptics.cproj`, CMake-introduced deviations: **`-ffast-math`** (Studio has none — sets FPU FZ/default-NaN globally at startup via crtfastmath, changes ALL float behavior → PRIME suspect), `-mlong-calls`, `--specs=nano.specs`/`-lc_nano` (newlib-nano: smaller reentrancy/heap vs full newlib), and `-D__SAMG55G19__` typo (chip is J19; selects samg55g19.h CMSIS header — compile-benign since no J19-only pin macros referenced, but WRONG, fix to `__SAMG55J19__`). NOTE: `.cproj` is NOT the true production config — it has `BOARD=SAMG55_XPLAINED_PRO` but real Beyond HW init is gated `#if BOARD==USER_EXT_BOARD` (main.c 149/168/326, usart_interface.c 158), and CMake correctly uses `USER_EXT_BOARD`. So `.cproj` board/linker(`flash_usb_bootloader.ld` for AppImage) deltas are likely intentional-correct; trust the prebuilt AppImage hex (official Studio artifacts, in-repo up to `build/v0.3.9/Beyond_AppImage_v039_250328.hex`) as the real baseline, NOT `.cproj`. No prebuilt 0.3.10–0.3.19 committed.

**NEXT EXPERIMENTS:** (A, fastest functional test) rebuild 0.4.x with `-ffast-math` removed + `__SAMG55G19__`→`__SAMG55J19__`, flash, retest with addons. Wedge gone ⇒ build flags were it. (B, no-hardware analysis) build an in-repo prebuilt's source (e.g. v0.3.9) via CMake toolchain, binary/symbol-diff vs the committed official `Beyond_AppImage_v039` hex to see exactly what the toolchain changes (exact CRC match unlikely across toolchains — use section/symbol diff, not raw CRC). Headless build+flash code-46 retry quirk applies. Verify MCU liveness read-only via `get_hmd_fw_version` (QBU bs_hmd_tools). Don't power past a wedge — power-cycle first. Related: [[beyond-synaptics-firmware-build]], [[hmd-bench-rig]].


The file C:\Users\decid\.ccs\instances\bigscreen\projects\C--Users-decid-Documents-projects-sauna\memory\steamvr-forcekill-mcu-hang.md has been updated successfully. (file state is current in your context — no need to Read it back)

Also ELIMINATED: v0.3.18→v0.3.19 source delta (baseline was v0.3.18; HMD jumped straight 0.3.18→0.4.3). That delta is ONLY an RGB-LED-animation feature (commit b2c696a: `report[4]` mode byte on the 'L'/0x4c cmd + LED blinking task). LED-task only, can't gate prox/HID. Not the wedge.

**LEADING HYPOTHESIS = BUILD/TOOLCHAIN (source is inert).** The 0.4.3 flashed is the headless CMake/arm-gcc-12.2 build; known-good v0.3.18 was an official build. Compared `CMakeLists.txt` vs `Beyond_Synaptics.cproj`, CMake-introduced deviations: **`-ffast-math`** (Studio has none — sets FPU FZ/default-NaN globally at startup via crtfastmath, changes ALL float behavior → PRIME suspect), `-mlong-calls`, `--specs=nano.specs`/`-lc_nano` (newlib-nano: smaller reentrancy/heap vs full newlib), and `-D__SAMG55G19__` typo (chip is J19; selects samg55g19.h CMSIS header — compile-benign since no J19-only pin macros referenced, but WRONG, fix to `__SAMG55J19__`). NOTE: `.cproj` is NOT the true production config — it has `BOARD=SAMG55_XPLAINED_PRO` but real Beyond HW init is gated `#if BOARD==USER_EXT_BOARD` (main.c 149/168/326, usart_interface.c 158), and CMake correctly uses `USER_EXT_BOARD`. So `.cproj` board/linker(`flash_usb_bootloader.ld` for AppImage) deltas are likely intentional-correct; trust the prebuilt AppImage hex (official Studio artifacts, in-repo up to `build/v0.3.9/Beyond_AppImage_v039_250328.hex`) as the real baseline, NOT `.cproj`. No prebuilt 0.3.10–0.3.19 committed.

**NEXT EXPERIMENTS:** (A, fastest functional test) rebuild 0.4.x with `-ffast-math` removed + `__SAMG55G19__`→`__SAMG55J19__`, flash, retest with addons. Wedge gone ⇒ build flags were it. (B, no-hardware analysis) build an in-repo prebuilt's source (e.g. v0.3.9) via CMake toolchain, binary/symbol-diff vs the committed official `Beyond_AppImage_v039` hex to see exactly what the toolchain changes (exact CRC match unlikely across toolchains — use section/symbol diff, not raw CRC). Headless build+flash code-46 retry quirk applies. Verify MCU liveness read-only via `get_hmd_fw_version` (QBU bs_hmd_tools). Don't power past a wedge — power-cycle first. Related: [[beyond-synaptics-firmware-build]], [[hmd-bench-rig]].

---
name: steamvr-forcekill-mcu-hang
description: 0.4.x firmware wedges the Beyond when any SteamVR Beyond-addon runs — prox dies, brightness sticks ~7, power-cycle to recover
metadata:
  node_type: memory
  type: project
  originSessionId: 92a9c1d9-a8d0-47c8-b932-02f7be39d701
---

ROOT CAUSE (confirmed by Brandon 2026-06-13, SteamVR-alone repro, NO sauna): a beyond_synaptics **0.4.x firmware** regression. Whenever EITHER official SteamVR addon (BeyondEyetracking OR BeyondSteamVR) runs, the Beyond's **proximity sensor stops working for that session** (reads untriggered → displays show picture but brightness latched ~7 ≈ a doze-floor value). Then a **SteamVR shutdown leaves the Beyond WEDGED** — usually the RIGHT optic lit with a dim/black image; MCU 0101 still enumerates but stops ACKing (`get_hmd_fw_version` → None). Recovers ONLY on a physical power-cycle. NOT present on pre-0.4.0 firmware (before the M5 doze mods). So a 0.4.x doze/prox/brightness change broke it.

**Earlier wrong theories (this same session) — do NOT trust them:** (1) "force-killing SteamVR mid-session hangs the MCU" and (2) "SteamVR's BeyondProximity driver collides with sauna on 0101." Both were conjecture. Deregistering BeyondProximity (vrpathreg) did NOT fix it; the wedge reproduces with sauna not running at all and with a clean SteamVR quit. **sauna is blameless.**

**Why it matters:** blocks SteamVR coexistence on 0.4.x firmware — the whole point of sauna is to coexist with SteamVR.

**DISPROVEN 2026-06-13 (source-checked, not guessed):** the "doze logic mishandles an addon HID command" theory is dead. (1) The doze state (`doze_active` latch) can ONLY be set by a feature report with `report[0]==0x48` ('H' sleep); wake is 0x68 ('h'). (2) The addons' full command set is in `../HMDUtility/src/hid_handler.cpp` — every code it sends to 0101: `2A 25 26 7E 5E 5A 53 47 67 46 66 52 50 49 42 65 4C 55 57 56 4D 4B 54 44 41 59 4E 4A 40 64 6F 22`. **No 0x48, no 0x68.** So doze never triggers in an addon session and every doze branch in `video_proc.c` is provably inert (all gate on `doze_active`/`doze_phase`, which stay false). Frame note: HMDUtility sends `[0]=0x00 ReportID,[1]=Code`; USB strips the report-ID so firmware `report[0]`==Code.

**Remaining real variables (v0.3.19 shipped → 0.4.3 flashed; 0.4.3 is a strict SUPERSET of v0.3.19 source, no lost commits):** only TWO things differ on always-run / addon-driven paths: (1) **fan kickstart** (`test_and_debug.c` task_fan: jumps to `FAN_MIN_START`=35 on any 0→N fan change; addon drives fan via 0x46/0x66) + `#include <math.h>`/libm linkage; (2) the **BUILD/TOOLCHAIN** — 0.4.3 is the headless CMake/arm-gcc-12.2 `-O3` build ([[beyond-synaptics-firmware-build]]) vs the official Studio build of the known-good firmware. Build had documented hazards incl. CMSIS `adc.h` shadowing `src/Drivers/adc.h` — and **prox reads via ADC**, matching "prox stops working." NOTE: still need to confirm the actual known-good baseline (official production binary, possibly NOT in this repo — v0.3.19 is just the latest tag).

**DECISIVE NEXT EXPERIMENT (isolates build vs source):** build *pure v0.3.19 source* with the SAME CMake/arm-gcc toolchain, flash, test with addons. v0.3.19-via-CMake ALSO wedges ⇒ it's the BUILD/toolchain (not doze source). v0.3.19-via-CMake works but 0.4.3 wedges ⇒ it's the 0.4.x source delta (fan-kickstart prime suspect → bisect by reverting it). Headless build+flash code-46 retry quirk applies. Verify MCU liveness read-only via `get_hmd_fw_version` (QBU bs_hmd_tools). Don't power past a wedge — power-cycle first. Related: [[hmd-bench-rig]].

-**DECISIVE NEXT EXPERIMENT (isolates build vs source):** build *pure v0.3.19 source* with the SAME CMake/arm-gcc toolchain, flash, test with addons. v0.3.19-via-CMake ALSO wedges ⇒ it's the BUILD/toolchain (not doze source). v0.3.19-via-CMake works but 0.4.3 wedges ⇒ it's the 0.4.x source delta (fan-kickstart prime suspect → bisect by reverting it). Headless build+flash code-46 retry quirk applies. Verify MCU liveness read-only via `get_hmd_fw_version` (QBU bs_hmd_tools). Don't power past a wedge — power-cycle first. Related: [[hmd-bench-rig]].

+Also ELIMINATED: v0.3.18→v0.3.19 source delta (baseline was v0.3.18; HMD jumped straight 0.3.18→0.4.3). That delta is ONLY an RGB-LED-animation feature (commit b2c696a: `report[4]` mode byte on the 'L'/0x4c cmd + LED blinking task). LED-task only, can't gate prox/HID. Not the wedge.

+**LEADING HYPOTHESIS = BUILD/TOOLCHAIN (source is inert).** The 0.4.3 flashed is the headless CMake/arm-gcc-12.2 build; known-good v0.3.18 was an official build. Compared `CMakeLists.txt` vs `Beyond_Synaptics.cproj`, CMake-introduced deviations: **`-ffast-math`** (Studio has none — sets FPU FZ/default-NaN globally at startup via crtfastmath, changes ALL float behavior → PRIME suspect), `-mlong-calls`, `--specs=nano.specs`/`-lc_nano` (newlib-nano: smaller reentrancy/heap vs full newlib), and `-D__SAMG55G19__` typo (chip is J19; selects samg55g19.h CMSIS header — compile-benign since no J19-only pin macros referenced, but WRONG, fix to `__SAMG55J19__`). NOTE: `.cproj` is NOT the true production config — it has `BOARD=SAMG55_XPLAINED_PRO` but real Beyond HW init is gated `#if BOARD==USER_EXT_BOARD` (main.c 149/168/326, usart_interface.c 158), and CMake correctly uses `USER_EXT_BOARD`. So `.cproj` board/linker(`flash_usb_bootloader.ld` for AppImage) deltas are likely intentional-correct; trust the prebuilt AppImage hex (official Studio artifacts, in-repo up to `build/v0.3.9/Beyond_AppImage_v039_250328.hex`) as the real baseline, NOT `.cproj`. No prebuilt 0.3.10–0.3.19 committed.

+**NEXT EXPERIMENTS:** (A, fastest functional test) rebuild 0.4.x with `-ffast-math` removed + `__SAMG55G19__`→`__SAMG55J19__`, flash, retest with addons. Wedge gone ⇒ build flags were it. (B, no-hardware analysis) build an in-repo prebuilt's source (e.g. v0.3.9) via CMake toolchain, binary/symbol-diff vs the committed official `Beyond_AppImage_v039` hex to see exactly what the toolchain changes (exact CRC match unlikely across toolchains — use section/symbol diff, not raw CRC). Headless build+flash code-46 retry quirk applies. Verify MCU liveness read-only via `get_hmd_fw_version` (QBU bs_hmd_tools). Don't power past a wedge — power-cycle first. Related: [[beyond-synaptics-firmware-build]], [[hmd-bench-rig]].


## Bottom line

Investigated end-to-end, source-checked, no guessing. Wedge is **not** doze logic and **not** the 0.3.19 LED change — both eliminated. It's the **build/toolchain**.

**Eliminated:**
- Doze opcode collision — addon never sends 0x48/0x68 (full HMDUtility cmd set checked).
- Doze state machine — provably inert when `doze_active` never set.
- 0.3.18→0.3.19 delta — RGB-LED-animation only, LED task can't gate prox/HID.

**Leading cause — CMake build deviates from official build:**
- **`-ffast-math`** (CMake-only) — biggest suspect. Links `crtfastmath`, sets FPU flush-to-zero + default-NaN globally at boot → changes *all* float behavior firmware-wide (gain, eyetracking, temp, doze). Addon exercises float paths. Can flip control-flow branches → hang/wedge.
- `-mlong-calls`, newlib-**nano** (`--specs=nano.specs`) — reentrancy/heap differs from full newlib.
- `__SAMG55G19__` typo — should be `J19`. Compile-benign but wrong.
- `.cproj` is *not* the true production config (its `BOARD=SAMG55_XPLAINED_PRO` skips the real HW init that CMake correctly compiles via `USER_EXT_BOARD`). So trust the official prebuilt hex (in-repo to v0.3.9), not `.cproj`.

Pick next step:


AskUserQuestion

Question: Which experiment next?

Choices:
Rebuild w/o -ffast-math, flash, retest (Recommended)
Fastest path to truth. Strip -ffast-math + -mlong-calls, fix __SAMG55G19__→J19, rebuild 0.4.x, flash (code-46 retry), run addon session. Wedge gone = build flags confirmed. One build+flash cycle.
CMakeLists: drop -ffast-math
  -mlong-calls; J19 fix
→ build .beyondfw → flash
→ SteamVR+addon → wedge?
Binary-diff vs official hex (no hardware)
Build v0.3.9 source via CMake toolchain, section/symbol-diff against committed official Beyond_AppImage_v039 hex. Shows exactly what the toolchain changes. Pure analysis, no flash, no wedge risk.
cmake build @ v0.3.9
vs build/v0.3.9/...v039.hex
arm-none-eabi-objdump diff
(CRC won't match; use symbols)
Run the no-hardware binary-diff to characterize the toolchain delta AND do the flag-fix rebuild+flash retest. Belt and suspenders.
Strip ONLY -ffast-math (leave -mlong-calls, nano-specs, J19 as-is) so a positive result pins the cause to exactly that flag, not a bundle.
single-variable test:
-ffast-math removed, rest same
→ cleanest attribution


Your questions have been answered: "Which experiment next?"=(no option selected) notes: both in parallel. you can ref 0.3.18 at "C:\Users\decid\Documents\projects\HMDUtility\src\latest.beyondfw". You can now continue with these answers in mind.

Question: Which experiment next?

Choices:
Rebuild w/o -ffast-math, flash, retest (Recommended)
Fastest path to truth. Strip -ffast-math + -mlong-calls, fix __SAMG55G19__→J19, rebuild 0.4.x, flash (code-46 retry), run addon session. Wedge gone = build flags confirmed. One build+flash cycle.
CMakeLists: drop -ffast-math
  -mlong-calls; J19 fix
→ build .beyondfw → flash
→ SteamVR+addon → wedge?
Binary-diff vs official hex (no hardware)
Build v0.3.9 source via CMake toolchain, section/symbol-diff against committed official Beyond_AppImage_v039 hex. Shows exactly what the toolchain changes. Pure analysis, no flash, no wedge risk.
cmake build @ v0.3.9
vs build/v0.3.9/...v039.hex
arm-none-eabi-objdump diff
(CRC won't match; use symbols)
Run the no-hardware binary-diff to characterize the toolchain delta AND do the flag-fix rebuild+flash retest. Belt and suspenders.
Strip ONLY -ffast-math (leave -mlong-calls, nano-specs, J19 as-is) so a positive result pins the cause to exactly that flag, not a bundle.
single-variable test:
-ffast-math removed, rest same
→ cleanest attribution


Both tracks it is — and the real 0.3.18 reference at `HMDUtility/src/latest.beyondfw` enables your exact CRC idea. Let me set up: verify toolchain, read the build runbook, and inspect the prebuilt 0.3.18.


Bash

echo "===toolchain present?===" && (ls "/c/Program Files (x86)/Arm GNU Toolchain arm-none-eabi/12.2 mpacbti-rel1/bin/arm-none-eabi-gcc.exe" 2>/dev/null && echo "ARM-GCC: yes" || echo "ARM-GCC: MISSING") && (where ninja 2>/dev/null || ninja --version 2>/dev/null && echo "ninja: yes" || echo "ninja: check") && (cmake --version 2>/dev/null | head -1 || echo "cmake: MISSING") && echo "" && echo "===prebuilt 0.3.18 ref===" && ls -la "C:/Users/decid/Documents/projects/HMDUtility/src/latest.beyondfw" 2>/dev/null && echo "" && echo "===CMakePresets===" && cat C:/Users/decid/Documents/projects/beyond_synaptics/CMakePresets.json

Verify toolchain + inspect prebuilt + presets


Command running in background with ID: bpg8s94wc. Output is being written to: C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-sauna\d3fb9be1-d61d-4f88-b77c-2a2a282b11fd\tasks\bpg8s94wc.output. You will be notified when it completes. To check interim output, use Read on that file path.


<task-notification>
<task-id>bpg8s94wc</task-id>
<tool-use-id>toolu_01P9qUYPsb4mkC2u1od7pzKV</tool-use-id>
<output-file>C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-sauna\d3fb9be1-d61d-4f88-b77c-2a2a282b11fd\tasks\bpg8s94wc.output</output-file>
<status>completed</status>
<summary>Background command "Verify toolchain + inspect prebuilt + presets" completed (exit code 0)</summary>
</task-notification>


1	===toolchain present?===
2	/c/Program Files (x86)/Arm GNU Toolchain arm-none-eabi/12.2 mpacbti-rel1/bin/arm-none-eabi-gcc.exe
3	ARM-GCC: yes
4	C:\Users\decid\AppData\Local\Microsoft\WinGet\Links\ninja.exe
5	ninja: yes
6	cmake version 4.3.1
7
8	===prebuilt 0.3.18 ref===
9	-rw-r--r-- 1 decid 197609 79055 Jun  9 19:34 C:/Users/decid/Documents/projects/HMDUtility/src/latest.beyondfw
10
11	===CMakePresets===
12	{
13	    "version": 8,
14	    "configurePresets": [
15	        {
16	            "name": "arm-gcc-toolchain.cmake",
17	            "displayName": "Configure preset using toolchain file",
18	            "description": "Sets Ninja generator, build and install directory",
19	            "generator": "Ninja",
20	            "binaryDir": "${sourceDir}/out/build/${presetName}",
21	            "cacheVariables": {
22	                "CMAKE_BUILD_TYPE": "Debug",
23	                "CMAKE_TOOLCHAIN_FILE": "arm-gcc-toolchain.cmake",
24	                "CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}"
25	            }
26	        }
27	    ]
28	}

===toolchain present?===
/c/Program Files (x86)/Arm GNU Toolchain arm-none-eabi/12.2 mpacbti-rel1/bin/arm-none-eabi-gcc.exe
ARM-GCC: yes
C:\Users\decid\AppData\Local\Microsoft\WinGet\Links\ninja.exe
ninja: yes
cmake version 4.3.1

===prebuilt 0.3.18 ref===
-rw-r--r-- 1 decid 197609 79055 Jun  9 19:34 C:/Users/decid/Documents/projects/HMDUtility/src/latest.beyondfw

===CMakePresets===
{
    "version": 8,
    "configurePresets": [
        {
            "name": "arm-gcc-toolchain.cmake",
            "displayName": "Configure preset using toolchain file",
            "description": "Sets Ninja generator, build and install directory",
            "generator": "Ninja",
            "binaryDir": "${sourceDir}/out/build/${presetName}",
            "cacheVariables": {
                "CMAKE_BUILD_TYPE": "Debug",
                "CMAKE_TOOLCHAIN_FILE": "arm-gcc-toolchain.cmake",
                "CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}"
            }
        }
    ]
}


Prompt:
<task-notification>
<task-id>bpg8s94wc</task-id>
<tool-use-id>toolu_01P9qUYPsb4mkC2u1od7pzKV</tool-use-id>
<output-file>C:\Users\decid\AppData\Local\Temp\claude\C--Users-decid-Documents-projects-sauna\d3fb9be1-d61d-4f88-b77c-2a2a282b11fd\tasks\bpg8s94wc.output</output-file>
<status>completed</status>
<summary>Background command "Verify toolchain + inspect prebuilt + presets" completed (exit code 0)</summary>
</task-notification>


Toolchain present (arm-gcc 12.2, ninja, cmake 4.3.1). Prebuilt 0.3.18 = 79KB `.beyondfw`. Note: preset says `Debug` but runbook says **Release/-O3 only (Debug fails to link)**. Reading the runbook for exact build+package commands.