Difference between revisions of "Hardware And Software Setup"

From EdWiki

m (Hardware And Software Setup)
m (Hardware And Software Setup)
Line 13: Line 13:
<ul class="tabs" data-tab>
<ul class="tabs" data-tab>
           <li class="tab-title active">Introduction</li>
           <li class="tab-title active">Introduction</li>
  <li class="tab-title">Requirements</li>
  <li class="tab-title">CCS (Win)</li>
  <li class="tab-title">CCS (Linux)</li>
  <li class="tab-title">Tivaware</li>
          <li class="tab-title">GNU ARM</li>
<div class="tabs-content">
<div class="tabs-content">
  <div class="content active" id="ToolSubTabIntro">
  <div class="content active" id="ToolSubTabIntro">
  <div class="content" id="ToolSubTab1">
{{EmSys:Using GCC with Tiva TM4C123G LaunchPad in CCSv6}}
  <div class="content" id="ToolSubTab2">
{{EmSys:Install Code Composer Studio v6}}
  <div class="content" id="ToolSubTab3">
{{EmSys:Install Code Composer Studio v6 Ubuntu}}
  <div class="content" id="ToolSubTab4">
{{EmSys:Install TivaWare for C Series}}
  <div class="content" id="ToolSubTab6">
{{EmSys:Installing Toolchain}}
Line 48: Line 28:
   <div class="content" id="panelCCSOverview">
   <div class="content" id="panelCCSOverview">
    {{EmSys:TM4C123G LaunchPad - CCS GNU GCC Direct Register Model}}
   <div class="content" id="panelVSCodeSetup">
   <div class="content" id="panelVSCodeSetup">

Revision as of 13:22, 5 April 2022

Hardware And Software Setup

What is Toolchain?

  • A toolchain is a collection of programming tools.
  • It consists of a compiler, linker, assembler, and a debugger.
  • The GNU toolchain is a programming tools produced by the GNU Project.


