Skip to content

Commit 5a42365

Browse files
authored
Merge branch 'main' into 0-0-1-preps
2 parents 9c7cb5e + b1de637 commit 5a42365

File tree

5 files changed

+108
-66
lines changed

5 files changed

+108
-66
lines changed

README.md

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,21 @@ The following extensions are included in this extension pack:
2323
## pyOCD Debug Setup
2424

2525
- Install `GCC compiler for ARM CPUs` with the `Arm Tools Environment Manager` to get access to a GDB (`arm-none-eabi-gdb`).
26-
27-
- (Temporary, should become obsolete with full `*.cbuild-run.yml` support in pyOCD)<br>
26+
- **Temporary** - should become obsolete with full `*.cbuild-run.yml` support in pyOCD:<br>
2827
Make sure to set up your CMSIS Pack installation root folder by one of the following methods:
2928
- Set your system environment variable `CMSIS_PACK_ROOT`.
3029
- Add the following to your debug launch configuration
3130
```
3231
"environment": {
3332
"CMSIS_PACK_ROOT": "</path/to/your/pack/cache>"
3433
}
35-
3634
```
3735
36+
## Segger J-Link Debug Setup
37+
38+
- Install the latest [J-Link Software and Documentation Pack](https://www.segger.com/downloads/jlink/#J-LinkSoftwareAndDocumentationPack) from [Segger](https://www.segger.com/). Ensure all required drivers and host platform specific settings are done.
39+
- Ensure the installation folder is added to your system's `PATH` environment variable. Alternatively, you can add an absolute path to your installation in the debug launch configuration.
40+
3841
## Additional Extension Functionality
3942
4043
This extension contributes additional functionality to more seamlessly integrate the included extensions:
@@ -48,15 +51,26 @@ This section describes the contributed pseudo debugger types and their support t
4851
4952
#### CMSIS Debugger (pyOCD) - `cmsis-debug-pyocd`
5053
51-
TODO:
52-
- Assumed setup and where to find things.
53-
- Automatically filled in values on debug start.
54+
The `cmsis-debug-pyocd` debugger type allows to add default debug configurations to the workspace's `launch.json` file to debug via GDB and pyOCD. The actually used debugger type is `gdbtarget`.
55+
56+
In addition this extension contributes a debug configuration resolver which automatically fills the following gaps during debug launch:
57+
- If option `target`.`server` is set to `pyocd`, then it expands this option to the absolute path of the built-in pyOCD distribution.
58+
- Adds/extends the `target`.`serverParameters` list of `pyocd` command line arguments:
59+
- Prepends `gdbserver` if not present.
60+
- Appends `--port` and the corresponding `port` value if `target`.`port` is set.
61+
- Appends `--cbuild-run` and the corresponding `cbuildRunFile` path if `cmsis`.`cbuildRunFile` is set.
62+
63+
**Note**: The built-in version of pyOCD supports the command line option `--cbuild-run`. However, this is a new option which isn't contained yet in releases outside this extension.
5464
5565
#### CMSIS Debugger (J-Link) - `cmsis-debug-jlink`
5666
57-
TODO:
58-
- Assumed setup and where to find things.
59-
- Automatically filled in values on debug start.
67+
The `cmsis-debug-jlink` debugger type allows to add default debug configurations to the workspace's `launch.json` file to debug via GDB and the Segger J-Link GDB server. The actually used debugger type is `gdbtarget`.
68+
69+
**Note**: The generated default debug configuration uses `JLinkGDBServer` as `target`.`server` setting. The executable with this name has slightly differing behavior depending on your host platform. It launches a GUI-less server on Linux and MacOS. Whereas a GDB server with GUI is launched on Windows. Please change the value to `JLinkGDBServerCL` to suppress the GUI on Windows.
70+
71+
In addition this extension contributes a debug configuration resolver which automatically fills the following gaps during debug launch:
72+
- Adds/extends the `target`.`serverParameters` list of `JLinkGDBServer`/`JLinkGDBServerCL` command line arguments:
73+
- Appends `--port` and the corresponding `port` value if `target`.`port` is set.
6074
6175
## Trademarks
6276
Visual Studio is a trademark of the Microsoft group of companies.

package.json

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,6 @@
119119
"target": {
120120
"server": "JLinkGDBServer",
121121
"serverParameters": [
122-
"-select",
123-
"USB",
124122
"-device",
125123
"${command:cmsis-csolution.getDeviceName}",
126124
"-endian",
@@ -130,11 +128,9 @@
130128
"-speed",
131129
"auto",
132130
"-noir",
133-
"-LocalhostOnly",
134131
"-vd",
135132
"-nogui",
136-
"-port",
137-
"3333"
133+
"-localhostonly"
138134
],
139135
"port": "3333"
140136
}
@@ -160,8 +156,6 @@
160156
"target": {
161157
"server": "JLinkGDBServer",
162158
"serverParameters": [
163-
"-select",
164-
"USB",
165159
"-device",
166160
"^\"\\${command:cmsis-csolution.getDeviceName}\"",
167161
"-endian",
@@ -171,11 +165,9 @@
171165
"-speed",
172166
"auto",
173167
"-noir",
174-
"-LocalhostOnly",
175168
"-vd",
176169
"-nogui",
177-
"-port",
178-
"3333"
170+
"-localhostonly"
179171
],
180172
"port": "3333"
181173
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* Copyright 2025 Arm Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import * as vscode from 'vscode';
18+
import { GDBTargetConfiguration } from '../gdbtarget-configuration';
19+
20+
export abstract class BaseConfigurationProvider implements vscode.DebugConfigurationProvider {
21+
22+
protected async commandExists(commandName: string): Promise<boolean> {
23+
const commands = await vscode.commands.getCommands();
24+
return !!commands.find(command => command === commandName);
25+
};
26+
27+
protected parameterExists(name: string, params: string[]): boolean {
28+
return !!params.find(param => param.trim() === name);
29+
}
30+
31+
protected async shouldAppendParameter(params: string[], paramName: string, commandName?: string): Promise<boolean> {
32+
return !this.parameterExists(paramName, params) && (!commandName || await this.commandExists(commandName));
33+
}
34+
35+
protected abstract resolveServerParameters(debugConfiguration: GDBTargetConfiguration): Promise<GDBTargetConfiguration>;
36+
37+
public resolveDebugConfigurationWithSubstitutedVariables(
38+
_folder: vscode.WorkspaceFolder | undefined,
39+
debugConfiguration: vscode.DebugConfiguration,
40+
_token?: vscode.CancellationToken
41+
): Promise<vscode.DebugConfiguration | null | undefined> {
42+
return this.resolveServerParameters(debugConfiguration);
43+
}
44+
45+
}

src/debug-configuration/subproviders/jlink-configuration-provider.ts

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,29 @@
1414
* limitations under the License.
1515
*/
1616

17-
import * as vscode from 'vscode';
1817
import { logger } from '../../logger';
18+
import { BaseConfigurationProvider } from './base-configuration-provider';
19+
import { GDBTargetConfiguration } from '../gdbtarget-configuration';
1920

20-
export const JLINK_SERVER_TYPE_REGEXP = /.*JLinkGDBServer(|.exe)\s*$/i;
21+
export const JLINK_SERVER_TYPE_REGEXP = /.*JLinkGDBServer(|CL)(|.exe|Exe)\s*$/i;
2122

22-
export class JlinkConfigurationProvider implements vscode.DebugConfigurationProvider {
23+
const JLINK_CLI_ARG_PORT = '-port';
2324

24-
public async resolveDebugConfigurationWithSubstitutedVariables(
25-
_folder: vscode.WorkspaceFolder | undefined,
26-
debugConfiguration: vscode.DebugConfiguration,
27-
_token?: vscode.CancellationToken
28-
): Promise<vscode.DebugConfiguration | null | undefined> {
29-
logger.debug('Resolving J-Link configuration');
25+
export class JlinkConfigurationProvider extends BaseConfigurationProvider {
26+
27+
protected async resolveServerParameters(debugConfiguration: GDBTargetConfiguration): Promise<GDBTargetConfiguration> {
28+
logger.debug('Resolving J-Link GDB server parameters');
29+
if (!debugConfiguration.target) {
30+
return debugConfiguration;
31+
}
32+
// serverParameters
33+
debugConfiguration.target.serverParameters ??= [];
34+
const parameters = debugConfiguration.target.serverParameters;
35+
// port (use value defined in 'port' outside 'serverParamters')
36+
const port = debugConfiguration.target?.port;
37+
if (port && await this.shouldAppendParameter(parameters, JLINK_CLI_ARG_PORT)) {
38+
parameters.push(JLINK_CLI_ARG_PORT, `${port}`);
39+
}
3040
return debugConfiguration;
3141
}
3242

src/debug-configuration/subproviders/pyocd-configuration-provider.ts

Lines changed: 19 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -14,76 +14,57 @@
1414
* limitations under the License.
1515
*/
1616

17-
import * as vscode from 'vscode';
1817
import { logger } from '../../logger';
1918
import { GDBTargetConfiguration, TargetConfiguration } from '../gdbtarget-configuration';
2019
import { BuiltinToolPath } from '../../desktop/builtin-tool-path';
20+
import { BaseConfigurationProvider } from './base-configuration-provider';
2121

2222
const PYOCD_BUILTIN_PATH = 'tools/pyocd/pyocd';
23-
export const PYOCD_EXECUTABLE_ONLY_REGEXP = /^\s*pyocd(|.exe)\s*$/i;
23+
const PYOCD_EXECUTABLE_ONLY_REGEXP = /^\s*pyocd(|.exe)\s*$/i;
2424
export const PYOCD_SERVER_TYPE_REGEXP = /.*pyocd(|.exe)\s*$/i;
2525

26-
export class PyocdConfigurationProvider implements vscode.DebugConfigurationProvider {
27-
protected builtinPyocd = new BuiltinToolPath(PYOCD_BUILTIN_PATH);
28-
29-
protected async hasCommand(commandName: string): Promise<boolean> {
30-
const commands = await vscode.commands.getCommands();
31-
return !!commands.find(command => command === commandName);
32-
};
33-
34-
protected hasParam(name: string, params: string[]): boolean {
35-
return !!params.find(param => param.trim() === name);
36-
}
26+
const PYOCD_CLI_ARG_GDBSERVER = 'gdbserver';
27+
const PYOCD_CLI_ARG_PORT = '--port';
28+
const PYOCD_CLI_ARG_CBUILDRUN = '--cbuild-run';
3729

38-
protected async shouldAppendParam(params: string[], paramName: string, commandName?: string): Promise<boolean> {
39-
return !this.hasParam(paramName, params) && (!commandName || await this.hasCommand(commandName));
40-
}
30+
export class PyocdConfigurationProvider extends BaseConfigurationProvider {
31+
protected builtinPyocd = new BuiltinToolPath(PYOCD_BUILTIN_PATH);
4132

4233
protected resolveServerPath(target: TargetConfiguration): void {
4334
const targetServer = target.server;
4435
const useBuiltin = !targetServer || PYOCD_EXECUTABLE_ONLY_REGEXP.test(targetServer);
45-
const builtinUri = useBuiltin ? this.builtinPyocd.getAbsolutePath() : undefined;
46-
if (builtinUri) {
47-
target.server = builtinUri.fsPath;
36+
const updateUri = useBuiltin ? this.builtinPyocd.getAbsolutePath() : undefined;
37+
if (updateUri) {
38+
target.server = updateUri.fsPath;
4839
}
4940
}
5041

5142
protected async resolveServerParameters(debugConfiguration: GDBTargetConfiguration): Promise<GDBTargetConfiguration> {
43+
logger.debug('Resolving pyOCD server parameters');
5244
if (!debugConfiguration.target) {
5345
return debugConfiguration;
5446
}
5547
// server
5648
this.resolveServerPath(debugConfiguration.target);
5749
// serverParameters
58-
const parameters = debugConfiguration.target.serverParameters ??= [];
50+
debugConfiguration.target.serverParameters ??= [];
51+
const parameters = debugConfiguration.target.serverParameters;
5952
// gdbserver
60-
if (await this.shouldAppendParam(parameters, 'gdbserver')) {
53+
if (await this.shouldAppendParameter(parameters, PYOCD_CLI_ARG_GDBSERVER)) {
6154
// Prepend, it must be the first argument
62-
parameters.unshift('gdbserver');
55+
parameters.unshift(PYOCD_CLI_ARG_GDBSERVER);
6356
}
6457
// port (use value defined in 'port' outside 'serverParamters')
6558
const port = debugConfiguration.target?.port;
66-
if (port && await this.shouldAppendParam(parameters, '--port')) {
67-
parameters.push('--port');
68-
parameters.push(`${port}`);
59+
if (port && await this.shouldAppendParameter(parameters, PYOCD_CLI_ARG_PORT)) {
60+
parameters.push(PYOCD_CLI_ARG_PORT, `${port}`);
6961
}
7062
// cbuild-run
7163
const cbuildRunFile = debugConfiguration.cmsis?.cbuildRunFile;
72-
if (cbuildRunFile && await this.shouldAppendParam(parameters, '--cbuild-run')) {
73-
parameters.push('--cbuild-run');
74-
parameters.push(`${cbuildRunFile}`);
64+
if (cbuildRunFile && await this.shouldAppendParameter(parameters, PYOCD_CLI_ARG_CBUILDRUN)) {
65+
parameters.push(PYOCD_CLI_ARG_CBUILDRUN, `${cbuildRunFile}`);
7566
}
7667
return debugConfiguration;
7768
}
7869

79-
public async resolveDebugConfigurationWithSubstitutedVariables(
80-
_folder: vscode.WorkspaceFolder | undefined,
81-
debugConfiguration: vscode.DebugConfiguration,
82-
_token?: vscode.CancellationToken
83-
): Promise<vscode.DebugConfiguration | null | undefined> {
84-
logger.debug('Resolving pyOCD configuration');
85-
const resolvedConfig = await this.resolveServerParameters(debugConfiguration);
86-
return resolvedConfig;
87-
}
88-
8970
}

0 commit comments

Comments
 (0)