Skip to content

Commit

Permalink
flash: Add option to prevent resetting of device after programming (#…
Browse files Browse the repository at this point in the history
…1492)

This adds a --no-reset command line argument that can be used to
prevent a target being reset after a program operation has finished.
The use-case for such a scenario includes when programming multiple
images whereby one of the images enables security such as disabling
the debugger, without this patch, only the first image would be
flashed.
  • Loading branch information
nordicjm authored Jan 17, 2023
1 parent 447416d commit df257a6
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 7 deletions.
8 changes: 6 additions & 2 deletions pyocd/flash/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ def add_page_with_existing_data():
page = add_page_with_existing_data()
sector_page_addr += page.size

def program(self, chip_erase=None, progress_cb=None, smart_flash=True, fast_verify=False, keep_unwritten=True):
def program(self, chip_erase=None, progress_cb=None, smart_flash=True, fast_verify=False, keep_unwritten=True, no_reset=False):
"""@brief Determine fastest method of flashing and then run flash programming.
Data must have already been added with add_data().
Expand All @@ -419,6 +419,8 @@ def program(self, chip_erase=None, progress_cb=None, smart_flash=True, fast_veri
written, there may be ranges of flash that would be erased but not written with new
data. This parameter sets whether the existing contents of those unwritten ranges will
be read from memory and restored while programming.
@param no_reset Boolean indicating whether if the device should not be reset after the
programming process has finished.
"""

# Send notification that we're about to program flash.
Expand Down Expand Up @@ -512,7 +514,9 @@ def program(self, chip_erase=None, progress_cb=None, smart_flash=True, fast_veri

# Cleanup flash algo and reset target after programming.
self.flash.cleanup()
self.flash.target.reset_and_halt()

if no_reset is not True:
self.flash.target.reset_and_halt()

program_finish = time()
self.perf.program_time = program_finish - program_start
Expand Down
9 changes: 7 additions & 2 deletions pyocd/flash/file_programmer.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ def __init__(self,
chip_erase: Optional[bool] = None,
smart_flash: Optional[bool] = None,
trust_crc: Optional[bool] = None,
keep_unwritten: Optional[bool] = None
keep_unwritten: Optional[bool] = None,
no_reset: Optional[bool] = None
):
"""@brief Constructor.
Expand All @@ -85,12 +86,15 @@ def __init__(self,
written, there may be ranges of flash that would be erased but not written with new
data. This parameter sets whether the existing contents of those unwritten ranges will
be read from memory and restored while programming.
@param no_reset Boolean indicating whether if the device should not be reset after the
programming process has finished.
"""
self._session = session
self._chip_erase = chip_erase
self._smart_flash = smart_flash
self._trust_crc = trust_crc
self._keep_unwritten = keep_unwritten
self._no_reset = no_reset
self._progress = progress
self._loader = None

Expand Down Expand Up @@ -149,7 +153,8 @@ def program(self, file_or_path: Union[str, IO[bytes]], file_format: Optional[str
chip_erase=self._chip_erase,
smart_flash=self._smart_flash,
trust_crc=self._trust_crc,
keep_unwritten=self._keep_unwritten)
keep_unwritten=self._keep_unwritten,
no_reset=self._no_reset)

# file_obj = None
# Open the file if a path was provided.
Expand Down
11 changes: 9 additions & 2 deletions pyocd/flash/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,14 +145,16 @@ class MemoryLoader:
_smart_flash: Optional[bool]
_trust_crc: Optional[bool]
_keep_unwritten: Optional[bool]
_no_reset: Optional[bool]

def __init__(self,
session: "Session",
progress: Optional[ProgressCallback] = None,
chip_erase: Optional[bool] = None,
smart_flash: Optional[bool] = None,
trust_crc: Optional[bool] = None,
keep_unwritten: Optional[bool] = None
keep_unwritten: Optional[bool] = None,
no_reset: Optional[bool] = None
):
"""@brief Constructor.
Expand All @@ -173,6 +175,8 @@ def __init__(self,
written, there may be ranges of flash that would be erased but not written with new
data. This parameter sets whether the existing contents of those unwritten ranges will
be read from memory and restored while programming.
@param no_reset Boolean indicating whether if the device should not be reset after the
programming process has finished.
"""
self._session = session
assert session.board
Expand All @@ -195,6 +199,8 @@ def __init__(self,
else self._session.options.get('fast_program')
self._keep_unwritten = keep_unwritten if (keep_unwritten is not None) \
else self._session.options.get('keep_unwritten')
self._no_reset = no_reset if (no_reset is not None) \
else self._session.options.get('no_reset')

self._reset_state()

Expand Down Expand Up @@ -290,7 +296,8 @@ def commit(self):
progress_cb=self._progress_cb,
smart_flash=self._smart_flash,
fast_verify=self._trust_crc,
keep_unwritten=self._keep_unwritten)
keep_unwritten=self._keep_unwritten,
no_reset=self._no_reset)
perfList.append(perf)
didChipErase = True

Expand Down
5 changes: 4 additions & 1 deletion pyocd/subcommands/load_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ def get_args(cls) -> List[argparse.ArgumentParser]:
"all must be of this type.")
parser_options.add_argument("--skip", metavar="BYTES", default=0, type=int_base_0,
help="Skip programming the first N bytes. Binary files only.")
parser_options.add_argument("--no-reset", action="store_true",
help="Specify to prevent resetting device after programming has finished.")

parser.add_argument("file", metavar="<file-path>", nargs="+",
help="File to write to memory. Binary files can have an optional base address appended to the file "
Expand Down Expand Up @@ -96,7 +98,8 @@ def invoke(self) -> int:
with session:
programmer = FileProgrammer(session,
chip_erase=self._args.erase,
trust_crc=self._args.trust_crc)
trust_crc=self._args.trust_crc,
no_reset=self._args.no_reset)
for filename in self._args.file:
# Get an initial path with the argument as-is.
file_path = Path(filename).expanduser()
Expand Down

0 comments on commit df257a6

Please sign in to comment.