The toolchain used for embedded development is a cross toolchain (cross compiler). In other words, when the host and target architectures are different, the toolchain is called a cross compiler (e.g. if we develop a code on a Linux machine based on the x64 architecture, but we're compiling for an ARM target, then we need Linux-based ARM-targeting cross compiler).

Host and Target

When talking about toolchains, one must distinguish three different machines:

  • the build machine, on which the toolchain is built
  • the host machine, on which the toolchain is executed
  • the target machine, for which the toolchain generates code

Toolchain - Name convention

Toolchain name usually contains the so-called target triple, which is in the form of arch[-system][-abi] or in a longer form arch[-vendor][-system][-abi], e.g. arm-linux-gnueabihf. Typically, local toolchains have symbolic links that omit triple in binary name: we use gcc instead of the full name x86_64-linux-gnu-gcc.

  • arch - architecture
    arm, mips, x86, i686, etc.
  • vendor - tool chain supplier
  • os - operating system
    linux, none (bare metal)
  • abi - application binary interface
    eabi, gnueabi, gnueabihf



This toolchain targets the ARM architecture, has no vendor, does not target an operating system (i.e. targets a "bare metal" system), and complies with the ARM eabi. (Note) arm-elf and arm-none-eabi just use two versions of the ARM abi. The eabi toolchain uses a newer revision, but could also be called arm-elf-eabi, as it generates elf too.


This toolchain targets the Intel i686 architecture, the vendor is Apple, and the target OS is Darwin version 10.


The toolchain that can be installed in Debian-based systems using a package manager like apt (the package is called gcc-arm-linux-gnueabi). This toolchain targets the ARM architecture, has no vendor, creates binaries that run on the Linux operating system, and uses the GNU EABI. In other words, it is used to target ARM-based Linux systems.


This is actually binary for gcc which produces objects for ARM architecture to be run on Linux with default configuration (abi) provided by toolchain.


32-bit GNU/linux


Android ARM compiler


x86_64 architecture means AMD64, w64 is actually mingw-w64 used as a "vendor" here, mingw32 is the same as win32 API for gcc's perspective.


32-bit, "pc" is a generic name, msys binary

Tiva C Series EK-TM4C123GXL LaunchPad Boad

Tiva C Series EK-TM4C123GXL Evaluation Kit


The TM4C123G LaunchPad Evaluation Kit is a low-cost evaluation platform for ARM Cortex-M4F based microcontrollers from Texas Instruments. The design of the TM4C123G LaunchPad highlights the TM4C123GH6PM microcontroller with a USB 2.0 device interface and hibernation module.

The EK-TM4C123GXL also features programmable user buttons and an RGB LED for custom applications. The stackable headers of the TM4C123G LaunchPad BoosterPack™ XL Interface make it easy and simple to expand the functionality of the TM4C123G LaunchPad when interfacing to other peripherals with Texas Instruments MCU BoosterPack.


The ARM Cortex-M4F Based MCU TM4C123G LaunchPad Evaluation Kit (EK-TM4C123GXL) offers these features:

  • High Performance TM4C123GH6PM MCU:
    1. 80MHz 32-bit ARM Cortex-M4F CPU
    2. 256KB Flash, 32KB SRAM, 2KB EEPROM
    3. Two Controller Area Network (CAN) modules
    4. Dual 12-bit 2MSPS ADCs, motion control PWMs
    5. 8 UART, 6 I2C, 4 SPI
  • On-board In-Circuit Debug Interface (ICDI)
  • USB Micro-B plug to USB-A plug cable
  • Preloaded RGB quick-start application
  • Tiva C Series TM4C123G LaunchPad -- Readme First

Tiva C Series TM4C123G LaunchPad Evaluation Board


Switch and LED interface

Switch and LED interfaces
  • PC0-PC3 is used for JTAG connections to the debugger on the LaunchPad.
  • The LaunchPad connects PB6 to PD0, and PB7 to PD1.
  • If you wish to use both PB6 and PD0 you will need to remove the R9 resistor.
  • Similarly, to use both PB7 and PD1 remove the R10 resistor

GPIO Pin Pin Function USB Device
PA0 U0RX Virtual COM P0rt (RxD)
PA1 U0TX Virtual COM Port (TxD)
Table: EK-TM4c123GXl LaunchPad - Switches, LEDs and Virtual COM Port

Interface connectors

Ek tm123gxl launchpad headers.png

Pin J1 J3 J4 J2
1 3.3V 5V PF2 GND
3 PB0 PD0 PB3 PE0
4 PB1 PD1 PC4 PF0
6 PE5 PD3 PC6 PB7
7 PB4 PE1 PC7 PB6
8 PA5 PE2 PD6 PA4
9 PA6 PE3 PD7 PA3
10 PA7 PF1 PF4 PA2


  1. Tiva C Series TM4C123G LaunchPad -- Readme First
  2. Tiva C Series TM4C123G LaunchPad Evaluation Kit -- User's Manual
  3. TM4C123GH6PM Microcontroller -- Data Sheet

Hardware Setup

Kit Contents

You should find the following in your box:

Connecting the board

Tm4c123gxl board setup.png
Tiva™ C Series TM4C123G LaunchPad

The TM4C123GXL LaunchPad Board ICDI USB port (marked DEBUG and shown in the picture below) is a composite USB port and consists of three connections:

  • Stellaris ICDI JTAG/SWD Interface - debugger connection
  • Stellaris ICDI DFU Device - firmware update connection
  • Stellaris Virtual Serial Port - a serial data connection

Using the included USB cable,

  • connect the USB emulation connector on your evaluation board (marked DEBUG) to a free USB port on your PC.
    A PC’s USB port is capable of sourcing up to 500 mA for each attached device, which is sufficient for the evaluation board.
    If connecting the board through a USB hub, it must be a powered hub.
  • The drivers should install automatically.


Make sure that the power switch in the upper left hand corner of your board is in the right-hand DEBUG position as shown:


  • Switch the POWER SELECT switch to the right for DEBUG mode.
  • Connect the USB-A cable plug to an available port on the PC and the Micro-B plug to the Debug USB port on the Board.
  • Verify that the POWER LED D4 on the board is lit.

Developing Cortex M3/M4 Applications Using Visual Studio Code

Visual Studio Code (VSCode) can be used to edit the source code, build the application and finally debug it.

Required Software Components

In contrast to fully integrated IDEs, setting up Visual Studio Code requires us to setup a number of software packages, which finally work together to build the complete development environment. The software packages can be split into three groups:

  1. VSCode and plugins
  2. ARM Build Tools (compiler etc.)
  3. Debug tools
  • The packages can be installed in any order
  • VSCode must be installed before VSCode plugins can be installed.

1. Visual Studio Code and Plugins

Visual Studio Code

We can look at VSCode as an intelligent text editor which provides an extensive framework to add functionality through plugins. VSCode includes a project explorer, which can show the contents of one or multiple folders as a workspace. There is more information on required plugins further down in this list.

Required Plugins


This plugin offers many features to simplify editing of C/C++ code, including Syntax highlighting, Intellisense (finding definitions of symbols), auto-completion of keywords and identifier names, and marking syntax errors while typing. For more details, please refer the following documents:


This plugin adds support for debugging ARM Cortex-M devices executable through a GDB Server.


CMake Language Support for Visual Studio Code.


Syntax highlighting for ARM assembly code

Linker Script

Syntax highlighting for linker scripts

Plugin Name
Plugin Description
Code Name
Vscode plugin c cpp.png C/C++ C/C++ support for Visual Studio Code to enable cross-platform
C and C++ development on Windows, Linux, and macOS.
Required ms-vscode.cpptools
Vscode plugin cortex-debug.png Cortex-Debug Cortex-Debug is an extension to add debugging capabilities for
ARM Cortex-M devices to Visual Studio Code.
Required marus25.cortex-debug
Vscode plugin CMake Syntax Highlighting.png CMake Syntax Highlighting CMake Language Support for Visual Studio Code Optional twxs.cmake
Vscode plugin ARM Assembly highlighting.png ARM Assembly highlighting ARM Assembly highlighting Optional dan-c-underwood.arm
Vscode plugin Linker Script.png GNU linker script Language support for GNU linker script Optional Zixuan Wang

2. ARM Build Tools

GNU ARM Embedded Toolchain

GNU ARM Embedded Toolchain is the C/C++ compiler and linker along with additional tools. It is used to turn your source code into a binary executable.


CMake is a tool which turns compiler-independent project definitions into compiler-specific project definitions. CMake converts these into makefiles that can be processed by the GNU ARM Embedded Toolchain.

3. Debugger Tools


OpenOCD is an open-source debugger, supporting a wide variety of JTAG hardware interfaces. For customers using a JTAG adapter other than the J-Link, this probably is the matching software. The package contains a GDB server, which connects to VSCode on one side, and to the J-Link JTAG/SWD hardware on the other side.

Chocolatey (The Package Manager For Windows)

The Windows versions of required software will be installed using Chocolately

  • Launch Power shell as an administrator, then run the following command:

> Get-ExecutionPolicy

If it returns Restricted, then run the following command:

> Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString(''))

