Debugging in Visual Studio Code w/ GDB + Cortex-Debug Extension

Hi all - maybe it will be helpful for me to (briefly) explain the debuging setup that I’ve been using lately.

First of all know that there are many ways to skin this cat. robin_hodgson posted this great topic: [Success: Using Segger Embedded Studio with Artemis. His PDF instructions make it very easy to get a ‘pro’ ide up and running so that you can write C/C++ code from {nearly] scratch and perform single-step debugging with a Segger J-Link. There is nothing wrong with this method.

(though off-topic here’s a plug for the development environment I have been using + maintaining: [artemis_dev_platform. It simplifies installation of the required toolchains and incorporates some tools / scripts I have written to speed up development. Build system is pure Make and runs inside a Docker container for cross-platform standardization)

If you want to use VSC then you can use the [Cortex-Debug extension. Because this extension is build on top of GDB it might be a little more permissive of debug probes from different vendors.

Getting started is not too hard.

  1. Add the Cortex-Debug extension into VSC through the extensions browser (Ctrl + Shift + X)

  2. Open the Debug panel (Ctrl + Shift + D)

  3. Create a launch.json file (there should be a prompt in a few locations, or you can directly create one in the ‘.vscode’ directory of your workspace. The contents of the file will be discussed below)

  4. Ensure the launch.json file is correctly configured (see below)

  5. Begin debugging. Shortcut F5 or use options in the ‘Debug’ dropdown menu

The launch.json file

This file is the single file that is used to configure VSCode debug sessions. It has several fields - I will explain the ones that are important to change. (also a demo file is pasted below)

  • “cwd”: this will be the base path that VSC uses to try to identify source files from the filepaths included in the ELF (or AXF) file. If this is incorrectly configured VSC will fall back to disassembly to indicate what the cpu is doing. You will be able to tell that it is wrong by the warning that is displayed in the ‘Debug Console’ which will say something to the effect of ‘can’t find the file [path_to_file/filename.ext].’ That message can help you figure out what to put in the “cwd” field. You can use expressions such as ${workspaceRoot} to get the absolute path to the VSC workspace.

  • “executable”: this tells which executable to read information from. It must match the code that is on the board or else the debug will not make sense (program counter will map incorrectly to source code that does not match what is really happening). The executable can be an ELF or an AXF but not a ‘.bin’ because that contains no metadata to locate sources.

  • “serverpath”: Cortex-Debug is built on the GDB standard. In this field you need to supply the path to the executable for your host that will fire up a GDB server. In the example I use the JLinkGDBServerCL.exe but perhaps other GDB servers will work depending on what debug probe you want to use

  • “servertype”: should be appropriate for the GDB server you are using. Check Cortex-Debug docs for information on what is supported

  • “device”: Leave this set to “AMA3B1KK-KBR” if you are using an Artemis module. (Perhaps one day the exact revision of the Apollo3 that is used in the Artemis will change but for now that is the right version)

  • “interface”: Leave this set to “swd” for Artemis. “jtag” is also supported if you are sure that your target is using a jtag interface.

  • “runToMain”: If true the debugger will automatically breakpoint at the main function.

  • “svdFile”: This needs to be a path to the .svd file that relays specifics about the chip. This file is included in the [url=http://s3.ambiqmicro.com/pack/AmbiqMicr … 1.1.0.pack]Ambiq Device Family Pack{/url]

Here’s an example:

{
  // Use IntelliSense to learn about possible attributes.
  // Hover to view descriptions of existing attributes.
  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
      {
          "type": "cortex-debug",
          "request": "launch",
          "name": "Cortex Debug",
          "cwd": "${workspaceRoot}/path_to_project/project_top_level_dir",
          "executable": "${workspaceRoot}/path_to_project/project_top_level_dir/path_to_built_executable/executable",
          "serverpath": "C:/Program Files (x86)/SEGGER/JLink_V642/JLinkGDBServerCL.exe",
          "servertype": "jlink",
          "device": "AMA3B1KK-KBR",
          "interface": "swd", // or "jtag" - but usually "swd"
          "serialNumber": "", //if you have more than one J-Link probe add the serial number here 
          "runToMain": true,
          "svdFile": "C:/path_to_ambiq_dfp/AmbiqMicro.Apollo_DFP.1.1.0/SVD/apollo3.svd",
      }
  ]
}

Features

The Debug terminal provides a standard GDB interface - you can try standard GDB instructions there but for a beginner (like me) the GUI provided by Cortex-Debug will be easier.

You can use shortcuts to jump over, into, and out of lines of source code. When you need to single-step instructions I go to the Debug Console and use the ‘stepi’ command

Another pane of information offers a view of variables (local, global, and static), the call stack (so you can know how you got where you are now), a watch window (where you can query the value of expressions involving program variables), and the cortex CPU registers themselves (program counter, stack pointer, general-purpose registers, and status register to name a few).](Cortex-Debug - Visual Studio Marketplace)](GitHub - sparkfun/artemis_dev_platform: Containerized development platform for Artemis / Apollo3)](https://forum.sparkfun.com/viewtopic.php?f=171&t=51492)

That’s a good guide to debugging with VS Code, GDB, and JLink. I’ve been using this method for a while. I think VS Code is a great alternative to the Eclipse based IDE’s. Also, I think it might be possible to use the SWO to output debug printf’s directly into a VS Code console, but I haven’t figured out how the get that running. In the meantime, I’m using the JLinkSWOViewer GUI. Works well after incorporating your suggestions from the SWO issue #19 on Github. I have found that for the JLinkSWOViewer to connect properly, you need to specify “-device … -cpufreq … -swofreq …” on the command line and you need to already have a debug session running in VS Code.

The following may be of benefit to people who desire to use Visual Studio Code and debug with tools like Segger J-Link. It builds on a lot of the information posted on this site, but puts it together into one project that can be used as a template. The documentation (README) should be sufficient to get anyone started.

-Oxcart

https://github.com/0xcart/artemis

Awesome!!! Can’t wait to try it out! Thanks for sharing

I would like to try OpenOCD in place of the JLink GDBServer in the above configuration to try and isolate an issue I am having (noted in another thread). Has anyone got Apollo3, OpenOCD, and JLink working with Cortex-Debug? I have OpenOCD connecting to the JLink and I am hoping someone has a target config that works for the Apollo3.

Thanks in anticipation,

Sid

I made an update to the repository: https://github.com/0xcart/artemis

It now includes example code for I2C and SPI. The README has been updated as well and includes a Configuration section (towards the bottom) that describes how to configure things to conform with IOM modules defined in am_bsp_pins.h.

Hey all, I’ve been having a problem where upon a breakpoint, my cortex-debug extension is unable to read the memory for all the apollo3’s registers like ADC/DMA/IOM etc. I’m using a Redboard ATP with a Segger J-Link EDU Mini.

I have the cortex-debug extension configured, and can program/step through my code just fine, but I can’t seem to view any registers when paused. Any ideas?