pxt-microbit 5.1.35 → 5.1.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/built/editor.js +185 -208
- package/built/target.js +1 -1
- package/built/target.json +1 -1
- package/built/targetlight.json +1 -1
- package/package.json +1 -1
package/built/editor.js
CHANGED
|
@@ -3219,17 +3219,15 @@ class DAPWrapper {
|
|
|
3219
3219
|
this.xchgAddr = null;
|
|
3220
3220
|
this.sendQ = [];
|
|
3221
3221
|
this.familyID = 0x0D28; // this is the microbit vendor id, not quite UF2 family id
|
|
3222
|
-
this.io.onDeviceConnectionChanged = (connect) => {
|
|
3222
|
+
this.io.onDeviceConnectionChanged = async (connect) => {
|
|
3223
3223
|
log(`device connection changed`);
|
|
3224
|
-
this.disconnectAsync()
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
this.reconnectAsync();
|
|
3232
|
-
});
|
|
3224
|
+
await this.disconnectAsync();
|
|
3225
|
+
// we don't know what's being connected
|
|
3226
|
+
this.usesCODAL = undefined;
|
|
3227
|
+
this.jacdacInHex = undefined;
|
|
3228
|
+
if (!connect)
|
|
3229
|
+
return;
|
|
3230
|
+
await this.reconnectAsync();
|
|
3233
3231
|
};
|
|
3234
3232
|
this.io.onData = buf => {
|
|
3235
3233
|
// console.log("RD: " + pxt.Util.toHex(buf))
|
|
@@ -3469,14 +3467,14 @@ class DAPWrapper {
|
|
|
3469
3467
|
if (this.flashAborted)
|
|
3470
3468
|
throw new Error(lf("Download cancelled"));
|
|
3471
3469
|
}
|
|
3472
|
-
disconnectAsync() {
|
|
3470
|
+
async disconnectAsync() {
|
|
3473
3471
|
log(`disconnect`);
|
|
3474
3472
|
this.flashAborted = true;
|
|
3475
3473
|
this.initialized = false;
|
|
3476
|
-
|
|
3477
|
-
|
|
3474
|
+
await this.stopReadersAsync();
|
|
3475
|
+
await this.io.disconnectAsync();
|
|
3478
3476
|
}
|
|
3479
|
-
reflashAsync(resp, progressCallback) {
|
|
3477
|
+
async reflashAsync(resp, progressCallback) {
|
|
3480
3478
|
var _a, _b;
|
|
3481
3479
|
pxt.tickEvent("hid.flash.start");
|
|
3482
3480
|
log("reflash");
|
|
@@ -3485,32 +3483,34 @@ class DAPWrapper {
|
|
|
3485
3483
|
const codalJson = resp.outfiles["codal.json"];
|
|
3486
3484
|
this.jacdacInHex = codalJson && !!((_b = (_a = pxt.Util.jsonTryParse(codalJson)) === null || _a === void 0 ? void 0 : _a.definitions) === null || _b === void 0 ? void 0 : _b.JACDAC_WEBUSB);
|
|
3487
3485
|
this.flashAborted = false;
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3486
|
+
if (!this.io.isConnected()) {
|
|
3487
|
+
await this.io.reconnectAsync();
|
|
3488
|
+
}
|
|
3489
|
+
await this.stopReadersAsync();
|
|
3490
|
+
await this.cortexM.init();
|
|
3491
|
+
await this.cortexM.reset(true);
|
|
3492
|
+
await this.checkStateAsync();
|
|
3493
|
+
const uicr = await this.readUICR();
|
|
3494
|
+
pxt.tickEvent("hid.flash.uicr", { uicr });
|
|
3495
|
+
// shortcut, do a full flash
|
|
3496
|
+
if (uicr != 0 || this.forceFullFlash) {
|
|
3497
|
+
pxt.tickEvent("hid.flash.uicrfail");
|
|
3498
|
+
await this.fullVendorCommandFlashAsync(resp, progressCallback);
|
|
3499
|
+
}
|
|
3500
|
+
else {
|
|
3501
3501
|
// check flash checksums
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3502
|
+
const chk = await this.computeFlashChecksum(resp);
|
|
3503
|
+
pxt.tickEvent("hid.flash.checksum", { quick: chk.quick ? 1 : 0, changed: chk.changed ? chk.changed.length : 0 });
|
|
3504
|
+
if (chk.quick) {
|
|
3505
3505
|
// let's do a quick flash!
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
}
|
|
3511
|
-
}
|
|
3512
|
-
|
|
3513
|
-
|
|
3506
|
+
await this.quickHidFlashAsync(chk.changed, progressCallback);
|
|
3507
|
+
}
|
|
3508
|
+
else {
|
|
3509
|
+
await this.fullVendorCommandFlashAsync(resp, progressCallback);
|
|
3510
|
+
}
|
|
3511
|
+
}
|
|
3512
|
+
await this.checkStateAsync(true);
|
|
3513
|
+
pxt.tickEvent("hid.flash.success");
|
|
3514
3514
|
// don't disconnect here
|
|
3515
3515
|
// the micro:bit will automatically disconnect and reconnect
|
|
3516
3516
|
// via the webusb events
|
|
@@ -3521,117 +3521,108 @@ class DAPWrapper {
|
|
|
3521
3521
|
else
|
|
3522
3522
|
return this.pbuf.shiftAsync();
|
|
3523
3523
|
}
|
|
3524
|
-
dapCmd(buf) {
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
}
|
|
3540
|
-
throw new Error(msg);
|
|
3541
|
-
}, err => {
|
|
3542
|
-
throw new Error(msg);
|
|
3543
|
-
});
|
|
3524
|
+
async dapCmd(buf) {
|
|
3525
|
+
await this.io.sendPacketAsync(buf);
|
|
3526
|
+
const resp = await this.recvPacketAsync();
|
|
3527
|
+
if (resp[0] != buf[0]) {
|
|
3528
|
+
pxt.tickEvent('hid.flash.cmderror', { req: buf[0], resp: resp[0] });
|
|
3529
|
+
const msg = `bad dapCmd response: ${buf[0]} -> ${resp[0]}`;
|
|
3530
|
+
// in case we got an invalid response, try to get another response, in case the current
|
|
3531
|
+
// response is a left-over from previous communications
|
|
3532
|
+
log(msg + "; retrying");
|
|
3533
|
+
try {
|
|
3534
|
+
const secondTryResp = await this.recvPacketAsync();
|
|
3535
|
+
if (secondTryResp[0] === buf[0]) {
|
|
3536
|
+
log(msg + "; retry success");
|
|
3537
|
+
return secondTryResp;
|
|
3538
|
+
}
|
|
3544
3539
|
}
|
|
3545
|
-
|
|
3546
|
-
|
|
3540
|
+
catch (e) {
|
|
3541
|
+
log(e);
|
|
3542
|
+
}
|
|
3543
|
+
throw new Error(`retry failed ${msg}`);
|
|
3544
|
+
}
|
|
3545
|
+
return resp;
|
|
3547
3546
|
}
|
|
3548
3547
|
dapCmdNums(...nums) {
|
|
3549
3548
|
return this.dapCmd(new Uint8Array(nums));
|
|
3550
3549
|
}
|
|
3551
|
-
fullVendorCommandFlashAsync(resp, progressCallback) {
|
|
3550
|
+
async fullVendorCommandFlashAsync(resp, progressCallback) {
|
|
3552
3551
|
log("full flash");
|
|
3553
3552
|
pxt.tickEvent("hid.flash.full.start");
|
|
3554
3553
|
const start = Date.now();
|
|
3555
3554
|
const chunkSize = 62;
|
|
3556
3555
|
let sentPages = 0;
|
|
3557
|
-
|
|
3558
|
-
.
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
}
|
|
3565
|
-
const binFile = this.getBinFile(resp);
|
|
3566
|
-
log(`bin file ${this.binName} in ${Object.keys(resp.outfiles).join(', ')}, ${(binFile === null || binFile === void 0 ? void 0 : binFile.length) || -1}b`);
|
|
3567
|
-
const hexUint8 = pxt.U.stringToUint8Array(binFile);
|
|
3568
|
-
log(`hex ${(hexUint8 === null || hexUint8 === void 0 ? void 0 : hexUint8.byteLength) || -1}b, ~${(hexUint8.byteLength / chunkSize) | 0} chunks of ${chunkSize}b`);
|
|
3569
|
-
const sendPages = (offset = 0) => {
|
|
3570
|
-
const end = Math.min(hexUint8.length, offset + chunkSize);
|
|
3571
|
-
const nextPageData = hexUint8.slice(offset, end);
|
|
3572
|
-
const cmdData = new Uint8Array(2 + nextPageData.length);
|
|
3573
|
-
cmdData[0] = 0x8C; /* DAPLinkFlash.WRITE */
|
|
3574
|
-
cmdData[1] = nextPageData.length;
|
|
3575
|
-
cmdData.set(nextPageData, 2);
|
|
3576
|
-
if (sentPages % 128 == 0) { // reduce logging
|
|
3577
|
-
progressCallback(offset / hexUint8.length);
|
|
3578
|
-
log(`next page ${sentPages}: [${offset.toString(16)}, ${end.toString(16)}] (${Math.ceil((hexUint8.length - end) / 1000)}kb left)`);
|
|
3556
|
+
try {
|
|
3557
|
+
await pxt.Util.promiseTimeout(FULL_FLASH_TIMEOUT, (async () => {
|
|
3558
|
+
const dapOpenRes = await this.dapCmdNums(0x8A /* DAPLinkFlash.OPEN */, 1);
|
|
3559
|
+
log(`daplinkflash open: ${pxt.U.toHex(dapOpenRes)}`);
|
|
3560
|
+
if (dapOpenRes[1] !== 0) {
|
|
3561
|
+
pxt.tickEvent('hid.flash.full.error.open', { res: dapOpenRes[1] });
|
|
3562
|
+
throw new Error(lf("Download failed, please try again"));
|
|
3579
3563
|
}
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3564
|
+
const binFile = this.getBinFile(resp);
|
|
3565
|
+
log(`bin file ${this.binName} in ${Object.keys(resp.outfiles).join(', ')}, ${(binFile === null || binFile === void 0 ? void 0 : binFile.length) || -1}b`);
|
|
3566
|
+
const hexUint8 = pxt.U.stringToUint8Array(binFile);
|
|
3567
|
+
log(`hex ${(hexUint8 === null || hexUint8 === void 0 ? void 0 : hexUint8.byteLength) || -1}b, ~${(hexUint8.byteLength / chunkSize) | 0} chunks of ${chunkSize}b`);
|
|
3568
|
+
let offset = 0;
|
|
3569
|
+
while (offset < hexUint8.length) {
|
|
3570
|
+
const end = Math.min(hexUint8.length, offset + chunkSize);
|
|
3571
|
+
const nextPageData = hexUint8.slice(offset, end);
|
|
3572
|
+
const cmdData = new Uint8Array(2 + nextPageData.length);
|
|
3573
|
+
cmdData[0] = 0x8C; /* DAPLinkFlash.WRITE */
|
|
3574
|
+
cmdData[1] = nextPageData.length;
|
|
3575
|
+
cmdData.set(nextPageData, 2);
|
|
3576
|
+
if (sentPages % 128 == 0) { // reduce logging
|
|
3577
|
+
progressCallback(offset / hexUint8.length);
|
|
3578
|
+
log(`next page ${sentPages}: [${offset.toString(16)}, ${end.toString(16)}] (${Math.ceil((hexUint8.length - end) / 1000)}kb left)`);
|
|
3586
3579
|
}
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
log(`full flash done after ${Date.now() - start}ms`);
|
|
3603
|
-
pxt.tickEvent("hid.flash.full.success");
|
|
3604
|
-
}), timeoutMessage).catch((e) => {
|
|
3580
|
+
await this.dapCmd(cmdData);
|
|
3581
|
+
this.checkAborted();
|
|
3582
|
+
sentPages++;
|
|
3583
|
+
offset = end;
|
|
3584
|
+
}
|
|
3585
|
+
log("close");
|
|
3586
|
+
const closeRes = await this.dapCmdNums(0x8B /* DAPLinkFlash.CLOSE */);
|
|
3587
|
+
log(`daplinkclose: ${pxt.U.toHex(closeRes)}`);
|
|
3588
|
+
const resetRes = await this.dapCmdNums(0x89 /* DAPLinkFlash.RESET */);
|
|
3589
|
+
log(`daplinkreset: ${pxt.U.toHex(resetRes)}`);
|
|
3590
|
+
log(`full flash done after ${Date.now() - start}ms`);
|
|
3591
|
+
pxt.tickEvent("hid.flash.full.success");
|
|
3592
|
+
})(), timeoutMessage);
|
|
3593
|
+
}
|
|
3594
|
+
catch (e) {
|
|
3605
3595
|
log(`error: abort`);
|
|
3606
3596
|
pxt.tickEvent("hid.flash.full.error");
|
|
3607
3597
|
this.flashAborted = true;
|
|
3608
3598
|
return this.resetAndThrowAsync(e);
|
|
3609
|
-
}
|
|
3599
|
+
}
|
|
3600
|
+
;
|
|
3610
3601
|
}
|
|
3611
|
-
resetAndThrowAsync(e) {
|
|
3602
|
+
async resetAndThrowAsync(e) {
|
|
3612
3603
|
log(`reset on error`);
|
|
3613
3604
|
pxt.tickEvent("hid.flash.reset");
|
|
3614
3605
|
console.debug(e);
|
|
3615
3606
|
// reset any pending daplink
|
|
3616
|
-
|
|
3617
|
-
.
|
|
3607
|
+
try {
|
|
3608
|
+
await this.dapCmdNums(0x89 /* DAPLinkFlash.RESET */);
|
|
3609
|
+
}
|
|
3610
|
+
catch (e) {
|
|
3618
3611
|
// Best effort reset, no-op if there's an error
|
|
3619
|
-
}
|
|
3620
|
-
|
|
3621
|
-
.
|
|
3612
|
+
}
|
|
3613
|
+
try {
|
|
3614
|
+
await this.cortexM.reset(false);
|
|
3615
|
+
}
|
|
3616
|
+
catch (e) {
|
|
3622
3617
|
// Best effort reset, no-op if there's an error
|
|
3623
|
-
}
|
|
3624
|
-
|
|
3625
|
-
throw e;
|
|
3626
|
-
});
|
|
3618
|
+
}
|
|
3619
|
+
throw e;
|
|
3627
3620
|
}
|
|
3628
|
-
readUICR() {
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
return uicr;
|
|
3634
|
-
});
|
|
3621
|
+
async readUICR() {
|
|
3622
|
+
const v = await this.readWords(0x10001014, 1);
|
|
3623
|
+
const uicr = v[0] & 0xff;
|
|
3624
|
+
log(`uicr: ${uicr.toString(16)} (${v[0].toString(16)})`);
|
|
3625
|
+
return uicr;
|
|
3635
3626
|
}
|
|
3636
3627
|
getBinFile(resp) {
|
|
3637
3628
|
var _a;
|
|
@@ -3643,31 +3634,29 @@ class DAPWrapper {
|
|
|
3643
3634
|
return resp.outfiles[pxtc.BINARY_HEX];
|
|
3644
3635
|
throw new Error(`unable to find ${this.binName} in outfiles ${Object.keys(resp.outfiles).join(', ')}`);
|
|
3645
3636
|
}
|
|
3646
|
-
computeFlashChecksum(resp) {
|
|
3637
|
+
async computeFlashChecksum(resp) {
|
|
3647
3638
|
const binFile = this.getBinFile(resp);
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
};
|
|
3664
|
-
});
|
|
3639
|
+
const checksums = await this.getFlashChecksumsAsync();
|
|
3640
|
+
log(`checksums ${pxt.Util.toHex(checksums)}`);
|
|
3641
|
+
// TODO this is seriously inefficient (130ms on a fast machine)
|
|
3642
|
+
const uf2 = ts.pxtc.UF2.newBlockFile();
|
|
3643
|
+
ts.pxtc.UF2.writeHex(uf2, binFile.split(/\r?\n/));
|
|
3644
|
+
const bytes = pxt.U.stringToUint8Array(ts.pxtc.UF2.serializeFile(uf2));
|
|
3645
|
+
const parsed = ts.pxtc.UF2.parseFile(bytes);
|
|
3646
|
+
const aligned = DAPWrapper.pageAlignBlocks(parsed, this.pageSize);
|
|
3647
|
+
const changed = DAPWrapper.onlyChanged(aligned, checksums, this.pageSize);
|
|
3648
|
+
const quick = changed.length < aligned.length / 2;
|
|
3649
|
+
log(`pages: ${aligned.length}, changed ${changed.length}, ${quick ? "quick" : "full"}`);
|
|
3650
|
+
return {
|
|
3651
|
+
quick,
|
|
3652
|
+
changed
|
|
3653
|
+
};
|
|
3665
3654
|
}
|
|
3666
|
-
quickHidFlashAsync(changed, progressCallback) {
|
|
3655
|
+
async quickHidFlashAsync(changed, progressCallback) {
|
|
3667
3656
|
log("quick flash");
|
|
3668
3657
|
pxt.tickEvent("hid.flash.quick.start");
|
|
3669
3658
|
const start = Date.now();
|
|
3670
|
-
const runFlash = (b, dataAddr) => {
|
|
3659
|
+
const runFlash = async (b, dataAddr) => {
|
|
3671
3660
|
const cmd = this.cortexM.prepareCommand();
|
|
3672
3661
|
cmd.halt();
|
|
3673
3662
|
cmd.writeCoreRegister(15 /* PC */, loadAddr + 4 + 1);
|
|
@@ -3676,85 +3665,73 @@ class DAPWrapper {
|
|
|
3676
3665
|
cmd.writeCoreRegister(0, b.targetAddr);
|
|
3677
3666
|
cmd.writeCoreRegister(1, dataAddr);
|
|
3678
3667
|
cmd.writeCoreRegister(2, this.pageSize >> 2);
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
.then(() => {
|
|
3685
|
-
// starts the program
|
|
3686
|
-
logV(`cortex.debug.enable`);
|
|
3687
|
-
return this.cortexM.debug.enable();
|
|
3688
|
-
});
|
|
3668
|
+
logV("setregs");
|
|
3669
|
+
await cmd.go();
|
|
3670
|
+
// starts the program
|
|
3671
|
+
logV(`cortex.debug.enable`);
|
|
3672
|
+
return this.cortexM.debug.enable();
|
|
3689
3673
|
};
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
logV("write next");
|
|
3717
|
-
let buf = new Uint32Array(next.data.buffer);
|
|
3718
|
-
return this.cortexM.memory.writeBlock(nextAddr, buf);
|
|
3719
|
-
})
|
|
3720
|
-
.then(() => {
|
|
3674
|
+
const quickHidFlashCoreAsync = async () => {
|
|
3675
|
+
await this.cortexM.memory.writeBlock(loadAddr, flashPageBIN);
|
|
3676
|
+
for (let i = 0; i < changed.length; i++) {
|
|
3677
|
+
this.checkAborted();
|
|
3678
|
+
let b = changed[i];
|
|
3679
|
+
if (b.targetAddr >= 0x10000000) {
|
|
3680
|
+
log(`target address 0x${b.targetAddr.toString(16)} > 0x10000000`);
|
|
3681
|
+
continue;
|
|
3682
|
+
}
|
|
3683
|
+
log(`about to write at 0x${b.targetAddr.toString(16)}`);
|
|
3684
|
+
progressCallback(i / changed.length);
|
|
3685
|
+
const thisAddr = (i & 1) ? dataAddr : dataAddr + this.pageSize;
|
|
3686
|
+
const nextAddr = (i & 1) ? dataAddr + this.pageSize : dataAddr;
|
|
3687
|
+
if (i == 0) {
|
|
3688
|
+
const u32data = new Uint32Array(b.data.length / 4);
|
|
3689
|
+
for (let i = 0; i < b.data.length; i += 4)
|
|
3690
|
+
u32data[i >> 2] = pxt.HF2.read32(b.data, i);
|
|
3691
|
+
await this.cortexM.memory.writeBlock(thisAddr, u32data);
|
|
3692
|
+
}
|
|
3693
|
+
await runFlash(b, thisAddr);
|
|
3694
|
+
const next = changed[i + 1];
|
|
3695
|
+
if (next) {
|
|
3696
|
+
logV("write next");
|
|
3697
|
+
const buf = new Uint32Array(next.data.buffer);
|
|
3698
|
+
await this.cortexM.memory.writeBlock(nextAddr, buf);
|
|
3699
|
+
}
|
|
3721
3700
|
logV("wait");
|
|
3722
|
-
|
|
3723
|
-
})
|
|
3724
|
-
.then(() => {
|
|
3701
|
+
await this.cortexM.waitForHalt(500);
|
|
3725
3702
|
logV("done block");
|
|
3726
|
-
}
|
|
3727
|
-
}))
|
|
3728
|
-
.then(() => {
|
|
3703
|
+
}
|
|
3729
3704
|
log(`quick flash done after ${Date.now() - start}ms`);
|
|
3730
|
-
|
|
3731
|
-
})
|
|
3732
|
-
.then(() => {
|
|
3705
|
+
await this.cortexM.reset(false);
|
|
3733
3706
|
pxt.tickEvent("hid.flash.quick.success");
|
|
3734
|
-
|
|
3735
|
-
}
|
|
3707
|
+
await this.checkStateAsync(true);
|
|
3708
|
+
};
|
|
3709
|
+
try {
|
|
3710
|
+
await pxt.Util.promiseTimeout(PARTIAL_FLASH_TIMEOUT, quickHidFlashCoreAsync(), timeoutMessage);
|
|
3711
|
+
}
|
|
3712
|
+
catch (e) {
|
|
3736
3713
|
pxt.tickEvent("hid.flash.quick.error");
|
|
3737
3714
|
this.flashAborted = true;
|
|
3738
3715
|
return this.resetAndThrowAsync(e);
|
|
3739
|
-
}
|
|
3716
|
+
}
|
|
3740
3717
|
}
|
|
3741
|
-
getFlashChecksumsAsync() {
|
|
3718
|
+
async getFlashChecksumsAsync() {
|
|
3742
3719
|
log("flash checksums");
|
|
3743
3720
|
let pages = this.numPages;
|
|
3744
|
-
|
|
3745
|
-
|
|
3721
|
+
await this.cortexM.runCode(computeChecksums2, loadAddr, loadAddr + 1, 0xffffffff, stackAddr, true, dataAddr, 0, this.pageSize, pages);
|
|
3722
|
+
return this.cortexM.memory.readBlock(dataAddr, pages * 2, this.pageSize);
|
|
3746
3723
|
}
|
|
3747
|
-
readWords(addr, numWords) {
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3724
|
+
async readWords(addr, numWords) {
|
|
3725
|
+
const u8 = await this.cortexM.memory.readBlock(addr, numWords, this.pageSize);
|
|
3726
|
+
// assume browser is little-endian
|
|
3727
|
+
return new Uint32Array(u8.buffer);
|
|
3751
3728
|
}
|
|
3752
3729
|
writeWords(addr, buf) {
|
|
3753
3730
|
return this.cortexM.memory.writeBlock(addr, buf);
|
|
3754
3731
|
}
|
|
3755
|
-
readBytes(addr, numBytes) {
|
|
3756
|
-
|
|
3757
|
-
|
|
3732
|
+
async readBytes(addr, numBytes) {
|
|
3733
|
+
const u8 = await this.cortexM.memory.readBlock(addr, (numBytes + 3) >> 2, this.pageSize);
|
|
3734
|
+
return u8.length == numBytes ? u8 : u8.slice(0, numBytes);
|
|
3758
3735
|
}
|
|
3759
3736
|
static onlyChanged(blocks, checksums, pageSize) {
|
|
3760
3737
|
return blocks.filter(b => {
|