If you ship firmware for a car, an infusion pump, or a factory controller, "we tested it" is not enough — you need to show which code your tests actually exercised. For teams building on IAR Embedded Workbench, the good news is that you can get that structural coverage without changing your toolchain or your source: RKTracer plugs straight into the IDE and measures coverage on the real target while you debug.
This is a hands-on, step-by-step guide. We'll integrate RKTracer with the IDE, enable instrumentation, capture coverage on the embedded target during a C-SPY debug session, generate an HTML report, and finally narrow coverage down to a chosen set of folders, files, or even individual functions. Every command, file name, and menu entry below matches the RKTracer workflow exactly — copy them as you read.
Run rktracer -iar -integrate once, turn RKTracer ON in the Tools menu, rebuild, run your tests on the target, then click RKTracer Reports. That's three clicks and one command to certifiable, on-target coverage.
What is IAR Embedded Workbench?
IAR Embedded Workbench is a complete integrated development environment (IDE) and toolchain for embedded software, developed and maintained by IAR Systems AB, a Swedish company. It bundles everything you need to go from C or C++ source to firmware running on a microcontroller, inside a single workbench.
Its core components are the highly optimizing IAR C/C++ Compiler, the IAR ILINK Linker, an assembler, and the integrated IAR C-SPY Debugger. IAR also ships code-analysis add-ons alongside the core toolchain — C-STAT for static analysis and C-RUN for runtime error checking. The product family supports more than 20 processor architectures, including Arm, RISC-V, 8051, MSP430, AVR, and several Renesas families such as RX, RL78, and RH850.
The C-SPY Debugger is where coverage happens. It performs on-chip (hardware) debugging by connecting to the target MCU through a debug probe and the chip's debug interface — for example JTAG or SWD on Arm Cortex-M devices — giving you source-level control such as breakpoints, stepping, and inspection of memory and variables. C-SPY works with IAR's own I-jet and I-jet Trace probes as well as third-party probes like Segger J-Link, PE Micro, and ST-LINK. Because of this reach and its mature toolchain, IAR Embedded Workbench is used heavily in safety- and reliability-critical industries: automotive, industrial automation, and medical devices.
Why measure code coverage inside the IDE
Code coverage — also called structural coverage — measures how thoroughly your tests exercise the structure of your code. The common metrics are statement coverage (did every line run?), decision or branch coverage (did every branch go both ways?), and MC/DC (did each condition independently affect the outcome?). On an embedded target, those numbers only mean something if they're collected from code built with your production compiler and run on the actual silicon.
That's the whole argument for measuring coverage inside the IDE, on the target, during your normal debug flow. You're already flashing the device and stepping through it with C-SPY; capturing structural coverage in that same session means the evidence reflects reality — the same compiler, the same optimization settings, the same hardware behavior — rather than a convenient host build that may optimize away the very branches you need to prove.
For regulated work this is not optional. Functional-safety standards relevant to IAR users require increasing levels of structural coverage as criticality rises, with MC/DC demanded at the highest levels — ISO 26262 ASIL D and DO-178C DAL A. IAR's built-in C-SPY code coverage is typically statement-level, so teams chasing decision or MC/DC coverage usually reach for a complementary tool. That's exactly the gap RKTracer fills: it measures the full ladder of metrics on the target. (For a deeper look at the metric itself, see our walkthrough of MC/DC for DO-178C, and our overview of RKTracer as a code coverage tool.)
Step 1: Integrate RKTracer with IAR Embedded Workbench
Integration is a one-time setup that teaches the IDE about RKTracer and adds its controls to the Tools menu. First, make sure IAR Embedded Workbench is closed — the integrator edits IDE configuration files, so the IDE must not be running. Then open a new command prompt and run the integrate command:
:: Make sure IAR Embedded Workbench is fully closed first > rktracer -iar -integrate
Run this once per IAR installation. Reopen the IDE afterward to pick up the new menu entries.
Now reopen IAR Embedded Workbench and look in the Tools menu. Integration is successful when you see three new entries:
- RKTracer ON — enables the RKTracer tool so your next build is instrumented for coverage.
- RKTracer OFF — disables the tool and returns you to ordinary, uninstrumented builds.
- RKTracer Reports — converts the captured coverage data into an HTML report.
If those three options are present, RKTracer is wired into your workbench and you're ready to collect coverage.
Step 2: Enable coverage and rebuild
Before you turn coverage on, satisfy two prerequisites. First, integration must have completed successfully (Step 1). Second — and this catches people out — you need to have built and tested the application on the embedded target in debug mode at least once, then restarted the IDE. That first clean debug build establishes the project's working directory and build state that RKTracer relies on.
With that in place, enable instrumentation by navigating to Tools → RKTracer ON. The first time you enable RKTracer, you might see a popup requesting read/write permission for the IAR Embedded Workbench installation folder — grant it, because RKTracer needs to write its instrumentation artifacts there. (On Windows this often means running the IDE with the right privileges so the permission can be granted.)
Once RKTracer is ON, rebuild the application. This rebuild is where the magic happens: RKTracer instruments your code during compilation using the IAR compiler that's already building your firmware. Your source files are never modified — instrumentation is injected at build time — so the binary you flash is functionally your binary, now carrying lightweight coverage probes.
RKTracer auto-detects the IAR compiler and instruments during the build. You don't add macros to your code, swap headers, or maintain a separate "coverage build" — you just flip RKTracer ON and rebuild.
Step 3: Capture coverage on the embedded target
With an instrumented binary on the device, you collect coverage simply by running your tests through a C-SPY debug session. There are two ways the coverage data gets saved.
The automatic way. If the embedded target is connected to the host machine during testing, RKTracer automatically saves the coverage data to the application's working directory when you terminate the debug process after running your test cases on the target. Run your tests, stop debugging, and the data is written out for you — no extra steps.
The runtime way. Sometimes you want coverage saved at a precise moment — for example, right after a particular test routine finishes, rather than at the end of the whole session. You can trigger a save when a specific source line executes. Connect to the target before running tests, set a breakpoint on that line, right-click to edit the breakpoint, and add the following action:
// Edit the breakpoint → add this as the action/macro rkdump()
When the breakpoint line executes, RKTracer writes coverage to RK-MEM.raw in the project working directory.
When the breakpoint line is reached at runtime, rkdump() tells RKTracer to save the coverage data to the RK-MEM.raw file in the project working directory. As with the automatic method, make sure the target is connected to the host while you test on the embedded target — that connection is how the data makes it back to your machine.
If your embedded target is not connected to the host, the coverage data can't stream back over the debug probe. Contact RKTracer support for a customized script that transfers the coverage data from the target to the host machine.
Step 4: Generate the HTML coverage report
Once coverage data has been captured, turning it into a readable report is a single click: navigate to Tools → RKTracer Reports. RKTracer generates a full HTML report you can browse file by file and function by function.
Under the hood, the report pipeline is straightforward. RKTracer takes the captured RK-MEM.raw data file and converts it to rk-coverage.txt. It then maps that data against the JSON files generated during instrumentation (which live in the rktracer folder) to reconstruct which lines, branches, and conditions were exercised. The result is the set of HTML pages. If you'd rather open the report yourself instead of letting the menu launch it, just open index.html from the report output.
The four-step loop
- Integrate once with
rktracer -iar -integrate(IDE closed), then reopen. - Tools → RKTracer ON, grant the folder permission, and rebuild.
- Run tests on the target; coverage saves on terminate, or on demand via
rkdump()toRK-MEM.raw. - Tools → RKTracer Reports turns
RK-MEM.rawinto browsable HTML — openindex.html.
Targeting specific files, folders, and functions
By default RKTracer instruments your whole application, which is what you want for a full coverage picture. But on a large embedded codebase you often care about a subset — the safety-relevant modules, the driver you just rewrote, or three functions under review. You can scope instrumentation precisely by editing rktracer.config in the RKTracer installation folder and adding a few directives at the end of the file. Two common scenarios follow.
Coverage for selected folders
Suppose your project tree contains several module folders and you only want coverage for the power, core, and keys subsystems — while explicitly excluding the firmware-loader and lockdown folders. Add this to rktracer.config:
ignore *.c instrument */power/* */core/* */keys/* never */firmware_loader/* */lockdown/*
Reading it line by line:
ignore *.c— start by ignoring all C source files, so nothing is instrumented unless you opt it back in.instrument */power/* */core/* */keys/*— opt thepower,core, andkeysfolders back in for instrumentation.never */firmware_loader/* */lockdown/*— hard-exclude these folders so they are never instrumented, even if a broader rule would otherwise catch them.
The never directive is the strongest: use it for code you must keep untouched, such as a secure firmware loader or a lockdown path.
Coverage for selected functions
You can go finer still and instrument only specific functions. Say you need coverage for fun_X(), fun_Y(), and fun_Z(), which live in three different source files. Add this to rktracer.config:
ignore *.c instrument *source-file-X.c *source-file-Y.c *source-file-Z.c function-ignore * function-instrument fun_X() fun_Y() fun_Z()
Each directive narrows the scope a little more:
ignore *.c— ignore all C source files to begin with.instrument *source-file-X.c *source-file-Y.c *source-file-Z.c— bring just those three source files back into scope.function-ignore *— within those files, ignore all functions by default.function-instrument fun_X() fun_Y() fun_Z()— and finally, do not ignore these three functions, so they alone are instrumented.
The result is a tightly focused report covering exactly three functions — handy for a code review, a targeted regression, or proving coverage on a single safety-critical routine without the noise of the whole codebase.
From line coverage to MC/DC
It's worth stressing what those reports can contain. RKTracer doesn't stop at line counts — it measures statement, decision, condition, MC/DC, and multiple-condition coverage. That full ladder is precisely what matters to IAR users working in safety-critical domains, where IAR's built-in C-SPY coverage is typically statement-level and a complementary tool is needed to reach decision or MC/DC.
So if you're an automotive or medical team on IAR Embedded Workbench chasing ASIL D or DAL A, the same four-step loop above produces MC/DC evidence on the real target, not just a green statement-coverage bar. And where a gap is genuine rather than justified, RKTracer's AI test generation proposes the unit tests that close it — including the boundary cases needed to satisfy a missing MC/DC pair. To go deeper, read MC/DC Explained for DO-178C and our metric-by-metric primer, Everything You Need to Know About Code Coverage. For the broader on-target testing picture, see our guide to embedded system testing.
Coverage you measure on the host is a promise. Coverage you measure on the target is evidence.
Frequently asked questions
RK-MEM.raw in the project working directory. With a connected target, it saves automatically when you terminate the debug session; with the rkdump() breakpoint action, it saves the moment that line executes.The bottom line
Getting trustworthy code coverage out of IAR Embedded Workbench doesn't require a parallel toolchain or a single edit to your source. Integrate RKTracer once, flip RKTracer ON, rebuild, run your tests on the target through C-SPY, and click RKTracer Reports. The data lands in RK-MEM.raw, flows through rk-coverage.txt and the instrumentation JSON, and comes out as an HTML report you can open at index.html.
When you need to focus, a few lines in rktracer.config scope coverage down to specific folders, files, or functions. And because RKTracer measures the full ladder from statement to MC/DC on the real silicon, the numbers you hand to an auditor are the numbers that actually ran on the device. That's the difference between a coverage report and coverage evidence.