pyocd / pyOCD

Open source Python library for programming and debugging Arm Cortex-M microcontrollers
https://pyocd.io
Apache License 2.0
1.13k stars 484 forks source link

Flashing a device occasionally crashes pyOCD when multiple devices are connected #711

Open thegecko opened 5 years ago

thegecko commented 5 years ago

OS: MacOS 10.12.16 pyOCD: 0.21.0 Devices: nRF51-DK, F042k6, Disco-L475, Nucleo-F446, etc.

When multiple devices are connected, the uid switch needs to be provided in order to target the correct device during a flash operation. e.g.:

./pyocd flash --uid 1100021844203120324C46383230353138303035B9C7DFD8 --target nrf51 --erase=chip "/Users/bob/Mbed Programs/mbed-os-example-blinky-tes/BUILD/NRF51_DK/ARMC6/mbed-os-example-blinky.hex"

This can often fail with the following error:

0000140:ERROR:__main__:uncaught exception: 'utf16' codec can't decode byte 0x6c in position 30: truncated data
Traceback (most recent call last):
  File "/Users/robmor01/mbed-studio-tools/python/lib/python2.7/site-packages/pyocd/__main__.py", line 304, in run
    self._commands[self._args.cmd]()
  File "/Users/robmor01/mbed-studio-tools/python/lib/python2.7/site-packages/pyocd/__main__.py", line 369, in do_flash
    **convert_session_options(self._args.options))
  File "/Users/robmor01/mbed-studio-tools/python/lib/python2.7/site-packages/pyocd/core/helpers.py", line 141, in session_with_chosen_probe
    allProbes = ConnectHelper.get_all_connected_probes(blocking=blocking, unique_id=board_id)
  File "/Users/robmor01/mbed-studio-tools/python/lib/python2.7/site-packages/pyocd/core/helpers.py", line 78, in get_all_connected_probes
    allProbes = DebugProbeAggregator.get_all_connected_probes(unique_id=unique_id)
  File "/Users/robmor01/mbed-studio-tools/python/lib/python2.7/site-packages/pyocd/probe/aggregator.py", line 32, in get_all_connected_probes
    probes += cls.get_all_connected_probes()
  File "/Users/robmor01/mbed-studio-tools/python/lib/python2.7/site-packages/pyocd/probe/cmsis_dap_probe.py", line 73, in get_all_connected_probes
    return [cls(dev) for dev in DAPAccess.get_connected_devices()]
  File "/Users/robmor01/mbed-studio-tools/python/lib/python2.7/site-packages/pyocd/probe/pydapaccess/dap_access_cmsis_dap.py", line 449, in get_connected_devices
    all_interfaces = _get_interfaces()
  File "/Users/robmor01/mbed-studio-tools/python/lib/python2.7/site-packages/pyocd/probe/pydapaccess/dap_access_cmsis_dap.py", line 56, in _get_interfaces
    interfaces += INTERFACE[USB_BACKEND_V2].get_all_connected_interfaces()
  File "/Users/robmor01/mbed-studio-tools/python/lib/python2.7/site-packages/pyocd/probe/pydapaccess/interface/pyusb_v2_backend.py", line 178, in get_all_connected_interfaces
    for board in all_devices:
  File "/Users/robmor01/mbed-studio-tools/python/lib/python2.7/site-packages/usb/core.py", line 1249, in device_iter
    if _interop._all(tests) and (custom_match is None or custom_match(d)):
  File "/Users/robmor01/mbed-studio-tools/python/lib/python2.7/site-packages/pyocd/probe/pydapaccess/interface/pyusb_v2_backend.py", line 274, in __call__
    cmsis_dap_interface = usb.util.find_descriptor(config, custom_match=match_cmsis_dap_interface_name)
  File "/Users/robmor01/mbed-studio-tools/python/lib/python2.7/site-packages/usb/util.py", line 190, in find_descriptor
    return _interop._next(desc_iter(**args))
  File "/Users/robmor01/mbed-studio-tools/python/lib/python2.7/site-packages/usb/_interop.py", line 66, in _next
    return next(iter)
  File "/Users/robmor01/mbed-studio-tools/python/lib/python2.7/site-packages/usb/util.py", line 183, in desc_iter
    if _interop._all(tests) and (custom_match is None or custom_match(d)):
  File "/Users/robmor01/mbed-studio-tools/python/lib/python2.7/site-packages/pyocd/probe/pydapaccess/interface/pyusb_v2_backend.py", line 256, in match_cmsis_dap_interface_name
    interface_name = usb.util.get_string(desc.device, desc.iInterface)
  File "/Users/robmor01/mbed-studio-tools/python/lib/python2.7/site-packages/usb/util.py", line 330, in get_string
    return buf[2:buf[0]].tostring().decode('utf-16-le')
  File "/Users/robmor01/mbed-studio-tools/python/lib/python2.7/encodings/utf_16_le.py", line 16, in decode
    return codecs.utf_16_le_decode(input, errors, True)
UnicodeDecodeError: 'utf16' codec can't decode byte 0x6c in position 30: truncated data

When this happens, the device is left in an odd state and can only be recovered by flashing without the uid switch (and other devices disconnected so it becomes the default) or by using mass storage device flash.

flit commented 5 years ago

There is a known issue with some versions of STLinkV2 where the strings are invalid Unicode. This is described by comments in #607. Previously I created #613 based on a report from your team (the log looks almost exactly the same as this one). I thought it was fixed with this code to catch a UnicodeDecodeError. But apparently that doesn't catch all cases?

thegecko commented 5 years ago

Not all boards this error is seen on are st boards. Would having an st board being plugged in be enough to cause this?