Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import { exec, ChildProcess } from 'child_process';
- import { write } from 'fs';
- import { EventEmitter } from 'events';
- const ERRORS = {
- get PROCESS_NOT_RUNNING() { return new Error("Process not running"); },
- get CANNOT_STOP_MDB() { return new Error("Cannot stop MDB"); },
- get TIMEOUT() { return new Error("timeout"); },
- get DEVICE_NOT_SELECTED() { return new Error("Device not selected"); },
- get TOOL_NOT_SELECTED() { return new Error("Tool not selected"); },
- get PROGRAMMING_FAILED() { return new Error("Programming failed"); },
- get IMAGE_NOT_LOADED() { return new Error("Image not loaded"); },
- get DEVICE_RUNNING() { return new Error("Device running"); },
- };
- const MDB_COMMANDS = {
- QUIT: () => 'quit',
- HALT: () => 'halt',
- DEVICE: (name: string) => `Device ${name}`,
- HW_TOOL: (id: string, justProgram: boolean, index?: number) => `HwTool ${id}${justProgram?" -p":""}${index?` ${index}`:''}`,
- PROGRAM: (imageName: string) => `Program "${imageName}"`,
- CHANGE_DIR: (dir: string) => `cd "${dir}"`,
- RESET: () => 'Reset',
- CONTINUE: () => 'Continue',
- RUN: () => 'Run',
- NEXT: () => 'Next', // Advance to next program line, skipping subroutine calls
- STEP: () => 'Step', // Advance to different program line, following subroutine calls (only thouse with source line information)
- STEPI: (count?: number) => `Stepi${count?` ${count}`:''}`, // Step one instruction
- BACKTRACE: (full?: boolean) => `Backtrace${full?' full':''}`,
- PRINT: (variable: string, format?: 'x' | 'd' | 'a', datasize?: 1 | 2 | 4) => (
- `print${format?` /${format}`:''}${datasize?` /datasize:${datasize}`:''} ${variable}`
- ),
- PRINT_PIN: (name: string) => `Print pin ${name}`,
- WRITE: (addr: number, data: number[], type?: 'r' | 'p' | 'm' | 'e') => (
- `write${type?` ${type}`:''} ${addr}${data.reduce((val, prev) => `${prev} ${val}`, '')}`
- ),
- WRITE_PIN: (name: string, value: 'low' | 'high' | number) => (
- `write pin ${name} ${(typeof value === 'string')?value:`${value}v`}`
- ),
- BREAK_FILE: (name: string, line: number, passCount?: number) => `break ${name}:${line}${passCount?` ${passCount}`:''}`,
- BREAK_ADDRESS: (address: number, passCount?: number) => `break *0x${address.toString(16)}${passCount?` ${passCount}`:''}`,
- BREAK_FUNCTION: (name: string, passCount?: number) => `break ${name}${passCount?` ${passCount}`:''}`,
- };
- interface CancellableHandler<T> {
- promise: Promise<T>;
- cancel: () => void;
- }
- /**
- * Resolves or rejects with the provided promise or rejects with `ERRORS.TIMEOUT` on timeout.
- *
- * @param promise Promise to wait for
- * @param ms Timeout duration in miliseconds or 0 to never timeout
- */
- function waitForPromiseOrTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {
- let timeout: NodeJS.Timeout;
- const timeoutPromise = new Promise<T>((_, reject) => {
- timeout = setTimeout(
- () => (ms > 0) ? reject(ERRORS.TIMEOUT) : null,
- ms
- );
- });
- promise.finally(() => clearTimeout(timeout));
- return Promise.race([timeoutPromise, promise]);
- }
- /**
- * Resolves or rejects with the first handler to finish or rejects with `ERRORS.TIMEOUT` on timeout and
- * automatically cancells all handlers upon resolving.
- *
- * @param ms Timeout duration in miliseconds or 0 to never timeout
- * @param handlers Handler objects to wait for
- */
- function raceForCancellableHandlersOrTimeout(ms: number, ...handlers: CancellableHandler<any>[]): Promise<void> {
- let timeout: NodeJS.Timeout | undefined;
- const timeoutPromise = new Promise((_, reject) => {
- timeout = setTimeout(
- () => (ms > 0) ? reject(ERRORS.TIMEOUT) : null,
- ms
- );
- });
- handlers.forEach(p => p.promise.finally(() => {
- if (timeout) {
- handlers.forEach(h => h.cancel());
- clearTimeout(timeout);
- timeout = undefined;
- }
- }));
- return Promise.race([timeoutPromise, ...(handlers.map(h => h.promise))]);
- }
- /**
- * Creates `CancellableEventHandlerObject` which resolves when provided event name is fired.
- * Promise is resolved with the first argument passed by event emitter.
- *
- * @param emitter `EventEmitter` object to listen to
- * @param eventName Name of event to listen to
- * @param errorFactory If provided created promise will reject with error returned by factory instead of resolving
- */
- function cancellableEventHandler<T = any>(emitter: EventEmitter, eventName: string, errorFactory?: (...args: any[]) => Error): CancellableHandler<T> {
- let cancel : () => void = () => null;
- const promise = new Promise<T>((resolve, reject) => {
- const handler = (errorFactory) ? ((...args: any[]) => reject(errorFactory(...args))) : (arg: T) => resolve(arg);
- emitter.once(eventName, handler);
- cancel = () => emitter.removeListener(eventName, handler);
- });
- return { cancel, promise };
- }
- /**
- * Waits for eventName to happen and resolves with the first argument
- * passed to the eventName callback or rejects when timemout happens first.
- *
- * @param emitter eventName emitter to listen to
- * @param eventName Name of eventName to wait to
- * @param timeoutMs Number of miliseconds to wait before timeout or 0 to wait indefinetly
- */
- async function waitForEventOrTimeout<T = any>(emitter: EventEmitter, eventName: string, timeoutMs: number) {
- const awaiter = cancellableEventHandler(emitter, eventName);
- if (timeoutMs === 0) {
- return awaiter.promise;
- }
- try {
- return await waitForPromiseOrTimeout<T>(awaiter.promise, timeoutMs);
- } finally {
- awaiter.cancel();
- }
- }
- export interface HwTool {
- name: string;
- id: string;
- index?: number;
- }
- export interface HaltInfo {
- breakpoint?: boolean;
- address?: number;
- file?: string;
- line?: number;
- }
- export interface BreakpointInfo {
- id: number;
- address?: number;
- function?: string;
- file?: {
- name: string;
- line: number;
- };
- }
- export const MDB_EVENTS = {
- CONSOLE_DATA: 'console:data',
- CONSOLE_WARNING: 'console:warning',
- CONSOLE_ERROR: 'console:error',
- CONSOLE_WRITE: 'console:write',
- MDB_CHANGE_DIRECTORY: 'mdb:change_directory',
- MDB_INITIALIZED: 'mdb:initialized',
- MDB_STOP: 'mdb:stop',
- DEVICE_HALT: 'device:halt',
- DEVICE_RUNNING: 'device:running',
- DEVICE_BREAKPOINT_SET: 'device:breakpoint:set',
- DEVICE_PRORGRAMING_START: 'device:programing:start',
- DEVICE_PRORGRAMING_SUCCESS: 'device:programing:success',
- DEVICE_PRORGRAMING_FAIL: 'device:programing:fail',
- };
- export class MdbWrapper extends EventEmitter {
- // TODO: Find this path from Windows Registry or some other means on Linux.
- private _mdbPath = '"C:\\Program Files (x86)\\Microchip\\MPLABX\\v5.05\\mplab_platform\\bin\\mdb.bat';
- private _process ?: ChildProcess = undefined;
- private _running = false;
- private _initialized = false;
- private _deviceSelected = false;
- private _toolMode : 'NONE' | 'PROGRAM' | 'DEBUG' = 'NONE';
- private _imageLoaded = false;
- private _haltInfo: HaltInfo = {};
- private _lastBreakpoint = -1;
- /**
- * Waits for eventName to happen and resolves with the first argument
- * passed to the eventName callback or rejects when timemout happens first.
- *
- * @param eventName name of eventName to listen to
- * @param ms Number of miliseconds to wait before timeout or 0 to wait indefinetly
- */
- public async waitForEventOrTimeout<T = any>(eventName: string, ms: number) {
- return waitForEventOrTimeout<T>(this, eventName, ms);
- }
- /**
- * (re)Starts mdb.bat process
- * If already running stops the process.
- *
- * @param timeoutMs Number of miliseconds to wait for MDB to start or 0 to not wait
- */
- public async start(timeoutMs: number = 60000) {
- if (this._process) {
- await this.stop(timeoutMs);
- }
- console.log("MDB starting");
- this._running = false;
- this._initialized = false;
- this._deviceSelected = false;
- this._toolMode = 'NONE';
- this._imageLoaded = false;
- this._process = exec(this._mdbPath);
- this._process.on("error", this.onError);
- this._process.on("exit", this.onExit);
- this._process.stdout.on("data", this.onData);
- this._process.stdout.on("data", (data) => {
- const str = String(data).trim();
- if (str.length > 0) {
- this.emit(MDB_EVENTS.CONSOLE_DATA, str);
- }
- });
- this._process.stderr.on("data", (data) => {
- const str = String(data).trim();
- if (str.length > 0) {
- this.emit(MDB_EVENTS.CONSOLE_ERROR, str);
- }
- });
- await this.writeLn("set system.yestoalldialog true");
- if (timeoutMs > 0) {
- await this.waitUntilInitialized(timeoutMs);
- }
- }
- /**
- * Stops currently running process, gracefully if possible
- *
- * @param timeoutMs Number of miliseconds to wait for process to gracefully stop or 0 to wait indefinetly
- */
- public async stop(timeoutMs: number = 60000) {
- if (! this._process) { return; }
- // If program is currently running MDB tends to hang when just `quit` is written
- if (this._running) {
- await this.writeLn(MDB_COMMANDS.HALT());
- await this.waitForEventOrTimeout(MDB_EVENTS.DEVICE_HALT, timeoutMs);
- }
- await this.writeLn(MDB_COMMANDS.QUIT());
- try {
- await this.waitForEventOrTimeout(MDB_EVENTS.MDB_STOP, timeoutMs);
- } catch(e) {
- console.warn("Cannot gracefuly stop the process", e);
- if (this._process) {
- this._process.kill();
- try {
- await this.waitForEventOrTimeout(MDB_EVENTS.MDB_STOP, 1000);
- } catch(e) {
- console.error("Cannot forcefully stop the process", e);
- }
- }
- }
- // By now the process should have been set to undefined by onExit handler
- if (this._process) {
- throw ERRORS.CANNOT_STOP_MDB;
- }
- }
- /**
- * Selects provided MCU for programming and debugging operations.
- *
- * @param device Part number of device to program i.e. PIC16F18857
- * @param timeoutMs Timeout after given number of miliseconds. Pass 0 to waint indefinetly
- */
- public async selectDevice(device: string, timeoutMs: number = 60000) {
- // TODO: Find better way of ensuring that device is selected
- await this.writeLnAndWaitForEvent(
- MDB_COMMANDS.DEVICE(device),
- MDB_EVENTS.CONSOLE_DATA,
- timeoutMs
- );
- this._deviceSelected = true;
- }
- /**
- * Initializes privided tool for programming or debugging operation depending on `justProgram` flag.
- * This operation might involve changing tool's firmware and communicating with target.
- * This must be called after `selectDevice` has been called.
- *
- * @param tool Tool to initialize
- * @param justProgram If true tool is initialized for production programming operation, otherwise for debugging
- * @param timeoutMs Timeout after given number of miliseconds. Pass 0 to waint indefinetly
- */
- public async selectHwTool(tool: HwTool, justProgram: boolean = false, timeoutMs: number = 60000) {
- if (! this._deviceSelected) {
- throw ERRORS.DEVICE_NOT_SELECTED;
- }
- // TODO: Find better way of ensuring that the tool is ready
- // As with any real tool a lot of data is printed before it's actually ready
- await this.writeLnAndWaitForEvent(
- MDB_COMMANDS.HW_TOOL(tool.id, justProgram, tool.index),
- MDB_EVENTS.CONSOLE_DATA,
- timeoutMs
- );
- this._toolMode = justProgram ? 'PROGRAM' : 'DEBUG';
- }
- /**
- * Change current working directory
- *
- * @param newDirectory Relative or absolute path to new working directory
- * @param timeoutMs Timeout after given number of miliseconds. Pass 0 to waint indefinetly
- */
- public async changeDirectory(newDirectory: string, timeoutMs: number = 60000) {
- await this.writeLnAndWaitForEvent(
- MDB_COMMANDS.CHANGE_DIR(newDirectory),
- MDB_EVENTS.MDB_CHANGE_DIRECTORY,
- timeoutMs
- );
- }
- /**
- * Programs the provided image file (ELF or Intel HEX) into device's memory
- *
- * @param imageName Relative or absolute path to image file
- * @param timeoutMs Timeout after given number of miliseconds. Pass 0 to waint indefinetly
- */
- public async program(imageName: string, timeoutMs: number = 60000) {
- if (this._toolMode === 'NONE') {
- throw ERRORS.TOOL_NOT_SELECTED;
- }
- await this.waitUntilInitialized(1000);
- await this.writeLn(MDB_COMMANDS.PROGRAM(imageName));
- const successAwaiter = cancellableEventHandler(this, MDB_EVENTS.DEVICE_PRORGRAMING_SUCCESS);
- const failureAwaiter = cancellableEventHandler(this, MDB_EVENTS.DEVICE_PRORGRAMING_FAIL, () => ERRORS.PROGRAMMING_FAILED);
- await raceForCancellableHandlersOrTimeout(timeoutMs, successAwaiter, failureAwaiter);
- }
- /**
- * Sets breakpoint at provided address or timeouts
- *
- * @param address Address in image to break at
- * @param passCount Number of hits before halting
- * @param timeoutMs Timeout after given number of miliseconds. Pass 0 to waint indefinetly
- */
- public async breakpoint_address(address: number, passCount?: number, timeoutMs: number = 60000): Promise<BreakpointInfo> {
- if (! this._imageLoaded) {
- throw ERRORS.IMAGE_NOT_LOADED;
- }
- return this.writeLnAndWaitForEvent<BreakpointInfo>(
- MDB_COMMANDS.BREAK_ADDRESS(address, passCount),
- MDB_EVENTS.DEVICE_BREAKPOINT_SET,
- timeoutMs
- );
- }
- /**
- * Sets breakpoint at provided file and line number or timeouts
- *
- * @param file Filename to break at
- * @param line Line number to break at
- * @param passCount Number of hits before halting
- * @param timeoutMs Timeout after given number of miliseconds. Pass 0 to waint indefinetly
- */
- public async breakpoint_line(file: string, line: number, passCount?: number, timeoutMs: number = 60000): Promise<BreakpointInfo> {
- if (! this._imageLoaded) {
- throw ERRORS.IMAGE_NOT_LOADED;
- }
- return this.writeLnAndWaitForEvent<BreakpointInfo>(
- MDB_COMMANDS.BREAK_FILE(file, line, passCount),
- MDB_EVENTS.DEVICE_BREAKPOINT_SET,
- timeoutMs
- );
- }
- /**
- * Sets breakpoint at the beggining of provided funtion or timeouts
- *
- * @param name Name of the function to break on
- * @param passCount Number of hits before halting
- * @param timeoutMs Timeout after given number of miliseconds. Pass 0 to waint indefinetly
- */
- public async breakpoint_function(name: string, passCount?: number, timeoutMs: number = 60000): Promise<BreakpointInfo> {
- if (! this._imageLoaded) {
- throw ERRORS.IMAGE_NOT_LOADED;
- }
- return this.writeLnAndWaitForEvent<BreakpointInfo>(
- MDB_COMMANDS.BREAK_FUNCTION(name, passCount),
- MDB_EVENTS.DEVICE_BREAKPOINT_SET,
- timeoutMs
- );
- }
- public async reset(timeoutMs: number = 60000) {
- if (! this._imageLoaded) {
- throw ERRORS.IMAGE_NOT_LOADED;
- }
- // TODO: Find a good way of detecting that device is reset. Apperently for each HwTool the output is different
- // For now wait for MDB to output anything
- this.writeLnAndWaitForEvent(MDB_COMMANDS.RESET(), MDB_EVENTS.CONSOLE_DATA, timeoutMs);
- }
- public async run(timeoutMs: number = 60000) {
- if (! this._imageLoaded) {
- throw ERRORS.IMAGE_NOT_LOADED;
- }
- if (this._running) {
- throw ERRORS.DEVICE_RUNNING;
- }
- this.writeLnAndWaitForEvent(MDB_COMMANDS.RUN(), MDB_EVENTS.DEVICE_RUNNING, timeoutMs);
- }
- public async stepOver(timeoutMs: number = 60000) {
- if (! this._imageLoaded) {
- throw ERRORS.IMAGE_NOT_LOADED;
- }
- if (this._running) {
- throw ERRORS.DEVICE_RUNNING;
- }
- this._running = true;
- this.writeLnAndWaitForEvent(MDB_COMMANDS.NEXT(), MDB_EVENTS.DEVICE_HALT, timeoutMs);
- }
- public async stepIn(timeoutMs: number = 60000) {
- if (! this._imageLoaded) {
- throw ERRORS.IMAGE_NOT_LOADED;
- }
- if (this._running) {
- throw ERRORS.DEVICE_RUNNING;
- }
- this._running = true;
- this.writeLnAndWaitForEvent(MDB_COMMANDS.STEP(), MDB_EVENTS.DEVICE_HALT, timeoutMs);
- }
- public async step(count?: number, timeoutMs: number = 60000) {
- if (! this._imageLoaded) {
- throw ERRORS.IMAGE_NOT_LOADED;
- }
- if (this._running) {
- throw ERRORS.DEVICE_RUNNING;
- }
- this._running = true;
- this.writeLnAndWaitForEvent(MDB_COMMANDS.STEPI(), MDB_EVENTS.DEVICE_HALT, timeoutMs);
- }
- public async continue(timeoutMs: number = 60000) {
- if (! this._imageLoaded) {
- throw ERRORS.IMAGE_NOT_LOADED;
- }
- this.writeLnAndWaitForEvent(MDB_COMMANDS.CONTINUE(), MDB_EVENTS.DEVICE_RUNNING, timeoutMs);
- }
- /**
- * Currently this function is just a stub, it will query MDB for connected tools
- *
- * @param timeoutMs
- */
- public async getHwTools(timeoutMs: number = 60000): Promise<HwTool[]> {
- return [
- { id: "SIM", name: "Simulator" }
- ];
- }
- private async writeLnAndWaitForEvent<T = any>(value: string, eventName: string, timeoutMs: number) {
- await this.waitUntilInitialized(1000);
- await this.writeLn(value);
- return await this.waitForEventOrTimeout<T>(eventName, timeoutMs);
- }
- private async writeLn(value: string) {
- return new Promise((resolve, reject) => {
- if (! this._process) {
- return reject(ERRORS.PROCESS_NOT_RUNNING);
- }
- this._process.stdin.write(value + "\n", (err) => {
- if (err) {
- return reject(err);
- }
- this.emit(MDB_EVENTS.CONSOLE_WRITE, value + "\n");
- resolve();
- });
- });
- }
- private onData = (data: any) => {
- type Resolver<T> = {
- eventName: string,
- args?: (data: T) => any[],
- } | ((data: T) => void);
- interface ValueHandlerString {
- key: string;
- resolver: Resolver<string>;
- }
- interface ValueHandlerRegExp {
- key: RegExp;
- resolver: Resolver<RegExpExecArray>;
- }
- const valueHandlers: Array<ValueHandlerString | ValueHandlerRegExp> = [
- { key: '>', resolver: () => {
- if (! this._initialized) {
- this._initialized = true;
- this.emit(MDB_EVENTS.MDB_INITIALIZED);
- }
- }},
- { key: 'Programming target...', resolver: { eventName: MDB_EVENTS.DEVICE_PRORGRAMING_START } },
- { key: 'Program succeeded.', resolver: () => this._imageLoaded = true },
- { key: 'Program succeeded.', resolver: {eventName: MDB_EVENTS.DEVICE_PRORGRAMING_SUCCESS } },
- { key: 'Running', resolver: { eventName: MDB_EVENTS.DEVICE_RUNNING }},
- { key: 'Running', resolver: () => this._running = true },
- { key: 'HALTED', resolver: {
- eventName: MDB_EVENTS.DEVICE_HALT,
- args: () => [{...this._haltInfo, breakpoint: this._haltInfo.address === this._lastBreakpoint}]
- }},
- { key: 'HALTED', resolver: () => { this._running = false; this._lastBreakpoint = -1; } },
- { key: /^>?Working directory: (.*)$/, resolver: {eventName: MDB_EVENTS.MDB_CHANGE_DIRECTORY, args: (arr: RegExpExecArray) => [arr[1]]}},
- { key: /^>?(W[0-9]{4}-[A-Z]{3}): .*$/, resolver: {eventName: MDB_EVENTS.CONSOLE_WARNING, args: (arr: RegExpExecArray) => [arr[0], arr[1], arr[2]]} },
- { key: /^>?Single breakpoint: @0x([0-9A-F]+)$/, resolver: (arr: RegExpExecArray) => this._lastBreakpoint = parseInt(arr[1], 16) },
- { key: /^>?Breakpoint ([0-9]+) at 0x([0-9a-f]+).$/, resolver: {
- eventName: MDB_EVENTS.DEVICE_BREAKPOINT_SET,
- args: (arr: RegExpExecArray) => [{ id: parseInt(arr[1], 10), address: parseInt(arr[2], 16) }]
- }},
- { key: /^>?Breakpoint ([0-9]+) at function (.+)\.$/, resolver: {
- eventName: MDB_EVENTS.DEVICE_BREAKPOINT_SET,
- args: (arr: RegExpExecArray) => [{ id: parseInt(arr[1], 10), function: arr[2] }]
- }},
- { key: /^>?Breakpoint ([0-9]+) at file (.+), line ([0-9]+).$/, resolver: {
- eventName: MDB_EVENTS.DEVICE_BREAKPOINT_SET,
- args: (arr: RegExpExecArray) => [{ id: parseInt(arr[1], 10), file: { name: arr[2], line: parseInt(arr[3], 10) } }]
- }},
- { key: 'Stop at', resolver: () => this._haltInfo = {} },
- { key: /^>?address:0x([0-9a-f]+)$/, resolver: (matches: RegExpExecArray) => this._haltInfo.address = parseInt(matches[1], 16) },
- { key: /^>?file:(.+)$/, resolver: (matches: RegExpExecArray) => this._haltInfo.file = matches[1] },
- { key: /^>?source line:([0-9]+)$/, resolver: (matches: RegExpExecArray) => this._haltInfo.line = parseInt(matches[1], 10) },
- { key: /^>?---debug/, resolver: () => null } /* Silence "---debug peripheral accessed" - provide interface for it later */,
- { key: 'Simulator halted', resolver: () => null } /* Silence "Simulator halted" it's the same as HALTED */,
- { key: 'Stepping', resolver: () => this._running = true } /* Silence "Stepping" - it's output after "stepi" command */,
- ];
- const callResolver = <T>(resolver: Resolver<T>, arg: T) => {
- if (typeof resolver === 'function') {
- resolver(arg);
- } else {
- const args = resolver.args ? resolver.args(arg) : [];
- this.emit(resolver.eventName, ...args);
- }
- };
- const lines = String(data).split("\n").map(line => line.trim()).filter(line => line.length > 0);
- lines.forEach(line => {
- const altLine = (line[0] === '>') ? line.substring(1) : line;
- let handled = false;
- for (const handler of valueHandlers) {
- if (typeof handler.key === 'string') {
- if (line !== handler.key) {
- if (altLine === handler.key) {
- callResolver((handler as ValueHandlerString).resolver, altLine);
- handled = true;
- }
- } else {
- callResolver((handler as ValueHandlerString).resolver, line);
- handled = true;
- }
- } else {
- const match = handler.key.exec(line);
- if (match) {
- callResolver((handler as ValueHandlerRegExp).resolver, match);
- handled = true;
- }
- }
- }
- if (! handled) {
- console.warn("Unhandled line", line);
- }
- });
- }
- private onExit = (code: number, signal: string) => {
- if (code !== 0) {
- console.warn("MDB didn't exit cleanly, code:", code, ", signal:", signal);
- }
- this._process = undefined;
- this._running = false;
- this._initialized = false;
- this.emit(MDB_EVENTS.MDB_STOP);
- }
- private onError = (err: any) => {
- console.warn("Childprocess reported an error", err);
- }
- private async waitUntilInitialized(timeoutMs: number) {
- if (! this._process) {
- throw ERRORS.PROCESS_NOT_RUNNING;
- }
- if (this._initialized) {
- return;
- }
- const exitAwaiter = cancellableEventHandler(this._process, "exit", () => ERRORS.PROCESS_NOT_RUNNING);
- const dataAwaiter = cancellableEventHandler(this, MDB_EVENTS.MDB_INITIALIZED);
- await raceForCancellableHandlersOrTimeout(timeoutMs, exitAwaiter, dataAwaiter);
- }
- }
- const test = async () => {
- const mdb = new MdbWrapper();
- try {
- let halting = false;
- //mdb.on(MDB_EVENTS.CONSOLE_DATA, data => console.log(data));
- mdb.on(MDB_EVENTS.CONSOLE_WRITE, data => console.log(data));
- mdb.on(MDB_EVENTS.CONSOLE_ERROR, data => console.log("E:", data));
- mdb.on(MDB_EVENTS.DEVICE_HALT, (haltInfo: HaltInfo) => {
- console.log(`Device halted at ${haltInfo.breakpoint?'breakpoint ':''}"${haltInfo.file}":${haltInfo.line} (${haltInfo.address})`);
- if (! halting) {
- setImmediate(() => {
- if (haltInfo.breakpoint) {
- mdb.stepIn();
- } else {
- mdb.continue();
- }
- });
- }
- });
- await mdb.start();
- await mdb.selectDevice("PIC16F18857");
- const tool = (await mdb.getHwTools())[0];
- await mdb.selectHwTool(tool);
- await mdb.changeDirectory('C:\\dev\\hipernet\\SterownikiOswietlenia\\PSS\\build');
- await mdb.program('prosty-sterownik-schodow\\prosty-sterownik-schodow.elf');
- await mdb.reset();
- console.log(await mdb.breakpoint_address(3433));
- console.log(await mdb.breakpoint_function("main"));
- console.log(await mdb.breakpoint_line("main.c", 170));
- //await new Promise(resolve => setTimeout(resolve, 3000));
- await mdb.run();
- await new Promise(resolve => setTimeout(resolve, 3000));
- halting = true;
- //await new Promise(resolve => setTimeout(resolve, 3000));
- } finally {
- await mdb.stop();
- }
- };
- test().then(() => console.log("Finished"), (err) => console.error("Error", err));
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement