Skip to content

Commit aea6e06

Browse files
committed
Add support for selecting a core to debug in PyOCD
1 parent 1241bca commit aea6e06

File tree

4 files changed

+58
-21
lines changed

4 files changed

+58
-21
lines changed

package.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@
8282
"type": "array",
8383
"default": []
8484
},
85+
"gdbCore": {
86+
"description": "Core number gdb will connect to",
87+
"type": "number",
88+
"default": 0
89+
},
8590
"gdbServer": {
8691
"type": "string",
8792
"description": "Path to gdb server",
@@ -138,6 +143,11 @@
138143
"type": "array",
139144
"default": []
140145
},
146+
"gdbCore": {
147+
"description": "Core number gdb will connect to",
148+
"type": "number",
149+
"default": 0
150+
},
141151
"gdbServer": {
142152
"type": "string",
143153
"description": "Path to gdb server",

src/abstract-server.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,20 @@ export abstract class AbstractServer extends EventEmitter {
4141
protected launchReject?: (error: any) => void;
4242
protected timer?: NodeJS.Timer;
4343

44-
public spawn(args: CmsisRequestArguments): Promise<void> {
44+
constructor(protected args: CmsisRequestArguments) {
45+
super();
46+
}
47+
48+
public spawn(): Promise<void> {
4549
return new Promise(async (resolve, reject) => {
4650
this.launchResolve = resolve;
4751
this.launchReject = reject;
4852

4953
try {
5054
this.timer = setTimeout(() => this.onSpawnError(new Error('Timeout waiting for gdb server to start')), TIMEOUT);
5155

52-
const command = args.gdbServer || 'gdb-server';
53-
const serverArguments = await this.resolveServerArguments(args.gdbServerArguments);
56+
const command = this.args.gdbServer || 'gdb-server';
57+
const serverArguments = await this.resolveServerArguments(this.args.gdbServerArguments);
5458
this.process = spawn(command, serverArguments, {
5559
cwd: dirname(command),
5660
});
@@ -80,6 +84,10 @@ export abstract class AbstractServer extends EventEmitter {
8084
}
8185
}
8286

87+
public resolveGdbPort(port: number): number {
88+
return port;
89+
}
90+
8391
protected async resolveServerArguments(serverArguments?: string[]): Promise<string[]> {
8492
return serverArguments || [];
8593
}

src/cmsis-debug-session.ts

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import * as mi from './mi';
3636

3737
export interface CmsisRequestArguments extends RequestArguments {
3838
runToMain?: boolean;
39+
gdbCore?: number;
3940
gdbServer?: string;
4041
gdbServerArguments?: string[];
4142
objdump?: string;
@@ -47,7 +48,7 @@ const STATIC_HANDLES_FINISH = 0x01FFFF;
4748

4849
export class CmsisDebugSession extends GDBDebugSession {
4950

50-
protected gdbServer = new PyocdServer();
51+
protected gdbServer: PyocdServer | undefined;
5152
protected portScanner = new PortScanner();
5253
protected symbolTable!: SymbolTable;
5354
protected globalHandle!: number;
@@ -200,27 +201,20 @@ export class CmsisDebugSession extends GDBDebugSession {
200201
this.gdb.on('execAsync', (resultClass, resultData) => this.handleGDBAsync(resultClass, resultData));
201202
this.gdb.on('notifyAsync', (resultClass, resultData) => this.handleGDBNotify(resultClass, resultData));
202203

203-
// gdb server has main info channel on stderr
204-
this.gdbServer.on('stderr', data => this.sendEvent(new OutputEvent(data, 'stdout')));
205-
this.gdbServer.on('error', message => {
206-
this.sendEvent(new TerminatedEvent());
207-
throw message;
208-
});
209-
204+
// Load debug symbols
210205
try {
211206
this.symbolTable = new SymbolTable(args.program, args.objdump);
212207
await this.symbolTable.loadSymbols();
213208
} catch (error) {
214209
this.sendEvent(new OutputEvent(`Unable to load debug symbols: ${error.message}`));
215210
}
216211

217-
const port = await this.portScanner.findFreePort();
218-
if (!port) {
212+
// Determine free port for gdb server
213+
const serverPort = await this.portScanner.findFreePort();
214+
if (!serverPort) {
219215
throw new Error('Unable to find a free port to use for debugging');
220216
}
221-
this.sendEvent(new OutputEvent(`Selected port ${port} for debugging`));
222-
223-
const remote = `localhost:${port}`;
217+
this.sendEvent(new OutputEvent(`Selected port ${serverPort} for debugging`));
224218

225219
// Set gdb arguments
226220
if (!args.gdbArguments) {
@@ -232,18 +226,30 @@ export class CmsisDebugSession extends GDBDebugSession {
232226
if (!args.gdbServerArguments) {
233227
args.gdbServerArguments = [];
234228
}
235-
args.gdbServerArguments.push('--port', port.toString());
229+
args.gdbServerArguments.push('--port', serverPort.toString());
230+
231+
// gdb server has main info channel on stderr
232+
this.gdbServer = new PyocdServer(args);
233+
this.gdbServer.on('stderr', data => this.sendEvent(new OutputEvent(data, 'stdout')));
234+
this.gdbServer.on('error', message => {
235+
this.sendEvent(new TerminatedEvent());
236+
throw message;
237+
});
236238

237-
// Start gdb client and server
239+
// Start gdb server and client
238240
this.progressEvent(0, 'Starting Debugger');
239-
await this.gdbServer.spawn(args);
241+
await this.gdbServer.spawn();
240242
await this.spawn(args);
241243

244+
// Find correct debug client port
245+
const clientPort = this.gdbServer.resolveGdbPort(serverPort);
246+
const remote = `localhost:${clientPort}`;
247+
242248
// Send commands
243249
await mi.sendTargetAsyncOn(this.gdb);
244250
await mi.sendTargetSelectRemote(this.gdb, remote);
245251
await mi.sendMonitorResetHalt(this.gdb);
246-
this.sendEvent(new OutputEvent(`Attached to debugger on port ${port}`));
252+
this.sendEvent(new OutputEvent(`Attached to debugger on port ${clientPort}`));
247253

248254
// Download image
249255
const progressListener = (percent: number) => this.progressEvent(percent, 'Loading Image');
@@ -365,7 +371,10 @@ export class CmsisDebugSession extends GDBDebugSession {
365371
} catch (e) {
366372
// Need to catch here in case the connection has already been closed
367373
}
368-
this.gdbServer.kill();
374+
375+
if (this.gdbServer) {
376+
this.gdbServer.kill();
377+
}
369378
}
370379

371380
public async shutdown() {

src/pyocd-server.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,16 @@ export class PyocdServer extends AbstractServer {
3535
protected portScanner = new PortScanner();
3636
protected progress = 0;
3737

38+
public resolveGdbPort(port: number): number {
39+
if (this.args.gdbCore) {
40+
// PyOCD starts each core on a subsequent port
41+
// (e.g. core 0 on starting port, core 1 on starting port +1, etc.)
42+
port += this.args.gdbCore;
43+
}
44+
45+
return port;
46+
}
47+
3848
protected async resolveServerArguments(serverArguments?: string[]): Promise<string[]> {
3949
if (!serverArguments) {
4050
serverArguments = [];

0 commit comments

Comments
 (0)