toitware / esptool.js

TypeScript port of the esptool
MIT License
109 stars 12 forks source link

Reboot device #16

Closed miqmago closed 1 year ago

miqmago commented 1 year ago

Thanks for this awesome library!!!

In my case, sometimes the device gets stucked in download mode. In this device I have to press a button to put IO12 low in order the device to be flashed (MTDI(IO12) in ttgo lora). So if the download has started, the device gets in download mode, but if the button is not pressed, the device keeps in download mode. The previous firmware is there and working but the device is stuck in download mode. The only way to reboot the device is with hardware reset button or disconnecting the battery.

Would be really great to have a method to reset the device when it is in waiting for download.

I've tried to manually send a flash finish with no success, it throws a timeout:

            const loader = new EspLoader(this.port, { debug: true, logger: console });
            await loader.connect();
            await loader.flashFinish();
            await loader.disconnect();

The output logs I get are the following ones, it seems to be communicating with the device:

trying to sync with bootloader...
sync started
Writing 46 bytes: Uint8Array(46) [192, 0, 8, 36, 0, 0, 0, 0, 0, 7, 7, 18, 32, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 192, buffer: ArrayBuffer(64), byteLength: 46, byteOffset: 0, length: 46, Symbol(Symbol.toStringTag): 'Uint8Array']
sync error timeout
Writing 46 bytes: Uint8Array(46) [192, 0, 8, 36, 0, 0, 0, 0, 0, 7, 7, 18, 32, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 192, buffer: ArrayBuffer(64), byteLength: 46, byteOffset: 0, length: 46, Symbol(Symbol.toStringTag): 'Uint8Array']
sync error timeout
Writing 46 bytes: Uint8Array(46) [192, 0, 8, 36, 0, 0, 0, 0, 0, 7, 7, 18, 32, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 192, buffer: ArrayBuffer(64), byteLength: 46, byteOffset: 0, length: 46, Symbol(Symbol.toStringTag): 'Uint8Array']
sync error timeout
Writing 46 bytes: Uint8Array(46) [192, 0, 8, 36, 0, 0, 0, 0, 0, 7, 7, 18, 32, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 192, buffer: ArrayBuffer(64), byteLength: 46, byteOffset: 0, length: 46, Symbol(Symbol.toStringTag): 'Uint8Array']
sync error timeout
Writing 46 bytes: Uint8Array(46) [192, 0, 8, 36, 0, 0, 0, 0, 0, 7, 7, 18, 32, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 192, buffer: ArrayBuffer(64), byteLength: 46, byteOffset: 0, length: 46, Symbol(Symbol.toStringTag): 'Uint8Array']
sync error timeout
Writing 46 bytes: Uint8Array(46) [192, 0, 8, 36, 0, 0, 0, 0, 0, 7, 7, 18, 32, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 192, buffer: ArrayBuffer(64), byteLength: 46, byteOffset: 0, length: 46, Symbol(Symbol.toStringTag): 'Uint8Array']
sync error timeout
Writing 46 bytes: Uint8Array(46) [192, 0, 8, 36, 0, 0, 0, 0, 0, 7, 7, 18, 32, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 192, buffer: ArrayBuffer(64), byteLength: 46, byteOffset: 0, length: 46, Symbol(Symbol.toStringTag): 'Uint8Array']
sync error timeout
sync stopped
failed to sync with bootloader
retrying...
trying to sync with bootloader...
sync started
Writing 46 bytes: Uint8Array(46) [192, 0, 8, 36, 0, 0, 0, 0, 0, 7, 7, 18, 32, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 192, buffer: ArrayBuffer(64), byteLength: 46, byteOffset: 0, length: 46, Symbol(Symbol.toStringTag): 'Uint8Array']
sync error timeout
Writing 46 bytes: Uint8Array(46) [192, 0, 8, 36, 0, 0, 0, 0, 0, 7, 7, 18, 32, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 192, buffer: ArrayBuffer(64), byteLength: 46, byteOffset: 0, length: 46, Symbol(Symbol.toStringTag): 'Uint8Array']
Reading 12 bytes: Uint8Array(12) [1, 8, 4, 0, 18, 32, 85, 85, 0, 0, 0, 0, buffer: ArrayBuffer(1024), byteLength: 12, byteOffset: 1, length: 12, Symbol(Symbol.toStringTag): 'Uint8Array']
value: (4) [18, 32, 85, 85] data: (3) [0, 0, 0]
synced with bootloader
Reading Register 1073745920
Writing 14 bytes: Uint8Array(14) [192, 0, 10, 4, 0, 0, 0, 0, 0, 0, 16, 0, 64, 192, buffer: ArrayBuffer(64), byteLength: 14, byteOffset: 0, length: 14, Symbol(Symbol.toStringTag): 'Uint8Array']
Reading 12 bytes: Uint8Array(12) [1, 10, 4, 0, 131, 29, 240, 0, 0, 0, 0, 0, buffer: ArrayBuffer(1024), byteLength: 12, byteOffset: 1, length: 12, Symbol(Symbol.toStringTag): 'Uint8Array']
value: (4) [131, 29, 240, 0] data: (3) [0, 0, 0]
Writing 18 bytes: Uint8Array(18) [192, 0, 13, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, buffer: ArrayBuffer(64), byteLength: 18, byteOffset: 0, length: 18, Symbol(Symbol.toStringTag): 'Uint8Array']
Reading 12 bytes: Uint8Array(12) [1, 13, 4, 0, 131, 29, 240, 0, 0, 0, 0, 0, buffer: ArrayBuffer(1024), byteLength: 12, byteOffset: 1, length: 12, Symbol(Symbol.toStringTag): 'Uint8Array']
value: (4) [131, 29, 240, 0] data: (3) [0, 0, 0]
Writing 34 bytes: Uint8Array(34) [192, 0, 11, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 1, 0, 0, 16, 0, 0, 0, 1, 0, 0, 255, 255, 0, 0, 192, buffer: ArrayBuffer(64), byteLength: 34, byteOffset: 0, length: 34, Symbol(Symbol.toStringTag): 'Uint8Array']
Reading 12 bytes: Uint8Array(12) [1, 11, 4, 0, 131, 29, 240, 0, 0, 0, 0, 0, buffer: ArrayBuffer(1024), byteLength: 12, byteOffset: 1, length: 12, Symbol(Symbol.toStringTag): 'Uint8Array']
value: (4) [131, 29, 240, 0] data: (3) [0, 0, 0]
Write size 0  blocks  0  block size  1024  offset 0x0000
Writing 26 bytes: Uint8Array(26) [192, 0, 2, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 192, buffer: ArrayBuffer(64), byteLength: 26, byteOffset: 0, length: 26, Symbol(Symbol.toStringTag): 'Uint8Array']
timeout

