mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-06-05 19:56:34 +00:00
ATL-61: Implemented burn bootloader.
Signed-off-by: Akos Kitta <kittaakos@typefox.io>
This commit is contained in:
parent
525e688d70
commit
b5d7c3b45d
@ -117,6 +117,7 @@ import { EditorWidgetFactory as TheiaEditorWidgetFactory } from '@theia/editor/l
|
||||
import { EditorWidgetFactory } from './theia/editor/editor-widget-factory';
|
||||
import { OutputWidget as TheiaOutputWidget } from '@theia/output/lib/browser/output-widget';
|
||||
import { OutputWidget } from './theia/output/output-widget';
|
||||
import { BurnBootloader } from './contributions/burn-bootloader';
|
||||
|
||||
const ElementQueries = require('css-element-queries/src/ElementQueries');
|
||||
|
||||
@ -358,4 +359,5 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
Contribution.configure(bind, QuitApp);
|
||||
Contribution.configure(bind, SketchControl);
|
||||
Contribution.configure(bind, Settings);
|
||||
Contribution.configure(bind, BurnBootloader);
|
||||
});
|
||||
|
@ -0,0 +1,94 @@
|
||||
import { inject, injectable } from 'inversify';
|
||||
import { OutputChannelManager } from '@theia/output/lib/common/output-channel';
|
||||
import { CoreService } from '../../common/protocol';
|
||||
import { ArduinoMenus } from '../menu/arduino-menus';
|
||||
import { BoardsDataStore } from '../boards/boards-data-store';
|
||||
import { MonitorConnection } from '../monitor/monitor-connection';
|
||||
import { BoardsServiceClientImpl } from '../boards/boards-service-client-impl';
|
||||
import { SketchContribution, Command, CommandRegistry, MenuModelRegistry } from './contribution';
|
||||
|
||||
@injectable()
|
||||
export class BurnBootloader extends SketchContribution {
|
||||
|
||||
@inject(CoreService)
|
||||
protected readonly coreService: CoreService;
|
||||
|
||||
@inject(MonitorConnection)
|
||||
protected readonly monitorConnection: MonitorConnection;
|
||||
|
||||
@inject(BoardsDataStore)
|
||||
protected readonly boardsDataStore: BoardsDataStore;
|
||||
|
||||
@inject(BoardsServiceClientImpl)
|
||||
protected readonly boardsServiceClientImpl: BoardsServiceClientImpl;
|
||||
|
||||
@inject(OutputChannelManager)
|
||||
protected readonly outputChannelManager: OutputChannelManager;
|
||||
|
||||
registerCommands(registry: CommandRegistry): void {
|
||||
registry.registerCommand(BurnBootloader.Commands.BURN_BOOTLOADER, {
|
||||
execute: () => this.burnBootloader()
|
||||
});
|
||||
}
|
||||
|
||||
registerMenus(registry: MenuModelRegistry): void {
|
||||
registry.registerMenuAction(ArduinoMenus.TOOLS__BOARD_SETTINGS_GROUP, {
|
||||
commandId: BurnBootloader.Commands.BURN_BOOTLOADER.id,
|
||||
label: 'Burn Bootloader',
|
||||
order: 'z99'
|
||||
});
|
||||
}
|
||||
|
||||
async burnBootloader(): Promise<void> {
|
||||
const monitorConfig = this.monitorConnection.monitorConfig;
|
||||
if (monitorConfig) {
|
||||
await this.monitorConnection.disconnect();
|
||||
}
|
||||
try {
|
||||
const { boardsConfig } = this.boardsServiceClientImpl;
|
||||
if (!boardsConfig || !boardsConfig.selectedBoard) {
|
||||
throw new Error('No boards selected. Please select a board.');
|
||||
}
|
||||
if (!boardsConfig.selectedBoard.fqbn) {
|
||||
throw new Error(`No core is installed for the '${boardsConfig.selectedBoard.name}' board. Please install the core.`);
|
||||
}
|
||||
const { selectedPort } = boardsConfig;
|
||||
if (!selectedPort) {
|
||||
throw new Error('No ports selected. Please select a port.');
|
||||
}
|
||||
|
||||
const port = selectedPort.address;
|
||||
const [fqbn, { selectedProgrammer: programmer }] = await Promise.all([
|
||||
this.boardsDataStore.appendConfigToFqbn(boardsConfig.selectedBoard.fqbn),
|
||||
this.boardsDataStore.getData(boardsConfig.selectedBoard.fqbn)
|
||||
]);
|
||||
|
||||
if (!programmer) {
|
||||
throw new Error('Programmer is not selected. Please select a programmer from the `Tools` > `Programmer` menu.');
|
||||
}
|
||||
|
||||
this.outputChannelManager.getChannel('Arduino: bootloader').clear();
|
||||
await this.coreService.burnBootloader({
|
||||
fqbn,
|
||||
programmer,
|
||||
port
|
||||
});
|
||||
this.messageService.info('Done burning bootloader.', { timeout: 1000 });
|
||||
} catch (e) {
|
||||
this.messageService.error(e.toString());
|
||||
} finally {
|
||||
if (monitorConfig) {
|
||||
await this.monitorConnection.connect(monitorConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export namespace BurnBootloader {
|
||||
export namespace Commands {
|
||||
export const BURN_BOOTLOADER: Command = {
|
||||
id: 'arduino-burn-bootloader'
|
||||
};
|
||||
}
|
||||
}
|
@ -103,7 +103,7 @@ export class UploadSketch extends SketchContribution {
|
||||
if (usingProgrammer) {
|
||||
const programmer = selectedProgrammer;
|
||||
if (!programmer) {
|
||||
throw new Error('Programmer is not selected. Please select a programmer.');
|
||||
throw new Error('Programmer is not selected. Please select a programmer from the `Tools` > `Programmer` menu.');
|
||||
}
|
||||
let port: undefined | string = undefined;
|
||||
// If the port is set by the user, we pass it to the CLI as it might be required.
|
||||
|
@ -30,7 +30,7 @@ export namespace ArduinoMenus {
|
||||
export const TOOLS = [...MAIN_MENU_BAR, '4_tools'];
|
||||
// `Auto Format`, `Library Manager...`, `Boards Manager...`
|
||||
export const TOOLS__MAIN_GROUP = [...TOOLS, '0_main'];
|
||||
// Core settings, such as `Processor` and `Programmers` for the board.
|
||||
// Core settings, such as `Processor` and `Programmers` for the board and `Burn Bootloader`
|
||||
export const TOOLS__BOARD_SETTINGS_GROUP = [...TOOLS, '1_board_settings'];
|
||||
|
||||
// Context menu
|
||||
|
@ -11,6 +11,7 @@ export const CoreService = Symbol('CoreService');
|
||||
export interface CoreService extends JsonRpcServer<CoreServiceClient> {
|
||||
compile(options: CoreService.Compile.Options): Promise<void>;
|
||||
upload(options: CoreService.Upload.Options): Promise<void>;
|
||||
burnBootloader(options: CoreService.Bootloader.Options): Promise<void>;
|
||||
}
|
||||
|
||||
export namespace CoreService {
|
||||
@ -29,4 +30,12 @@ export namespace CoreService {
|
||||
Compile.Options & Readonly<{ programmer: Programmer, port?: string }>;
|
||||
}
|
||||
|
||||
export namespace Bootloader {
|
||||
export interface Options {
|
||||
readonly fqbn: string;
|
||||
readonly programmer: Programmer;
|
||||
readonly port: string;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import { BoardsService } from '../common/protocol/boards-service';
|
||||
import { CoreClientProvider } from './core-client-provider';
|
||||
import * as path from 'path';
|
||||
import { ToolOutputServiceServer } from '../common/protocol/tool-output-service';
|
||||
import { UploadReq, UploadResp } from './cli-protocol/commands/upload_pb';
|
||||
import { UploadReq, UploadResp, BurnBootloaderReq, BurnBootloaderResp } from './cli-protocol/commands/upload_pb';
|
||||
|
||||
@injectable()
|
||||
export class CoreServiceImpl implements CoreService {
|
||||
@ -113,9 +113,9 @@ export class CoreServiceImpl implements CoreService {
|
||||
|
||||
try {
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
result.on('data', (cr: UploadResp) => {
|
||||
this.toolOutputService.append({ tool: 'upload', chunk: Buffer.from(cr.getOutStream_asU8()).toString() });
|
||||
this.toolOutputService.append({ tool: 'upload', chunk: Buffer.from(cr.getErrStream_asU8()).toString() });
|
||||
result.on('data', (resp: UploadResp) => {
|
||||
this.toolOutputService.append({ tool: 'upload', chunk: Buffer.from(resp.getOutStream_asU8()).toString() });
|
||||
this.toolOutputService.append({ tool: 'upload', chunk: Buffer.from(resp.getErrStream_asU8()).toString() });
|
||||
});
|
||||
result.on('error', error => reject(error));
|
||||
result.on('end', () => resolve());
|
||||
@ -127,6 +127,40 @@ export class CoreServiceImpl implements CoreService {
|
||||
}
|
||||
}
|
||||
|
||||
async burnBootloader(options: CoreService.Bootloader.Options): Promise<void> {
|
||||
const coreClient = await this.coreClientProvider.client();
|
||||
if (!coreClient) {
|
||||
return;
|
||||
}
|
||||
const { fqbn, port, programmer } = options;
|
||||
if (!fqbn) {
|
||||
throw new Error('The selected board has no FQBN.');
|
||||
}
|
||||
if (!port) {
|
||||
throw new Error('Port must be specified.');
|
||||
}
|
||||
const { client, instance } = coreClient;
|
||||
const req = new BurnBootloaderReq();
|
||||
req.setFqbn(fqbn);
|
||||
req.setPort(port);
|
||||
req.setProgrammer(programmer.id);
|
||||
req.setInstance(instance);
|
||||
const result = client.burnBootloader(req);
|
||||
try {
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
result.on('data', (resp: BurnBootloaderResp) => {
|
||||
this.toolOutputService.append({ tool: 'bootloader', chunk: Buffer.from(resp.getOutStream_asU8()).toString() });
|
||||
this.toolOutputService.append({ tool: 'bootloader', chunk: Buffer.from(resp.getErrStream_asU8()).toString() });
|
||||
});
|
||||
result.on('error', error => reject(error));
|
||||
result.on('end', () => resolve());
|
||||
});
|
||||
} catch (e) {
|
||||
this.toolOutputService.append({ tool: 'bootloader', chunk: `Error while burning the bootloader: ${e}\n`, severity: 'error' });
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
setClient(client: CoreServiceClient | undefined): void {
|
||||
this.client = client;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user