private fullVendorCommandFlashAsync()

in editor/flash.ts [375:438]


    private fullVendorCommandFlashAsync(resp: pxtc.CompileResult): Promise<void> {
        log("full flash")
        pxt.tickEvent("hid.flash.full.start");

        const chunkSize = 62;
        let sentPages = 0;
        return pxt.Util.promiseTimeout(
            FULL_FLASH_TIMEOUT,
            Promise.resolve()
                .then(() => this.dapCmdNums(0x8A /* DAPLinkFlash.OPEN */, 1))
                .then((res) => {
                    log(`daplinkflash open: ${pxt.U.toHex(res)}`)
                    if (res[1] !== 0) {
                        pxt.tickEvent('hid.flash.full.error.open', { res: res[1] })
                        throw new Error(lf("Download failed, please try again"));
                    }
                    const binFile = resp.outfiles[this.binName];
                    log(`bin file ${this.binName} in ${Object.keys(resp.outfiles).join(', ')}, ${binFile?.length || -1}b`)
                    const hexUint8 = pxt.U.stringToUint8Array(binFile);
                    log(`hex ${hexUint8?.byteLength || -1}b, ~${(hexUint8.byteLength / chunkSize) | 0} chunks of ${chunkSize}b`)

                    const sendPages = (offset: number = 0): Promise<void> => {
                        const end = Math.min(hexUint8.length, offset + chunkSize);
                        const nextPageData = hexUint8.slice(offset, end);
                        const cmdData = new Uint8Array(2 + nextPageData.length)
                        cmdData[0] = 0x8C /* DAPLinkFlash.WRITE */
                        cmdData[1] = nextPageData.length
                        cmdData.set(nextPageData, 2)
                        if (sentPages % 128 == 0) // reduce logging
                            log(`next page ${sentPages}: [${offset.toString(16)}, ${end.toString(16)}] (${Math.ceil((hexUint8.length - end) / 1000)}kb left)`)
                        return this.dapCmd(cmdData)
                            .then(() => {
                                this.checkAborted()
                                if (end < hexUint8.length) {
                                    sentPages++;
                                    return sendPages(end);
                                }
                                return Promise.resolve()
                            });
                    }

                    return sendPages();
                })
                .then(() => {
                    log(`close`)
                    return this.dapCmdNums(0x8B /* DAPLinkFlash.CLOSE */);
                })
                .then(res => {
                    log(`daplinkclose: ${pxt.U.toHex(res)}`)
                    return this.dapCmdNums(0x89 /* DAPLinkFlash.RESET */);
                })
                .then((res) => {
                    log(`daplinkreset: ${pxt.U.toHex(res)}`)
                    log(`full flash done`);
                    pxt.tickEvent("hid.flash.full.success");
                }),
            timeoutMessage
        ).catch((e) => {
            log(`error: abort`)
            pxt.tickEvent("hid.flash.full.error");
            this.flashAborted = true;
            return this.resetAndThrowAsync(e);
        });
    }