Skip to content

Building and Debugging from Visual Studio Code

Felipe Torrezan edited this page Nov 18, 2025 · 15 revisions

This article outlines the steps to configure a CMake project, compiled with the IAR C/C++ Compiler, directly from Visual Studio Code on Windows.

Prerequisites and Required Software

Before starting, ensure you have administrative access to install software and that your system meets the hardware requirements for Arm development (e.g., Windows 10/11 with sufficient RAM). The following software versions were used in this updated guide. Newer versions should work with minimal changes. Always check the official documentation for compatibility:

Software Version Download Link
IAR Embedded Workbench for Arm 9.70.1 or later Free Trial
Microsoft Visual Studio Code 1.105.1 or later Download
IAR Debug Extension for VS Code 1.42.1 or later VS Code Marketpace
Microsoft C/C++ Extension Pack 1.3.1 or later VS Code Marketpace
CMake 4.1.2 or later Download
  • Install VS Code extensions via the Extensions view (Ctrl+Shift+X) in VS Code.
  • Ensure CMake is added to your system's PATH environment variable for easy access.
  • If using IAR Build Tools instead of the full IAR Embedded Workbench, adjust paths accordingly (e.g., replace ewarm-9.70.1 with your build tools directory).

Step-by-step Procedure

This assumes a fresh setup. We'll create a simple "Hello World" project for an Arm Cortex-M4 device, compile it with the IAR C/C++ Compiler, and debug it using the IAR C-SPY Debugger.

1. Set Up Your Project Folder

  1. Open Visual Studio Code.
  2. Select: FileOpen Folder... (Ctrl+K, Ctrl+O).
  3. Create and select a new empty folder (e.g., C:\Projects\hello). This will be your project directory, referred to as <proj-dir>.

Note: VS Code may prompt you to "trust" the folder's authors. Select "Yes" to enable full features.

  1. In the folder, create a file named main.c with the following content:
#include <intrinsics.h>
#include <stdio.h>
#include <stdint.h>

__root uint_fast8_t counter = 0;

void main() {
   while (counter < 10) {
     printf("Hello world! %u\n", counter);
     ++counter;
   }
   for(;;) {
      ++counter;
   }
}

This is a basic loop that prints "Hello world!" 10 times and then spins infinitely, allowing us to test debugging.

2. Create the CMakeLists.txt File

Create /CMakeLists.txt with the following content:

cmake_minimum_required(VERSION 4.1.2) # Updated to a more standard minimum; adjust if using older CMake

# Set the project name and languages (add CXX for C++ if needed)
project(example LANGUAGES C)

# Add the executable
add_executable(hello)

# Add source files
target_sources(hello PRIVATE main.c)

# Compiler options (tailor to your target device)
target_compile_options(hello PRIVATE
  --cpu=Cortex-M4
  --fpu=VFPv4_SP
  -e  # Enable IAR Language Extensions
)

# Linker options
target_link_options(hello PRIVATE
  --config "${TOOLKIT_DIR}/config/linker/ST/stm32f407xG.icf"
  --semihosting  # Enable semihosting for printf output
  --map . # Generate a map file for debugging
)

This file defines the project, sources, and IAR-specific options. The ${TOOLKIT_DIR} variable will be set later via CMake kits.

3. Configure CMake Tools Extension

Create <proj-dir>/.vscode/cmake-kits.json (adjust paths to your IAR installation):

[
  {
    "name": "IAR EWARM",
    "compilers": {
      "C":   "C:/iar/ewarm-9.70.1/arm/bin/iccarm.exe",
      "CXX": "C:/iar/ewarm-9.70.1/arm/bin/iccarm.exe",
      "ASM": "C:/iar/ewarm-9.70.1/arm/bin/iasmarm.exe"
    },
    "cmakeSettings": {
      "CMAKE_BUILD_TYPE": "Debug",
      "TOOLKIT_DIR": "C:/iar/ewarm-9.70.1/arm",
      "CMAKE_MAKE_PROGRAM": "C:/iar/ewarm-9.70.1/common/bin/ninja.exe"
    }
  }
]

The cmake-kits.json file is used by the CMake Tools VS Code extension to define one or more kits (toolchain configurations). You can extend this file by adding new kits or custom settings as needed.

Tips

  • CMake Tools will prefer Ninja if it is present, unless configured otherwise.
  • If you change the active kit while a project is configured, the project configuration will be re-generated with the chosen kit.

Configure the project

  1. Press CTRL+SHIFT+P to open the Command Palette.
  2. Type and select CMake: Select Kit.
  3. Choose "IAR EWARM".
  4. Then, select CMake: Configure from the palette. These steps will generate build files in a build folder.

4. Build the Project

  1. Open the Command Palette (CTRL+SHIFT+P).
  2. Select CMake: Build.
  3. Watch the terminal for build progress. The executable will be in <proj-dir>\build\hello.elf

Enable Accurate Intellisense for the IAR Compiler

Intellisense provides code completion and error checking. The Microsoft C/C++ extension needs IAR-specific macros and keywords.

Generate Predefined Macros Header

Run these commands in a terminal (adjust IAR path):

