Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions pyocd/core/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ def __init__(
auto_open: bool = True,
options: Optional[Mapping[str, Any]] = None,
option_defaults: Optional[Mapping[str, Any]] = None,
command: Optional[str] = None,
**kwargs
) -> None:
"""@brief Session constructor.
Expand Down Expand Up @@ -166,6 +167,7 @@ def __init__(
self._probe = probe
self._closed: bool = True
self._inited: bool = False
self._command = command
self._user_script_namespace: Dict[str, Any] = {}
self._user_script_proxy: Optional[UserScriptDelegateProxy] = None
self._user_script_print_proxy = PrintProxy()
Expand Down Expand Up @@ -331,6 +333,11 @@ def probe(self) -> Optional[DebugProbe]:
"""@brief The @ref pyocd.probe.debug_probe.DebugProbe "DebugProbe" instance."""
return self._probe

@property
def command(self) -> Optional[str]:
"""@brief The current command being executed in the session."""
return self._command

@property
def board(self) -> Optional[Board]:
"""@brief The @ref pyocd.board.board.Board "Board" object."""
Expand Down
1 change: 1 addition & 0 deletions pyocd/subcommands/erase_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ def invoke(self) -> int:
frequency=self._args.frequency,
blocking=(not self._args.no_wait),
connect_mode=self._args.connect_mode,
command=self._args.cmd,
options=convert_session_options(self._args.options),
option_defaults=self._modified_option_defaults(),
)
Expand Down
1 change: 1 addition & 0 deletions pyocd/subcommands/load_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ def invoke(self) -> int:
frequency=self._args.frequency,
blocking=(not self._args.no_wait),
connect_mode=self._args.connect_mode,
command=self._args.cmd,
options=convert_session_options(self._args.options),
option_defaults=self._modified_option_defaults(),
)
Expand Down
1 change: 1 addition & 0 deletions pyocd/subcommands/reset_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ def invoke(self) -> None:
connect_mode=self._args.connect_mode,
resume_on_disconnect=not self._args.halt,
reset_type=self._args.reset_type,
command=self._args.cmd,
options=convert_session_options(self._args.options),
option_defaults=self._modified_option_defaults(),
)
Expand Down
49 changes: 30 additions & 19 deletions pyocd/target/pack/cbuild_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,10 @@ def _cbuild_target_init(self, session: Session) -> None:
super(self.__class__, self).__init__(session, self._cbuild_device.memory_map)
self.vendor = self._cbuild_device.vendor
self.part_number = self._cbuild_device.target
self._svd_location = SVDFile(filename=self._cbuild_device.svd)
if session.command not in ('load', 'erase', 'reset'):
# SVD file is not required for load/erase/reset commands
_svd = self._cbuild_device.svd
self._svd_location = SVDFile(filename=_svd) if _svd else None
self.debug_sequence_delegate = CbuildRunDebugSequenceDelegate(self, self._cbuild_device)

@staticmethod
Expand Down Expand Up @@ -277,11 +280,11 @@ def _pack_path(cmsis_pack: str) -> Optional[Path]:
if pack is not None:
self._required_packs[pack] = _pack_path(pack)

def _check_path(self, file_path: Path) -> Path:
"""@brief Checks if the required CMSIS pack is installed."""
def _check_path(self, file_path: Path, required: bool = False) -> Path:
"""@brief Checks if the required files are accessible and verifies pack installation if needed."""
file_path = Path(os.path.expandvars(str(file_path))).expanduser().resolve()
# If the path exists, we don't need to do any further checks
if file_path.exists():
# If the file exists, we don't need to do any further checks
if file_path.is_file():
return file_path

def _is_under(parent: Path, child: Path) -> bool:
Expand All @@ -291,20 +294,28 @@ def _is_under(parent: Path, child: Path) -> bool:
except ValueError:
return False

self._get_required_packs()
# Select appropriate logging level and error message based on whether the file is required
if required:
log = LOG.error
err = f"File '{file_path}' is required but not found"
else:
log = LOG.warning
err = f"File '{file_path}' not found"

self._get_required_packs()
# Verify pack installation only if the file is located within a required pack.
for pack, pack_path in self._required_packs.items():
if pack_path is not None and _is_under(pack_path, file_path):
if not pack_path.exists():
raise CbuildRunError(f"Pack '{pack}' is required but not installed. "
f"Install with: cpackget add {pack}")
elif not file_path.exists():
raise CbuildRunError(f"Installed pack '{pack}' is corrupted or incomplete. "
f"Reinstall with: cpackget add -F {pack}")
log("Pack '%s' is required but not installed. "
"Install with: cpackget add %s", pack, pack)
else:
log("Installed pack '%s' is corrupted or incomplete. "
"Reinstall with: cpackget add -F %s", pack, pack)
# We've found the relevant pack, no need to check further
break

# If we reach here, the file was not found and is not under any required pack.
raise CbuildRunError(f"File '{file_path}' is required but not found")
raise CbuildRunError(err)

@property
def target(self) -> str:
Expand Down Expand Up @@ -354,19 +365,19 @@ def memory_map(self) -> MemoryMap:
return self._memory_map

@property
def svd(self) -> Optional[IO[bytes]]:
"""@brief File-like object for the device's SVD file."""
def svd(self) -> Optional[str]:
"""@brief Path to the SVD file for the target device."""
#TODO handle multicore devices
try:
for desc in self.system_descriptions:
if desc['type'] == 'svd':
svd_path = self._check_path(Path(desc['file']))
LOG.debug("SVD path: %s", svd_path)
return io.BytesIO(svd_path.read_bytes())
return str(svd_path)
except CbuildRunError as err:
LOG.error("SVD file error: %s", err)
LOG.warning("SVD file error: %s", err)
except (KeyError, IndexError):
LOG.error("Could not locate SVD in cbuild-run system-descriptions.")
LOG.warning("Could not locate SVD in cbuild-run system-descriptions.")
return None

