Measure code coverage on ARM Cortex-M microcontrollers


The ARM Cortex-M family is becoming a more popular architecture for microcontrollers. This article will show you how to measure code coverage on one microcontroller from this family - the ATSAMD21G18. We will use Squish Coco, a development board from SparkFun SAMD21 Dev Breakout and the Atmel-ICE programmer:

Selecting Build Environment

After the installation of Atmel Studio and Squish Coco, start the Coco tool called Build Environment Selection (toolselector.exe). You can find this tool in the Start menu of your operating system. On Windows 7 it should look like this:

In the dialog which appears after starting this tool, first select the GNU Embedded Tools (without I/O functions) as the Tool Suite, then select GNU Embedded directory. Finally, click the button Install GNU Support.

Be careful to select the folder C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\arm\arm-gnu-toolchain and not its parent or children. The button Install GNU Support will otherwise not be available.

Once the GNU Support is added, go to the Coco installation folder and navigate to the newly created arm-gnu-toolchain\wrapper folder (in this case that is C:\Program Files\squishcoco\arm-gnu-toolchain\wrapper). You will find the file arm-none-eabi-gcc.cspro, and inside of it there should be the two settings, CONSTRUCTOR_ATTRIBUTE and DESTRUCTOR_ATTRIBUTE. In case the value of these setting is __attribute__((constructor)), please remove this value for both settings.

Adding Coco Flavour

Now open Atmel Studio, and under the menu Tools, select the item Options. This will open the Options dialog, in which you will have to select Package Configuration under Toolchain options. Here, add the Coco "Flavour" by clicking the button Add Flavour and by entering Coco in the Package Name field, and C:\Program Files\squishcoco\arm-gnu-toolchain\wrapper in the field Package Base Path.

This Coco "flavour" will be used later on in your projects when compiling them with the Squish Coco support, i.e. code instrumentation.

Checking Device Connection

Optionally, before creating a new project, you can check whether the development board is available in the Atmel Studio. For this, first select Device Programming under the menu Tools. Then in the dialog which appears, select Atmel-ICE in the combo box Tool, enter or select ATSAMD21G18 in Device field, and click the Apply button. Finally, in the Device Information tab, click on the Read button, which you will find there initially. You should now see the information about your microcontroller.

Sample Project

Before starting to use the Coco Flavour in your projects, you can optionally check your setup in a sample project. To do this, create a new GCC C Executable Project, and open its properties. Select the device ATSAMD21G18 under the Device properties, and under the Advanced properties select the Coco Flavour.

In the Toolchain properties, for both C compiler and C linker, under the Miscellaneous settings in the Other flags field, add the following additional flags:

--cs-memory-pool=4096 --cs-libgen=-mthumb --cs-on --cs-hit --cs-counter-size=1 --cs-exclude-file-wildcard=*_samd21.c --cs-exclude-file-wildcard=c:*.* --cs-minimal-api --cs-libgen=-g --cs-libgen=-O0

The important part here is to add --cs-libgen=-mthumb because, by default, the project is using the thumb instruction set.

Following this, you can add one or two simple functions to try to compile and debug the project on the microcontroller.

Retrieving Coverage Data

For getting the coverage data back from the device, you can use the same approach which is described in the blog post Retrieve code coverage data via a remote debugger connection. You will have to add (implement) Coco Custom IO functions and to use the GDB debugger. You can find the console window for this tool in the Atmel Studio under the menu View >Other Windows >GDB Console:

We will write more about this in a future blog article*. For now, if you would like to try this example yourself, here the source code:

[*] Published on March 5, 2019: Retrieving Code Coverage from ARM Cortex-M Microcontrollers