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 v8 or greater.
- The latest version of the SimpleLink SDK for your LaunchPad. This will be installed as part of Lab 1.
Hardware
- Any SimpleLink LaunchPad that has SimpleLink SDK support, including:
- CC1310 LaunchPad (LAUNCHXL-CC1310)
- CC1350 LaunchPad (LAUNCHXL-CC1350)
- CC1312R LaunchPad (LAUNCHXL-CC1312R1)
- CC1352R LaunchPad (LAUNCHXL-CC1352R1)
- MSP432P401R LaunchPad (MSP-EXP432P401R)
- MSP432P4111 LaunchPad (MSP-EXP432P4111)
- MSP432E401Y LaunchPad (MSP-EXP432E401Y)
- CC26X2R LaunchPad (LAUNCHXL-CC26X2R1)
- CC2640R2 LaunchPad (LAUNCHXL-CC2640R2)
- CC3220S LaunchPad (CC3220S-LAUNCHXL)
- CC3220SF LaunchPad (CC3220SF-LAUNCHXL)
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.
You can use Resource Explorer to browse through documentation, libraries, and software examples.
From the home page of Resource Explorer, scroll down to the Working Offline section, and download and install the latest SimpleLink SDK that corresponds to your LaunchPad. For example, if you are using the CC1310 LaunchPad, you would need to download and install the SimpleLink CC13X0 SDK. You may also be prompted to download and install SimpleLink Academy; this is optional.
Expand the Software folder in the tree view on the left, and verify that SimpleLink (YourDeviceFamily) SDK -v:(X.X.X.X) is present, with a green down-arrow on the icon. The green down-arrow indicates that the most recent version of this software package is downloaded and installed locally.
Note: to return to the home page from another view in Resource Explorer, click on the Home button near the top-right.
Note: If the optional step of downloading and installing SimpleLink Academy was skipped, then the down-arrow for it will be grey.
From the “Select a Device or Board” box near the top-left of the Resource Explorer view, search for and select your SimpleLink LaunchPad.
This will filter the tree view to only display results matching your LaunchPad.
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 to IDE button at the top-right.
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.
Note: When importing the project using CCSv8.3.0, CCS may give an error stating that the project requires XDCtools v3.50.999 or later - even if the user has version v3.51 installed. A workaround is to install the version of XDCtools originally used with the SDK version being used (ex: XDCtools v3.50.08.24 with SimpleLink CC2640R2 SDK v2.30.00.28) using Resource Explorer in CCS. This issue has been fixed in CCSv9.0.
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 your Project Explorer: the empty project as well as 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 open and read through include Board.html, Board.h, empty.c, and main_tirtos.c.
- Board.html: Provides an overview of your LaunchPad hardware. Location of GPIO Buttons and LEDs on the board. Jumper settings. Board resources and peripherals.
- Board.h: Header file containing define macros that enable the use of generic references such as Board_GPIO_LED1 for 100% code portability across SimpleLink devices.
- 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.
From the top menubar, select Run → Debug. This will prompt to save source files, build the project, start the debugger, switch to 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.
- There are icons near the top-right of the toolbar which allow you to go between the CCS Debug and the CCS Edit perspectives.
- When running in debug mode, your LaunchPad is at first suspended. Click on Resume near the top left on the toolbar, or under the menubar at Run → Resume, for your LaunchPad to run the program.
- 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 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 by inspecting your Board.html or Board.h files. For example, in the Board.h file for the CC3220S/CC3220SF LaunchPad it can be seen that Board_GPIO_LED0, Board_GPIO_LED1, and Board_GPIO_LED2 all refer to the same LED.
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, such 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
./* Board_GPIO_LED0 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(Board_GPIO_LED0); }
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(Board_GPIO_LED0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW); GPIO_setConfig(Board_GPIO_LED1, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW); /* Initialize LED states to ON */ GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_ON); GPIO_write(Board_GPIO_LED1, Board_GPIO_LED_ON);
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 of led0_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. Note: these function definitions need to be placed directly above the definition of mainThread().
/* * ======== gpioButtonFxn0 ======== * Callback function for the GPIO interrupt on Board_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(Board_GPIO_LED1); } /* * ======== gpioButtonFxn1 ======== * Callback function for the GPIO interrupt on Board_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(Board_GPIO_LED1); }
Finally, some code needs to be added to mainThread() between the LED configuring/initialization and the main loop, to configure the buttons as interrupts, install the callbacks, and enable interrupts.
/* Configure the board Pushbuttons as interrupts */ GPIO_setConfig(Board_GPIO_BUTTON0, GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_FALLING); GPIO_setConfig(Board_GPIO_BUTTON1, GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_FALLING); /* Install Button callbacks */ GPIO_setCallback(Board_GPIO_BUTTON0, gpioButtonFxn0); GPIO_setCallback(Board_GPIO_BUTTON1, gpioButtonFxn1); /* Enable interrupts */ GPIO_enableInt(Board_GPIO_BUTTON0); GPIO_enableInt(Board_GPIO_BUTTON1);
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.
That's it!
/*
* 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 <unistd.h>
#include <stdint.h>
#include <stddef.h>
/* Driver Header files */
#include <ti/drivers/GPIO.h>
// #include <ti/drivers/I2C.h>
// #include <ti/drivers/SDSPI.h>
// #include <ti/drivers/SPI.h>
// #include <ti/drivers/UART.h>
// #include <ti/drivers/Watchdog.h>
/* Board Header file */
#include "Board.h"
/* Board_GPIO_LED0 on and off time in microseconds */
uint32_t led0_on_off_useconds = 500000;
/*
* ======== gpioButtonFxn0 ========
* Callback function for the GPIO interrupt on Board_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(Board_GPIO_LED1);
}
/*
* ======== gpioButtonFxn1 ========
* Callback function for the GPIO interrupt on Board_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(Board_GPIO_LED1);
}
/*
* ======== mainThread ========
*/
void *mainThread(void *arg0)
{
/* Call driver init functions */
GPIO_init();
// I2C_init();
// SDSPI_init();
// SPI_init();
// UART_init();
// Watchdog_init();
/* Configure the LED 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);
/* Initialize LED states to ON */
GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_ON);
GPIO_write(Board_GPIO_LED1, Board_GPIO_LED_ON);
/* Configure the board Pushbuttons as interrupts */
GPIO_setConfig(Board_GPIO_BUTTON0, GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_FALLING);
GPIO_setConfig(Board_GPIO_BUTTON1, GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_FALLING);
/* Install Button callbacks */
GPIO_setCallback(Board_GPIO_BUTTON0, gpioButtonFxn0);
GPIO_setCallback(Board_GPIO_BUTTON1, gpioButtonFxn1);
/* Enable interrupts */
GPIO_enableInt(Board_GPIO_BUTTON0);
GPIO_enableInt(Board_GPIO_BUTTON1);
while (1) {
usleep(led0_on_off_useconds);
GPIO_toggle(Board_GPIO_LED0);
}
}
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.
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 of led0_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.
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 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. 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.
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.
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.
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.