An MCU is a network of connected resources
This study examines whether a different way of presenting MCU knowledge can make an embedded coding agent more efficient.
“Configure SPI with DMA” involves clocks, pins, DMA requests, channels, interrupts, driver dependencies and conflicts with other peripherals. With isolated documentation passages, a model can spend retrieval call after retrieval call reconstructing those relationships.
The BKPT approach combines source-backed MCU knowledge, a capability graph, and reusable tools that act on those relationships. The aim is to reduce repeated discovery and integration work.
MCP can expose a graph. JSON can represent it. Markdown can describe the workflow. The design question is how much useful knowledge and which operations those interfaces provide.
BKPT through two paths, compared with ST Toolkit and raw Claude
Both BKPT setups use the same underlying tools and knowledge. The difference is who controls the agent loop: BKPT’s native harness or Claude Code with an agent definition and skill.
- BKPT-AI native
- A Rust harness controls the model loop and tool execution, using BKPT’s knowledge, capability graph and project operations. This is the API path.
- Claude Code + BKPT agent / skill
- Claude Code owns the loop. An agent definition and skill teach it to use the same BKPT tools and knowledge. Both fresh runs used a subscription login, with no API key selected.
- Claude Code + ST Toolkit
- Claude Code with ST’s STM32Cube for Agentic AI toolkit, including official contexts, skills, MCP services and CLI tools.
- Raw Claude Code
- The coding agent without either embedded toolkit.
Same recorded model, same task prompt, fresh sessions. The model was Opus 5.5 at medium effort. The STM32C5 task combined concurrent I2C and SPI DMA transfers, UART commands and replies, timer interrupts and timeout handling. Tools and host instructions differed. There was no hardware access.
Both BKPT rows are means of two fresh attempts recorded on November 10 with the latest shared tools. The ST Toolkit row is the mean of two API runs and the raw Claude row is one API run, all recorded on November 9; neither was rerun. All four fresh BKPT builds passed and all four bounded source audits met the ten requirements they checked. No hardware validation.
Task prompt and recorded setup
The task was a command-driven dual-bus snapshot collector on NUCLEO-C542RC, using the STM32C542RCT6 in LQFP64. It combined concurrent transfers, a fixed reply format, buffer ownership, deadlines and bounded recovery while an independent timer tick continued.
- Target and software resources
- NUCLEO-C542RC with installed STM32C5 HAL2, Device Family Pack (DFP) and NUCLEO-C542RC board packs at version 2.1.0. The shared prompt required using these installed source and tool versions.
- Recorded toolchain
- GNU Arm Embedded 13.3.1+st.8, CMake 4.0.1+st.3 and Ninja 1.12.1+st.9.
- Required deliverable
- Firmware source, a build result and any unverified assumptions. The task explicitly prohibited flashing hardware. External devices, wiring and runtime behavior required separate verification.
Each setup received the same application requirements below. The excerpt is verbatim. The original prompt also contained installed-resource paths and source-access instructions, which are omitted here. The full original prompt hash is recorded under Methodology and limits.
Read the exact firmware task
Create and build firmware for NUCLEO-C542RC that acts as a command-driven dual-bus snapshot collector. Receive fixed 4-byte commands through USART2 DMA at 115200 8N1. The host waits for a reply before sending its next command.
For each complete command, read 8 bytes from 7-bit I2C address 0x52 using I2C1 controller DMA at 1 MHz, and exchange 16 bytes full duplex through SPI1 DMA at 9 MHz, 8-bit mode 0, with active-low GPIO PA4 chip select. The SPI transmit byte at index i is the low byte of (command[i modulo 4] + i), for i=0..15. Allow the two bus transactions to progress concurrently: do not wait for either bus transaction to finish before starting the other. They do not need to start in the same CPU cycle.
After both bus transactions finish, send one 32-byte USART2 DMA reply containing a uint32 sequence number in little-endian order, the original 4 command bytes, the 8 I2C bytes, and the 16 SPI received bytes, in that order. The sequence starts at zero and increments once for each complete command accepted for processing. Do not send a successful reply until both bus results are available, and do not begin a later snapshot until the preceding reply finishes.
Keep an independent 1000 Hz hardware timer interrupt tick running. Use fixed storage, bounded interrupt handlers, and a responsive main loop while transfers are active. An idle UART command receiver may remain armed indefinitely; once started, each I2C, SPI and UART reply transfer has a 25 ms deadline. Count completed replies and failed requests. On a transfer error or timeout, do not continue with stale data or reuse any channel or buffer that an earlier operation might still own. If all affected transfers cannot be confirmed quiescent within a bounded recovery, enter a bounded fail-stop while the timer keeps running. Automatic retry and error replies are not required. External I2C and SPI device protocols, pull-ups and wiring are to be verified separately. Do not flash hardware. Finish with the build result and any unverified assumptions.
The excerpt describes the requested behavior. It does not include BKPT’s internal knowledge representation, graph schemas, agent instructions or tool implementation.
Both BKPT paths recorded shorter workflows
BKPT-AI native recorded the shortest elapsed mean at 92.7 seconds. The Claude Code agent/skill path averaged 97.6 seconds. The ST Toolkit runs averaged 467.3 seconds and the raw Claude run took 618.3 seconds.
0 700 seconds
The native mean used 80.2% less elapsed time than the ST mean and 85.0% less than raw Claude. The agent/skill mean used 79.1% and 84.2% less respectively. These are ratios of these observations, not estimates of general speedup.
| Setup | Elapsed | Model / provider | Tools |
|---|---|---|---|
| BKPT-AI nativeAPI, 2 fresh runs | 92.7 s | 87.9 s | 4.2 s |
| Claude + BKPT skillsSubscription, 2 fresh runs | 97.6 s | 91.3 s | 5.5 s |
| Claude + ST ToolkitAPI, 2 runs on 2026-11-09 | 467.3 s | 378.0 s | 86.1 s |
| Raw Claude CodeAPI, 1 run on 2026-11-09 | 618.3 s | 602.1 s | 15.3 s |
The individual native attempts took 88.343 and 97.047 seconds; the agent/skill attempts took 106.125 and 89.015 seconds; the ST attempts took 498.370 and 436.143 seconds. Elapsed time measures process launch to agent stop. Internal counters are explained under Methodology and limits.
The same task on Fable 5.2
As a check on a newer model, three setups were run once each on Fable 5.2 at medium effort through a subscription login. The BKPT agent/skill path finished in 127.0 seconds with 7 model responses and a passing build and source audit. The ST Toolkit run finished in 625.0 seconds with 43 model responses. Raw Claude Code was stopped at the 900 second deadline after 57 model responses and 10.7 million cumulative input tokens, before it reported a result. Its trace shows where the time went: the first source file was written 532 seconds in. Before that, 44 shell calls read pack layouts, HAL headers and driver sources, board and pinout descriptors, DMA request definitions and clock macros, returning about 367,000 characters, to work out the same pin, clock, DMA and interrupt relationships the BKPT path receives from one allocation step. It then wrote its own board bring-up and application, 965 lines in five files, and was in its first full build when the deadline arrived. These are single runs and are not part of the Opus 5.5 comparison above.
0 1,000 seconds
| Setup | Elapsed | Responses | Tool calls | Output tokens | Cumulative input |
|---|---|---|---|---|---|
| Claude + BKPT skillsSubscription, 1 fresh run | 127.0 s | 7 | 7 | 14,561 | 191,613 |
| Claude + ST ToolkitSubscription, 1 fresh run | 625.0 s | 43 | 47 | 51,936 | 6,097,183 |
| Raw Claude CodeSubscription, 1 fresh run, stopped at the 900 s deadline | > 900 s | 57 | 61 | 88,694 | 10,671,848 |
Context growth and generated tokens
Both BKPT paths used fewer model responses and generated fewer output tokens than the ST Toolkit and raw Claude observations. The two BKPT paths were close to each other; the agent/skill path had the lower cumulative input.
Every recorded run appears; a second run of the same setup is dashed. Largest single inputs: native 54,828, BKPT skills 44,499, ST 130,306 and raw 158,048 tokens.
ReasoningCode, tool arguments and text
0 70,000 tokens
| Setup | Responses | Tool calls | Output tokens |
|---|---|---|---|
| BKPT-AI nativeAPI, 2 fresh runs | 8 | 7.5 | 10,019 |
| Claude + BKPT skillsSubscription, 2 fresh runs | 7 | 7.5 | 10,112 |
| Claude + ST ToolkitAPI, 2 runs on 2026-11-09 | 44 | 43.5 | 37,998 |
| Raw Claude CodeAPI, 1 run on 2026-11-09 | 57 | 59 | 59,162 |
| Setup | Cumulative input | Of input: cache reads | Input + output |
|---|---|---|---|
| BKPT-AI nativeAPI, 2 fresh runs | 263,586 | 221,124 | 273,605 |
| Claude + BKPT skillsSubscription, 2 fresh runs | 177,478 | 140,538 | 187,590 |
| Claude + ST ToolkitAPI, 2 runs on 2026-11-09 | 3,032,956 | 2,907,806.5 | 3,070,954 |
| Raw Claude CodeAPI, 1 run on 2026-11-09 | 4,667,358 | 4,515,216 | 4,726,520 |
The BKPT and ST rows retain exact two-run means. Reasoning is already included in output; cache reads are already included in input. Cumulative input counts reused history across requests, not one giant prompt. These totals are not a cost comparison.
What happened inside the tools
Both refreshed BKPT paths used managed UART, SPI and I2C operations. The source audits confirmed that all four BKPT applications actually used those operations and left the generated drivers unchanged. This is integration evidence, with runtime behavior still unverified on hardware.
| Setup | Tool category | Calls | Time |
|---|---|---|---|
| BKPT-AI native | Build | 1 | 2.736 s |
| BKPT-AI native | Source / project inspection | 1 | 0.006 s |
| BKPT-AI native | Other BKPT tools | 5.5 | 1.410 s |
| Claude + BKPT skills | Shell commands | 4 | 4.265 s |
| Claude + BKPT skills | MCP calls | 0 | 0.000 s |
| Claude + BKPT skills | Other host tools | 3.5 | 1.202 s |
| Claude + ST Toolkit | Shell commands | 38 | 85.132 s |
| Claude + ST Toolkit | MCP calls | 1 | 0.842 s |
| Claude + ST Toolkit | Other host tools | 4.5 | 0.080 s |
| Raw Claude Code | Shell commands | 56 | 15.266 s |
| Raw Claude Code | MCP calls | 0 | 0.000 s |
| Raw Claude Code | Other host tools | 3 | 0.068 s |
Native “Source / project inspection” groups file reads and project inspection. The other rows group shell commands, MCP calls and remaining host tools. The ST runs spent most of their tool time in shell commands; each made one MCP call, averaging 0.842 seconds. Tool calls are host invocations, and one shell call can bundle several operations.
Methodology, application gaps and limits
Four fresh BKPT attempts built successfully. All four met the ten requirements checked by independent bounded source audits. The idle UART receiver now uses an arm operation with no deadline, so the idle-timeout gap reported for the earlier runs no longer appears. The audits noted smaller differences that the task does not rule on, such as whether a refused UART start at boot is retried. The November 9 ST and raw runs were rated partial by their audits: their deadline checks expire one tick late.
Build success and source inspection do not establish full application conformance or hardware qualification. Clock realization, transfer timing, electrical conditions, external device protocols and behavior on hardware remain unverified. No hardware was flashed or tested.
- One original dual-bus snapshot task, with two new attempts per BKPT path on November 10. Two ST Toolkit runs and one raw Claude run from November 9 were not repeated.
- Same recorded Opus 5.5 model at medium effort and same canonical task text. Dates, scheduling, host instructions, tools and authentication routes differ, preventing a causal ranking.
- Native BKPT used the API. Both Claude Code agent/skill attempts used a verified subscription login with no API key selected. Since the earlier BKPT runs, the project handoff returned by the tools, the Claude skill and the native workflow text were revised so the agent receives complete application context in one response; the task prompt was not changed.
- No task-prompt tuning and no cost comparison.
How the counters were measured
Elapsed time runs from process launch to agent stop. Model/provider time includes generation and provider or network waiting; it is not pure reasoning time. Native tool time uses agent-measured execution duration. Claude Code tool time uses observed call-to-result spans, including host overhead. Overlapping spans and differing host counters mean these times are not additive partitions of elapsed time.
Each request includes the conversation accumulated so far. Cumulative input sums those requests, including reused history and cache reads. Generated output already includes reasoning. Fractional response, call and token counts are means of two runs, not fractional individual operations. Displayed timing values are rounded independently.
The results do not isolate the capability graph’s contribution. BKPT also supplies reusable integration components and project operations; both paths share that foundation.
Recorded source and version details
Source: timestamped tool traces, provider usage counters and independent source/integration audits. Full traces, frozen inputs, firmware and audit records are retained. Native agent 5589190; both BKPT paths used shared tools and the agent/skill definitions at 02c8bc2.
Canonical full-task SHA-256, using LF line endings and including the omitted resource/access instructions. Newly logged prompt files use CRLF; normalized text matches the original. This is not the hash of the public excerpt alone:
02ad68c41a45f4a74ac14247a57e3cca8af1837449959bee1af89c6ebbdc8828The benefit appeared in both BKPT paths
Across elapsed time, model responses and generated output, both BKPT paths recorded lower values than the ST Toolkit and raw Claude runs. Native had the shortest elapsed mean by a small margin. The Claude Code path used the same BKPT tools and knowledge while an agent definition and skill provided the integration.
The common foundation is BKPT’s tools and knowledge. The observations support exploring that foundation across both a custom harness and an agent/skill integration. They do not establish equal application quality or prove which component caused the difference. More repeated tasks and hardware validation are needed.
Should vendors publish queryable peripheral relationships and constraints alongside their reference manuals? How would you represent and validate that knowledge?