Connection being lost when flashing via USB

Hi All,

While building a project, I am finding myself having to detaching the usb cable and connecting it again in order to flash the device. After doing that, it works fine. But then again after few minutes, I see the following:

:::: PUTTING DEVICE INTO DFU MODE
▌ Sending a command to the device…
(the process goes to a halt not like usual while the photon is blinking yellow anyways)

Any idea what it could be? bad cable?
Im on mac and dedvice OS is 2.0.1

Not sure I fully understand the problem you are having.

When using the Workbench have you Configured for Device; OS, Photon and name of device. Is the name of the device the same as the one you are flashing to?
I then presume you have used Local Compile followed by Local Flash?
Sometimes the serial port can’t send a signal to the photon - it could be a bad cable. Sometimes the switch to DFU (flashing yellow) is very easy and sometimes it helps to put the device in DFU mode before the flash.

1 Like

TL;DR: When Workbench hangs when trying to put a device into DFU mode, end the task and then retry. To reset a device without pressing the button or unplugging it you can use particle usb reset.

Internally, Workbench uses particle usb dfu to place devices into DFU mode. If you specify the device name in the project, I believe it will specify the name of the device as an additional argument to particle usb dfu.

In my experience, when a request to place a device into DFU mode hangs, the device has made it into DFU mode but Particle CLI does not realize and eventually times out after a minute.

If you send a SIGTERM to particle usb dfu with ^C and then attempt to run particle usb dfu again, the subsequent invocation will realize that the device is DFU mode.


I managed to sporadically reproduce this on a photon running 2.0.1 using particle-cli 2.10.0. I’m uncertain if the use of a USB hub influences particle usb dfu to hang more often.

$ particle usb listen # Put photon in listening mode
Done.
$ particle identify # Get deviceID and deviceOS version

Your device id is [REDACTED]
Your system firmware version is 2.0.1
$ system_profiler SPUSBDataType # Verify that photon is present on USB

--- Wait 5 minutes ---

$ particle usb dfu # Put photon in DFU mode. Fails.

# Hangs for one minute, and then the following error is printed:

TimeoutError [VError]
    at RequestSender.delay (/Users/nrobinson/.particle/node_modules/particle-cli/node_modules/particle-usb/lib/device.js:106:13)
    at /Users/nrobinson/.particle/node_modules/particle-cli/node_modules/particle-usb/lib/device.js:212:17
    at async Promise.all (index 0)
    at async CLI.runCommand (/Users/nrobinson/.particle/node_modules/particle-cli/dist/app/cli.js:160:7)
    at async CLI.run (/Users/nrobinson/.particle/node_modules/particle-cli/dist/app/cli.js:190:14) {
  jse_shortmsg: '',
  jse_info: {},
  message: ''
}

$ particle usb reset # Reset the device. Succeeds.

Here are the commands again, but simplified:

$ particle usb listen
$ particle identify
$ system_profiler SPUSBDataType
$ particle usb dfu
$ particle usb reset

Looking at ~/.particle/node_modules/particle-cli/node_modules/particle-usb/lib/device.js, the error happens in the enterDfuMode method:

  enterDfuMode({
    timeout = _config.globalOptions.requestTimeout
  } = {}) {
    if (this.isInDfuMode) {
      return;
    }

    return this.timeout(timeout, async s => {
      await s.sendRequest(_request.Request.DFU_MODE);
      await s.close();
      let isInDfuMode;

      while (!isInDfuMode) {
        try {
          await s.open({
            includeDfu: true
          });
          isInDfuMode = s.device.isInDfuMode;
        } catch (error) {// device is reconnecting, ignore
        }

        await s.close();
        await s.delay(500);
      }
    });
  }

Line 212 is await s.delay(500);

Update:

In ~/.particle/node_modules/particle-cli/node_modules/particle-usb/lib/device-base.js the open() method is defined beginning on line 158.

I changed all instances of this._log.trace to console.log.

When reproduced:

