Overview
--------
**Serial Wire Output (SWO) Trace** is a single pin trace interface that allow users to trace the program flow and profile hardware events. These profiling capabilities are very important for debugging, validating and characterizing applications. In this workshop, you will experience using SWO Trace, via the **Trace Visualization Toolkit**, using basic examples.
Lab Prerequisites
---------------
###Requirements
* [Code Composer Studio (CCS)](https://software-dl.ti.com/ccs/esd/documents/ccs_downloads.html) (preferably version 10 or later)
* Any SimpleLink LaunchPad that has SimpleLink SDK support, *with the exception of* the CC32xx LaunchPads.
* The latest SimpleLink SDK for your LaunchPad
###Check Target Configuration
For each new project you create (including the labs in this workshop), you will have to follow these steps.
In order to use the Trace Visualization Toolkit, you need to check if the target configuration is configured for it.
1. Double-click the ***.ccxml** file under **targetConfigs** in **Project Explorer** to open it in CCS.
![targetConfigs file image](images/swo_requirements1.PNG)
2. Click on the **Advanced** Tab near the bottom left of the view and click on the USB Debug Probe.
![USB Debug Probe image](images/swo_requirements2.PNG)
3. Follow the steps for your device below:
[[+g For MSP432 boards (Expand):
Make sure that the target uses SWD as the debug protocol with TDO connection to the Aux COM port:
![correct setting](images/swo_cor_config.PNG)
+]]
[[+g For the other boards (Expand):
Make sure the parameters are correct in the .ccmxl file is correct:
![correct setting](images/swo_cor_config2.PNG)
In the <YourLaunchPad>_LAUNCHXL_fxns.c file found under the project, copy the following code
into the function `Board_initHook()`:
```
// Map Serial Wire Viewer to JTAG TDO pin
IOCPortConfigureSet(IOID_16, IOC_PORT_MCU_SWV, IOC_STD_OUTPUT);
```
For example, if you are using a [CC1310 LaunchPad](https://www.ti.com/store/ti/en/p/product/?p=LAUNCHXL-CC1310), the file is called CC1310_LAUNCHXL_fxns.c. The modifications to `Board_initHook()` would look like this:
![pinmux for swo](images/swo_pinmux.PNG)
[[r Note:
This is not supported on some older SDKs. Make sure you are using the latest version of the SimpleLink SDK for your LaunchPad.]]
+]]
Lab 1: Statistical Function Profile
--
**Statistical Function Profile** is a useful tool that shows the frequency of function calls within a program using statistical methods. The **Program Counter (PC)** is regularly sampled, and the function being executed is determined based on the PC value. This tool is important because it can show which functions are more crucial.
### 1.1 Example program
1. The basis for the example is the **empty** project which can be imported from the **SDK** using [Resource Explorer](https://software-dl.ti.com/ccs/esd/documents/users_guide/ccs_getting-started.html#resource-explorer).
The path to the project is **Software → SimpleLink (YourDeviceFamily) SDK – v:(X.X.X.X) → Examples → Development Tools → (YourLaunchPad) → TI Drivers → empty → TI-RTOS → CCS Compiler → empty**.
2. Make sure you've completed all the setup required as specified in [Check Target Configuration](#check-target-configuration).
3. Add the following dummy functions before the `mainThread()` function in empty.c:
```javascript
void divBy2() {
int i = 0;
for (i=0;i<50;i++) {
}
}
void divBy4() {
int i = 0;
for (i=0;i<50;i++) {
}
}
void divBy8() {
int i = 0;
for (i=0;i<50;i++) {
}
}
```
4. Replace the while loop in the `mainThread()` function with the following for loop:
```c
int counter=0;
for (counter=0;counter<=1600;counter++) {
if (counter % 2 == 0) {
divBy2();
}
if (counter % 4 == 0) {
divBy4();
}
if (counter % 8 == 0) {
divBy8();
}
}
counter=0;
```
This loop will create an interesting function call pattern for each dummy function.
5. Set a **breakpoint** (by double-clicking in the editor margin of the source file) at the line `counter=0;` right after exiting the loop. This breakpoint will be used to stop the tool from running after the loop exits.
[[+d If your device supports SysConfig, your **empty.c** file should look like this. (Expand)
```c
/*
* Copyright (c) 2015-2017, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* ======== empty.c ========
*/
/* For usleep() */
#include
#include
#include
/* Driver Header files */
#include
// #include
// #include
// #include
// #include
// #include
/* Driver configuration */
#include "ti_drivers_config.h"
void divBy2() {
int i = 0;
for (i=0;i<50;i++) {
}
}
void divBy4() {
int i = 0;
for (i=0;i<50;i++) {
}
}
void divBy8() {
int i = 0;
for (i=0;i<50;i++) {
}
}
/*
* ======== mainThread ========
*/
void *mainThread(void *arg0)
{
/* Call driver init functions */
GPIO_init();
// I2C_init();
// SDSPI_init();
// SPI_init();
// UART_init();
// Watchdog_init();
/* Configure the LED pin */
GPIO_setConfig(CONFIG_GPIO_LED_0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
/* Turn on user LED */
GPIO_write(CONFIG_GPIO_LED_0, CONFIG_GPIO_LED_ON);
int counter=0;
for (counter=0;counter<=1600;counter++) {
if (counter % 2 == 0) {
divBy2();
}
if (counter % 4 == 0) {
divBy4();
}
if (counter % 8 == 0) {
divBy8();
}
}
counter=0;
}
```
+]]
[[+d If your device *does not* support SysConfig, your **empty.c** file should look like this. (Expand)
```c
/*
* Copyright (c) 2015-2017, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* ======== empty.c ========
*/
/* For usleep() */
#include
#include
#include
/* Driver Header files */
#include
// #include
// #include
// #include
// #include
// #include
/* Board Header file */
#include "Board.h"
void divBy2() {
int i = 0;
for (i=0;i<50;i++) {
}
}
void divBy4() {
int i = 0;
for (i=0;i<50;i++) {
}
}
void divBy8() {
int i = 0;
for (i=0;i<50;i++) {
}
}
/*
* ======== mainThread ========
*/
void *mainThread(void *arg0)
{
/* Call driver init functions */
GPIO_init();
// I2C_init();
// SDSPI_init();
// SPI_init();
// UART_init();
// Watchdog_init();
/* Configure the LED pin */
GPIO_setConfig(Board_GPIO_LED0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
/* Turn on user LED */
GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_ON);
int counter=0;
for (counter=0;counter<=1600;counter++) {
if (counter % 2 == 0) {
divBy2();
}
if (counter % 4 == 0) {
divBy4();
}
if (counter % 8 == 0) {
divBy8();
}
}
counter=0;
}
```
+]]
[[b Note:
If your project contains a file called **<ProjectName>.syscfg**, that means it supports SysConfig.
]]
### 1.2 Using the tool
1. Click **Run → Debug** (or **F11**) to launch the debugger.
2. Select **Tools → Code Analysis → Event Analysis** to launch the **Configure Event Profile**.
3. Check the box for **Statistical Function Profile** under **Common Configuration**. Start by choosing a **Sampling Interval** of 256 cycles (or 512 if you are using the MSP432E4).
[[+y If you are using the **MSP432E4** boards (Expand)
If you are using the MSP432E4 boards, you will have to manually set the system clock frequency.
Scroll to the bottom of the **Configure Event Profile** modal. Expand **Export Interface Configuration**, and uncheck the **System Clock** box.
In the **Enter Frequency in Hz...** box, enter **120000000**.
![Manually set System Clock Frequency](images\swo_tvt_set_system_clock.png)
+]]
[[b Note:
Shorter sampling intervals can be chosen, but high sampling rates can cause overflow and packet loss if the data cannot be drained fast enough. When the sampling rate is getting too high, warnings of overflow will appear in the **Raw Data** tab.
The **Raw Data** view displays the raw data collected by the tracer.
]]
![256 cycles function profile](images/swo_tvt_256cycles.png)
This means that the profiler will read and record the PC location every 256 or 512 cycles (depending on which you chose), creating a dense profile. Click on **OK** to save the changes.
[[+y CCS cannot determine the System Clock frequency automatically? (expand)
You might receive an error message saying "Could not determine the target System Clock frequency automatically. Please enter the frequency in the Export Interface Configuration.
Uncheck the box for System Clock to enter the frequency.".
In this case, you will have to **Terminate** the program, and restart this section, making sure you manually set the System Clock frequency:
Scroll to the bottom of the **Configure Event Profile** modal. Expand **Export Interface Configuration**, and uncheck the **System Clock** box.
In the **Enter Frequency in Hz...** box, enter the CPU frequency for your board:
* 120000000 for the MSP432E4
* 48000000 for the other boards used in this lab
+]]
4. Click on **Start Capture** on the top right to capture data.
[[b Note:
You can check **Display each channel message on a separate line with timestamp** to get the messages.
![start capture](images/start_capture.png)
]]
5. **Resume** the program (**Run → Resume**, or F8), and it should run and halt at the breakpoint you have set earlier. In the **Statistical Function Profile** tab, it shows the number of times a function is encountered by the tracer. You might need to wait for a few seconds for CCS to process all the data before the view shows the results.
![256 cycles function profile result](images/swo_tvt_256_result.png)
Looking at the **Count** of the dummy functions, you will find that they closely match the expected calling ratio. i.e. `divBy2()` should be called twice as often as `divBy4()` and four times as often as `divBy8()`.
The field shows very large numbers due to the short sampling interval of 256 cycles.
Also notice that the list shows a lot of small helper functions as well.
6. Click on the **Settings** button on the top left corner and change the **Sampling Interval** to 4096 cycles.
![function but](images/swo_tvt_change_but.png)
Click **OK**.
7. **Restart** the program (**Run → Restart**), **Resume** execution (**Run → Resume**, or F8), and observe the results.
![4096 cycles function profile result](images/swo_tvt_4096_result.png)
The list is much shorter than last time, with only a few encounters of helper functions. The calling ratio of the dummy functions may also diverge more than before from the expectations. This is because the sampling interval is very long, potentially skipping entire calls to a function.
8. That's it! When you are finished, close the **Event Analysis** window and **Terminate** (**Run → Terminate** or Ctrl+F2) the debug session.
Lab 2: Exception Profile
---
### 2.1 Example program
1. Follow the below steps according to the board you are using:
[[+g If you are using an MSP432 board (Expand)
The basis for the example is the **timerled** project which can be imported from the SDK at
**Software → SimpleLink (YourDeviceFamily) SDK – v:(X.X.X.X) → Examples → Development Tools → (YourLaunchPad) → TI Drivers → timerled → TI-RTOS → CCS Compiler → timerled**.
+]]
[[+g If you are using the other boards (Expand)
For this example, the **empty** project is used as a base and the contents of empty.c are replaced with a program that behaves like the **timerled** project used for the MSP432 boards.
1. Before importing the **empty** project again, rename the project used in Lab 1 to something else.
2. Import the **empty** project from the SDK at
**Software → SimpleLink (YourDeviceFamily) SDK – v:(X.X.X.X) → Examples → Development Tools → (YourLaunchPad) → TI Drivers → empty → TI-RTOS → CCS Compiler → empty**.
3. If your device does not support SysConfig, skip to the next step. If it does, open **empty.syscfg** and add a new **Timer** under **TI Drivers**.
You can leave the default settings as is.
![Add Timer in SysConfig](images/swo_tvt_syscfg_timer.png)
4. Replace the contents of empty.c with the following code, depending on whether or not your board supports SysConfig:
If your board supports SysConfig, use this code:
```c
/*
* This is a modified version of an example given in the GPTimerCC26XX.h File Reference
* It will toggle the led once per second
*/
/* Driver Header files */
#include
#include
#include // For Types_FreqHz
#include // For BIOS_getCpuFreq
/* Driver configuration */
#include "ti_drivers_config.h"
// Callback to toggle the LED
void timerCallback(GPTimerCC26XX_Handle timerHandle, GPTimerCC26XX_IntMask interruptMask)
{
GPIO_toggle(CONFIG_GPIO_LED_0);
}
/*
* ======== mainThread ========
*/
void *mainThread(void *arg0)
{
/* Call driver init functions */
GPIO_init();
/* Configure the LED pin */
GPIO_setConfig(CONFIG_GPIO_LED_0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
/* Turn off user LED */
GPIO_write(CONFIG_GPIO_LED_0, CONFIG_GPIO_LED_OFF);
GPTimerCC26XX_Params params;
GPTimerCC26XX_Params_init(¶ms);
params.width = GPT_CONFIG_32BIT;
params.mode = GPT_MODE_PERIODIC_UP;
params.debugStallMode = GPTimerCC26XX_DEBUG_STALL_OFF;
GPTimerCC26XX_Handle hTimer = GPTimerCC26XX_open(CONFIG_TIMER_0, ¶ms);
if (hTimer == NULL) {
/* Failed to initialized timer */
while (1) {}
}
// This timer will count up (from zero) to the value specified by loadVal and then call our callback.
// We set loadVal equal to our processor frequency so that the callback period is one second.
Types_FreqHz freq;
BIOS_getCpuFreq(&freq);
GPTimerCC26XX_Value loadVal = freq.lo - 1;
GPTimerCC26XX_setLoadValue(hTimer, loadVal);
GPTimerCC26XX_registerInterrupt(hTimer, timerCallback, GPT_INT_TIMEOUT);
GPTimerCC26XX_start(hTimer);
return (NULL);
}
```
If your board does not support SysConfig, use this instead:
```c
/*
* This is a modified version of an example given in the GPTimerCC26XX.h File Reference
* It will toggle the led once per second
*/
/* Driver Header files */
#include
#include
#include // For Types_FreqHz
#include // For BIOS_getCpuFreq
/* Board Header file */
#include "Board.h"
// Callback to toggle the LED
void timerCallback(GPTimerCC26XX_Handle timerHandle, GPTimerCC26XX_IntMask interruptMask)
{
GPIO_toggle(Board_GPIO_LED0);
}
/*
* ======== mainThread ========
*/
void *mainThread(void *arg0)
{
/* Call driver init functions */
GPIO_init();
/* Configure the LED pin */
GPIO_setConfig(Board_GPIO_LED0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
/* Turn off user LED */
GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_OFF);
GPTimerCC26XX_Params params;
GPTimerCC26XX_Params_init(¶ms);
params.width = GPT_CONFIG_32BIT;
params.mode = GPT_MODE_PERIODIC_UP;
params.debugStallMode = GPTimerCC26XX_DEBUG_STALL_OFF;
GPTimerCC26XX_Handle hTimer = GPTimerCC26XX_open(Board_GPTIMER0A, ¶ms);
if (hTimer == NULL) {
/* Failed to initialized timer */
while (1) {}
}
// This timer will count up (from zero) to the value specified by loadVal and then call our callback.
// We set loadVal equal to our processor frequency so that the callback period is one second.
Types_FreqHz freq;
BIOS_getCpuFreq(&freq);
GPTimerCC26XX_Value loadVal = freq.lo - 1;
GPTimerCC26XX_setLoadValue(hTimer, loadVal);
GPTimerCC26XX_registerInterrupt(hTimer, timerCallback, GPT_INT_TIMEOUT);
GPTimerCC26XX_start(hTimer);
return (NULL);
}
```
+]]
The example program uses a timer interrupt to toggle the on-board LED every second. You will use the the **Exception Profiling** tool to observe these interrupts.
2. Make sure you've completed all the setup required as specified in [Check Target Configuration](#check-target-configuration).
### 2.2 Using the tool
1. Click **Run → Debug** to launch the debugger.
2. Select **Tools → Code Analysis → Event Analysis** to launch the **Configure Event Profile**.
Check the **Exception Profile** option, and use the default options (unless you need to input the clock speed manually). Press **OK**.
[[+d If you need to input the clock speed manually (Expand)
Scroll to the bottom of the **Configure Event Profile** modal. Expand **Export Interface Configuration**, and uncheck the **System Clock** box.
In the **Enter Frequency in Hz...** box, enter the CPU frequency for your board:
* 120000000 for the MSP432E4
* 48000000 for the other boards used in this lab
+]]
3. Click on **Start Capture** to capture the data.
4. **Resume** the program, and observe the on-board LED. After the LED toggles 2-3 times, **Suspend** (**Run → Suspend**, or Alt+F8) the program from the debugger.
[[b Note:
A window may appear stating that "You are opening a large file." You can decline to change the scalability settings. If the file seems too large for CCS to handle, you can restart and pause the program after fewer LED toggles.]]
5. Click on the **Exception Profile** tab, and you will see the **Graphical view of exception** as well as the **Exception Statistics**.
The **Raw Data** tab to the right shows the raw data captured by the trace.
![Interrupt Profiling Result](images/swo_tvt_int_result.png)
6. In the **Exception Profile** tab, look for the row corresponding to the interrupt that was instantiated in the program in the **Exception Statistics** table. The interrupts can vary by board.
Board
Interrupt
MSP432P401R
T32_INT1
MSP432P411
ANALOGCOMP0
MSP432E4
16/32TIMER2A
CC13xx / CC2640R2 / CC2652
Timer 0A
Also take note of the value under the **Number** column for the interrupt.
7. Zoom in/out by placing your cursor on the section of the graph where you want to focus, and scroll up/down to see more details. If you want to zoom out completely, double-click on the graph.
The number of lines should be the same as the number of times the LED was toggled earlier. These straight lines mark when in the program runtime the interrupt (timer) was triggered.
As you move across the graph, you can see which interrupts occurred at certain times.
For example, in the below graph, the LED was toggled 5 times. At time 2000.9513333333334ms, there was an entry into Exception #31 (i.e. Timer 0A).
![example exceptions graph](images/swo_tvt_exc.png)
8. That's it! When you are finished, close the **Event Analysis** window and **Terminate** the debug session.
Lab 3: Variable Profile
---
### 3.1 Example program
1. The basis for the example is the **gpiointerrupt** project which can be imported from the SDK at
**Software → SimpleLink (YourDeviceFamily) SDK – v:(X.X.X.X) → Examples → Development Tools → (YourLaunchPad) → TI Drivers → gpiointerrupt → TI-RTOS → CCS Compiler → gpiointerrupt**.
2. Make sure you've completed all the setup required as specified in [Check Target Configuration](#check-target-configuration).
3. Open gpiointerrupt.c and add a global variable **click_count** right before all the functions.
The left and right buttons on your board will be changing the value of this variable.
```c
unsigned int click_count = 0;
```
[[b Note:
We use an unsigned integer because the Variable Trace does not distinguish between signed and unsigned data.]]
4. At the end of `gpioButtonFxn0()` function, add the following:
```c
click_count++;
```
5. At the end of the `gpioButtonFxn1()` function, add the following:
```c
if (click_count > 0)
click_count--;
```
[[+d Your **gpiointerrupt.c** file should look like this if your device supports SysConfig (Expand):
```c
/*
* Copyright (c) 2015-2019, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* ======== gpiointerrupt.c ========
*/
#include
#include
/* Driver Header files */
#include
/* Driver configuration */
#include "ti_drivers_config.h"
unsigned int click_count = 0;
/*
* ======== gpioButtonFxn0 ========
* Callback function for the GPIO interrupt on CONFIG_GPIO_BUTTON_0.
*/
void gpioButtonFxn0(uint_least8_t index)
{
/* Clear the GPIO interrupt and toggle an LED */
GPIO_toggle(CONFIG_GPIO_LED_0);
click_count++;
}
void gpioButtonFxn1(uint_least8_t index)
{
/* Clear the GPIO interrupt and toggle an LED */
GPIO_toggle(CONFIG_GPIO_LED_1);
if (click_count > 0)
click_count--;
}
/*
* ======== mainThread ========
*/
void *mainThread(void *arg0)
{
/* Call driver init functions */
GPIO_init();
/* Configure the LED and button pins */
GPIO_setConfig(CONFIG_GPIO_LED_0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
GPIO_setConfig(CONFIG_GPIO_LED_1, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
GPIO_setConfig(CONFIG_GPIO_BUTTON_0, GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_FALLING);
/* Turn on user LED */
GPIO_write(CONFIG_GPIO_LED_0, CONFIG_GPIO_LED_ON);
/* install Button callback */
GPIO_setCallback(CONFIG_GPIO_BUTTON_0, gpioButtonFxn0);
/* Enable interrupts */
GPIO_enableInt(CONFIG_GPIO_BUTTON_0);
/*
* If more than one input pin is available for your device, interrupts
* will be enabled on CONFIG_GPIO_BUTTON1.
*/
if (CONFIG_GPIO_BUTTON_0 != CONFIG_GPIO_BUTTON_1) {
/* Configure BUTTON1 pin */
GPIO_setConfig(CONFIG_GPIO_BUTTON_1, GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_FALLING);
/* Install Button callback */
GPIO_setCallback(CONFIG_GPIO_BUTTON_1, gpioButtonFxn1);
GPIO_enableInt(CONFIG_GPIO_BUTTON_1);
}
return (NULL);
}
```
+]]
[[+d Your **gpiointerrupt.c** file should look like this if your device *does not* support SysConfig (Expand):
```c
/*
* Copyright (c) 2015-2019, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* ======== gpiointerrupt.c ========
*/
#include
#include
/* Driver Header files */
#include
/* Example/Board Header files */
#include "Board.h"
unsigned int click_count = 0;
/*
* ======== gpioButtonFxn0 ========
* Callback function for the GPIO interrupt on Board_GPIO_BUTTON0.
*/
void gpioButtonFxn0(uint_least8_t index)
{
/* Clear the GPIO interrupt and toggle an LED */
GPIO_toggle(Board_GPIO_LED0);
click_count++;
}
/*
* ======== gpioButtonFxn1 ========
* Callback function for the GPIO interrupt on Board_GPIO_BUTTON1.
* This may not be used for all boards.
*/
void gpioButtonFxn1(uint_least8_t index)
{
/* Clear the GPIO interrupt and toggle an LED */
GPIO_toggle(Board_GPIO_LED1);
if (click_count > 0)
click_count--;
}
/*
* ======== mainThread ========
*/
void *mainThread(void *arg0)
{
/* Call driver init functions */
GPIO_init();
/* Configure the LED and button pins */
GPIO_setConfig(Board_GPIO_LED0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
GPIO_setConfig(Board_GPIO_LED1, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
GPIO_setConfig(Board_GPIO_BUTTON0, GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_FALLING);
/* Turn on user LED */
GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_ON);
/* install Button callback */
GPIO_setCallback(Board_GPIO_BUTTON0, gpioButtonFxn0);
/* Enable interrupts */
GPIO_enableInt(Board_GPIO_BUTTON0);
/*
* If more than one input pin is available for your device, interrupts
* will be enabled on Board_GPIO_BUTTON1.
*/
if (Board_GPIO_BUTTON0 != Board_GPIO_BUTTON1) {
/* Configure BUTTON1 pin */
GPIO_setConfig(Board_GPIO_BUTTON1, GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_FALLING);
/* Install Button callback */
GPIO_setCallback(Board_GPIO_BUTTON1, gpioButtonFxn1);
GPIO_enableInt(Board_GPIO_BUTTON1);
}
return (NULL);
}
```
+]]
### 3.2 Using the tool
1. Click **Run → Debug** to launch the debugger.
2. Select **Tools → Code analysis → Event Analysis**. Check **Variable Profile**. In the **Variable Address** field, enter **click_count**.
You may have to wait a few seconds for it to find the address of the variable.
When the text above the input box says **Address in hex: 0x***, press **OK** (unless you need to input the clock speed manually).
[[+d If you need to input the clock speed (Expand)
Scroll to the bottom of the **Configure Event Profile** modal. Expand **Export Interface Configuration**, and uncheck the **System Clock** box.
In the **Enter Frequency in Hz...** box, enter the CPU frequency for your board:
* 120000000 for the MSP432E4
* 48000000 for the other boards used in this lab
+]]
3. **Resume** the program, press the left button (**BUTTON_0**) a few times and then press the right button (**BUTTON_1**) a few times.
**Suspend** the program afterwards.
4. Click on the **Variable Profile** tab, you will see the graphical view of how the watched variable changes as well as a **Tabular view of reads and writes**. You can see a graph that shows the value of **click_count** going up and down.
For example, in the graph below, **BUTTON_0** was pressed 3 times, followed by **BUTTON_1** 3 times.
![Variable Profiling Result](images/swo_lab3.PNG)
5. In the **Tabular view of reads and writes** table, the record of button clicks can be seen under click_count Rd and click_count Wr. The time when the buttons are clicked are also recorded.
6. That's it! When you are finished, **Terminate** the debug session and close the **Event Analysis** window.
Summary
---
The **Trace Visualization Toolkit** functionalities are very helpful tools for analyzing, debugging and monitoring a program.
In this workshop, you have learned the basics of **Statistical Function Profile**, **Exception Profile** and **Variable Profile**.
These simple examples are meant to get you familiar with the capabilities of Trace Visualization Toolkit, in order to be able to apply them to your projects.