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

[0.26.1] ProbeError: J-Link is already open #877

Closed Hoohaha closed 4 years ago

Hoohaha commented 4 years ago

pyocd sometimes occured jlink related exceptions. Looks like it try to open connected jlink probes. Actually we do not want it. It might cause segger jlink error if it is in parallel. Is possible to add an option to control such behaviour? just list specified probes by user.

  File "C:\Python27\lib\site-packages\pyocd\core\helpers.py", line 236, in session_with_chosen_probe
    unique_id=unique_id,
  File "C:\Python27\lib\site-packages\pyocd\core\helpers.py", line 137, in choose_probe
    allProbes = ConnectHelper.get_all_connected_probes(blocking=blocking, unique_id=unique_id)
  File "C:\Python27\lib\site-packages\pyocd\core\helpers.py", line 82, in get_all_connected_probes
    allProbes = DebugProbeAggregator.get_all_connected_probes(unique_id=unique_id)
  File "C:\Python27\lib\site-packages\pyocd\probe\aggregator.py", line 34, in get_all_connected_probes
    probes += cls.get_all_connected_probes()
  File "C:\Python27\lib\site-packages\pyocd\probe\jlink_probe.py", line 62, in get_all_connected_probes
    return [cls(str(info.SerialNumber)) for info in jlink.connected_emulators()]
  File "C:\Python27\lib\site-packages\pyocd\probe\jlink_probe.py", line 96, in __init__
    self.open()
  File "C:\Python27\lib\site-packages\pyocd\probe\jlink_probe.py", line 155, in open
    six.raise_from(self._convert_exception(exc), exc)
  File "C:\Python27\lib\site-packages\six.py", line 718, in raise_from
    raise value
ProbeError: J-Link is already open.
juhhov commented 4 years ago

Hi @Hoohaha, @flit. This is a problem for us also. The offending operation is https://github.com/pyocd/pyOCD/blob/d4cdcf7e532cae17caad866839287bbe1e0d952b/pyocd/probe/jlink_probe.py#L99. This issue easily occurs when there is multiple boards connected and the boards are ran parallel, only one has to be jlink.

Could there be option to completely disable jlink from pyOCD?

flit commented 4 years ago

(Really sorry I hadn't seen this issue. I recently changed my flow for issue/PR notifications so hopefully I won't miss issues much anymore.)

You can restrict to a specific probe plugin when specifying the probe's unique ID via the -u / --uid / --probe option. The plugin name prefixes the UID and is followed by a colon, e.g. --probe=cmsisdap:02400. You can see the plugin names by running pyocd list --plugins. This doesn't allow multiple plugin names.

But the real problem here is a bug in the J-Link probe implementation in pyocd. It shouldn't allow the "already open" error to propagate when scanning for available probes, only if you explicitly attempt to open a J-Link by UID. I'll see if I can get a fix in the upcoming 0.28.3 release.

juhhov commented 4 years ago

Restricting to specific plugin type doesn't solve the issue when there is more than jlink probe connected to same host.

Having to open the probe connection when scanning for probes is the problem. Even if pyOCD can handle the raised error other applications running simultaneously may not.

self.open()
self._product_name = self._link.product_name
self._oem = self._link.oem

Is that information available from USB descriptors as well?

flit commented 4 years ago

Restricting to specific plugin type doesn't solve the issue when there is more than jlink probe connected to same host.

It should work if you know in advance the unique IDs of the probes you want to connect to.

Having to open the probe connection when scanning for probes is the problem. Even if pyOCD can handle the raised error other applications running simultaneously may not.

If pyOCD attempts to open a J-Link probe that another application already has open, then it won't affect that other application.

Is that information available from USB descriptors as well?

I don't have it in front of me right now, but I'm pretty sure that information wasn't available from the USB descriptors—there was some reason I had to open the probe. But I'll double check that.

Hoohaha commented 4 years ago

I think add plugin type might be help for us. Thanks @flit support!

flit commented 4 years ago

@Hoohaha After reviewing the code the plugin type will only work if there is a single J-Link probe connected. There is a DebugProbeAggregator.get_probe_with_id() API that will work, but it's not connected to the ConnectHelper class.

The problem is that the DebugProbeAggregator.get_probe_with_id() only accepts a full unique ID; it doesn't perform a contains match. So ConnectHelper uses DebugProbeAggregator.get_all_connected_probes() that has to iterate over the full list of available probes to match partial unique IDs—and we're back to the original problem. 😦 This should be improved so an initial check is performed to find a probe with a matching full unique ID, and if that doesn't match any probes then perform the contains match. It could also be pushed down to the DebugProbe methods for optional handling.

flit commented 4 years ago

@juhhov @Hoohaha Whenever you get a chance, would you mind checking whether the v0.28.3 release really fixes this issue in your setups? If not, please reopen this issue.