$ particle usb dfu
▌ Getting device information...Opening device
Device ID: [REDACTED]
Firmware version: 2.0.1
Device is open
▀ Sending a command to the device...Opening device
Device ID: [REDACTED]
Firmware version: 2.0.1
Device is open
▌ Sending a command to the device...Opening device
Device ID: [REDACTED]
Firmware version: 2.0.1
Device is open
▌ Sending a command to the device...Opening device
Device ID: [REDACTED]
Firmware version: 2.0.1
Device is open
▌ Sending a command to the device...Opening device
Device ID: [REDACTED]
▌ Sending a command to the device...Opening device
Device ID: [REDACTED]
▌ Sending a command to the device...Opening device
Device ID: [REDACTED]
▌ Sending a command to the device...Opening device
Device ID: [REDACTED]
▄ Sending a command to the device...Opening device
Device ID: [REDACTED]
▄ Sending a command to the device...Opening device
Device ID: [REDACTED]
▄ Sending a command to the device...Opening device

# Repeats for many lines

TimeoutError [VError]
    at RequestSender.delay (/Users/nrobinson/.particle/node_modules/particle-cli/node_modules/particle-usb/lib/device.js:106:13)
    at /Users/nrobinson/.particle/node_modules/particle-cli/node_modules/particle-usb/lib/device.js:212:17
    at async Promise.all (index 0)
    at async CLI.runCommand (/Users/nrobinson/.particle/node_modules/particle-cli/dist/app/cli.js:160:7)
    at async CLI.run (/Users/nrobinson/.particle/node_modules/particle-cli/dist/app/cli.js:190:14) {
  jse_shortmsg: '',
  jse_info: {},
  message: ''
}

I then tried adding console.log(error) on line 209 in the catch block in device.js:

$ particle usb dfu
▌ Getting device information...Opening device
Device ID: [REDACTED]
Firmware version: 2.0.1
Device is open
▀ Sending a command to the device...Opening device
Device ID: [REDACTED]
Firmware version: 2.0.1
Device is open
▌ Sending a command to the device...Opening device
Device ID: [REDACTED]
Firmware version: 2.0.1
Device is open
▌ Sending a command to the device...Opening device
Device ID: [REDACTED]
Firmware version: 2.0.1
Device is open
▄ Sending a command to the device...Opening device
Device ID: [REDACTED]
▌ Sending a command to the device...UsbError [VError]: Unknown interface
    at /Users/nrobinson/.particle/node_modules/particle-cli/node_modules/particle-usb/lib/usb-device-node.js:140:25
    at new Promise (<anonymous>)
    at new F (/Users/nrobinson/.particle/node_modules/particle-cli/node_modules/@babel/runtime-corejs2/node_modules/core-js/library/modules/_export.js:36:28)
    at UsbDevice.claimInterface (/Users/nrobinson/.particle/node_modules/particle-cli/node_modules/particle-usb/lib/usb-device-node.js:135:12)
    at Dfu.open (/Users/nrobinson/.particle/node_modules/particle-cli/node_modules/particle-usb/lib/dfu.js:168:21)
    at /Users/nrobinson/.particle/node_modules/particle-cli/node_modules/particle-usb/lib/device-base.js:192:26
    at async openDeviceById (/Users/nrobinson/.particle/node_modules/particle-cli/node_modules/particle-usb/lib/device-base.js:1039:3)
    at async RequestSender.open (/Users/nrobinson/.particle/node_modules/particle-cli/node_modules/particle-usb/lib/device.js:79:19)
    at async /Users/nrobinson/.particle/node_modules/particle-cli/node_modules/particle-usb/lib/device.js:204:11
    at async Promise.all (index 0) {
  jse_shortmsg: 'Unknown interface',
  jse_info: {},
  message: 'Unknown interface'
}
▄ Sending a command to the device...Opening device
Device ID: [REDACTED]
UsbError [VError]: Unknown interface
    at /Users/nrobinson/.particle/node_modules/particle-cli/node_modules/particle-usb/lib/usb-device-node.js:140:25
    at new Promise (<anonymous>)
    at new F (/Users/nrobinson/.particle/node_modules/particle-cli/node_modules/@babel/runtime-corejs2/node_modules/core-js/library/modules/_export.js:36:28)
    at UsbDevice.claimInterface (/Users/nrobinson/.particle/node_modules/particle-cli/node_modules/particle-usb/lib/usb-device-node.js:135:12)
    at Dfu.open (/Users/nrobinson/.particle/node_modules/particle-cli/node_modules/particle-usb/lib/dfu.js:168:21)
    at /Users/nrobinson/.particle/node_modules/particle-cli/node_modules/particle-usb/lib/device-base.js:192:26
    at async openDeviceById (/Users/nrobinson/.particle/node_modules/particle-cli/node_modules/particle-usb/lib/device-base.js:1039:3)
    at async RequestSender.open (/Users/nrobinson/.particle/node_modules/particle-cli/node_modules/particle-usb/lib/device.js:79:19)
    at async /Users/nrobinson/.particle/node_modules/particle-cli/node_modules/particle-usb/lib/device.js:204:11
    at async Promise.all (index 0) {
  jse_shortmsg: 'Unknown interface',
  jse_info: {},
  message: 'Unknown interface'
}

