Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Battery powered V2.2 WebUSB errors after unplugging & replugging USB #17

Open
microbit-carlos opened this issue Feb 10, 2023 · 7 comments

Comments

@microbit-carlos
Copy link
Collaborator

microbit-carlos commented Feb 10, 2023

With a micro:bit V2.2 running 0256 or 0257:

  • Connect a battery pack
  • Connect the USB cable
  • Open MakeCode or the Python Editor
  • Connect via WebUSB and flash
  • Disconnect and reconnect the USB cable
  • Try again to connect via WebUSB and flash
  • Eventually, after a few reconnections the micro:bit firmware will cause WebUSB connection errors

This is not replicable with V2.0 running DAPLink 0255.

Current reports:

@microbit-carlos microbit-carlos changed the title Battery powered V2.2 errors with WebUSB connection if reconnected multiple times Battery powered V2.2 WebUSB errors after unplugging and replugging USB Feb 10, 2023
@microbit-carlos microbit-carlos changed the title Battery powered V2.2 WebUSB errors after unplugging and replugging USB Battery powered V2.2 WebUSB errors after unplugging & replugging USB Feb 10, 2023
@martinwork
Copy link

Could not repeat this with V2.00 + 0258-beta1_kl27z_microbit_if_crc_1c60ddb_gcc.hex. Unplugging causes one of

Failed to execute 'transferOut' on 'USBDevice': A transfer error has occurred.
Failed to execute 'transferIn' on 'USBDevice': A transfer error has occurred.

and once there was Bad response for 5 -> 131 at CMSISDAP. which did cause a problem, but it went away after a retry.
makecode.microbit.org-1676231506869.log

@microbit-carlos
Copy link
Collaborator Author

I cannot replicate this in the Python Editor V2, but it does replicate quite easily in Python Editor V3 and MakeCode, so that points at being related to WebUSB serial being pulled.

Commenting out these lines from the Python Editor V3 "resolves" the issue, so I that confirms it's related to that:
https://github.com/microbit-foundation/python-editor-v3/blob/c5b20f13fc66cb8058c00ba4fd1c9325f108a02d/src/device/webusb.ts#L268-L273

@martinwork
Copy link

martinwork commented Mar 17, 2023

With V2.00 and 0258beta2, I saw none of the problems switching between power bank and PC USB with a battery connected given in https://github.com/microbit-foundation/DAPLink-microbit/issues/146.

After testing that 10-20 times, my first attempt to disconnect and connect WebUSB in MakeCode failed

Uncaught (in promise) Error: Bad response for 5 -> 131
    at CMSISDAP.<anonymous> (editor.js:2391:35)
    at step (editor.js:2317:23)
    at Object.next (editor.js:2298:53)
    at fulfilled (editor.js:2289:58)

When I power cycled micro:bit, it connected, and I flashed a program.

Repeatedly reconnecting the USB cable and flashing a program, the same error appears in the console every few (maybe 5-10) connections, the micro:bit logo next to Download keeps pulsing, but flashing always works and appears to fix the connection, though the console says:

Found an ARM Cortex-M4
editor.js:3325 try to access codal information before it is computed
The times when the console shows Bad response for 5 -> 131 correspond to the times that reconnecting doesn't cause a reset.

With a battery powered V2.0, reconnecting USB still seems to cause a glitch in MakeCode. In previous tests I said "WebUSB may be broken until micro:bit is power cycled", but with 0258beta2, all I see is that the MakeCode Download button continues pulsing. Ignoring the pulsing, and downloading anyway always seems to work, as does power cycling or simply reconnecting.

Python seems to repeat the pairing process whenever the USB is disconnected, instead of trying to reconnect, so doesn't see a problem. The only way I could trigger a problem in Python was to add a switch between MakeCode and Python.

@microbit-carlos
Copy link
Collaborator Author

microbit-carlos commented May 19, 2023

A quick note to add that response for command 131 is the ID_DAP_Vendor3 0x83, which in DAPLink is used for ID_DAP_UART_Read, which is reading serial data.

This is likely because the USB cable was disconnected between the editors sending a 131 command, to read serial data (as the Python Editor and MakeCode constantly do in the background) and DAPLink being able to send the respond back.
So, then on the next connection, the editors send a new command, but DAPLink responds with what it already had in its buffer from the previous session.

@microbit-carlos
Copy link
Collaborator Author

Adding a bit of extra logging to the Python Editor we can see the following set of events;

  • The user WebUSB connects, flashes the micro:bit and stays WebUSB connected
  • The editors on the background are constantly checking if there is any serial data to read
  • The editor most commonly sends command 131 (0x83 ID_DAP_Vendor3 -> read serial data), but could be other DAP commands
  • Before DAPLink has a chance to send the response back, the user disconnects the USB cable from the micro:bit
  • The response to command stays in the DAPLink output buffer
  • The user reconnects the micro:bit USB cable
  • The user or the editor reconnects WebUSB
  • The editor starts the connection or the flashing process by sending a DAP command (doesn't matter which)
  • DAPLink already has a response from the previous session in the buffer, so it sends that first
  • The editors detect that the response doesn't match to the last command request and throws an error
  • As part of the error recovery the editor might send other DAP commands like WriteAbort
  • DAPLink now responds with the next response in it's buffer, which was for the first DAP command send in this session
  • At this point DAPLink is always one off, sending a response for the previous request instead of the current one

Ideally we could find a way to reset the DAPLink state/buffers with existing DAP commands, but we haven't looked into this yet.

One possible workaround we could try to implement in the editors (to avoid having to ask users to update the micro:bit firmware with an updated DAPLink) could be the following:

  • Then the wrong DAP response is receive, start tracking what was the expected command
  • Send an innocuous DAP command, for example to read some DAP info
  • If DAPLink sends a response for the previous command instead we can detect we are in this "one off" state
    • Might be worth sending a couple of different commands to be 100% sure
  • From now this point on this WebUSB session we can send a dummy command in-between real commands, to counteract this "one off" issue
    • So it looks like this:
      • Send command 01 -> get bad response
      • Send dummy command -> get response for command 01
      • Send command 02 -> get dummy response
      • Send dummy command -> get response for command 02

@jaustin
Copy link

jaustin commented Jan 23, 2024

Thanks Carlos. Reading through this thread I can't quite determine whether 0258-beta3 fixes this, or whether we still think this is outstanding in DAPLink?

@microbit-carlos
Copy link
Collaborator Author

This is still outstanding in DAPLink.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants