# Introduction
SWO Trace is a single pin trace interface that is part of the Cortex M Coresight components from ARM Ltd.
It supports profiling hardware events such as periodic sampling of program counter, data variable reads and writes, interrupt entry and exit, counters as well as application generated software messages. It is also fully integrated into Code Composer Studio and supports the following Cortex M device families:
- MSP432
- Tiva C (TM4C129 and TM4C123)
- CC26xx
- CC13xx
The ARM documentation contains additional details about the SWO Technology as part of the CoreSight:
https://developer.arm.com/docs/ddi0314/h/serial-wire-output
For previous versions, please check the [SWO Trace CCSv9](emu_swo_trace_ccsv9.html).
# Requirements per device family or board
## MSP432 Launchpad
**Step 1:** Target Configuration
The MSP432 Launchpad has an onboard XDS110 debug probe which supports SWO Trace. MSP432 supports 2 debug protocols; JTAG and SWD. SWO Trace for MSP432 is output on the TDO pin in SWD mode only. As such SWO Trace is not available in JTAG mode. To use SWO Trace create your target configuration with SWD as the debug protocol with TDO connection to the Aux COM port as indicated in the snapshot below:
![](./images/emu_swo_trace_ccsv9_msp432-config.jpg)
**Step 2:** Basic Setup
Once the target configuration is selected, launch the debug session and load the application.
[[b Note:
SWO Trace requires trace clock setup which is dependent on the system clock of the target. If your application configures the system clock after main, run to the line after the system clock configuration and then we are ready to launch the trace capture.
]]
In the code snippet below, as indicated in line 145 the subsequent lines configure the main clock. Run to the highlighted line (line 152) and then setup the trace capture.
![](./images/emu_swo_trace_ccsv9_msp432-code.jpg)
**Step 3:** Start Trace Capture
Trace can be configured by going to menu Tools → Code Analysis → Event Analysis. CCS exposes the trace capabilities as 4 pre-configured Usecases:
- Statistical Function Profile: Periodic program counter samples.
- Exception Profile: Interrupt entry exit and preemption.
- Variable Profile: Variable reads and writes.
- Message Logging: Software messages.
For additional details please see the [Usecases](#usecases) section below.
## Tiva/TM4C
**Step 1:** Target Configuration
The Tiva/TM4C launchpads have the onboard ICDI debug probe that does not support SWO Trace. Instead use an external XDS200 debug probe. The XDS200 debug probe supports JTAG and SWD mode for Tiva/TM4C devices. SWO Trace is output on the TDO pin in SWD mode only. SWO Trace is not available in JTAG mode. To use SWO Trace create the target configuration as indicated in the snapshot below with SWD as the debug protocol and User COM port routed to TDO pin.
![](./images/emu_swo_trace_ccsv9_tivac-config.jpg)
**Step 2: Basic Setup**
Once the target configuration is selected, launch the debug session and load the application.
[[b Note:
SWO Trace requires trace clock setup which is dependent on the system clock of the target. If your application configures the system clock after main, run to the line after the system clock configuration and then we are ready to launch the trace capture.
]]
In the code snippet below, line 408 configures the system clock. Run to the highlighted line (line 415) and then setup the trace capture.
![](./images/emu_swo_trace_ccsv9_tivac-code.jpg)
**Step 3: Start Trace Capture**
Trace can be configured by going to menu Tools → Code Analysis → Event Analysis. CCS exposes the trace capabilities as 4 pre-configured Usecases:
- Statistical Function Profile: Periodic program counter samples.
- Exception Profile: Interrupt entry exit and preemption.
- Variable Profile: Variable reads and writes.
- Message Logging: Software messages.
For additional details please see the [Usecases](#usecases) section below.
## CC26xx and CC13xx
**Step 1:** Target Configuration
The CC26xx and CC13xx SensorTag development kits can be used with the optional Debugger DevPack (CC_DEVPACK_DEBUG) which is an XDS110 class debug probe that supports SWO Trace. These device families require the application to route the SWO Trace to a GPIO pin. The application will need to route the SWO Trace to TDO pin by including the line below in the application:
```c
// Map Serial Wire Viewer to JTAG TDO pin IOCPortConfigureSet(IOID_16, IOC_PORT_MCU_SWV, IOC_STD_OUTPUT);
```
And including the header file:
```c
#include "ioc.h"
```
This header file can be found in the SimpleLink SDK directory:
<SIMPLELINK SDK ROOT>/source/ti/devices/<DEVICE>/driverlib
This path must be added to the list of include search paths under the "Include Options" compiler properties in the project properties.
[[b Note:
If you are using one of the SimpleLink SDK examples, one option is to add the above IOCPortConfigureSet call to the <BOARD>\_initGeneral (ex. CC1310_LAUNCHXL_initGeneral() ) function in the device board file (ex. CC1310_LAUNCHXL.c). This file is responsible for setting up board specific items and already includes ioc.h, hence no need to have a statement to include the header file. The project properties already have the necessary include paths configured so no need to add any additional include search path to the project properties.
]]
Now, to use SWO Trace create the target configuration as indicated in the snapshot below with debug protocol as 2-pin cJTAG and TDO routed to Aux COM.
![](./images/emu_swo_trace_ccsv9_cc2650-config.jpg)
**Step 2: Basic Setup**
Once the target configuration is selected, launch the debug session and load the application.
[[b Note:
SWO Trace requires trace clock setup which is dependent on the system clock of the target. If your application halts at main and the application configures the system clock after main, run to the line after the system clock configuration and then we are ready to launch the trace capture.
]]
**Step 3:** Start Trace Capture
Trace can be configured by going to menu Tools → Code Analysis → Event Analysis. CCS exposes the trace capabilities as 4 pre-configured Usecases:
- Statistical Function Profile: Periodic program counter samples.
- Exception Profile: Interrupt entry exit and preemption.
- Variable Profile: Variable reads and writes.
- Message Logging: Software messages.
For additional details, please see the [Usecases](#usecases) section below.
# Usecases
CCS exposes trace capabilities in the form of usecases. SWO Trace has 4 pre-configured usecases:
- Statistical Function Profile
- Exception Profile
- Variable Profile
- Message Logging
To select a usecase, go to the menu Tools → Code Analysis → Event Analysis. A new view is opened and **Step 1** contains a list of all usecases and **Step 2** contains advanced settings in case there are multiple boards connected.
![](./images/emu_swo_trace_usecases_list.png)
In case cJTAG is used (most of the CC13xx and CC26xx devices), the view will show a message box with configuration details that must be added to the project, as shown below:
![](./images/emu_swo_trace_cjtag.png)
Each usecase is presented in detail in the following sub sections.
## Statistical Function Profile
Statistical function profile is useful for analyzing code execution. It brings to light the execution intensive functions which could either be smaller functions occurring frequently or larger functions taking more execution time.
The PC sample hardware events are generated by the DWT (Data Watchpoint and Trace Unit) and can be configured to output PC samples periodically at configurable intervals. When the Statistical Function Profile usecase is selected, the **Sampling Interval** option is shown. This option controls how frequently the Program Counter (PC) register is sampled. The lowest interval is 64 processor clocks.
![](./images/emu_swo_trace_stat-func-ui.png)
[[b Note:
Smaller intervals yield higher density trace which could cause overflows and packet loss if the data cannot be drained fast enough. If the trace data shows overflows increase the interval and try again.
]]
Once the **OK** button is clicked, the Trace viewer with its 5 tabs replace the previous setup view. For this particular usecase, only the Statistical Function Profile and the Raw Data are of interest.
The **Raw Data** tab shows the information sent by the target without processing, while the Statistical Function Profile shows analysis of the PC samples in terms of function execution. When the core is put to run the trace data gets processed and shown at specific intervals - an update also happens when the core is halted either due to a breakpoint or manually. The analysis window shows the percentage of time the various functions were encountered. The following snapshot was captured using the onboard XDS110 debug probe on a MSP432P4111 launchpad with the target executing the OutOfBox demo application.
![](./images/emu_swo_trace_stat-func-views.png)
The **Raw Data** tab also outputs messages indicating if the core is in sleep executing a wfi or wfe.
## Exception Profile
Exception Profile can be used to determine how and at what frequency exceptions are happening on the system.
Exception entry, exit and preemption information are all listed in the hardware events are generated by the DWT (Data Watchpoint and Trace) unit. There are no configurable parameters for this usecase as indicated in the snapshot below.
![](./images/emu_swo_trace_exception-ui.png)
Once the **OK** button is clicked, the Trace viewer with its 5 tabs replaces the previous setup view. For this particular usecase, only the **Exception Profile** and the **Raw Data** tabs are of interest.
The **Raw Data** tab shows the information sent by the target without processing, while the **Exception Profile** tab shows the timeline of the exception events. When the core is put to run, the trace data gets processed and the values are shown in both graph of exception ocurrences delimited by the Entry and Exit events and a tabular view with all captured data samples and its values - an update also happens when the core is halted either due to a breakpoint or manually.
![](./images/emu_swo_trace_exception-ui-view.png)
## Variable Profile
Variable Profile can be used to profile variable reads and writes.
Data variable read and write events are generated by the DWT (Data Watchpoint and Trace) Unit. The trace hardware outputs a packet every time the variable is read and/or written with the corresponding value and so this usecase is not statistical. When this usecase is selected in CCS, the tab is expanded and prompt for the address. The hex value of the address can be entered directly or, if symbols are loaded, a variable name can be typed directly.
![](./images/emu_swo_trace_data-var-ui.png)
Once the **OK** button is clicked, the Trace viewer with its 5 tabs replaces the previous setup view. For this particular usecase, only the **Variable Profile** and the **Raw Data** tabs are of interest.
The **Raw Data** tab shows the information sent by the target without processing, while the **Variable Profile** tab shows the read and write events. When the core is put to run, the trace data gets processed and the values are shown in both a graph of reads and writes and a tabular view with all captured data samples and its values - an update also happens when the core is halted either due to a breakpoint or manually.
![](./images/emu_swo_trace_data-var-views.png)
## Message Logging
Messages can be directly transferred by the application to the host, just like a printf() but using the trace channel instead of the Console I/O.
Message Logging is issued through the ITM (Instrumentation Trace Macrocell). The ITM in Cortex M has 32 stimulus ports. Writes to the stimulus ports result in a data packet of size word, half-word or byte depending on the size of the data written. When this usecase is selected in CCS, the tab is expanded and all the stimulus ports are shown with switches for binary or data formatted as characters.
![](./images/emu_swo_trace_message-ui.png)
Once the **OK** button is clicked, the Trace viewer with its 5 tabs replaces the previous setup view. For this particular usecase, only the **Message Logging** and the **Raw Data** tabs are of interest.
The messages can be displayed all together or separately by checking the box **Display each channel on a separate line with timestamp**.
In the example below, the channels 1 and 3 have the character filter enabled, while channels 2 and 4 have the binary data directly displayed (in decimal format).
![](./images/emu_swo_trace_message-ui-view.png)
Sample code with APIs to use ITM can be found below:
```c
//*****************************************************************************
//
// main.c template
//
//****************************************************************************
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
const unsigned ITM_BASE_ADDRESS = 0xE0000000;
const unsigned ITM_NUM_PORTS = 32;
const unsigned NUM_TRIALS = 2;
typedef volatile unsigned* ITM_port_t;
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;
}
void main(void)
{
unsigned trial_num, port_num = 1, port_address;
ITM_port_t port;
for (trial_num=0; trial_num < 10; ++trial_num) {
for (port_num=1; port_num<ITM_NUM_PORTS; ++port_num) {
// Send text to port 0
ITM_put_string((ITM_port_t)ITM_BASE_ADDRESS, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~`!@#$%^&*()-_=+[{]}\\|;:'\",<.>/? ");
ITM_put_string((ITM_port_t)ITM_BASE_ADDRESS, "hello\nworld");
delay(100);
// Get this port address
port_address = ITM_BASE_ADDRESS + (4*port_num);
port = (ITM_port_t)port_address;
// Send numeric data to this ports
ITM_put_32(port, 33);
delay(100);
ITM_put_32(port, 0x12345678);
delay(100);
ITM_put_16(port, 33);
delay(100);
ITM_put_16(port, 0x9abc);
delay(100);
ITM_put_08(port, 33);
delay(100);
ITM_put_08(port, 0xde);
delay(100);
ITM_put_string((ITM_port_t)ITM_BASE_ADDRESS, "end\n");
delay(10000);
}
delay(10000);
}
}
```
# Troubleshooting
1. I am seeing overflow packets in the trace data stream. How do I avoid them?
The first setting to change is the timestamp resolution. The timestamp resolution can be set at 4 different levels; divide by 1 (no prescale), divide by 4, divide by 16 and divide by 64. Divide by 1 gives the finest granularity and divide by 64 the lowest granularity but also fewer trace packets. To change the timestamp granularity, at **Step 1** of the main Event Analysis Setup view, select the drop down **Common Configuration** and choose a higher resolution value.
![](./images/emu_swo_trace_receiver-timestamp.jpg)
If you are using Statistical Function profile, then the density of the stream can be reduced by increasing the "Sampling interval" in the usecase setup UI.