mkdir %APPDATA%/Code/IAR
"C:/iar/ewarm-9.70.1/arm/bin/iccarm.exe" . --predef_macros=n %APPDATA%/Code/IAR/iccarm_predef.h

For C++ Projects...

  • using DLIB: add --c++ to the previous command line.
  • using libc++: add --c++ --libc++ to the previous command line.

Create Keywords Header

Create %APPDATA%/Code/IAR/iccarm_keywords.h with:

#define __fp16 float
#define __constrange(...)
#define __c99_generic(...)
#define __spec_string
#define __data
#define __func__ ""
#define __alignof__(a) 1
#define __ALIGNOF__ __alignof__
#define __section_begin(...) ((void*)0)
#define __section_end(...) ((void*)0)
#define __section_size(...) ((size_t)0)
#define __segment_begin(...) ((void*)0)
#define __segment_end(...) ((void*)0)
#define __segment_size(...) ((size_t)0)
#define __DATA_MEMORY_LIST1__()
#define __absolute
#define __arm
#define __big_endian
#define __cmse_nonsecure_call
#define __cmse_nonsecure_entry
#define __exception
#define __fiq
#define __interwork
#define __intrinsic
#define __irq
#define __little_endian
#define __naked
#define __no_alloc
#define __no_alloc16
#define __no_alloc_str
#define __no_alloc_str16
#define __nested
#define __no_init
#define __noreturn
#define __nounwind
#define __packed
#define __pcrel
#define __ramfunc
#define __root
#define __ro_placement
#define __sbrel
#define __stackless
#define __svc
#define __swi
#define __task
#define __thumb
#define __weak

Note This list is based on IAR C/C++ Compiler for Arm 9.70.1; check the docs for updates.

Configure VS Code Settings

Add %APPDATA%/Code/User/settings.json (or use VS Code's Settings editor):

{
    // Intellisense settings
    "C_Cpp.default.compilerPath": "",
    "C_Cpp.default.cStandard": "c17",
    "C_Cpp.default.cppStandard": "c++17", // use c++20 for libc++
    "C_Cpp.default.intelliSenseMode": "clang-arm",
    "C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools",
    "C_Cpp.default.mergeConfigurations": true,
    "C_Cpp.default.systemIncludePath": [
        //"C:/iar/ewarm-9.70.1/arm/inc/libcpp", // for C++ with libc++
        //"C:/iar/ewarm-9.70.1/arm/inc/cpp",    // for C++ with DLIB
        "C:/iar/ewarm-9.70.1/arm/inc/c",
        "C:/iar/ewarm-9.70.1/arm/inc/c/aarch32"
    ],
    "C_Cpp.default.forcedInclude": [
        "${env:APPDATA}/Code/IAR/iccarm_predef.h",
        "${env:APPDATA}/Code/IAR/iccarm_keywords.h"
    ]
}

Restart VS Code for changes to take effect. Intellisense should now highlight IAR-specific syntax correctly.

Debug the Project

Create <proj-dir>/.vscode/launch.json:

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "cspy",
      "name": "C-SPY: Simulator",
      "request": "launch",
      "program": "${command:cmake.launchTargetPath}",
      "stopOnEntry": true,
      "workbenchPath": "C:/iar/ewarm-9.70.1",
      "target": "arm",
      "driver": "Simulator",
      "driverOptions": [
        "--cpu=Cortex-M4",
        "--semihosting"
      ]
    }
  ]
}

To debug:

  1. In main.c, click the gutter next to ++counter; to set a breakpoint.
  2. Press F5 or go to RunStart Debugging.
  3. Use the debug toolbar to step through code, inspect variables, and view console output.

vscode-on-windows

Hardware Debugging

For real hardware (e.g., STM32 board with J-Link probe), add a new configuration to launch.json:

    }, // previous configuration ends here
    {
      "type": "cspy",
      "name": "C-SPY: J-Link",
      "request": "launch", // "attach" also supported
      "program": "${command:cmake.launchTargetPath}",
      "stopOnEntry": true,
      "workbenchPath": "C:/iar/ewarm-9.70.1",
      "target": "arm",
      "driver": "J-Link",
      "leaveTargetRunning": false,
      "driverOptions": [ // Match your CPU and probe
        "--device=STM32F407VG", 
        "--cpu=Cortex-M4",
        "-p C:/iar/ewarm-9.70.1/arm/config/debugger/ST/STM32F407VG.ddf",
        "--semihosting",
        "--drv_communication=USB0",
        "--drv_interface=SWD"
      ]
    }
  ]
}

For details on each supported attribute, refer to the autocompletion suggestions and tooltips provided directly in the launch.json file.

The driverOptions attribute accepts C-SPY command-line parameters. For complete reference, see "The C-SPY command line utility—cspybat" in the IAR Embedded Workbench C-SPY® Debugging Guide (PDF).

With the IAR C-SPY Debug extension you can enable flexible workflows, such as one to flash and launch the application in C-SPY, and another to reattach to the running target as needed ("leaveTargetRunning": true and "request": "attach").

Summary

This article described the steps to prepare a CMake project in Visual Studio Code, build it with the IAR C/C++ Compiler and debug it with the IAR C-SPY Debugger on Windows.

Clone this wiki locally