@property
Expand Down Expand Up @@ -683,7 +694,7 @@ def _memory_slice(memory: dict, start: int, size: int) -> None:
flash_attrs['_RAMsize'] = algorithm['ram-size']
if ('_RAMstart' not in flash_attrs) or ('_RAMsize' not in flash_attrs):
LOG.error("Flash algorithm '%s' has no RAMstart or RAMsize", algorithm['algorithm'])
algorithm_path = self._check_path(Path(algorithm['algorithm']))
algorithm_path = self._check_path(Path(algorithm['algorithm']), required=True)
flash_attrs['flm'] = PackFlashAlgo(str(algorithm_path))
# Set sector size to a fixed value to prevent any possibility of infinite recursion due to
# the default lambdas for sector_size and blocksize returning each other's value.
Expand Down
6 changes: 4 additions & 2 deletions pyocd/target/pack/cmsis_pack.py
Original file line number Diff line number Diff line change
Expand Up @@ -1025,8 +1025,11 @@ def svd(self) -> Optional[IO[bytes]]:
try:
svdPath = self._info.debugs[0].attrib['svd']
return self.get_file(svdPath)
except FileNotFoundError as err:
LOG.error("SVD file error: %s", err)
except (KeyError, IndexError):
return None
LOG.error("Could not locate SVD in CMSIS-Pack.")
return None

@property
def sequences(self) -> Set[DebugSequence]:
Expand Down Expand Up @@ -1287,4 +1290,3 @@ def _build_aps_map(self) -> None:

def __repr__(self):
return "<%s@%x %s>" % (self.__class__.__name__, id(self), self.part_number)

3 changes: 2 additions & 1 deletion pyocd/target/pack/pack_target.py
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,8 @@ def _pack_target__init__(self, session: Session) -> None: # type:ignore
self.part_families = self._pack_device.families
self.part_number = self._pack_device.part_number

self._svd_location = SVDFile(filename=self._pack_device.svd)
_svd = self._pack_device.svd
self._svd_location = SVDFile(filename=_svd) if _svd else None

self.debug_sequence_delegate = PackDebugSequenceDelegate(self, self._pack_device)

Expand Down
Loading