pxt-microbit 4.1.39 → 4.1.42

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 CHANGED
@@ -3160,11 +3160,13 @@ function bufferConcat(a, b) {
3160
3160
  class DAPWrapper {
3161
3161
  constructor(io) {
3162
3162
  this.io = io;
3163
+ this.initialized = false;
3163
3164
  this.flashAborted = false;
3164
3165
  this.connectionId = 0;
3165
3166
  this.pbuf = new pxt.U.PromiseBuffer();
3166
3167
  this.pageSize = 1024;
3167
3168
  this.numPages = 256;
3169
+ this.usesCODAL = undefined;
3168
3170
  // we don't know yet if jacdac was compiled in the hex
3169
3171
  this.jacdacInHex = undefined;
3170
3172
  this.forceFullFlash = /webusbfullflash=1/.test(window.location.href);
@@ -3178,11 +3180,11 @@ class DAPWrapper {
3178
3180
  log(`device connection changed`);
3179
3181
  this.disconnectAsync()
3180
3182
  .then(() => {
3181
- if (!connect)
3182
- return;
3183
3183
  // we don't know what's being connected
3184
3184
  this.usesCODAL = undefined;
3185
3185
  this.jacdacInHex = undefined;
3186
+ if (!connect)
3187
+ return;
3186
3188
  this.reconnectAsync();
3187
3189
  });
3188
3190
  };
@@ -3241,6 +3243,7 @@ class DAPWrapper {
3241
3243
  if (d > 500) {
3242
3244
  this.processSerialLine(this.pendingSerial);
3243
3245
  this.pendingSerial = null;
3246
+ this.lastPendingSerial = undefined;
3244
3247
  }
3245
3248
  }
3246
3249
  return len;
@@ -3250,12 +3253,21 @@ class DAPWrapper {
3250
3253
  log(`start read serial ${connectionId}`);
3251
3254
  const readSerialLoop = async () => {
3252
3255
  try {
3256
+ let numSer = 0;
3257
+ let numEv = 0;
3253
3258
  while (connectionId === this.connectionId) {
3254
- const len = await this.readSerial();
3255
- const hasData = len > 0;
3256
- //if (hasData)
3257
- // logV(`serial read ${len} bytes`)
3258
- await this.jacdacProcess(hasData);
3259
+ numSer = await this.readSerial();
3260
+ // we need to read jacdac in a tight loop
3261
+ // so we don't miss any event
3262
+ if (this.xchgAddr)
3263
+ numEv = await this.jacdacProcess();
3264
+ else
3265
+ numEv = 0;
3266
+ // no data on either side, wait as little as possible
3267
+ // the browser will eventually throttle this call
3268
+ // https://developer.mozilla.org/en-US/docs/Web/API/setTimeout#reasons_for_delays_longer_than_specified
3269
+ if (!numSer && !numEv)
3270
+ await pxt.U.delay(0);
3259
3271
  }
3260
3272
  log(`stopped serial reader ${connectionId}`);
3261
3273
  }
@@ -3272,10 +3284,21 @@ class DAPWrapper {
3272
3284
  // if we've been running for a while, try reconnecting
3273
3285
  if (timeRunning > 1000) {
3274
3286
  log(`auto-reconnect`);
3275
- await this.reconnectAsync();
3287
+ try {
3288
+ await this.reconnectAsync();
3289
+ }
3290
+ catch (e) {
3291
+ if (e.type === "devicenotfound")
3292
+ return;
3293
+ throw e;
3294
+ }
3276
3295
  }
3277
3296
  }
3278
3297
  }
3298
+ finally {
3299
+ this.pendingSerial = undefined;
3300
+ this.lastPendingSerial = undefined;
3301
+ }
3279
3302
  };
3280
3303
  readSerialLoop();
3281
3304
  }
@@ -3296,23 +3319,39 @@ class DAPWrapper {
3296
3319
  this.cortexM = new DapJS.CortexM(this.dap);
3297
3320
  }
3298
3321
  get binName() {
3322
+ if (this.usesCODAL === undefined)
3323
+ console.warn('try to access codal information before it is computed');
3299
3324
  return (this.usesCODAL ? "mbcodal-" : "mbdal-") + pxtc.BINARY_HEX;
3300
3325
  }
3301
3326
  unsupportedParts() {
3327
+ if (this.usesCODAL === undefined)
3328
+ console.warn('try to access codal information before it is computed');
3302
3329
  if (!this.usesCODAL) {
3303
3330
  return ["logotouch", "builtinspeaker", "microphone", "flashlog"];
3304
3331
  }
3305
3332
  return [];
3306
3333
  }
3334
+ isConnected() {
3335
+ return this.io.isConnected() && this.initialized;
3336
+ }
3337
+ isConnecting() {
3338
+ return this.io.isConnecting() || (this.io.isConnected() && !this.initialized);
3339
+ }
3307
3340
  async reconnectAsync() {
3308
3341
  log(`reconnect`);
3342
+ this.initialized = false;
3309
3343
  this.flashAborted = false;
3344
+ this.io.onConnectionChanged();
3310
3345
  function stringResponse(buf) {
3311
3346
  return pxt.U.uint8ArrayToString(buf.slice(2, 2 + buf[1]));
3312
3347
  }
3313
3348
  await this.stopReadersAsync();
3349
+ const connectionId = this.connectionId;
3314
3350
  this.allocDAP(); // clean dap apis
3315
3351
  await this.io.reconnectAsync();
3352
+ // halt before reading from dap
3353
+ // to avoid interference from data logger
3354
+ await this.cortexM.halt();
3316
3355
  // before calling into dapjs, we use our dapCmdNums() a few times, which which will make sure the responses
3317
3356
  // to commends from previous sessions (if any) are flushed
3318
3357
  const info = await this.dapCmdNums(0x00, 0x04); // info
@@ -3337,11 +3376,13 @@ class DAPWrapper {
3337
3376
  this.pageSize = res[0];
3338
3377
  this.numPages = res[1];
3339
3378
  log(`page size ${this.pageSize}, num pages ${this.numPages}`);
3379
+ // jacdac needs to run to set the xchg address
3340
3380
  await this.checkStateAsync(true);
3381
+ await this.initJacdac(connectionId);
3382
+ this.initialized = true;
3383
+ this.io.onConnectionChanged();
3341
3384
  // start jacdac, serial async
3342
- const connectionId = this.connectionId;
3343
- this.startJacdacSetup(connectionId)
3344
- .then(() => this.startReadSerial(connectionId));
3385
+ this.startReadSerial(connectionId);
3345
3386
  }
3346
3387
  async checkStateAsync(resume) {
3347
3388
  const states = ["reset", "lockup", "sleeping", "halted", "running"];
@@ -3364,6 +3405,7 @@ class DAPWrapper {
3364
3405
  disconnectAsync() {
3365
3406
  log(`disconnect`);
3366
3407
  this.flashAborted = true;
3408
+ this.initialized = false;
3367
3409
  return this.stopReadersAsync()
3368
3410
  .then(() => this.io.disconnectAsync());
3369
3411
  }
@@ -3424,8 +3466,10 @@ class DAPWrapper {
3424
3466
  log(msg + "; retrying");
3425
3467
  return this.recvPacketAsync()
3426
3468
  .then(resp => {
3427
- if (resp[0] == buf[0])
3469
+ if (resp[0] == buf[0]) {
3470
+ log(msg + "; retry success");
3428
3471
  return resp;
3472
+ }
3429
3473
  throw new Error(msg);
3430
3474
  }, err => {
3431
3475
  throw new Error(msg);
@@ -3706,11 +3750,10 @@ class DAPWrapper {
3706
3750
  return null;
3707
3751
  }
3708
3752
  /**
3709
- * Start trying to connect to Jacdac in the background
3710
- * and gracefull cancel as needed
3753
+ * Sniff Jacdac exchange address
3711
3754
  * @returns
3712
3755
  */
3713
- async startJacdacSetup(connectionId) {
3756
+ async initJacdac(connectionId) {
3714
3757
  this.xchgAddr = null;
3715
3758
  this.irqn = undefined;
3716
3759
  this.lastXchg = undefined;
@@ -3730,7 +3773,8 @@ class DAPWrapper {
3730
3773
  let xchg;
3731
3774
  while (xchg == null && xchgRetry++ < 3) {
3732
3775
  log(`jacdac: finding xchg address (retry ${xchgRetry})`);
3733
- await pxt.Util.delay(500); // wait for the program to start and setup memory correctly
3776
+ if (xchgRetry > 0)
3777
+ await pxt.Util.delay(500); // wait for the program to start and setup memory correctly
3734
3778
  if (connectionId != this.connectionId)
3735
3779
  return;
3736
3780
  xchg = await this.findJacdacXchgAddr(connectionId);
@@ -3775,12 +3819,7 @@ class DAPWrapper {
3775
3819
  const addr = 0xE000E200 + (this.irqn >> 5) * 4;
3776
3820
  await this.writeWord(addr, 1 << (this.irqn & 31));
3777
3821
  }
3778
- async jacdacProcess(hadSerial) {
3779
- if (this.xchgAddr == null) {
3780
- if (!hadSerial)
3781
- await this.dapDelay(5000);
3782
- return;
3783
- }
3822
+ async jacdacProcess() {
3784
3823
  const now = Date.now();
3785
3824
  if (this.lastXchg && now - this.lastXchg > 50) {
3786
3825
  logV("slow xchg: " + (now - this.lastXchg) + "ms");
@@ -3832,15 +3871,7 @@ class DAPWrapper {
3832
3871
  }
3833
3872
  }
3834
3873
  }
3835
- if (numev == 0 && !hadSerial)
3836
- await this.dapDelay(5000);
3837
- }
3838
- dapDelay(micros) {
3839
- if (micros > 0xffff)
3840
- throw new Error("too large delay");
3841
- const cmd = new Uint8Array([0x09, 0, 0]);
3842
- pxt.HF2.write16(cmd, 1, micros);
3843
- return this.dapCmd(cmd);
3874
+ return numev;
3844
3875
  }
3845
3876
  }
3846
3877
  function mkDAPLinkPacketIOWrapper(io) {