Skip to main content
Use this workflow to improve a firmware budget with evidence from the intended build and target. Choose one metric, record a reproducible baseline, make a bounded change, and repeat the same measurement before drawing a conclusion.
Embedder provides build, telemetry, debugger, trace, coverage, and power-measurement workflows. It does not maintain an automatic performance-baseline database or calculate a before-and-after report for every change. Record the protocol and results in the project so another run can reproduce the comparison.

Choose one primary metric

State the workload, unit, acceptance threshold, and measurement method before changing code. Do not optimize “performance” as one combined number. A smaller image can run more slowly; lower average current can hide a longer active period; extra telemetry can change timing and power.

Write a repeatable measurement protocol

1

Define the workload

Specify inputs, duration or operation count, firmware state, peripheral activity, and environmental conditions.
2

Fix the build configuration

Record the source revision, compiler and version, optimization flags, linker script, feature flags, and target artifact. Compare like with like.
3

Choose the observation path

Prefer a measurement that minimally perturbs the behavior. Use a pin or instrument for timing-sensitive code, and use instrumented logs only when their overhead is acceptable.
4

Record setup and provenance

Save the board revision, probe or instrument, wiring, supply voltage, warm-up period, requested and achieved sample rate, trigger, and matching ELF.
5

Run the baseline more than once

Use enough repetitions to expose variation. Report the distribution or at least minimum, maximum, and average when one sample is not representative.
Keep the protocol in EMBEDDER.md, a benchmark file, or a hardware case under .embedder/hardware/cases/. A prose statement such as “power was lower” is not a reproducible baseline.

Measure flash and RAM

Embedder uses the project’s shell commands and toolchain output for image size; there is no separate firmware-size tool. Ask it to build the exact configuration, preserve the linker map, and report sections rather than only the artifact’s file size:
For a candidate change:
Check the map when a total changes unexpectedly. Generated tables, unwind data, alignment, link-time optimization, and dead-code removal can move bytes without an obvious source-line change.

Measure latency and throughput

Choose the observation method by the timescale and required confidence. Emit numeric Teleplot lines over serial or RTT when the firmware can tolerate logging:
In the VS Code extension, ask Embedder to start a plot, confirm the discovered channels, and save the recording:
Device timestamps preserve spacing when transport output is batched. Logging from a tight interrupt or high-rate loop can perturb the workload, so compare against an uninstrumented physical measurement when the overhead matters.

Use a logic analyzer or oscilloscope for real timing

Toggle a GPIO at the boundaries of the operation, then capture it with the bus or electrical signal:
Use an oscilloscope when analog thresholds, rise time, rail behavior, or pulse shape affect the result. Use a logic analyzer when decoded protocol traffic and digital edge timing answer the question.

Use GDB for state, not transparent timing

GDB can inspect variables, registers, memory, stacks, and task views. Halting, stepping, and breakpoints perturb real-time behavior. Use it to explain a measured bottleneck or confirm configuration, not as the only proof of latency.

Measure execution and coverage

Choose the trace type by the question:
  • RTT or ITM events show firmware-generated application or RTOS events over time.
  • instruction_trace records the most recent bounded ETM instruction window.
  • coverage_run reports function, source-line, and instruction coverage for a bounded run.
  • Streamed ETM starts from a known point and retains a longer rolling instruction history.
ETM capture requires a SEGGER J-Trace, fine-pitch CoreSight-20 cable, target ETM routing, SEGGER host software, a valid device name, and the matching ELF.
Coverage can show that a workload reached a function; it does not prove that the function is a bottleneck. ETM instruction order has no real timestamps. A CPU frequency can produce an estimate, not a measured duration.

Measure current and energy

Use a Nordic PPK2 or Jetperch Joulescope in Debug mode. Run hardware_status first, identify the exact instrument, and confirm wiring before a measurement.

PPK2

  • Use source-meter mode when the PPK2 supplies the device.
  • Use ampere-meter mode when an external supply powers the device.
  • On a Nordic DK, remove the current-measurement jumper for inline measurement and restore it before using the on-board debugger interfaces.

Joulescope

A Joulescope is an inline analyzer and does not supply the target. Use an external supply. The JS220 can decode UART while measuring current and voltage, which provides one instrument timebase for state markers and power:
One-shot Joulescope measurements buffer up to 60 seconds in memory. Use streaming statistics or a JLS recording for a longer run.

Make one bounded change

Use Plan mode when an optimization changes architecture, scheduling, memory layout, clocking, or power-state policy. Require the plan to identify the expected mechanism, tradeoffs, and verification protocol. Use Act mode for a focused implementation:
Avoid combining unrelated optimizations in one measurement. If the metric moves, a bounded diff makes the cause reviewable; if it regresses, the rollback is clear.

Re-measure under the same conditions

1

Rebuild from the candidate revision

Use the same toolchain, configuration, linker script, and feature flags.
2

Restore the target state

Use the same board, power source, peripheral state, warm-up, and starting condition. Record any reset or reflash.
3

Run the unchanged protocol

Keep the workload, duration, trigger, sample rate, telemetry, and analysis method identical.
4

Report the comparison

Include baseline, candidate, absolute delta, percentage delta where meaningful, run-to-run variation, and measurement uncertainty.
5

Check secondary budgets

Confirm that a speed improvement did not violate flash, RAM, power, correctness, timing, or maintainability constraints.
Use a result record like:

Interpret results conservatively

  • A bounded ETM instruction capture is usually the tail of a longer run.
  • Streamed ETM repeatedly halts the target and can break timing-sensitive behavior.
  • J-Trace coverage and instruction capture reset and run the target; they are not attach-only observations.
  • GDB state and post-reset trace are not one uninterrupted execution.
  • Software-polled Joulescope GPI windows operate at about 50 ms and cannot prove microsecond timing.
  • Separate instruments do not share a clock unless you provide a marker or use an instrument-native combined capture.
  • A requested analyzer sample rate can be adjusted to a supported rate; use the achieved value in calculations.
  • A different ELF, optimization level, board revision, supply, or workload invalidates a direct comparison.
  • Static analyzer performance findings identify code patterns, not measured target speed.

Live plots

Record serial telemetry, derive channels, and export measurements.

Power analyzer

Configure PPK2 and Joulescope measurements safely.

Coverage and trace

Choose RTT, ITM, ETM instruction, or source-coverage evidence.

Combined workflows

Correlate measurements with logs, GPIO markers, and target state.
Last modified on August 24, 2026