in editor/flash.ts [244:345]
private quickHidFlashAsync(resp: pxtc.CompileResult): Promise<void> {
log("quick flash")
let logV = (msg: string) => { }
//let logV = log
let aborted = false;
const runFlash = (b: ts.pxtc.UF2.Block, dataAddr: number) => {
const cmd = this.cortexM.prepareCommand();
cmd.halt();
cmd.writeCoreRegister(DapJS.CortexReg.PC, loadAddr + 4 + 1);
cmd.writeCoreRegister(DapJS.CortexReg.LR, loadAddr + 1);
cmd.writeCoreRegister(DapJS.CortexReg.SP, stackAddr);
cmd.writeCoreRegister(0, b.targetAddr);
cmd.writeCoreRegister(1, dataAddr);
cmd.writeCoreRegister(2, this.pageSize >> 2);
return Promise.resolve()
.then(() => {
logV("setregs")
return cmd.go()
})
.then(() => {
logV("dbg en")
// starts the program
return this.cortexM.debug.enable()
})
}
let checksums: Uint8Array
return this.getFlashChecksumsAsync()
.then(buf => {
checksums = buf;
log("write code");
return this.cortexM.memory.writeBlock(loadAddr, flashPageBIN);
})
.then(() => {
log("convert");
// TODO this is seriously inefficient (130ms on a fast machine)
let uf2 = ts.pxtc.UF2.newBlockFile();
ts.pxtc.UF2.writeHex(uf2, resp.outfiles[this.binName].split(/\r?\n/));
let bytes = pxt.U.stringToUint8Array(ts.pxtc.UF2.serializeFile(uf2));
let parsed = ts.pxtc.UF2.parseFile(bytes);
let aligned = DAPWrapper.pageAlignBlocks(parsed, this.pageSize);
log(`initial: ${aligned.length} pages`);
aligned = DAPWrapper.onlyChanged(aligned, checksums, this.pageSize);
log(`incremental: ${aligned.length} pages`);
return Promise.mapSeries(pxt.U.range(aligned.length),
i => {
if (aborted) return Promise.resolve();
let b = aligned[i];
if (b.targetAddr >= 0x10000000)
return Promise.resolve();
logV("about to write at 0x" + b.targetAddr.toString(16));
let writeBl = Promise.resolve();
let thisAddr = (i & 1) ? dataAddr : dataAddr + this.pageSize;
let nextAddr = (i & 1) ? dataAddr + this.pageSize : dataAddr;
if (i == 0) {
let u32data = new Uint32Array(b.data.length / 4);
for (let i = 0; i < b.data.length; i += 4)
u32data[i >> 2] = pxt.HF2.read32(b.data, i);
writeBl = this.cortexM.memory.writeBlock(thisAddr, u32data);
}
return writeBl
.then(() => runFlash(b, thisAddr))
.then(() => {
let next = aligned[i + 1];
if (!next)
return Promise.resolve();
logV("write next");
let buf = new Uint32Array(next.data.buffer);
return this.cortexM.memory.writeBlock(nextAddr, buf);
})
.then(() => {
logV("wait");
return this.cortexM.waitForHalt(500);
})
.then(() => {
logV("done block");
});
})
.then(() => {
log("flash done");
pxt.tickEvent("hid.flash.done");
return this.cortexM.reset(false);
});
})
.timeout(25000, timeoutMessage)
.catch((e) => {
aborted = true;
return Promise.reject(e);
});
}