Skip to content

scripts: runners: nrf: Extend the erase options #88551

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
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
4 changes: 2 additions & 2 deletions doc/releases/migration-guide-4.2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ Boards
* All boards based on a Nordic IC of the nRF54L series now default to not
erasing any part of the internal storage when flashing. If you'd like to
revert to the previous default of erasing the pages that will be written to by
the firmware to be flashed you can use the new ``--erase-pages`` command-line
switch when invoking ``west flash``.
the firmware to be flashed you can set the new ``--erase-mode`` command-line
switch when invoking ``west flash`` to ``ranges``.
Note that RRAM on nRF54L devices is not physically paged, and paging is
only artificially provided, with a page size of 4096 bytes, for an easier
transition of nRF52 software to nRF54L devices.
Expand Down
60 changes: 44 additions & 16 deletions scripts/west_commands/runners/nrf_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ class NrfBinaryRunner(ZephyrBinaryRunner):
'''Runner front-end base class for nrf tools.'''

def __init__(self, cfg, family, softreset, pinreset, dev_id, erase=False,
erase_pages=False, reset=True, tool_opt=None, force=False,
recover=False):
erase_mode=None, ext_erase_mode=None, reset=True,
tool_opt=None, force=False, recover=False):
super().__init__(cfg)
self.hex_ = cfg.hex_file
# The old --nrf-family options takes upper-case family names
Expand All @@ -89,7 +89,8 @@ def __init__(self, cfg, family, softreset, pinreset, dev_id, erase=False,
self.pinreset = pinreset
self.dev_id = dev_id
self.erase = bool(erase)
self.erase_pages = bool(erase_pages)
self.erase_mode = erase_mode
self.ext_erase_mode = ext_erase_mode
self.reset = bool(reset)
self.force = force
self.recover = bool(recover)
Expand Down Expand Up @@ -139,9 +140,14 @@ def do_add_parser(cls, parser):
help='''erase all user available non-volatile
memory and disable read back protection before
flashing (erases flash for both cores on nRF53)''')
parser.add_argument('--erase-pages', required=False,
action='store_true', dest='erase_pages',
help='erase pages to be used by the firmware')
parser.add_argument('--erase-mode', required=False,
choices=['none', 'ranges', 'all'],
help='Select the type of erase operation for the '
'internal non-volatile memory')
parser.add_argument('--ext-erase-mode', required=False,
choices=['none', 'ranges', 'all'],
help='Select the type of erase operation for the '
'external non-volatile memory')

parser.set_defaults(reset=True)

Expand Down Expand Up @@ -341,6 +347,18 @@ def _get_core(self):

return None

def _get_erase_mode(self, mode):
if not mode:
return None
elif mode == "none":
return "ERASE_NONE"
elif mode == "ranges":
return "ERASE_RANGES_TOUCHED_BY_FIRMWARE"
elif mode == "all":
return "ERASE_ALL"
else:
raise RuntimeError(f"Invalid erase mode: {mode}")

def program_hex(self):
# Get the command use to actually program self.hex_.
self.logger.info(f'Flashing file: {self.hex_}')
Expand Down Expand Up @@ -421,13 +439,11 @@ def program_hex(self):
else:
if self.erase:
erase_arg = 'ERASE_ALL'
elif self.family == 'nrf54l' and not self.erase_pages:
erase_arg = 'ERASE_NONE'
elif self.family == 'nrf54l':
erase_arg = self._get_erase_mode(self.erase_mode) or 'ERASE_NONE'
else:
erase_arg = 'ERASE_RANGES_TOUCHED_BY_FIRMWARE'

self.logger.debug(f'Erase type: {erase_arg}')

