Skip to content

Commit

Permalink
Switch to espressif's esptool-js library
Browse files Browse the repository at this point in the history
  • Loading branch information
squix78 committed Jan 26, 2024
1 parent 21bdfbd commit df04c51
Show file tree
Hide file tree
Showing 10 changed files with 121 additions and 79 deletions.
36 changes: 27 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
"@angular/platform-browser": "^15.0.0",
"@angular/platform-browser-dynamic": "^15.0.0",
"@angular/router": "^15.0.0",
"esptool.ts": "^0.13.7",
"@types/crypto-js": "^4.2.2",
"crypto-js": "^4.2.0",
"esptool-js": "^0.3.2",
"rxjs": "~7.5.0",
"tailwindcss": "^3.2.4",
"tslib": "^2.3.0",
Expand All @@ -40,4 +42,4 @@
"karma-jasmine-html-reporter": "~2.0.0",
"typescript": "~4.8.2"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export class AddLocalConfigurationComponent implements OnInit {
imageSource: "",
partitions: [{
name: "Firmware",
data: new Uint8Array(),
data: "",
url: "",
offset: 0x00
}]
Expand Down
8 changes: 3 additions & 5 deletions src/app/components/testrunner/testrunner.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,15 @@ export class TestrunnerComponent implements OnInit {
try {
this.firmwareMessages = JSON.parse(message);
this.espPortService.stopMonitor();
if (this.firmwareMessages.length > 0) {
console.log("We have a message");
}
} catch(e) {
this.messageArea = this.messageArea + '\n' + message;
this.messageCount++;
}

})
this.espPortService.subjectLogger.logStatementStream.subscribe(message => {
this.messageArea = this.messageArea + '\n' + message;
this.messageCount++;
this.flasherConsole = message;
});
this.espPortService.testStateStream.subscribe(state => {
console.log("Test State: ", state);
switch(state) {
Expand Down
109 changes: 73 additions & 36 deletions src/app/shared/esp-port.service.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { EspLoader } from 'esptool.ts';

import { ESPLoader, FlashOptions, IEspLoaderTerminal, LoaderOptions, Transport } from "esptool-js";
import { firstValueFrom, Subject } from 'rxjs';
import { SubjectLogger } from './subject-logger';
import { LineBreakTransformer, Partition, PartitionProgress, sleep, TestState } from './utils.service';
import { MD5, enc } from 'crypto-js';


@Injectable({
providedIn: 'root'
Expand All @@ -16,6 +18,9 @@ export class EspPortService {

private controlCharacter: string = "\n";

private transport: Transport;
private esploader: ESPLoader;

// Publishes state changes of the selected serial port
private portStateSource = new Subject<boolean>();
portStateStream = this.portStateSource.asObservable();
Expand All @@ -37,12 +42,23 @@ export class EspPortService {
testStateStream = this.testStateSource.asObservable();

// Characters contained in the first messages after reboot in an ESP32
private resetMessageMatchers: string[] = ['rst:0x1', 'configsip', 'mode:DIO'];
private resetMessageMatchers: string[] = ['rst:0x1', 'configsip', 'mode:DIO', 'entry 0x'];

private reader!: ReadableStreamDefaultReader;
private readableStreamClosed!: any;

subjectLogger = new SubjectLogger();
private espLoaderTerminal = {
clean: () => {
this.monitorMessageSource.next("Clean");
},
writeLine: (data: any) => {
this.monitorMessageSource.next(data);
},
write: (data: any) => {
this.monitorMessageSource.next(data);
},
};


constructor(public httpClient: HttpClient) {
}
Expand All @@ -55,7 +71,24 @@ export class EspPortService {
await this.close();
this.setState(false);
}

const port = await navigator.serial.requestPort();
this.transport = new Transport(port);
try {

const flashOptions = {
transport: this.transport,
baudrate: 115200,
terminal: this.espLoaderTerminal

} as LoaderOptions;
this.esploader = new ESPLoader(flashOptions);

const chip = await this.esploader.main_fn();
console.log(this.esploader.chip);
} catch (e) {
console.error(e);
}
await this.openPort(port);

}
Expand All @@ -69,7 +102,9 @@ export class EspPortService {
this.port.addEventListener('disconnect', (event) => {
this.setState(false);
});
await this.port.open({ baudRate: 115200 });
if (!this.port.readable) {
await this.port.open({ baudRate: 115200 });
}
const portInfo = port.getInfo();
console.log(portInfo);
this.setState(true);
Expand Down Expand Up @@ -144,6 +179,7 @@ export class EspPortService {
}

async readLoop() {
console.log("Is port readable: " + this.port.readable);
while (this.port.readable && this.monitorPort) {
const textDecoder = new TextDecoderStream();
this.readableStreamClosed = this.port.readable.pipeTo(textDecoder.writable);
Expand Down Expand Up @@ -174,46 +210,40 @@ export class EspPortService {
}

async flash(partitions: Partition[]) {
this.loadData(partitions);
await this.loadData(partitions);
try {
const loader = new EspLoader(this.port, { debug: false, logger: this.subjectLogger });
console.log("connecting...");
try {
await loader.connect();
} catch(e) {
this.monitorMessageSource.next("Failed to connect. Close all open monitoring sessions.");
return;
}


try {
console.log("connected");
console.log("writing device partitions");
const chipName = await loader.chipName();
const macAddr = await loader.macAddr();
console.log("Device info. Chip: " + chipName + "mac: " + macAddr);
this.testStateSource.next(TestState.Flashing);
await loader.loadStub();
await loader.setBaudRate(115200, 921600);
let self = this;
const fileArray = [];
//const progressBars = [];
for (let i = 0; i < partitions.length; i++) {
console.log("\nWriting partition: " + partitions[i].name);
this.monitorMessageSource.next("Writing partition: " + partitions[i].name);
await loader.flashData(partitions[i].data, partitions[i].offset, function (idx, cnt) {
let progressPercent = Math.round((idx * 100 / cnt));
console.log("Flashing: ", progressPercent);
self.monitorMessageSource.next('Flashing ' + progressPercent + "%");
self.flashProgressSource.next({index: i, progress: progressPercent});
});
this.monitorMessageSource.next("Partition " + partitions[i].name + ": Done");
self.flashProgressSource.next({index: i, progress: 100});
sleep(100);
fileArray.push({ data: partitions[i].data, address: partitions[i].offset });
}
try {
const flashOptions: FlashOptions = {
fileArray: fileArray,
flashSize: "keep",
eraseAll: false,
compress: true,
reportProgress: (fileIndex, written, total) => {
this.flashProgressSource.next({index: fileIndex, progress: Math.round((written / total) * 100)});
},
calculateMD5Hash: (image) => MD5(enc.Latin1.parse(image)).toString(),
} as FlashOptions;
this.testStateSource.next(TestState.Flashing);
await this.esploader.write_flash(flashOptions);
} catch (e) {
console.error(e);

}
console.log("successfully written device partitions");
console.log("flashing succeeded");
this.testStateSource.next(TestState.Flashed);
await loader.flashFinish(true);
await this.esploader.flash_finish(false);
} finally {
await loader.disconnect();
await this.esploader.hard_reset();
}
} finally {
console.log("Done flashing");
Expand All @@ -224,7 +254,14 @@ export class EspPortService {
this.testStateSource.next(TestState.LoadingFirmware);
await Promise.all(partitions.map(async (partition) => {
let buffer = await firstValueFrom<ArrayBuffer>(this.httpClient.get(partition.url, { responseType: 'arraybuffer' }));
partition.data = new Uint8Array(buffer);
console.log("Array Buffer Length: %d", buffer.byteLength);
var byteArray = new Uint8Array(buffer);
var decoder = new TextDecoder();
var value: number;
for (var i = 0; i < byteArray.length; i++) {
partition.data += String.fromCharCode((byteArray.at(i) || 0));
}

}));
}

Expand Down
24 changes: 0 additions & 24 deletions src/app/shared/subject-logger.ts

This file was deleted.

4 changes: 2 additions & 2 deletions src/app/shared/utils.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export async function sleep(ms: number): Promise<void> {

export type Partition = {
name: string;
data: Uint8Array;
data: string;
offset: number;
url: string;
};
Expand Down Expand Up @@ -54,7 +54,7 @@ export class LineBreakTransformer {
export class JsonTransformer {

container: any = "";
transform(chunk: any, controller: any) {
transform(chunk: any, controller: any) {
try {
controller.enqueue(JSON.parse(chunk));
} catch(e) {
Expand Down
11 changes: 11 additions & 0 deletions src/assets/defaultDeviceConfiguration.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@
"url": "./assets/feather/app-firmware.bin"
}]
},
{
"id": "epulse-feather-c6",
"name": "ePulse Feather C6",
"imageSource": "assets/featherC6/epulsefeather_c6.jpg",
"partitions": [{
"name": "Firmware",
"data": [],
"offset": 0,
"url": "./assets/featherC6/app-firmware.bin"
}]
},
{
"id": "espgateway",
"name": "ESPGateway",
Expand Down
Binary file added src/assets/featherC6/app-firmware.bin
Binary file not shown.
Binary file added src/assets/featherC6/epulsefeather_c6.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit df04c51

Please sign in to comment.