From fd1645651d15552975178ca25b0cdd8f714c633e Mon Sep 17 00:00:00 2001 From: xoviat Date: Wed, 17 May 2023 16:08:56 -0500 Subject: [PATCH] rtt: allow printing defmt output with defmt-print --- package.json | 5 +++-- src/common.ts | 3 ++- src/frontend/extension.ts | 7 ++++-- src/frontend/swo/sources/socket.ts | 35 ++++++++++++++++++++++++++++++ src/jlink.ts | 2 +- src/openocd.ts | 2 +- 6 files changed, 47 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 36c2c616..ba899746 100644 --- a/package.json +++ b/package.json @@ -1134,10 +1134,11 @@ "type": { "enum": [ "console", - "binary" + "binary", + "defmt" ], "default": "console", - "description": "'console' with text input/output, 'binary' is for converting byte stream to other data types", + "description": "'console' with text input/output, 'binary' is for converting byte stream to other data types, 'defmt' uses defmt-print", "type": "string" }, "prompt": { diff --git a/src/common.ts b/src/common.ts index 05f547c2..0725d8f5 100644 --- a/src/common.ts +++ b/src/common.ts @@ -456,13 +456,14 @@ export class RTTServerHelper { }); } - public emitConfigures(cfg: RTTConfiguration, obj: EventEmitter): boolean { + public emitConfigures(cfg: RTTConfiguration, executable: string, obj: EventEmitter): boolean { let ret = false; if (cfg.enabled) { for (const dec of cfg.decoders) { if (dec.tcpPort || dec.tcpPorts) { obj.emit('event', new RTTConfigureEvent({ type: 'socket', + executable: executable, decoder: dec })); ret = true; diff --git a/src/frontend/extension.ts b/src/frontend/extension.ts index 89212063..31367219 100644 --- a/src/frontend/extension.ts +++ b/src/frontend/extension.ts @@ -12,7 +12,7 @@ import { MemoryContentProvider } from './memory_content_provider'; import Reporting from '../reporting'; import { CortexDebugConfigurationProvider } from './configprovider'; -import { JLinkSocketRTTSource, SocketRTTSource, SocketSWOSource, PeMicroSocketSource } from './swo/sources/socket'; +import { JLinkSocketRTTSource, SocketRTTSource, SocketSWOSource, PeMicroSocketSource, DefmtSocketRTTSource } from './swo/sources/socket'; import { FifoSWOSource } from './swo/sources/fifo'; import { FileSWOSource } from './swo/sources/file'; import { SerialSWOSource } from './swo/sources/serial'; @@ -770,7 +770,7 @@ export class CortexDebugExtension { private receivedRTTConfigureEvent(e: vscode.DebugSessionCustomEvent) { if (e.body.type === 'socket') { const decoder: RTTCommonDecoderOpts = e.body.decoder; - if ((decoder.type === 'console') || (decoder.type === 'binary')) { + if ((decoder.type === 'console') || (decoder.type === 'binary') || (decoder.type === 'defmt')) { Reporting.sendEvent('RTT', 'Source', 'Socket: Console'); this.rttCreateTerninal(e, decoder as RTTConsoleDecoderOpts); } else { @@ -793,6 +793,7 @@ export class CortexDebugExtension { // state. private createRTTSource(e: vscode.DebugSessionCustomEvent, tcpPort: string, channel: number): Promise { const mySession = CDebugSession.GetSession(e.session); + const wsPath = e.session.workspaceFolder.uri.fsPath; return new Promise((resolve, reject) => { let src = mySession.rttPortMap[channel]; if (src) { @@ -801,6 +802,8 @@ export class CortexDebugExtension { } if (mySession.config.servertype === 'jlink') { src = new JLinkSocketRTTSource(tcpPort, channel); + } else if (e.body.decoder.type === 'defmt') { + src = new DefmtSocketRTTSource(tcpPort, channel, e.body.executable, wsPath); } else { src = new SocketRTTSource(tcpPort, channel); } diff --git a/src/frontend/swo/sources/socket.ts b/src/frontend/swo/sources/socket.ts index 86326e6e..b91735a6 100644 --- a/src/frontend/swo/sources/socket.ts +++ b/src/frontend/swo/sources/socket.ts @@ -5,6 +5,8 @@ import { parseHostPort } from '../../../common'; import * as vscode from 'vscode'; import { TextDecoder } from 'util'; import { setFlagsFromString } from 'v8'; +import * as ChildProcess from 'child_process'; +import * as Path from 'path'; const TimerInterval = 250; export class SocketSWOSource extends EventEmitter implements SWORTTSource { @@ -135,6 +137,39 @@ export class SocketRTTSource extends SocketSWOSource { } } +export class DefmtSocketRTTSource extends SocketRTTSource { + private process: ChildProcess.ChildProcess; + private executable: string; + private cwd: string; + + protected processData(buffer: Buffer): void { + this.process.stdin.write(buffer); + } + + public start(timeout = (1000 * 60 * 5)): Promise { + this.process = ChildProcess.spawn( + 'defmt-print',['-e', this.executable], { cwd: this.cwd } + ); + + this.process.on('error', (e) => { + (e as any).message = `Failed to launch defmt-print (is it installed?)`; + this.emit('error', e); + this.dispose(); + }); + + this.process.stdout.on('data', (buffer) => this.emit('data', buffer)); + + return super.start(timeout); + } + + constructor(tcpPort: string, public readonly channel: number, executable: string, wsPath: string) { + super(tcpPort, channel); + + this.cwd = wsPath; + this.executable = Path.relative(wsPath, executable); + } +} + export class JLinkSocketRTTSource extends SocketRTTSource { constructor(tcpPort: string, public readonly channel: number) { super(tcpPort, channel); diff --git a/src/jlink.ts b/src/jlink.ts index ba0faa9c..d3cddc02 100644 --- a/src/jlink.ts +++ b/src/jlink.ts @@ -222,6 +222,6 @@ export class JLinkServerController extends EventEmitter implements GDBServerCont } public debuggerLaunchStarted(): void {} public debuggerLaunchCompleted(): void { - this.rttHelper.emitConfigures(this.args.rttConfig, this); + this.rttHelper.emitConfigures(this.args.rttConfig, this.args.executable, this); } } diff --git a/src/openocd.ts b/src/openocd.ts index c4543650..38f1130c 100644 --- a/src/openocd.ts +++ b/src/openocd.ts @@ -307,7 +307,7 @@ export class OpenOCDServerController extends EventEmitter implements GDBServerCo this.session = obj; } public debuggerLaunchCompleted(): void { - const hasRtt = this.rttHelper.emitConfigures(this.args.rttConfig, this); + const hasRtt = this.rttHelper.emitConfigures(this.args.rttConfig, this.args.executable, this); if (this.args.ctiOpenOCDConfig?.enabled) { this.ctiStopResume(CTIAction.init); }