If you don't see any errors, you are ready to use Chocolatey! Type choco or choco -? now, or see following documents for more info:

Note: Always run Chocolatey (choco) under Windows Power Shell (as an administrator)

4. Install VSCode



> choco install vscode

5. Installing Visual Studio Code Plugins

The easiest way is to install them from the command prompt inside the IDE:

code --install-extension ms-vscode.cpptools
code --install-extension marus25.cortex-debug
code --install-extension twxs.cmake
code --install-extension dan-c-underwood.arm
code --install-extension zixuanwang.linkerscript

Or we can use in the IDE the menu View > Extensions.

  1. Open VSCode
  2. Select View → Extensions
    This will show the Extension sidebar
  3. In the search box above the Extension sidebar, type the Code name from the above table (without the angle brackets) or another reasonable search term
  4. Click on the little green Install button which appears next to the found plugin.

Below is our installed extensions (menu File > Preferences > Extensions):

Vscode armdev plugins.png

6. Install Build Tools


GNU Arm Embedded Toolchain

  • Please follow this link to install GNU ARM Embedded Toolchain
  • OR, we can install using apt
$ sudo apt update
$ sudo apt install gcc-arm-none-eabi binutils-arm-none-eabi

Make and CMake

$ sudo apt update
$ sudo apt install make cmake


GNU Arm Embedded Toolchain

> choco install gcc-arm-embedded


> choco install make


> choco install cmake

7. Install Debugging Tools



$ sudo apt update
$ sudo apt install openocd


> choco install openocd

Please refer following documents to know more about how to run OpenOCD:

Sample Project

You can download sample project from here

VSCode - Workspace and Project(s)

Similar to other IDEs, Visual Studio Code is using the concept of a ‘workspace’. In simple words, a workspace is a collection of Folders open in the IDE. See workspaces for more details. In the most simple case a workspace just contains a folder which is the folder for the project. So all what we need is to add a folder.

Vscode add folder.png

Use menu File > Add Folder to Workspace …

Vscode menu add folder workspace.png

Browse to an existing new (empty) folder or simply create one from the dialog:

Vscode add blinky folder.png

Add a new file: main.c

Vscode add new file.png

Implement the main function, then save it (CTRL+S)

Sample Project

You can download sample project from here


VSCode – Include Paths

This article will describe how to set up the Include Paths for C/C++ in Visual Studio Code to support ARM development. Visual Studio Code with the C/C++ plugin has many useful features while we are writing our code:

  • syntax highlighting,
  • error checking while we type, and
  • automatic code completion, where it guesses while we type.

This can help us reduce errors and write faster. However, if the plugin is not correctly set up, these features will not work correctly or at all.

In order for Visual Studio Code and the C/C++ language plugin to understand our code, it needs to be able to find all of the header files referenced in our program. A header can further reference other headers, so they may be needed even if you didn’t explicitly call them yourself.

In main.c, VSCode is complaining that it cannot open tm4c123gh6pm.h' file'. The message is a little obscure, but it’s basically saying that it will interpret the file based on keywords and syntax, but can’t tell if things like function or variable names are correct.

Vscode include error.png

So, how do we fix this? If the cursor is on the error, you will see the lightbulb to the left. Click that, and then Update “includePath” setting. VSCode will create and open a file called “c_cpp_properties.json”, in our project under a “.vscode” folder. By default this will contain configurations for Mac, Linux, and Win32. These include default includePaths suitable for desktop applications, but are not correct for ARM.

There are two sections with paths. The first, “includePath”, is where VSCode will look for headers for the purpose of checking our code. Unlike GCC, this is not recursive; we need to explicitly list each folder that contains headers that are referenced, directly or indirectly.

The second section with just “path” is used by IntelliSense to suggest things for us.

