Code Debugging

  1. Hardware Preparation

  • Debug adapter: Supports DAP-Link (Default) or J-Link

  • Target chip for debugging

  1. Connection Steps

  • Connect the adapter’s SWDIO (SWD) to the target chip’s SWD DATA

  • Connect the adapter’s SWCLK (CLK) to the target chip’s SWD CLK

  • Connect the adapter’s GND to the target chip’s GND to ensure common ground

  • Connect the adapter to the PC via USB

  1. Select the target chip for debugging in the extension

  2. Optional debugging configurations as described in Optional Plugin Settings (Debug)

  3. Click the Debug button to launch the integrated debugger and start code debugging

Note

  1. RTL8730E KM4 core debugging limitation:

  • Disable the tickless feature before debugging, otherwise it will affect debugging behavior.

  1. SWD pin differences:

  • The SWD pin positions may vary across chips/packages. Refer to the corresponding PINMUX table for confirmation.

  1. Connection stability:

  • If the target is not recognized after connection, first check whether the pin mapping is correct.

  • If the connection is unstable, consider lowering the SWD clock frequency.

Debugging Framework

The debugging framework is shown below:

../_images/vsix_diagram_local.svg
  1. The target chip connects to the PC via a debug adapter.

  2. When debugging starts, OpenOCD (GDB server) is launched. You can view OpenOCD output logs and status in the VS Code terminal (gdb-server).

  3. The toolchain’s built-in GDB connects to OpenOCD, after which you can perform debugging operations.

Basic Debugging Tips

  1. Debug Toolbar

  • Continue: Resume program execution (default shortcut F5).

  • Pause: Pause the running program (default shortcut F6).

  • Step Over: Execute the current line without entering the function (default shortcut F10).

  • Step Into: Execute step by step and enter the function (default shortcut F11).

  • Step Out: Return from the current function to its caller (default shortcut Shift+F11).

  1. Variables

This is the most frequently used view during debugging; it displays all data visible at the current stop location. The system automatically categorizes:

  • Local: Local variables within the current function’s scope.

  • Global: Global variables.

  • Static: Static variables within the current file.

  • Registers: Register values of the current CPU core.

  1. Breakpoints

Breakpoints are the most commonly used tool during debugging. When execution reaches a breakpoint, it pauses automatically, allowing you to inspect current variables or register information.

Method

Breakpoint Management

Line Number Click

Add: Click the blank area to the left of the line number in the editor (a red dot will appear).

View: Use the Breakpoints panel on the left to list all breakpoints.

Delete: Click the red dot again to remove the breakpoint.

Right-Click Menu

Add: Right-click in the code area and select Add Hardware Breakpoint.

View: Use the Breakpoints panel on the left to list all breakpoints.

Delete: Use the Breakpoints panel to delete selected breakpoints.

Debug Console

Add: When the program is paused, enter GDB commands in the debug console

  • Function breakpoint: b function_name

    (Example: b main, pauses at the entry of the main function)

  • Conditional breakpoint: b location if condition

    (Example: b main if count > 10, triggers when the condition is met)

  • Thread breakpoint: b function_name thread thread_ID

    (Example: b shared_func thread 8, triggers when the specified thread reaches this function)

  • Line breakpoint: b line_number

    (Example: b 100, pauses at line 100 of the current file)

  • File line breakpoint: b filename:line_number

    (Example: b main.c:50, pauses at line 50 of the specified file)

  • Address breakpoint: b *address

    (Example: b *0x08001234, pauses at the specified memory address)

View: info breakpoints or info b

Delete: delete breakpoint_number or d breakpoint_number

(Example: delete 2, deletes breakpoint number 2)

Note

Different chip architectures have a limited number of hardware breakpoints. Exceeding this limit will cause breakpoints to become invalid.

  1. Watchpoints

Watchpoints monitor changes to memory addresses or variables, interrupting the program when a value is read, written, or modified.

Method

Watchpoint Management

Right-Click Menu

Add: When the program is paused,

  • Monitor global variables: In the Variables panel, select a global variable, right-click and choose Break on Value Read/Change/Access

  • Monitor registers: In the Variables panel, select a register, right-click and choose Break on Value Read/Change/Access

  • Monitor memory addresses: In the Watch panel, add a memory watch expression, right-click and choose Break on Value Read/Change/Access

View: The Breakpoints panel on the left side lists all watchpoints

Delete: In the Breakpoints panel on the left side, select and delete the selected watchpoint

Debug Console