# Repeats for many lines

TimeoutError [VError]
    at RequestSender.delay (/Users/nrobinson/.particle/node_modules/particle-cli/node_modules/particle-usb/lib/device.js:106:13)
    at /Users/nrobinson/.particle/node_modules/particle-cli/node_modules/particle-usb/lib/device.js:213:17
    at async Promise.all (index 0)
    at async CLI.runCommand (/Users/nrobinson/.particle/node_modules/particle-cli/dist/app/cli.js:160:7)
    at async CLI.run (/Users/nrobinson/.particle/node_modules/particle-cli/dist/app/cli.js:190:14) {
  jse_shortmsg: '',
  jse_info: {},
  message: ''
}

To resolve this bug, I think it would be good for enterDfuMode() to catch the UsbError:

catch (error) {
    console.log(error);
    if (error instanceof _error.UsbError) {
        console.log("Aborted!");
        return;
    }
}

When reproduced:

$ particle usb dfu
▌ Getting device information...Opening device
Device ID: [REDACTED]
Firmware version: 2.0.1
Device is open
▀ Sending a command to the device...Opening device
Device ID: [REDACTED]
Firmware version: 2.0.1
Device is open
▌ Sending a command to the device...Opening device
Device ID: [REDACTED]
Firmware version: 2.0.1
Device is open
▌ Sending a command to the device...Opening device
Device ID: [REDACTED]
Firmware version: 2.0.1
Device is open
▄ Sending a command to the device...Opening device
▌ Sending a command to the device...Device ID: [REDACTED]
UsbError [VError]: Unknown interface
    at /Users/nrobinson/.particle/node_modules/particle-cli/node_modules/particle-usb/lib/usb-device-node.js:140:25
    at new Promise (<anonymous>)
    at new F (/Users/nrobinson/.particle/node_modules/particle-cli/node_modules/@babel/runtime-corejs2/node_modules/core-js/library/modules/_export.js:36:28)
    at UsbDevice.claimInterface (/Users/nrobinson/.particle/node_modules/particle-cli/node_modules/particle-usb/lib/usb-device-node.js:135:12)
    at Dfu.open (/Users/nrobinson/.particle/node_modules/particle-cli/node_modules/particle-usb/lib/dfu.js:168:21)
    at /Users/nrobinson/.particle/node_modules/particle-cli/node_modules/particle-usb/lib/device-base.js:192:26
    at async openDeviceById (/Users/nrobinson/.particle/node_modules/particle-cli/node_modules/particle-usb/lib/device-base.js:1039:3)
    at async RequestSender.open (/Users/nrobinson/.particle/node_modules/particle-cli/node_modules/particle-usb/lib/device.js:79:19)
    at async /Users/nrobinson/.particle/node_modules/particle-cli/node_modules/particle-usb/lib/device.js:204:11
    at async Promise.all (index 0) {
  jse_shortmsg: 'Unknown interface',
  jse_info: {},
  message: 'Unknown interface'
}
Aborted!
Done.

The photon successfully enters DFU mode and particle usb dfu catches the error and aborts.


Interestingly enough, I can occasionally trigger a hang by simply running particle usb dfu soon after manually resetting the photon.

Also, I’m looking at particle-usb on GitHub, and the latest release is v1.2.2, yet particle-cli v2.10.0 is uses particle-usb 1.2.1, but I doubt that impacts this issue.


I have opened an issue in particle-usb.

1 Like

Thank you all. As you said the photon does go into DFU sometimes, but VS code doesn’t realise that and gives a timeout or whatever…

Will try your suggestions. Thanks a lot :slight_smile:

1 Like

@m_m Is this a known issue?