All field notes

Embedded AI

AI shouldn’t have to rediscover the MCU

Explicit peripheral relationships and reusable operations can reduce the discovery and integration work embedded AI agents face. Early BKPT results examine that approach across four agent setups.

BKPT Labs /

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.

End-to-end elapsed time, in seconds
BKPT-AI native92.7 s
Claude + BKPT skills97.6 s
Claude + ST Toolkit467.3 s
Raw Claude Code618.3 s

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.

Recorded timing counters
SetupElapsedModel / providerTools
BKPT-AI nativeAPI, 2 fresh runs92.7 s87.9 s4.2 s
Claude + BKPT skillsSubscription, 2 fresh runs97.6 s91.3 s5.5 s
Claude + ST ToolkitAPI, 2 runs on 2026-11-09467.3 s378.0 s86.1 s
Raw Claude CodeAPI, 1 run on 2026-11-09618.3 s602.1 s15.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.

Fable 5.2: end-to-end elapsed time, in seconds
Claude + BKPT skills127.0 s
Claude + ST Toolkit625.0 s
Raw Claude Code> 900 s, stopped at deadline

0 1,000 seconds

Fable 5.2 counters
SetupElapsedResponsesTool callsOutput tokensCumulative input
Claude + BKPT skillsSubscription, 1 fresh run127.0 s7714,561191,613
Claude + ST ToolkitSubscription, 1 fresh run625.0 s434751,9366,097,183
Raw Claude CodeSubscription, 1 fresh run, stopped at the 900 s deadline> 900 s576188,69410,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.

Input tokens per request. Native traces end at 7 and 9 responses, BKPT skills at 7 and 7, ST Toolkit at 48 and 40 and raw Claude at 57.

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.

Generated output tokens

ReasoningCode, tool arguments and text

BKPT-AI native10,019
Claude + BKPT skills10,112
Claude + ST Toolkit37,998
Raw Claude Code59,162

0 70,000 tokens

Model responses, tool calls and generated output
SetupResponsesTool callsOutput tokens
BKPT-AI nativeAPI, 2 fresh runs87.510,019
Claude + BKPT skillsSubscription, 2 fresh runs77.510,112
Claude + ST ToolkitAPI, 2 runs on 2026-11-094443.537,998
Raw Claude CodeAPI, 1 run on 2026-11-09575959,162
Cumulative token counters
SetupCumulative inputOf input: cache readsInput + output
BKPT-AI nativeAPI, 2 fresh runs263,586221,124273,605
Claude + BKPT skillsSubscription, 2 fresh runs177,478140,538187,590
Claude + ST ToolkitAPI, 2 runs on 2026-11-093,032,9562,907,806.53,070,954
Raw Claude CodeAPI, 1 run on 2026-11-094,667,3584,515,2164,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.

What the recorded tool time contains
SetupTool categoryCallsTime
BKPT-AI nativeBuild12.736 s
BKPT-AI nativeSource / project inspection10.006 s
BKPT-AI nativeOther BKPT tools5.51.410 s
Claude + BKPT skillsShell commands44.265 s
Claude + BKPT skillsMCP calls00.000 s
Claude + BKPT skillsOther host tools3.51.202 s
Claude + ST ToolkitShell commands3885.132 s
Claude + ST ToolkitMCP calls10.842 s
Claude + ST ToolkitOther host tools4.50.080 s
Raw Claude CodeShell commands5615.266 s
Raw Claude CodeMCP calls00.000 s
Raw Claude CodeOther host tools30.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:

02ad68c41a45f4a74ac14247a57e3cca8af1837449959bee1af89c6ebbdc8828

The 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?