pyocd / pyOCD

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

pyocd 0.29.0: TypeError with '&' operation in dap_access_cmsis_dap.py #1110

Closed pfalcon closed 3 years ago

pfalcon commented 3 years ago

We've seen a case when command line pyocd-flashtool -d debug -t k64f -f 3000000 -O connect_mode=under-reset --board 0240000034544e45004d00028aa900222011000097969900 /var/lib/lava/dispatcher/tmp/2379758/deployimages-dl229rxw/zephyr/zephyr.bin leads to:

Traceback (most recent call last):
  File "/usr/local/bin/pyocd-flashtool", line 10, in <module>
    sys.exit(main())
  File "/usr/local/lib/python3.7/dist-packages/pyocd/tools/flash_tool.py", line 161, in main
    with session:
  File "/usr/local/lib/python3.7/dist-packages/pyocd/core/session.py", line 343, in __enter__
    self.open()
  File "/usr/local/lib/python3.7/dist-packages/pyocd/core/session.py", line 457, in open
    self._probe.open()
  File "/usr/local/lib/python3.7/dist-packages/pyocd/probe/cmsis_dap_probe.py", line 148, in open
    self._link.open()
  File "/usr/local/lib/python3.7/dist-packages/pyocd/utility/concurrency.py", line 28, in _locking
    return func(self, *args, **kwargs)
  File "/usr/local/lib/python3.7/dist-packages/pyocd/probe/pydapaccess/dap_access_cmsis_dap.py", line 608, in open
    self._has_swo_uart = (self._capabilities & Capabilities.SWO_UART) != 0
TypeError: unsupported operand type(s) for &: 'str' and 'int'

That's definitely not a common situation (first time I see that), and it likely happens in extreme conditions (we run it on RaspberryPi4 which is not as stable with USB connections as a typical desktop computer, and run against board which has kind of worn-out flash). But the bottom line is the same: self._capabilities above may unexpectedly end up with a string instead of int.

Detailed run log for reference: https://validation.linaro.org/scheduler/job/2379758#L35

flit commented 3 years ago

Thanks for the report.

This is the key part in CMSISDAPProtocol.dap_info: https://github.com/pyocd/pyOCD/blob/e2796e50eacde5ca94aa3194204837e8b1f211b0/pyocd/probe/pydapaccess/cmsis_dap_core.py#L159-L168

Since the requested ID (id_) determines the string versus int response type, the only path where a string can be returned for the Capabilities request is if the value length in the response packet is something other than {1, 2, 4}. (Not shown here, None can be returned if the len is 0.) That would be a pretty corrupted USB packet.

I'm armour plating this code to better check the response. But you'll still get an exception if the response packet is invalid, so I'm not sure it will really help your situation.

(Btw, pyocd-flashtool is removed in version 0.30.0, as it has been deprecated for a couple years. Please switch to the combined pyocd tool with flash subcommand.)

pfalcon commented 3 years ago

@flit, thanks for the response.

(Btw, pyocd-flashtool is removed in version 0.30.0, as it has been deprecated for a couple years. Please switch to the combined pyocd tool with flash subcommand.)

We're definitely ready to do that when it comes. The current situation however is that we have here (in a CI system) boards which work more reliably with older pyocd 0.13.1 than with the latest 0.29.0. And 0.13.1 didn't have the "pyocd" command, so we use pyocd-flashtool to easier switcher between the 2 versions. One particular trait of those boards we have is that they clearly have a worn-out flash. So, I don't try to submit that as a separate ticket ("With broken boards, latest pyocd works less reliably than older", huh), but, while we're waiting for replacement boards, still trying to investigate in background what may be involved and/or report side issues, like this.

Thanks for taking care of this, given that there's an associated PR and it's now merged, closing the ticket.