On the other side, would be also really awesome to have reader data available, so we could monitor devices on the browser. Right now I have my own monitor and when I want to flash, I stop my read loop, leaving port opened and then I connect to EspLoader. This way I could delegate all the work to the library, monitoring and flashing...

miqmago commented 1 year ago

In fact this is little more critical than a feature request. After flashing with the example, the device always remains in download mode.

        try {
            const loader = new EspLoader(this.port, { debug: true, logger: console });
            options.logger.log('connecting...');
            await loader.connect();
            try {
                options.logger.log('connected');
                options.logger.log('writing device partitions');
                const chipName = await loader.chipName();
                const macAddr = await loader.macAddr();
                options.logger.log(`chipname: ${chipName}, mac address: ${macAddr}`);
                await loader.loadStub();
                await loader.setBaudRate(115200, 921600);

                if (options.erase) {
                    options.logger.log('erasing device flash...');
                    await loader.eraseFlash();
                    options.logger.log('successfully erased device flash');
                }

                await partitions.reduce(async (lastFlash, partition) => {
                    await lastFlash;
                    options.logger.log(`\nWriting partition: ${partition.name}`);
                    await loader.flashData(partition.data, partition.offset, (idx, cnt) => {
                        if (options.progressCallback) {
                            options.progressCallback(partition.name, idx, cnt);
                        }
                    });
                    await new Promise((resolve) => { setTimeout(resolve, 100); });
                }, Promise.resolve());

                // Has no efect:
                await loader.flashFinish(true);
                options.logger.log('successfully written device partitions');
                options.logger.log('flashing succeeded');
            } finally {
                await loader.disconnect();
            }
        } finally {
            await this.port.close();
        }
floitsch commented 1 year ago

Thanks for the report.

There is currently little work happening on this library, but @leon0399 created a fork (https://github.com/openhaptics/esptool.ts) which might be more active.

lodemo commented 1 year ago

I am having the same issue, it seems that loader.flashFinish(true) has not the described effect. Its documentation states Leave flash mode and run/reboot, but that doesnt seem to happen.

I need a way to exist the bootloader and reboot into the normal firmware, which if my understanding is correct, is supposed to happen.

Im already using the fork of @openhaptics, but you cant open an issue there so im writing here.

lodemo commented 1 year ago

I have refactored my code to use the espressif/esptool-js library, after some tweaking, everything works fine, including reset after flashing.

miqmago commented 1 year ago

Thanks will give a try!