Skip to content

Commit

Permalink
probe: stlink: lazily load and cache board ID to improve discovery an…
Browse files Browse the repository at this point in the history
…d connect time (#1464)
  • Loading branch information
flit committed Oct 30, 2022
1 parent cac6e94 commit 72299f5
Showing 1 changed file with 39 additions and 16 deletions.
55 changes: 39 additions & 16 deletions pyocd/probe/stlink_probe.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
# limitations under the License.

from time import sleep
from typing import (Any, Callable, List, Optional, Sequence, Union, TYPE_CHECKING)
from typing import (Any, Callable, Dict, List, Optional, Sequence, Union, TYPE_CHECKING)

from .debug_probe import DebugProbe
from ..core.memory_interface import MemoryInterface
Expand All @@ -36,6 +36,12 @@
class StlinkProbe(DebugProbe):
"""@brief Wraps an STLink as a DebugProbe."""

_board_id: Optional[str]

# Shared cache for the STLink Mbed board IDs read from MSD volumes.
# The dict maps the serial number to 4-character board ID, or None if no ID is available.
_mbed_board_id_cache: Dict[str, Optional[str]] = {}

@classmethod
def get_all_connected_probes(cls, unique_id: Optional[str] = None,
is_explicit: bool = False) -> List["StlinkProbe"]:
Expand All @@ -55,29 +61,46 @@ def __init__(self, device: STLinkUSBInterface) -> None:
self._is_connected = False
self._nreset_state = False
self._memory_interfaces = {}
self._mbed_info = None
self._board_id = self._get_board_id()
self._board_id = None
self._caps = set()

@property
def board_id(self) -> str:
"""@brief Lazily loaded 4-character board ID."""
if self._board_id is None:
self._board_id = self._get_board_id()
return self._board_id

def _get_board_id(self) -> Optional[str]:
# Try to get the board ID first by sending a command, since it is much faster. This requires
# opening the USB device, however, and requires a recent STLink firmware version.
board_id = self._link.get_board_id()
if board_id is None:
# Try to detect associated board info via the STLinkV2-1 MSD volume.
detector = create_mbed_detector()
if detector is not None:
for info in detector.list_mbeds():
if info['target_id_usb_id'] == self._link.serial_number:
self._mbed_info = info
# Check the cache.
if self._link.serial_number in self._mbed_board_id_cache:
board_id = StlinkProbe._mbed_board_id_cache[self._link.serial_number]
else:
# Try to detect associated board info via the STLinkV2-1 MSD volume.
detector = create_mbed_detector()
if detector is not None:
for info in detector.list_mbeds():
usb_id = info['target_id_usb_id']

# Some STLink probes provide an MSD volume, but not the mbed.htm file.
# We can live without the board ID, so just ignore any error.
try:
board_id = info['target_id_mbed_htm'][0:4]
this_board_id = info['target_id_mbed_htm'][0:4]
except KeyError:
pass
break
# No board ID is available for this board.
StlinkProbe._mbed_board_id_cache[usb_id] = None
else:
# Populate the cache with the ID.
StlinkProbe._mbed_board_id_cache[usb_id] = this_board_id

# Use this ID if it's for our board.
if usb_id == self._link.serial_number:
board_id = this_board_id
break
return board_id

@property
Expand Down Expand Up @@ -114,16 +137,16 @@ def capabilities(self):

@property
def associated_board_info(self) -> Optional["BoardInfo"]:
if (self._board_id is not None) and (self._board_id in BOARD_ID_TO_INFO):
return BOARD_ID_TO_INFO[self._board_id]
if (self.board_id is not None) and (self.board_id in BOARD_ID_TO_INFO):
return BOARD_ID_TO_INFO[self.board_id]
else:
return None

def create_associated_board(self):
assert self.session is not None
board_info = self.associated_board_info
if board_info or self._board_id:
return MbedBoard(self.session, board_info=board_info, board_id=self._board_id)
if board_info or self.board_id:
return MbedBoard(self.session, board_info=board_info, board_id=self.board_id)
else:
return None

Expand Down

0 comments on commit 72299f5

Please sign in to comment.