MSP432 Lab5 Advanced Debug

Task1 Advanced Debug Features

The TI Code Composer Studio (CCS) IDE and other IDEs provide many debugging tools to help with software development. 

  • The MSP432 MCUs introduces a number of advanced debugging capabilities.
  • CoreSight components are the ARM debugging tools. The available debugging hardware modules vary depending on the processor selected. Please refer the slides for the detailed discussion of ARM CoreSight Components.
  • Three particular components can be used for debugging purposes: Embedded Trace Macrocell (ETM); Instrumentation Trace Macrocell (ITM); Data Watchpoint and Trace Unit (DWT)
  • The MSP432 features the ITM and DWT (ETM is not present), both of which are configured through the Trace Port Interface Unit (TPIU) and output through the Serial Wire Output (SWO) pin. The CCS Hardware Trace Analyzer tools use a Serial Wire Viewer (SWV) to collect the trace data on the SWO, and thus the feature is referred to as SWO Trace.
  • This lab focuses on how to leverage the SWO Trace debugging tools with the specific ARM Cortex-M4F implementation on MSP432 MCUs.

Different IDEs offer individual implementations of the ITM and DWT functions.

  • TI CCS IDE supports the following advanced debug features: Statistical Function Profiling; Data Variable Tracing; Interrupt Profiling; Custom Core Trace
  • These four use cases together are present in the Hardware Trace Analyzer menu in CCS.
  • To enable these features, TI XDS110 or TI XDS200 debugger hardware is required. The TI XDS110 is already integrated inside the TI LaunchPad including the MSP432 LaunchPad.

Task 1.1 Configure the device

Expand the project (you can use your previous CCS projects) in Project Explorer, and open MSP432P401R.ccxml in the targetConfigs folder as shown in the following figure

Keep the “MSP432P401R” selected, then click the “Target Configuration” in the right part. Click the “TI XDS110 USB Debug Probe”, you will get the following screen

You can select the JTAG and SWD mode in the last part of the Connection Properties. After you changed the debug mode, e.g., JTAG or SWD, you can click “Test Connection” to verify the connection is successful.

  • JTAG and SWD should all work without any modifications in the hardware
  • You should change to the third debug mode “SWD Mode – Aux COM port is target TDO pin” (enable the SWO trace) for the following lab procedures.
  • Press the Save button under the column of buttons, including Import…New…, and so on
  • Build the Project (click the hammer icon)
  • Enter a debug session. Right click the project name, select Debug As → Code Composer Studio Debug Session. Alternatively, click the bug icon.
  • In debug mode, go to Tools → Hardware Trace Analyzer, and choose the use case to use as show in the following figure. Note that only one SWO Trace use case can be open at a time.

Task 1.2 Statistical Function Profiling

Under Tools → Hardware Trace Analyzer, click Statistical Function Profiling.

  • There will be a popup prompt “Statistical Function Profiling Configuration”
  • You can choose how often the ITM samples the PC. The fastest rate that the ITM can sample is one sample per 64 clock cycles, which is a hardware limitation.
  • In this lab, we leave the default setup and select Start.

A new window appears in the bottom right corner of the debug view. The tab on the left traces the SWO trace output. The right tab displays the functions profiled.

  • You can now click Run → Resume to start running the program. Alternatively, press F8.
  • Either press Suspend (Alt + F8) when you want to pause the program and see the results, or set a breakpoint where you want it to stop.
  • You can now check the data in the “Statistical Function Profiling”. You should be able to see the following figure.

Task 1.3 Data Variable Tracing

Data Variable Tracing can help you track the continues value change of one particular variable or a memory address without halt the CPU. Under Tools → Hardware Trace Analyzer, click Data Variable Tracing.

  • If a different use case is open, a popup prompts you to close the current use case. (You can only open one)
  • The pop-up window lets you configure the use case. For the demo, the only thing you must do is choose a location to trace.
  • For example, we want to trace the value of a local variable “i”, we can put the “&i” in the address part of the following pop-up window.
  • For the variable address, you can select an exact memory address in hex, or use a pointer to a variable. Use a global variable, or step past the initialization of the variable so the debugger knows the address of the variable (you can only setup the local variable “i” when the variable is visible, i.e., inside the scope of “i”).
  • In this lab, we do not change other settings. You can click “Start” to open the Data

A new window appears in the bottom right corner of the debug view, the tab on the right is a graph of the value of the specified variable. You are now ready to run the use case.

  • Click Run → Resume to start running the program
  • Either press Suspend (Alt + F8) when you want to pause the program and see the results, or set a breakpoint where you want it to stop.
  • Zoom out as necessary to see the full window as shown in the following figure. You are able too see the variable changes over time.

Task 1.4 Interrupt Profiling

Open one of your previous project that contains the GPIO interrupt, e.g., click the button to toggle the LED. We will use the Interrupt Profiling to check the interrupt.

  • Build the Project (click the hammer icon)
  • Enter a debug session. Right click the project name, select Debug As → Code Composer Studio Debug Session. Alternatively, click the bug icon.
  • Under Tools → Hardware Trace Analyzer, click Interrupt Profiling.
  • Press Start to continue in the popup window.
  • A new window appears in the bottom right corner of the debug view.
  • The tab on the left traces the SWO trace output. The middle tab holds an interrupt graph; the right tab contains a detailed summary about the interrupts.
  • Click Run → Resume to start running the program.
  • Click the switch button multiple times to trigger the interrupt
  • Either press Suspend (Alt + F8) when you want to pause the program and see the results, or set a breakpoint where you want it to stop.
  • You should be able to see the following interrupt summary view

