Overview
This workshop provides an introduction to the Code Composer Studio integrated development environment. It will cover how to get started using a SimpleLink LaunchPad.
Requirements
Software:
- Code Composer Studio v10 or greater.
- The SimpleLink SDK for your LaunchPad, version 3.30 or greater. This will be installed as part of Lab 1.
Hardware
Any of the below SimpleLink LaunchPads:
- CC1312R LaunchPad (LAUNCHXL-CC1312R1)
- CC1352R LaunchPad (LAUNCHXL-CC1352R1)
- MSP432P401R LaunchPad (MSP-EXP432P401R)
- MSP432P4111 LaunchPad (MSP-EXP432P4111)
- MSP432E401Y LaunchPad (MSP-EXP432E401Y)
- CC26X2R LaunchPad (LAUNCHXL-CC26X2R1)
- CC3220S LaunchPad (CC3220S-LAUNCHXL)
- CC3220SF LaunchPad (CC3220SF-LAUNCHXL)
- CC3235S LaunchPad (CC3235S-LAUNCHXL)
CC3235SF LaunchPad (CC3235SF-LAUNCHXL)
Note:
If you are using an SDK version lower than 3.20, or you are using a LaunchPad that is not mentioned in the above list, please use the older existing workshop.
Recommended Reading
- You may wish to read more about the SimpleLink MCU Platform and the SimpleLink SDK.
- You may wish to read about concepts involving RTOS and TI-RTOS.
Lab 1: Importing, Editing, and Running a Project
This lab will go over importing an example project from the SimpleLink SDK, making some edits to modify the program's functionality, and flashing the program to the target (the SimpleLink LaunchPad) to run the program.
Importing and Running an Example Project
Connect your SimpleLink LaunchPad board to the computer via USB cable.
Open Code Composer Studio.
From the top menubar, open: View → Resource Explorer.
Note:
You can use Resource Explorer to browse through documentation, libraries, and software examples.
From the home page of Resource Explorer, search for your LaunchPad in the Keywords filter input box.
Expand the Software folder in the tree view on the left, and install the SDK for your device. You may also be prompted to download and install SimpleLink Academy; this is optional.
Once installed, SimpleLink (YourDeviceFamily) SDK -v: (X.X.X.X) will have a checkmark beside its name in the Software folder.
Note:
To return to the home page from another view in Resource Explorer, click on the Home button in the breadcrumb trail near the top.
Under the tree view, expand and select Software → SimpleLink (YourDeviceFamily) SDK – v:(X.X.X.X) → Examples → Development Tools → (YourLaunchPad) → TI Drivers → empty → TI-RTOS → CCS Compiler → empty, and then click the Import button at the top-right to import to IDE.
Note:
When importing the project, depending on the version of the SDK and the XDCtools you have, CCS may give a warning stating that the project could not find the specified version '3.60.999', and defaulted to '3.61.0.14_core_eng'. It is fine to use the defaulted newer version. Click OK to continue importing the project.
Note:
In Resource Explorer, you are also able to browse through examples and other resources that you have not yet installed locally. You will simply be prompted to download and install when attempting to import an example to IDE.
The empty project is a simple TI-RTOS program that blinks LED0 on your board (ON for one second and then OFF for one second). This project is useful as a bare starting point to develop your application.
Two projects should have appeared in Project Explorer (if you cannot see the view, you can open it by going to View → Project Explorer): the empty project, and the tirtos kernel configuration project. The empty project is dependent on this tirtos project, which contains the configuration for the TI-RTOS. More information about the TI-RTOS Kernel and configuration can be found in the SimpleLink MCU SDK User's Guide.
If you have multiple projects open in the Project Explorer, ensure that the empty project for your LaunchPad is active (it is shown as bold). If not, you can set it to the active project by double-clicking it.
You can use the Project Explorer to browse through the empty project. Useful files to look through include Board.html, empty.c, main_tirtos.c, and empty.syscfg.
- Board.html: Provides an overview of your LaunchPad hardware, and jumper settings.
- main_tirtos.c: The main() function is defined here, and in this case, simply creates a single thread that runs the mainThread() function indefinitely.
- empty.c: The application code will be in this file. The mainThread() function (which is called by the main() function in main_tirtos.c) will initialize and configure the needed drivers, before entering an infinite main loop. Other application functions such as interrupt callbacks can be defined in this file as well.
- empty.syscfg: A tool to simplify the configuration of your applicaion on a SimpleLink device.
You can also see the pins and resources being used by clicking Show Device and Show Board at the top right corner of SysConfig.
More information regarding SysConfig and examples to get started with the tool can be found at the SysConfig Basics page.
Click Debug on the toolbar (or select Run → Debug in the top menu bar). This will prompt to save source files, build the project, start the debugger, switch to the CCS Debug perspective, connect CCS to the target, and then flash (load) the program to the target. The first time you run this, it may take a minute to build the TI-RTOS kernel configuration project.
When running in debug mode, your LaunchPad is at first suspended. Click on Resume near the top left on the toolbar, or click Run → Resume in the menu bar, for your LaunchPad to run the program.
- There are icons near the top-right of the toolbar which allow you to switch between the CCS Debug and the CCS Edit perspectives.
- Note that LED0 on your LaunchPad board is now blinking at 0.5 Hz, as expected. The program is being run.
- You can Suspend and Resume program execution on the target as desired.
When you are done with this part of the lab, Terminate the debug session (which will also return you to the CCS Edit perspective).
Modifying the Project
Currently the program simply blinks LED0 on the LaunchPad at 0.5 Hz. Say that some functionality needs to be added to the program such that the blinking frequency of LED0 is controllable. The program will be modified as follows.
- When the program is first run on the LaunchPad, LED0 will initially be blinking at 1 Hz.
- Whenever GPIO_Button0 is pressed, the frequency of LED0 will be doubled, up to a maximum of 32 Hz.
- Whenever GPIO_Button1 is pressed, the frequency of LED0 will be halved, down to a minimum of 1 Hz.
Whenever either GPIO_Button0 or GPIO_Button1 is pressed, the state of LED1 will be toggled.
Note:
Some LaunchPad boards will not have a separate LED1 available for use for GPIO. This can be confirmed in SysConfig by clicking Show Board at the top right corner, and seeing what kind of hardware is available.
Even if your LaunchPad is affected, the following code modifications will build and run on the target. You simply won't see a second LED toggling on button presses.
Let's get started!
In empty.c, in mainThread(), the integer variable
time
is defined and initialized to 1. This variable is used in the infinite main loop at the bottom of mainThread() to set the delay in seconds between toggling LED0.- Move this code block from inside mainThread() to just below the include statements at the top of empty.c, making this a global variable, so that its value can be more easily modified from any function.
- Currently in the main loop, the sleep(seconds) function is being used. For more resolution, this will be changed to usleep(useconds), which uses microseconds. As such, for LED0 to be blinking at 1 Hz to start, the value of this variable needs to be initialized to 500000 (useconds).
Rename the variable from
time
to something more descriptive, likeled0_on_off_useconds
./* CONFIG_GPIO_LED_0 on and off time in microseconds */ uint32_t led0_on_off_useconds = 500000;
Modify the contents of the mainThread() main loop, to account for the changes that were just made.
while (1) { usleep(led0_on_off_useconds); GPIO_toggle(CONFIG_GPIO_LED_0); }
Regarding usleep():
The usleep(useconds) function can only take unsigned integer arguments strictly less than 1000000. Otherwise, an overflow may occur.
In mainThread(), configure and initialize the state of LED1, next to where this is already done for LED0.
/* Configure the LED 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); /* Initialize LED states to ON */ GPIO_write(CONFIG_GPIO_LED_0, CONFIG_GPIO_LED_ON); GPIO_write(CONFIG_GPIO_LED_1, CONFIG_GPIO_LED_ON);
In between mainThread() and the declaration of
led0_on_off_useconds
, define callback functions which will be called whenever Button0 or Button1 are pressed. These functions will double or halve the switching frequency of LED0, respectively, by halving or doubling the value ofled0_on_off_useconds
. Recall that the max switching frequency will be 32 Hz, and the min frequency will be 1 Hz, so those limits need to be guarded against. Both functions will also toggle the state of LED1./* * ======== gpioButtonFxn0 ======== * Callback function for the GPIO interrupt on CONFIG_GPIO_BUTTON0. */ void gpioButtonFxn0(uint_least8_t index) { /* Double LED0 frequency, and toggle LED1 */ if(led0_on_off_useconds >= 31250) { /* LED0 frequency currently <= 16 Hz; can double */ led0_on_off_useconds /= 2; } else { /* limit LED0 frequency to 32 Hz max */ led0_on_off_useconds = 15625; } GPIO_toggle(CONFIG_GPIO_LED_1); } /* * ======== gpioButtonFxn1 ======== * Callback function for the GPIO interrupt on CONFIG_GPIO_BUTTON1. */ void gpioButtonFxn1(uint_least8_t index) { /* Halve LED0 frequency, and toggle LED1 */ if(led0_on_off_useconds <= 250000) { /* LED0 frequency currently >= 2 Hz; can halve */ led0_on_off_useconds *= 2; } else { /* limit LED0 frequency to 1 Hz min */ led0_on_off_useconds = 500000; } GPIO_toggle(CONFIG_GPIO_LED_1); }
Double-click empty.sysconfig to open SysConfig and select the
<>
icon at the top right of the SysConfig GUI. Click on ti_drivers_config.c to preview the file. You will be able to see the changes you make in the SysConfig GUI reflected in this file in the next few steps.Select the + beside the GPIO module under the Software view, and change the settings to the following:
- Name : CONFIG_GPIO_LED_1
Use Hardware : LaunchPad LED Green
You can leave the rest of the settings as they are. Notice that your changes are automatically updated in the ti_drivers_config.c file.
Add another GPIO module, this time with the following settings:
- Name: SPEED_BUTTON
- Use Hardware: LaunchPad Button BTN-1 (Left)
Callback Function: gpioButtonFxn0
The callback function must match the one previously defined in empty.c.
Note:
Names in the Hardware drop-down list can vary depending on the target. For example, the name for the left button on MSP432P401R is "LaunchPad Button S1 (Left)".
Add the final GPIO module for the second button with the settings:
- Name: SLOW_BUTTON
- Use Hardware: LaunchPad Button BTN-2 (Right)
Callback Function: gpioButtonFxn1
Remember to save the file.
Finally, add the following code to mainThread() in empty.c between the LED configurations and the main while loop to configure the buttons as interrupts. The button names must match the ones defined earlier in SysConfig.
/* Enable interrupts */ GPIO_enableInt(SPEED_BUTTON); GPIO_enableInt(SLOW_BUTTON);
/*
* 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.
*/
/*
* ======== empty.c ========
*/
/* For usleep() */
#include <unistd.h>
#include <stdint.h>
#include <stddef.h>
/* Driver Header files */
#include <ti/drivers/GPIO.h>
// #include <ti/drivers/I2C.h>
// #include <ti/drivers/SPI.h>
// #include <ti/drivers/UART.h>
// #include <ti/drivers/Watchdog.h>
/* Driver configuration */
#include "ti_drivers_config.h"
/* 1 second delay */
uint32_t led0_on_off_useconds = 500000;
/*
* ======== gpioButtonFxn0 ========
* Callback function for the GPIO interrupt on CONFIG_GPIO_BUTTON0.
*/
void gpioButtonFxn0(uint_least8_t index)
{
/* Double LED0 frequency, and toggle LED1 */
if(led0_on_off_useconds >= 31250) { /* LED0 frequency currently <= 16 Hz; can double */
led0_on_off_useconds /= 2;
}
else { /* limit LED0 frequency to 32 Hz max */
led0_on_off_useconds = 15625;
}
GPIO_toggle(CONFIG_GPIO_LED_1);
}
/*
* ======== gpioButtonFxn1 ========
* Callback function for the GPIO interrupt on CONFIG_GPIO_BUTTON1.
*/
void gpioButtonFxn1(uint_least8_t index)
{
/* Halve LED0 frequency, and toggle LED1 */
if(led0_on_off_useconds <= 250000) { /* LED0 frequency currently >= 2 Hz; can halve */
led0_on_off_useconds *= 2;
}
else { /* limit LED0 frequency to 1 Hz min */
led0_on_off_useconds = 500000;
}
GPIO_toggle(CONFIG_GPIO_LED_1);
}
/*
* ======== mainThread ========
*/
void *mainThread(void *arg0)
{
/* Call driver init functions */
GPIO_init();
// I2C_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);
GPIO_setConfig(CONFIG_GPIO_LED_1, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
/* Turn on user LED */
GPIO_write(CONFIG_GPIO_LED_0, CONFIG_GPIO_LED_ON);
GPIO_write(CONFIG_GPIO_LED_1, CONFIG_GPIO_LED_ON);
/* Enable interrupts */
GPIO_enableInt(SPEED_BUTTON);
GPIO_enableInt(SLOW_BUTTON);
while (1) {
usleep(led0_on_off_useconds);
GPIO_toggle(CONFIG_GPIO_LED_0);
}
}
Click Run → Debug and then Resume to run the program on the target. Test the program by verifying that the pressing buttons on the LaunchPad controls the LED0 blink frequency and toggles the state of LED1.
That's it!
Note:
You can find very useful code snippets by browsing through various example projects in SimpleLink SDK → Examples → Development Tools → (YourLaunchPad) → TI Drivers. There will be simple projects that utilize hardware resources such as the ADC, GPIO interrupts, timers, PWM, etc.
Lab 2: Basic Debug Concepts
This lab will cover the basics of debugging, using the modified empty.c code from Lab 1. Specific tools and concepts that are covered are:
- Breakpoints
- Watchpoints
- Profile Clock
- Disassembly View
- Other Views
- Loading Symbols Only to Debug Flashed Program
Breakpoints
Breakpoints are specific points that can be set in the code, where the program is to halt execution. Once halted, the values in registers/memory/etc. can be inspected to gain a deeper understanding of the program execution. This is very useful when debugging.
Both software breakpoints and hardware breakpoints are available for use
A hardware breakpoint uses debug resources on the target as compared to a software breakpoint which is typically an opcode replacement. A hardware breakpoint is required when setting a breakpoint in Flash, while a software breakpoint can be used in RAM. While the number of software breakpoints available is practically limitless, the number of hardware breakpoints is typically small in number and varies per target. More information can be found here.
If your SimpleLink LaunchPad is currently running, ensure you are in the CCS Debug perspective and Suspend it. Otherwise, click on Run → Debug to flash the program to the target and suspend it.
Click on View → Breakpoints to open a Breakpoints view. There should be no breakpoints to start.
While staying in the CCS Debug perspective, in empty.c, scroll to the definition of the gpioButtonFxn1() function, and double-click on the margin to the left of the line number. This will insert a breakpoint that will halt program execution whenever it reaches this point in the code. CCS will automatically use either a hardware breakpoint or a software breakpoint, as necessary.
Click Run → Resume to resume program execution on the LaunchPad. Click Button0 on the board a few times, until LED0 is blinking at its max frequency of 32 Hz. Note that the program continues to run as expected without interruption. Click Button1 on the board, and note that the program has suspended due to the breakpoint.
- Place your mouse over an instance of the
led0_on_off_useconds
variable in empty.c. A tooltip will appear, showing the current value of the variable. The value is still 15625 (corresponding to a frequency of 32 Hz), because the breakpoint has suspended to program at the start of the function, before it has doubled the value ofled0_on_off_useconds
. - Apart from hovering your mouse over variables in the code, you can add Watch Expressions to inspect the value of any expression. Click View → Expressions. In the Expressions view, click Add a new expression, and add
led0_on_off_useconds
. You can watch any arbitrary expression; click Add a new expression and also add500000/led0_on_off_useconds
, which is the blinking frequency of LED0. Finally, click Continuous Refresh to automatically update these values even during program execution.
- Place your mouse over an instance of the
Note that there is a blue arrow next to the line of code where the breakpoint has suspended program execution. By clicking Run → Step Into or Run → Step Over (also available in the top toolbar), the target will step, or execute one line of code at a time, indicated by the blue arrow. Step until the value of
led0_on_off_useconds
has been modified, and note that this change is reflected in the Expressions view. Click Run → Resume to resume program execution.- Step into steps to the next line of code, including stepping into a new function call.
- Step over steps to the next line of code in the current function, but will not step into a new function call. It will remain in the current function until it ends or returns.
- Step return steps out of the current function before it reaches its end, and suspends execution on the next statement of the calling function.
After you are finished with this part of the lab, in the Breakpoints view, remove the hardware breakpoint. You can also remove it by double-clicking the margin next to the line number in empty.c, where the breakpoint currently exists.
Watchpoints
A watchpoint is a type of breakpoint that monitors activity on a memory address, for example where a variable's value is stored.
If your SimpleLink LaunchPad is currently running, ensure you are in the CCS Debug perspective and Suspend it. Otherwise, click on Run → Debug to flash the program to the target and suspend it.
In the Breakpoints view, click New (down arrow) → Hardware Watchpoint, set Location to
led0_on_off_useconds
and Memory to Write, and click OK. This installs a watchpoint which will suspend program execution on the target whenever the value ofled0_on_off_useconds
is modified (whenever it is written to).Run → Resume the program, and press the buttons on the board to test the watchpoint. As expected, whenever either button is pressed, a callback function is called that writes to
led0_on_off_useconds
, and the watchpoint suspends program execution.In the Breakpoints view, right-click on the existing hardware watchpoint and click Breakpoint Properties.... In the Breakpoint Properties window that opens, specific configurations can be made to the watchpoint. Expand the Hardware Configuration > Type property, and then set With Data to Yes, set Data Value to 15625, and click Apply and Close. This configures the watchpoint to only trigger (suspend program execution) when the value 15625 is written to
led0_on_off_useconds
. Resume program execution and verify that the program only suspends on button presses that set the LED blinking frequency to 32 Hz.After you are finished with this part of the lab, in the Breakpoints view, remove the hardware watchpoint.
Profile Clock
The profile clock can be used to count clock cycles, for example between two points in the program code.
If your SimpleLink LaunchPad is currently running, ensure you are in the CCS Debug perspective and Suspend it. Otherwise, click on Run → Debug to flash the program to the target and suspend it.
Click on Run → Clock → Enable in the menu bar. A Profile Clock icon should appear near the bottom-right of the Code Composer Studio window.
Double-click on the margin next to the line number, at the opening and closing braces of the definition of the gpioButtonFxn1() function. This creates two breakpoints, as can be seen in the Breakpoints view.
Click on Run → Resume to resume program execution on the LaunchPad.
- Press Button0 on the LaunchPad a few times. Note that this does not suspend program execution, because the breakpoints are in the gpioButtonFxn1() function, which is installed as a callback for Button1.
- Press Button1 on the LaunchPad. This triggers the first breakpoint and suspends program execution. Note that the Profile Clock at the bottom-right of Code Composer Studio is displaying a very large number. This is the number of clock cycles that have passed on the target since the program began execution. Double-click on the Profile Clock to reset this count to zero.
- Click on Run → Resume. The program will resume execution until the second breakpoint, at which point the program will suspend again. The Profile Clock should show a clock cycle count of about 100 or 200, depending on your specific LaunchPad. This is the number of clock cycles that the target takes to run the program between the two breakpoints.
After you are finished with this part of the lab, in the Breakpoints view, remove the breakpoints.
Disassembly View
If your SimpleLink LaunchPad is currently running, ensure you are in the CCS Debug perspective and Suspend it. Otherwise, click on Run → Debug to flash the program to the target and suspend it.
Click on View → Disassembly to open the Disassembly view. By default it will show the disassembly of the current location in the code. The location of the Program Counter is indicated with a small blue arrow.
Note:
You can enter in an address or symbol in the location box at the top-left of the Disassembly View to change the address that the view starts at. For example, you can enter 0x2600 or main.
Click Show Source in the Disassembly view to toggle interleaving of source code with the assembly code.
Other Views
Several other views are available under the View menu. Experiment with the various views.
Registers View
The Registers view is used to display and edit the values of core and memory mapped (peripheral) registers. More information can be found here.
Modules View
The Modules view enables browsing of loaded debug symbols. This can be especially useful in project-less debug sessions as it provides file and function listings. More information can be found here.
Loading Symbols for Flashed Program
If a program is already flashed to the target and you wish to just debug the existing code in flash without reloading the code every time, you can configure CCS to debug the program by only loading the symbols.
If you currently have a debug session active, click on Run → Terminate to terminate it. This will also enter the CCS Edit perspective.
Click on Run → Debug Configurations.... Debug configuration contains information about various debug settings. This information is created when a debug session is first launched for a project or target configuration and is cached for future use.
Select the empty project in the left pane, and then the Program tab in the right pane. Under Loading Options select Load symbols only. Click Apply and then Debug.
The debugger will start up, connect to the target, and load only the symbols for the program (no code is loaded/flashed on the target).
Note that the Program Counter is set to the entry point of the code, and not at the start of the main() function. To run the target until the start of main() and then suspend it, click on Run → Go Main. An alternate way to suspend program execution at main() is Run → Restart.
Click on Run → Resume for the target to run the program as normal. You can now debug as desired.
After you are finished with this part of the lab, click on Run → Terminate to terminate the debug session. You may also wish to re-open Debug Configurations in order to change the Loading options back to Load program.
Summary
Lab 1 covered using Code Composer Studio to import an example TI-RTOS project, modify it, and flash it to a target to run the program. Lab 2 provided information on the basics of using debug tools in Code Composer Studio.