xip_ranges = {
'nrf52': (0x12000000, 0x19FFFFFF),
'nrf53': (0x10000000, 0x1FFFFFFF),
Expand All @@ -437,8 +453,16 @@ def program_hex(self):
xip_start, xip_end = xip_ranges[self.family]
if self.hex_refers_region(xip_start, xip_end):
# Default to pages for the external memory
ext_mem_erase_opt = erase_arg if erase_arg == 'ERASE_ALL' else \
'ERASE_RANGES_TOUCHED_BY_FIRMWARE'
ext_mem_erase_opt = self._get_erase_mode(self.ext_erase_mode) or \
(erase_arg if erase_arg == 'ERASE_ALL' else \
'ERASE_RANGES_TOUCHED_BY_FIRMWARE')

if not ext_mem_erase_opt and self.ext_erase_mode:
self.logger.warning('Option --ext-erase-mode ignored, no parts of the '
'image refer to external memory')

self.logger.debug(f'Erase modes: chip:{erase_arg} ext_mem:'
f'{ext_mem_erase_opt}')

self.op_program(self.hex_, erase_arg, ext_mem_erase_opt, defer=True, core=core)
self.flush(force=False)
Expand Down Expand Up @@ -531,14 +555,18 @@ def do_run(self, command, **kwargs):
raise RuntimeError('Options --softreset and --pinreset are mutually '
'exclusive.')

if self.erase and self.erase_pages:
raise RuntimeError('Options --erase and --erase-pages are mutually '
if self.erase and self.erase_mode:
raise RuntimeError('Options --erase and --erase-mode are mutually '
'exclusive.')

if self.erase and self.ext_erase_mode:
raise RuntimeError('Options --erase and --ext-erase-mode are mutually '
'exclusive.')

self.ensure_family()

if self.family != 'nrf54l' and self.erase_pages:
raise RuntimeError('Option --erase-pages can only be used with the '
if self.family != 'nrf54l' and self.erase_mode:
raise RuntimeError('Option --erase-mode can only be used with the '
'nRF54L family.')

self.ensure_output('hex')
Expand Down
17 changes: 10 additions & 7 deletions scripts/west_commands/runners/nrfjprog.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@ class NrfJprogBinaryRunner(NrfBinaryRunner):
'''Runner front-end for nrfjprog.'''

def __init__(self, cfg, family, softreset, pinreset, dev_id, erase=False,
erase_pages=False, reset=True, tool_opt=None, force=False,
recover=False, qspi_ini=None):
erase_mode=None, ext_erase_mode=None, reset=True, tool_opt=None,
force=False, recover=False, qspi_ini=None):

super().__init__(cfg, family, softreset, pinreset, dev_id, erase,
erase_pages, reset, tool_opt, force, recover)
erase_mode, ext_erase_mode, reset, tool_opt, force,
recover)

self.qspi_ini = qspi_ini

Expand All @@ -46,9 +47,11 @@ def tool_opt_help(cls) -> str:
def do_create(cls, cfg, args):
return NrfJprogBinaryRunner(cfg, args.nrf_family, args.softreset,
args.pinreset, args.dev_id, erase=args.erase,
erase_pages=args.erase_pages, reset=args.reset,
tool_opt=args.tool_opt, force=args.force,
recover=args.recover, qspi_ini=args.qspi_ini)
erase_mode=args.erase_mode,
ext_erase_mode=args.ext_erase_mode,
reset=args.reset, tool_opt=args.tool_opt,
force=args.force, recover=args.recover,
qspi_ini=args.qspi_ini)
@classmethod
def do_add_parser(cls, parser):
super().do_add_parser(parser)
Expand Down Expand Up @@ -93,7 +96,7 @@ def do_exec_op(self, op, force=False):
cmd.append('--sectoranduicrerase')
else:
cmd.append('--sectorerase')
elif erase == 'NO_ERASE':
elif erase == 'ERASE_NONE':
pass
else:
raise RuntimeError(f'Invalid erase mode: {erase}')
Expand Down
15 changes: 9 additions & 6 deletions scripts/west_commands/runners/nrfutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ class NrfUtilBinaryRunner(NrfBinaryRunner):
'''Runner front-end for nrfutil.'''

def __init__(self, cfg, family, softreset, pinreset, dev_id, erase=False,
erase_pages=False, reset=True, tool_opt=None, force=False,
recover=False, suit_starter=False, ext_mem_config_file=None):
erase_mode=None, ext_erase_mode=None, reset=True, tool_opt=None,
force=False, recover=False, suit_starter=False,
ext_mem_config_file=None):

super().__init__(cfg, family, softreset, pinreset, dev_id, erase,
erase_pages, reset, tool_opt, force, recover)
erase_mode, ext_erase_mode, reset, tool_opt, force,
recover)

self.suit_starter = suit_starter
self.ext_mem_config_file = ext_mem_config_file
Expand Down Expand Up @@ -50,9 +52,10 @@ def tool_opt_help(cls) -> str:
def do_create(cls, cfg, args):
return NrfUtilBinaryRunner(cfg, args.nrf_family, args.softreset,
args.pinreset, args.dev_id, erase=args.erase,
erase_pages=args.erase_pages, reset=args.reset,
tool_opt=args.tool_opt, force=args.force,
recover=args.recover,
erase_mode=args.erase_mode,
ext_erase_mode=args.ext_erase_mode,
reset=args.reset, tool_opt=args.tool_opt,
force=args.force, recover=args.recover,
suit_starter=args.suit_manifest_starter,
ext_mem_config_file=args.ext_mem_config_file)

Expand Down
Loading