Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Coco: Measuring Code Coverage on Embedded Systems

DZone's Guide to

Coco: Measuring Code Coverage on Embedded Systems

Squish Coco is a fun tool that you can configure to measure code coverage on embedded systems. Let's run through a sample setup using the CAN bus.

· IoT Zone ·
Free Resource

Squish Coco generates the code execution measurement using streams and by default, the output of these streams is piped to a file on the file system. For embedded devices without a file system, this leads to problems. Squish Coco allows you to redirect the measurements stream via Custom IO Functions. In this article, we create a showcase with the common CAN bus.

The Basic Setup

The Basic Setup of a CAN bus is a transceiver that handles the voltage on the wires and a controller that saves incoming and outgoing frames into registers.

For this showcase, we will connect a microcontroller to a Linux system. This is achieved by connecting the Linux system via USB adapter to the CAN bus. The USB adapter integrates the controller and the transceiver. On the other side, we use an STM32 microcontroller which has the CAN bus controller already integrated. Finally, we need a transceiver, which is achieved by connecting the microcontroller to a Breakout board which contains the transceiver.

General Flowcharts for the PC Receiver and the Microcontroller

PC Receiver

The main task of the PC receiver is to invoke the __coveragescanner_save() function on the microcontroller, receive the data, and write it to files on the PC.

Microcontroller

The normal process is running on the microcontroller until the save message is received and the measurement data is sent.

Implementation of Custom IO Functions

When the microcontroller receives the RECEIVESAVECOMMANDMESSAGEID over CAN bus, the save is initialized.

status = HAL_CAN_Receive(&hcan, CAN_FIFO0, 100);
if (status != HAL_TIMEOUT)
{
    if(hcan.pRxMsg->ExtId != 0 )
    {
        if((hcan.pRxMsg->ExtId & 0xFFFF) == RECEIVESAVECOMMANDMESSAGEID ) 
        {
            #ifdef __COVERAGESCANNER__
            __coveragescanner_save();
            #endif
        }
    }
}


The Custom IO Functions on the STM32 microcontroller code look like this.

#ifdefined( __COVERAGESCANNER__ )
static int csfputs(const char *s, void *stream) 
{
    while(*s)
    {
        int counter = 0;
        CanTxMsgTypeDef sendMessage;
        sendMessage.ExtId = RETURNSAVEMESSAGEID;
        sendMessage.IDE = CAN_ID_EXT;
        sendMessage.RTR = CAN_RTR_DATA;
        while(*s  && (counter < 8))
        {
            sendMessage.Data[counter] = (uint8_t) *s;
            counter++;
            s++;
        }
        sendMessage.DLC = counter;
        hcan.pTxMsg = &sendMessage;
        HAL_CAN_Transmit(&hcan,TIMEOUTTIME);
    }
    return 0;
}
static void *csfopenappend(const char *path)          { return (void*)1; }
static int csfclose(void *fp) 
{
    CanTxMsgTypeDef sendMessage;
    sendMessage.ExtId = RETURNSAVEMESSAGEID;
    sendMessage.IDE = CAN_ID_EXT;
    sendMessage.RTR = CAN_RTR_DATA; 
    sendMessage.Data[0] = 0;
    sendMessage.DLC = 0;
    hcan.pTxMsg = &sendMessage;
    HAL_CAN_Transmit(&hcan,TIMEOUTTIME);
    return 1; 
}
#endif
Topics:
code coverage ,embedded development ,dynamic code analysis ,iot ,squish coco ,can bus ,tutorial

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}