This is the initial c_cpp_properties.json file:

    "configurations": [
            "name": "WIN32",
            "includePath": [
            "defines": [
            "compilerPath": "C:\\ProgramData\\chocolatey\\bin\\arm-none-eabi-gcc",
            "cStandard": "c99",
            "cppStandard": "gnu++17",
            "intelliSenseMode": "gcc-arm",
            "configurationProvider": "ms-vscode.cmake-tools"
            "name": "LINUX",
            "includePath": [
            "defines": [
            "compilerPath": "/opt/toolchains/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-gcc",
            "cStandard": "c99",
            "cppStandard": "gnu++17",
            "intelliSenseMode": "gcc-arm",
            "configurationProvider": "ms-vscode.cmake-tools"
    "version": 4
  • name: arbitrary name for the configuration
  • includePath: list here all locations where IntelliSense shall search for header files. It automatically will use the ones located in the toolchain (compiler) installation. The ‘**’ notation means it will search recursively that folder
  • defines: list all the extra defines which shall be considered.
  • forcedInclude: if using the -include compiler option, make sure you list that file here
  • compilerPath: path to the compiler executable.
  • cStandard and cppStandard: the C and C++ standard to be used
  • intelliSenseMode: mode to be used. ‘gcc-arm’ is considered legacy, but not sure what to use otherwise for ARM?

But where is stdint.h? GCC has built-in include paths that are used even if compiler flags don’t specify them. GCC will list the defaults by running “arm-none-eabi-gcc -xc -E -v -“, and add those paths as well. Be sure to list all sub folders with headers for the includePath section.


VSCode – Defines

It is common to pass defines to the compiler using flags at compile time.


Setting these for VSCode is simple: just add them to the “defines” section of c_cpp_properties.json, without the -D flag prefix:

    "defines": [

If the include paths and defines are properly set up in Visual Studio Code, the C/C++ plugin should be able to properly parse our code, identify syntax errors, and will provide Intellisense code completion to improve the speed and accuracy of writing!

CMake: Configure

We are going to use CMake with Make to build the project. CMake needs some information where to find the tools. How does CMake know which compiler to use? It checks the CC and CXX environment variables. They define what is the default compiler in the system. If we manually set CC or CXX to different values, then CMake will use these new settings as default compilers. After successful detection, CMake stores info about the current toolchain in the following variables:


They contain paths to the C and C++ compilers respectively.

When we cross-compile to another platform, we have to specify completely different toolchain both in terms of name and location of the binaries. This can be done in two ways:

  1. pass values for the toolchain variables from the command line,
  2. specify toolchain file.

First option is very explicit thus easy to understand, but big number of arguments makes it harder to use CMake in terminal:

cmake .. -DCMAKE_C_COMPILER=<path_to_c_compiler> -DCMAKE_CXX_COMPILER=<path_to_cxx_compiler> -DCMAKE_AR=<path_to_ar> -DCMAKE_LINKER=<path_to_linker> etc...

Second option is more elegant and is the preferred way of choosing the toolchain. All we need to do is to put toolchain variables into a separate file (e.g. <toolchain_name>.cmake) and set CMAKE_TOOLCHAIN_FILE variable to the path of that file. This can be done both in the command line or in CMakeLists.txt before project() command:

cmake .. -DCMAKE_TOOLCHAIN_FILE=<path_to_toolchain_file>


cmake_minimum_required(VERSION 3.15)
set(CMAKE_TOOLCHAIN_FILE <path_to_toolchain_file>)
project(<project_name> LANGUAGES C CXX)

Note: It is crucial to set the value of CMAKE_TOOLCHAIN_FILE before project() is invoked, because project() triggers toolchain detection and verification.

A simple and easy way is to to add the following file to the project. I have named it arm-toolchain.cmake and placed it in the project root folder.

CMake: Toolchain File

  1. # File: arm-toolchain.cmake
  2. # Toolchain file for arm-none-eabi-gcc
  4. set(CMAKE_SYSTEM_NAME Generic)
  8. # Set system depended extensions
  9. if(WIN32)
  10.   set(ARM_TOOLCHAIN_EXT ".exe" )
  11. else()
  12.   set(ARM_TOOLCHAIN_EXT "" )
  13. endif()
  15. if(WIN32)
  16.     set(ARM_TOOLCHAIN_DIR "C:/ProgramData/chocolatey/bin")
  17. else()
  18.     set(ARM_TOOLCHAIN_DIR "/opt/toolchains/gcc-arm-none-eabi-10.3-2021.10/bin")
  19. endif()
  23. set(TOOLCHAIN_PREFIX ${ARM_TOOLCHAIN_DIR}/arm-none-eabi-)
  31. set(CMAKE_OBJCOPY ${TOOLCHAIN_PREFIX}objcopy CACHE INTERNAL "objcopy tool")

ARM_TOOLCHAIN_DIR specifies the compiler to be used. Additionally it defines extra tools as size and objcopy.

CMake: CMakeLists.txt

To tell CMake what to do, create a file named CMakeList.txt in the project root.

  1. # File: CMakeList.txt
  2. # CMake file for tm4c123gxl
  4. cmake_minimum_required(VERSION 3.15.3)
  6. # Optional: print out extra messages to see what is going on. 
  7. # Comment it to have less verbose messages
  10. # Path to toolchain file. This one has to be before 'project()' 
  11. set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/arm-toolchain.cmake)
  13. # Setup project, output and linker file
  14. project(blinky VERSION 0.1)
  16. set(LINKER_FILE ${CMAKE_SOURCE_DIR}/ld/tm4c123gh6pm.ld)
  18. enable_language(C ASM)
  19. set(CMAKE_C_STANDARD 99)
  23. # Optional: issue a message to be sure it uses the correct toolchain file.
  26. # List of source files
  27. set(SRC_FILES
  28.         src/main.c
  29.         src/tm4c_startup.c
  30.         inc/tm4c_startup.h
  31.     )
  33. # Build the executable based on the source files
  34. add_executable(${EXECUTABLE} ${SRC_FILES})
  36. # List of compiler defines, prefix with -D compiler option
  37. target_compile_definitions(${EXECUTABLE} PRIVATE -DPART_TM4C123GH6PM)
  39. # List of include directories
  40. target_include_directories(${EXECUTABLE} PRIVATE
  41.         src 
  42.         inc
  43. if(WIN32)        
  44.         "E:/ti/TivaWare_C_Series-"
  45. else()
  46.         "/home/jshankar/ti/TivaWare_C_Series-"
  47. endif()
  48.         )
  50. # Compiler options
  51. target_compile_options(${EXECUTABLE} PRIVATE
  52.         -mcpu=cortex-m4
  53.         -mthumb
  54.         -mfpu=fpv4-sp-d16
  55.         -mfloat-abi=hard
  56.         -fdata-sections
  57.         -ffunction-sections
  58.         -Wall
  59.         -O0
  60.         -g3
  61.         )
  63. # Linker options
  64. target_link_options(${EXECUTABLE} PRIVATE
  65.         -T${LINKER_FILE}
  66.         -mcpu=cortex-m4
  67.         -mthumb
  68.         -mfpu=fpv4-sp-d16
  69.         -mfloat-abi=hard
  70.         -specs=nano.specs
  71.         -specs=nosys.specs
  72.         -lc
  73.         -lm
  74.         -Wl,-Map=${PROJECT_NAME}.map,--cref
  75.         -Wl,--gc-sections
  76.         -Xlinker -print-memory-usage -Xlinker
  77.         )
  79. # Optional: Print executable size as part of the post build process
  80. add_custom_command(TARGET ${EXECUTABLE}
  81.         POST_BUILD
  84. # Optional: Create hex, bin and S-Record files after the build
  85. add_custom_command(TARGET ${EXECUTABLE}
  86.         POST_BUILD
  87.         COMMAND ${CMAKE_OBJCOPY} -O srec --srec-len=64 ${EXECUTABLE} ${PROJECT_NAME}.s19
  89.         COMMAND ${CMAKE_OBJCOPY} -O binary ${EXECUTABLE} ${PROJECT_NAME}.bin)

The most important sections/entries are:

  • project(<your project name here>): Give your project a name
  • set(LINKER_FILE <your linker file here>): specify the linker file name
  • set(SRC_FILES <your source files here>): list of source files to compile
  • target_compile_definitions(${EXECUTABLE} PRIVATE <compiler defines here>): list of compiler #defines
  • target_include_directories(${EXECUTABLE} PRIVATE <list of include dir>): list of include directories
  • target_compile_options(${EXECUTABLE} PRIVATE <compiler options>): list of compiler options
  • target_link_options(${EXECUTABLE} PRIVATE <linker options>): list of linker options

This completes setting up the configuration for the build.


Next we are going to build it. Actually we need to ‘configure’ it first. With CMake it is a two stage process: running CMake to create (or configure) the make files and then we use ‘make’ to build it.

  • Close VSCode and Restart again
  • Open Command Palette ... (CTL+SHIFT+P)
  • Select CMake:Delete cache and Reconfigure
Vscode cmake delete-cache-reconfigure.png

CMake: Config Output

[variant] Loaded new set of variants
[kit] Successfully loaded 3 kits from /home/jshankar/.local/share/CMakeTools/cmake-tools-kits.json
[proc] Executing command: /opt/toolchains/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-gcc -v
[cmakefileapi-driver] This version of CMake does not support the "toolchains" object kind. Compiler paths will be determined by reading CMakeCache.txt.
[main] Configuring folder: blinky 
[proc] Executing command: /usr/bin/cmake --no-warn-unused-cli -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_C_COMPILER:FILEPATH=/opt/toolchains/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-gcc -DCMAKE_CXX_COMPILER:FILEPATH=/opt/toolchains/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-g++ -S/home/jshankar/codeprojects/tm4c123gxl/blinky -B/home/jshankar/codeprojects/tm4c123gxl/blinky/build -G "Unix Makefiles"
[cmake] Not searching for unused variables given on the command line.
[cmake] -- CMAKE_TOOLCHAIN_FILE is: /home/jshankar/codeprojects/tm4c123gxl/blinky/arm-toolchain.cmake
[cmake] -- Configuring done
[cmake] -- Generating done
[cmake] -- Build files have been written to: /home/jshankar/codeprojects/tm4c123gxl/blinky/build

Build it with make

Open a terminal in the build output folder:

cd build 

Instead of calling ‘make’ inside the build folder, following can be used which does the one or the other:

cmake --build .
  • The advantage of doing it this way is that if there has been a change in the CMakeList.txt it will run a configuration step first too.
  • If doing changes in the structure: make sure you do a configure to make sure things are correctly set up.


A ‘clean’ is to delete all the files inside the build folder. But CMake has a ‘clean’ command too:

cd build
cmake --build . --target clean

To do a ‘clean followed by a build’ use the following:

cd build

cmake --build . --clean-first

Make: Build Output

/usr/bin/cmake -S/home/jshankar/codeprojects/tm4c123gxl/blinky -B/home/jshankar/codeprojects/tm4c123gxl/blinky/build --check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake -E cmake_progress_start /home/jshankar/codeprojects/tm4c123gxl/blinky/build/CMakeFiles /home/jshankar/codeprojects/tm4c123gxl/blinky/build/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/home/jshankar/codeprojects/tm4c123gxl/blinky/build'
make -f CMakeFiles/blinky.elf.dir/build.make CMakeFiles/blinky.elf.dir/depend
make[2]: Entering directory '/home/jshankar/codeprojects/tm4c123gxl/blinky/build'
cd /home/jshankar/codeprojects/tm4c123gxl/blinky/build && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/jshankar/codeprojects/tm4c123gxl/blinky /home/jshankar/codeprojects/tm4c123gxl/blinky /home/jshankar/codeprojects/tm4c123gxl/blinky/build /home/jshankar/codeprojects/tm4c123gxl/blinky/build /home/jshankar/codeprojects/tm4c123gxl/blinky/build/CMakeFiles/blinky.elf.dir/DependInfo.cmake --color=
make[2]: Leaving directory '/home/jshankar/codeprojects/tm4c123gxl/blinky/build'
make -f CMakeFiles/blinky.elf.dir/build.make CMakeFiles/blinky.elf.dir/build
make[2]: Entering directory '/home/jshankar/codeprojects/tm4c123gxl/blinky/build'
[ 33%] Building C object CMakeFiles/blinky.elf.dir/src/main.c.obj
/opt/toolchains/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-gcc -DPART_TM4C123GH6PM -I/home/jshankar/codeprojects/tm4c123gxl/blinky/src -I/home/jshankar/codeprojects/tm4c123gxl/blinky/inc -I/home/jshankar/codeprojects/tm4c123gxl/blinky/if -I"/home/jshankar/codeprojects/tm4c123gxl/blinky/(" -I/home/jshankar/codeprojects/tm4c123gxl/blinky/WIN32 -I"/home/jshankar/codeprojects/tm4c123gxl/blinky/)" -I/home/jshankar/codeprojects/tm4c123gxl/blinky/E:/ti/TivaWare_C_Series- -I/home/jshankar/codeprojects/tm4c123gxl/blinky/else -I/home/jshankar/ti/TivaWare_C_Series- -I/home/jshankar/codeprojects/tm4c123gxl/blinky/endif  -g   -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fdata-sections -ffunction-sections -Wall -O0 -g3 -std=c99 -o CMakeFiles/blinky.elf.dir/src/main.c.obj   -c /home/jshankar/codeprojects/tm4c123gxl/blinky/src/main.c
[ 66%] Building C object CMakeFiles/blinky.elf.dir/src/tm4c_startup.c.obj
/opt/toolchains/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-gcc -DPART_TM4C123GH6PM -I/home/jshankar/codeprojects/tm4c123gxl/blinky/src -I/home/jshankar/codeprojects/tm4c123gxl/blinky/inc -I/home/jshankar/codeprojects/tm4c123gxl/blinky/if -I"/home/jshankar/codeprojects/tm4c123gxl/blinky/(" -I/home/jshankar/codeprojects/tm4c123gxl/blinky/WIN32 -I"/home/jshankar/codeprojects/tm4c123gxl/blinky/)" -I/home/jshankar/codeprojects/tm4c123gxl/blinky/E:/ti/TivaWare_C_Series- -I/home/jshankar/codeprojects/tm4c123gxl/blinky/else -I/home/jshankar/ti/TivaWare_C_Series- -I/home/jshankar/codeprojects/tm4c123gxl/blinky/endif  -g   -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fdata-sections -ffunction-sections -Wall -O0 -g3 -std=c99 -o CMakeFiles/blinky.elf.dir/src/tm4c_startup.c.obj   -c /home/jshankar/codeprojects/tm4c123gxl/blinky/src/tm4c_startup.c
[100%] Linking C executable blinky.elf
/usr/bin/cmake -E cmake_link_script CMakeFiles/blinky.elf.dir/link.txt --verbose=1
/opt/toolchains/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-gcc -g  -T/home/jshankar/codeprojects/tm4c123gxl/blinky/ld/tm4c123gh6pm.ld -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -specs=nano.specs -specs=nosys.specs -lc -lm -Wl,,--cref -Wl,--gc-sections -Xlinker -print-memory-usage CMakeFiles/blinky.elf.dir/src/main.c.obj CMakeFiles/blinky.elf.dir/src/tm4c_startup.c.obj  -o blinky.elf 
Memory region         Used Size  Region Size  %age Used
           FLASH:         980 B       256 KB      0.37%
            SRAM:         540 B        32 KB      1.65%
/opt/toolchains/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-size blinky.elf
   text    data     bss     dec     hex filename
    980       0     540    1520     5f0 blinky.elf
/opt/toolchains/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-objcopy -O srec --srec-len=64 blinky.elf blinky.s19
/opt/toolchains/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-objcopy -O ihex blinky.elf blinky.hex
/opt/toolchains/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-objcopy -O binary blinky.elf blinky.bin
make[2]: Leaving directory '/home/jshankar/codeprojects/tm4c123gxl/blinky/build'
[100%] Built target blinky.elf
make[1]: Leaving directory '/home/jshankar/codeprojects/tm4c123gxl/blinky/build'
/usr/bin/cmake -E cmake_progress_start /home/jshankar/codeprojects/tm4c123gxl/blinky/build/CMakeFiles 0

Sample Project

You can download sample project from here


VSCode Cortex-Debug Launch Configurations

Cortex-Debug is an extension for Visual Studio Code to streamline the debug process when working with ARM Cortex-M microcontrollers. This document covers writing launch configurations (launch.json).

  • Open the VSCode user settings file settings.json: File → Preferences → Settings
  • Select User settings:
    Enter "json" in the search bar (with or without double quotes). Locate a link "Edit in settings.json" and click on it. This will open the file ~/.config/Code/User/settings.json
  • Add the following lines to the settings.json file, between the curly braces {}:

    "cortex-debug.openocdPath": "/usr/bin/openocd",
    "cortex-debug.armToolchainPath.linux": "/opt/toolchains/gcc-arm- none-eabi-10.3-2021.10/bin",
    "": "C:\\ProgramData\\chocolatey\\bin",
    "cortex-debug.gdbPath.linux": "/opt/toolchains/gcc-arm-none-eabi-10.3-2021.10/bin//arm-none-eabi-gdb",
    "": "C:\\ProgramData\\chocolatey\\bin\\arm-none-eabi-gdb.exe"

Please note: The paths on your system might be different. Make sure the path matches your actual file locations.

  • Save the file settings.json

Launch configurations

To run or debug a simple app in VS Code, we can select Run and Debug on the Debug start view or we can press F5 and VS Code will try to run the currently active file.

Creating a launch configuration file is beneficial because it allows us to configure and save debugging setup details. VSCode keeps debugging configuration information in a launch.json file located in a .vscode folder in the workspace (project root folder).

The launch.json file is used to configure the debugger in Visual Studio Code.


Here is a list of parameters in launch.json. Configure them for your specific device and environment.

  • cwd: Path of project
  • configFiles: OpenOCD configuration file(s) to load
  • device: Target Device Identifier
  • interface: Debug Interface type to use for connections (defaults to SWD) - Used for J-Link and BMP probes.
  • name: Name of configuration; appears in the launch configuration dropdown menu.
  • preLaunchTask: Task to run before debug session starts. Specify a task defined in tasks.json.
  • request: Request type of configuration. Can be “launch” or “attach”.
  • runToEntryPoint: If enabled the debugger will run until start of the main function.
  • serialNumber: J-Link specific parameter. J-Link Serial Number - only needed if multiple J-Links are connected to the computer
  • servertype: GDB Server type - supported types are jlink, openocd, pyocd, pe and stutil
  • svdFile: Path to an SVD file describing the peripherals of the microcontroller; if not supplied then one may be selected based upon the ‘device’ entered. This may be automatically loaded depending on the "device".
  • swoConfig: SWO/ITM configuration.
  • enabled: Enable SWO decoding.
  • cpuFrequency: Target CPU frequency in Hz.
  • swoFrequency: SWO frequency in Hz.
  • source: Source for SWO data. Can either be “probe” to get directly from debug probe, or a serial port device to use a serial port external to the debug probe.
  • decoders: SWO Decoder Configuration
  • label: A label for the output window.
  • port: ITM Port Number

OpenOCD Specific Configuration

  • configFiles
    OpenOCD configuration files to use when debugging. Exactly equivalent to the OpenOCD command line argument -f.
  • searchDir
    Directories to search for configuration files in. Exactly equivalent to the OpenOCD command line argument -s. If no search directories are specified, it defaults to the configured cwd.
  • openOCDPreConfigLaunchCommands
    OpenOCD commands to run prior to loading configuration files.
  • openOCDLaunchCommands
    OpenOCD commands to run in order to launch target.

OpenOCD GDB Server

We modify launch.json to configure debug features.

Below is an example of a basic launch configuration using the OpenOCD GDB server.

In this configuration the device parameter is not required - but can be supplied to allow auto-selecting an appropriate SVD file if possible.

There is one OpenOCD specific parameter that must be supplied. The configFiles property takes an arrays of strings that are used to load openocd configuration files. These can either be a files in the openocd search path (like in this example), or a full path to your own configuration file. If you are using OpenOCD supplied files you typically will have either one file from the board section, or a file from the interface section and a file from the target section.

  • Open the VSCode launch configuration file launch.json: Run → Add Configuration...
  • Copy the following code
    "version": "0.2.0",
    "configurations": [
            "name": "Debug (OpenOCD)",
            "cwd": "${workspaceRoot}",
            "executable": "${workspaceRoot}/build/blinky.elf",
            "request": "launch",
            "type": "cortex-debug",
            "servertype": "openocd",
            "interface": "swd",
            "device": "TM4C123GH6PM",
            "runToEntryPoint": "main",
            "svdFile": "${workspaceRoot}/svd/TM4C123GH6PM.svd",
            "configFiles": [
            "preLaunchCommands": [
                "set mem inaccessible-by-default off",
                "monitor reset"
            "postLaunchCommands": [
                "monitor reset init",
                "monitor sleep 200"

  • Change "executable", "svdFile", and "device" parameter as appropriate and save it
  • SVD Files: The “svdFile” entry in the launch.json file is optional, but crucial to embedded system debugging because it describes the device peripheral registers.




VSCode Cortex Debugging

Use F5 or the menu Run > Start Debugging to start a debug session:


This starts debug session. In case of troubles, check the Debug Console:

Debug Console Output

Launching GDB: /opt/toolchains/gcc-arm-none-eabi-10.3-2021.10/bin//arm-none-eabi-gdb -q --interpreter=mi2 /home/jshankar/codeprojects/tm4c123gxl/blinky/build/blinky.elf
Set "showDevDebugOutput": true in your "launch.json" to see verbose GDB transactions here. Helpful to debug issues or report problems
Reading symbols from /home/jshankar/codeprojects/tm4c123gxl/blinky/build/blinky.elf...
Launching gdb-server: /usr/bin/openocd -c "gdb_port 50000" -c "tcl_port 50001" -c "telnet_port 50002" -s /home/jshankar/codeprojects/tm4c123gxl/blinky -f /home/jshankar/.vscode/extensions/marus25.cortex-debug-1.2.0/support/openocd-helpers.tcl -f board/ek-tm4c123gxl.cfg
Please check TERMINAL tab (gdb-server) for output from /usr/bin/openocd
0x00000000 in g_pfnVectors ()
Program stopped, probably due to a reset and/or halt issued by debugger
adapter speed: RCLK - adaptive
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x00000354 msp: 0x2000021c
adapter speed: RCLK - adaptive
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x00000354 msp: 0x2000021c
adapter speed: RCLK - adaptive
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x00000354 msp: 0x2000021c
Note: automatically using hardware breakpoints for read-only addresses.

Temporary breakpoint 1, main () at /home/jshankar/codeprojects/tm4c123gxl/blinky/src/main.c:16
16	    SYSCTL_RCGC2_R |= 0x00000020;


By default there are several debug views available. With the .svd file, we have access to the peripheral register too:


Debug Commands

There are the usual debug commands (continue, stepping, restart) plus a run and debug toolbar

  • Continue / Pause F5
  • Step Over F10
  • Step Into F11
  • Step Out Shift+F11
  • Restart Ctrl+Shift+F5
  • Stop Shift+F5

Assembly Stepping

Press CTRL+SHIFT+P to invoke command palette. Then Select Cortex-Debug:View Disassembly(Functon), type the function name you want to disassemble.

  1. 0x000002ac: 80 b5           	push	{r7, lr}
  2. 0x000002ae: 00 af           	add	r7, sp, #0
  3. 0x000002b0: 0e 4b           	ldr	r3, [pc, #56]	; (0x2ec <main+64>)
  4. 0x000002b2: 1b 68           	ldr	r3, [r3, #0]
  5. 0x000002b4: 0d 4a           	ldr	r2, [pc, #52]	; (0x2ec <main+64>)
  6. 0x000002b6: 43 f0 20 03     	orr.w	r3, r3, #32
  7. 0x000002ba: 13 60           	str	r3, [r2, #0]
  8. 0x000002bc: 0c 4b           	ldr	r3, [pc, #48]	; (0x2f0 <main+68>)
  9. 0x000002be: 0e 22           	movs	r2, #14
  10. 0x000002c0: 1a 60           	str	r2, [r3, #0]
  11. 0x000002c2: 0c 4b           	ldr	r3, [pc, #48]	; (0x2f4 <main+72>)
  12. 0x000002c4: 0e 22           	movs	r2, #14
  13. 0x000002c6: 1a 60           	str	r2, [r3, #0]
  14. 0x000002c8: 0b 4b           	ldr	r3, [pc, #44]	; (0x2f8 <main+76>)
  15. 0x000002ca: 0e 22           	movs	r2, #14
  16. 0x000002cc: 1a 60           	str	r2, [r3, #0]
  17. 0x000002ce: 4f f4 fa 70     	mov.w	r0, #500	; 0x1f4
  18. 0x000002d2: 00 f0 13 f8     	bl	0x2fc <delayMs>
  19. 0x000002d6: 08 4b           	ldr	r3, [pc, #32]	; (0x2f8 <main+76>)
  20. 0x000002d8: 1b 68           	ldr	r3, [r3, #0]
  21. 0x000002da: 07 4a           	ldr	r2, [pc, #28]	; (0x2f8 <main+76>)
  23. 0x000002dc: 03 f0 f1 03     	and.w	r3, r3, #241	; 0xf1
  24. 0x000002e0: 13 60           	str	r3, [r2, #0]
  25. 0x000002e2: 4f f4 fa 70     	mov.w	r0, #500	; 0x1f4
  26. 0x000002e6: 00 f0 09 f8     	bl	0x2fc <delayMs>
  27. 0x000002ea: ed e7           	b.n	0x2c8 <main+28>
  28. 0x000002ec: 08 e1           	b.n	0x500
  29. 0x000002ee: 0f 40           	ands	r7, r1
  30. 0x000002f0: 00 54           	strb	r0, [r0, r0]
  31. 0x000002f2: 02 40           	ands	r2, r0
  32. 0x000002f4: 1c 55           	strb	r4, [r3, r4]
  33. 0x000002f6: 02 40           	ands	r2, r0
  34. 0x000002f8: fc 53           	strh	r4, [r7, r7]
  35. 0x000002fa: 02 40           	ands	r2, r0

It is possible to set breakpoints in the assembly code, but one cannot see high level (C/C++) side-by-side with the assembly code. And the disassembly view does not show any more information or symbolic as the Eclipse CDT disassembly view does.


To view memory, use the Command Palette (CTRL+SHIFT+P) with Cortex-Debug:View Memory.


Then specify the expression for the memory location and a length.