west: runners: nrf: Add an option to control the ext erase mode

The erase mode for any external memory that is mapped to the address
space of the MCU is derived from the internal non-volatile memory erase
mode. In order to allow users to override the default value, add a new
--ext-erase-mode command-line option that takes an erase mode just like
--erase-mode does.

Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
This commit is contained in:
Carles Cufi 2025-04-12 17:48:51 +02:00 committed by Benjamin Cabé
commit 999b6a14a4
3 changed files with 40 additions and 19 deletions

View file

@ -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_mode=None, 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
@ -90,6 +90,7 @@ class NrfBinaryRunner(ZephyrBinaryRunner):
self.dev_id = dev_id
self.erase = bool(erase)
self.erase_mode = erase_mode
self.ext_erase_mode = ext_erase_mode
self.reset = bool(reset)
self.force = force
self.recover = bool(recover)
@ -140,9 +141,13 @@ class NrfBinaryRunner(ZephyrBinaryRunner):
memory and disable read back protection before
flashing (erases flash for both cores on nRF53)''')
parser.add_argument('--erase-mode', required=False,
choices=['none', 'ranges', 'all'], dest='erase_mode',
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)
@ -439,8 +444,6 @@ class NrfBinaryRunner(ZephyrBinaryRunner):
else:
erase_arg = 'ERASE_RANGES_TOUCHED_BY_FIRMWARE'
self.logger.debug(f'Erase type: {erase_arg}')
xip_ranges = {
'nrf52': (0x12000000, 0x19FFFFFF),
'nrf53': (0x10000000, 0x1FFFFFFF),
@ -450,8 +453,16 @@ class NrfBinaryRunner(ZephyrBinaryRunner):
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)
@ -548,6 +559,10 @@ class NrfBinaryRunner(ZephyrBinaryRunner):
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_mode:

View file

@ -18,11 +18,12 @@ class NrfJprogBinaryRunner(NrfBinaryRunner):
'''Runner front-end for nrfjprog.'''
def __init__(self, cfg, family, softreset, pinreset, dev_id, erase=False,
erase_mode=None, 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_mode, reset, tool_opt, force, recover)
erase_mode, ext_erase_mode, reset, tool_opt, force,
recover)
self.qspi_ini = qspi_ini
@ -46,9 +47,11 @@ class NrfJprogBinaryRunner(NrfBinaryRunner):
def do_create(cls, cfg, args):
return NrfJprogBinaryRunner(cfg, args.nrf_family, args.softreset,
args.pinreset, args.dev_id, erase=args.erase,
erase_mode=args.erase_mode, 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)

View file

@ -17,11 +17,13 @@ class NrfUtilBinaryRunner(NrfBinaryRunner):
'''Runner front-end for nrfutil.'''
def __init__(self, cfg, family, softreset, pinreset, dev_id, erase=False,
erase_mode=None, 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_mode, 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
@ -50,9 +52,10 @@ class NrfUtilBinaryRunner(NrfBinaryRunner):
def do_create(cls, cfg, args):
return NrfUtilBinaryRunner(cfg, args.nrf_family, args.softreset,
args.pinreset, args.dev_id, erase=args.erase,
erase_mode=args.erase_mode, 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)