You can switch to the following graph view (the middle tap) and zoom out as necessary to see all the interrupts.

  • You can see the PORT1 interrupts (your button click) vs the time, i.e., the green dot.
  • Other interrupts are used for the RTOS, e.g., TA0 as the clock source of the RTOS.

Task 1.5 Custom Core Trace

Custom Core Trace is unique in that ITM does not use hardware packets to trace. Rather, for the most basic version, users must send software messages to the ITM port manually. You can use the ITM trace to replace the debug message output via the UART pin (Save the UART for other sensors).

  • In this lab, we use the same sample project imported in Task 1.4.
  • Software messages are application initiated messages. Software Messages are issued through the ITM (Instrumentation Trace Macrocell). The ITM in Cortex M has 32 stimulus ports.
  • CCS reserves port 0 as a character port which means any data written to port 0 is interpreted by CCS as characters and not binary values. Use port 0 for printing strings and use ports 1 to 31 for printing binary values.

Before we utilize the ITM trace, we need to create one header file (.h) for all the ITM functions.

  • Right click the project, select New->Header File. Create one header file named “ITM.h” based on the following code
const unsigned ITM_BASE_ADDRESS = 0xE0000000;
const unsigned ITM_NUM_PORTS = 32;
const unsigned NUM_TRIALS = 2;

typedef volatile unsigned* ITM_port_t;


ITM_port_t getportnum(unsigned portnum)
{
    unsigned port_num, port_address;
    ITM_port_t port;
    // Get this port address
    port_address = ITM_BASE_ADDRESS + (4*portnum);
    port = (ITM_port_t)port_address;
    return port;
}

void delay(unsigned num_loops)
{
  unsigned i;
  for (i=0; i<num_loops; i++)
  {
      asm ("NOP");
  }
}

void port_wait(ITM_port_t port)
{
    delay(10);
    /* Wait while fifo ready */
    while (*port == 0);
}


/* Send a nul terminated string to the port */
void ITM_put_string(ITM_port_t port, const char* data)
{
    unsigned datapos  = 0;
    unsigned portpos  = 0;
    unsigned portdata = 0;

    while('\0' != data[datapos])
    {
        port_wait(port);
        portdata = 0;

        /* Get the next 4 bytes of data */
        for (portpos=0; portpos<4; ++portpos) {
            portdata |= data[datapos] << (8*portpos);
            if ('\0' != data[datapos]) {
                ++datapos;
            }
        }

        /* Write the next 4 bytes of data */
        *port = portdata;
    }
}

/* Send a 32 bit value to the port */
void ITM_put_32(ITM_port_t port, unsigned data)
{
    port_wait(port);
    *port = data;
}


/* Send a 16 bit value to the port */
void ITM_put_16(ITM_port_t port, unsigned short data)
{
    /* Cast port for 16-bit data */
    volatile unsigned short* myport = (volatile unsigned short*)port;
    port_wait(port);
    *myport = data;
}


/* Send a 8 bit value to the port */
void ITM_put_08(ITM_port_t port, unsigned char data)
{
    /* Cast port for 8-bit data */
    volatile unsigned char* myport = (volatile unsigned char*)port;
    port_wait(port);
    *myport = data;
}

In the project file (.c), include the ITM.h file

#include "ITM.h"

If you want to output one debug message (similar to the UART terminal debug message), we can add the following code at any place you like

ITM_put_string((ITM_port_t)ITM_BASE_ADDRESS, "Helloworld-start\n");

We use the ITM_BASE_ADDRESS to select the port 0, and output strings. CCS reserves port 0 as a character port which means any data written to port 0 is interpreted by CCS as characters.

Other ports 1 to 31 can be used to print binary values, for example, you can add the following code in the application

    ITM_put_32(getportnum(1), 33);
    delay(100);
    ITM_put_32(getportnum(1), 0x12345678);
    delay(100);

    ITM_put_16(getportnum(2), 33);
    delay(100);
    ITM_put_16(getportnum(2), 0x9abc);
    delay(100);

    ITM_put_string((ITM_port_t)ITM_BASE_ADDRESS, "end\n");
    delay(10000);

ITM_put_32 is our defined functions to send a 32 bit value to the port; ITM_put_16 is our defined functions to send a 16 bit value to the port;

Note: you can select the code section, right click to select the Source->Correct Indentation to correct the indent of any code (as shown in the following figure).


To use software messages, select Custom Core Trace from the Hardware Trace Analyzer menu as shown in the following figure

One configuration window will popup as shown in the following figure. Keep everything in default, and click start.

After you continue run the code, you will see the message output in the trace viewer as shown in the following figure. You can get all the Character and Binary output without using UART.

In the previous hardware trace configuration popup window (after you select Custom Core Trace from the Hardware Trace Analyzer menu). The configuration of Custom Core Trace allows the user to fully maximize the functions of the SWO Trace hardware capabilities.

For example, you can click the Advanced Settings, and select the “ITM SW Messages” to change the character or binary output of each channel as shown in the following figure.

You also can click the button in the upper-left corner to create a new trigger. You can configure various trigger types as shown in the following figure. Please check TI’s document (http://www.ti.com/lit/an/slaa674a/slaa674a.pdf) for more advanced features.

Leave a Reply

Your email address will not be published. Required fields are marked *