Add: When the program is paused, enter GDB commands in the debug console

  • Watch variable value: rwatch/watch/awatch [-l] variable_name

    (Example: watch -l count, triggers an interrupt when the value of count changes)

  • Watch memory address: rwatch/watch/awatch [-l] *address

    (Example: watch -l *0x2000b4f8, triggers an interrupt when the content at address 0x2000b4f8 changes)

View: info watchpoints or info watch

Delete: delete watchpoint_number or d watchpoint_number

(Example: delete 2, deletes watchpoint number 2)

Note

Different chip architectures have limitations on the number of watchpoints. Exceeding the limit will cause watchpoints to become invalid.

  1. Watch

The Watch panel allows you to monitor variables of interest. You can monitor in the following ways:

  • View variables:

    • Right-click on a variable in the code and select Add to Watch.

    • When the program is paused, right-click on the target variable in the Variables panel and select Add to Watch.

    • Click the + button in the Watch panel and enter the variable name.

  • View any memory address:

    • Enter an address cast expression directly, such as *(int*)0x20000004, to view the value at that address.

    • Memory view: Press F1 and enter MemoryView to open a dedicated panel to inspect large memory regions in Hex.

  • Type casting:

    • Supports C-style casting; for example, (char*)my_var to view a string value.

  1. Call Stack

When code logic is complex, the call stack clearly shows the program execution path.

  • Hierarchical navigation: The top frame is the current paused line, the next frame is the caller (parent function), and so on. Click different frames to jump and view the contextual variables at that time.

  1. Multi-core Debug Control

After enabling multi-core debugging, the Call Stack view lists debug sessions for all cores. You can switch between the following collaboration modes via the buttons on the view’s title bar.

Mode

Description

Run Sync

  • Meaning: Synchronous run mode. While paused, issuing a debug command (e.g., Continue, Step Into) on any core will apply the same operation to all other associated cores.

  • Purpose: Keep multi-core execution synchronized on the timeline to avoid inconsistencies that could cause shared-memory communication issues or logic errors.

  • Action: Click the RS button to toggle.

All Stop

  • Meaning: Global stop mode. When any core hits a halt condition (e.g., breakpoint), all cores are forced to halt.

  • Purpose: Ensure global consistency of the debugging context; disabling this allows independent debugging per core.

  • Action: Click the AS button to toggle.

Note

The full implementation of Run Sync typically relies on the All Stop mechanism. Their relationship is as follows:

  • With All Stop enabled, Pause/Continue and stepping actions are synchronized across all cores.

  • With All Stop disabled, each core behaves independently, suitable for single-core troubleshooting.

  1. RTOS-Aware

When RTOS-Aware is enabled, the debugger recognizes the operating system’s internal structures. When halted, the debugger displays all existing threads in the RTOS. It also allows you to inspect stacks, registers, and variables of other inactive threads.

In multi-core debugging, this needs to be controlled per core. Toggle it by clicking the RA button in the Call Stack view.

Advanced Debug Features

  1. Live Watch

The Variables and Watch views require the program to be paused to refresh, whereas Live Watch allows observing variable changes in real-time while the program runs at full speed.

  • Watch types: Global variables or static variables.

  • How to add:

    • Monitor variable values in the LIVE WATCH view. Click + and enter the variable name.

    • While paused, any variable in the Variables view can be added to Live Watch via right-click and selecting Add to live watch.

    • Any register in the XPERIPHERALS view can be added to Live Watch via right-click and selecting Add to live watch.

Note

You need to configure Live Watch parameters before starting a debugging session.

  1. Peripheral Registers

The XPERIPHERALS view allows you to view the values of on-chip peripheral registers.

  • Principle: Based on the chip’s SVD (System View Description) file to parse register addresses and bitfields.

Note

This view will be empty if the SVD file path is not configured correctly.

  1. RTOS Views

The RTOS kernel views comprehensively display various kernel objects managed by the RTOS. These objects are fundamental components for task management, synchronization, and communication in embedded systems. Note that these views are only available during a debugging session.

To open the RTOS views, press F1, run Open RTOS View, and select the view you want to display.

  • RTOS-TASK:

    • Displays the state of all tasks (Running, Ready, Blocked, Suspended).

    • Shows task name, address, stack usage/remaining stack space (useful for stack overflow diagnosis), runtime, and priority.

  • RTOS-QUEUE:

    • Displays queue name, capacity, current message count, and the list of tasks waiting on the queue.

  • RTOS-SOFTWARE TIMER:

    • Displays timer name, address, status (Active/Inactive, One-shot/Autoreload, Static/Dynamic), period, and callback function name and address.

  • RTOS-HEAP:

    • Displays the dynamic memory address range, allocation details, remaining heap size, and utilization.

  • RTOS-TASK NOTIFICATION:

    • Displays task name, address, the number of received and pending notifications.