From 999b6a14a4556f16d2f535207a84ceb2cca54f8a Mon Sep 17 00:00:00 2001 From: Carles Cufi Date: Sat, 12 Apr 2025 17:48:51 +0200 Subject: [PATCH] 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 --- scripts/west_commands/runners/nrf_common.py | 29 ++++++++++++++++----- scripts/west_commands/runners/nrfjprog.py | 15 ++++++----- scripts/west_commands/runners/nrfutil.py | 15 ++++++----- 3 files changed, 40 insertions(+), 19 deletions(-) diff --git a/scripts/west_commands/runners/nrf_common.py b/scripts/west_commands/runners/nrf_common.py index 5ce69c41503..d18029c6b2e 100644 --- a/scripts/west_commands/runners/nrf_common.py +++ b/scripts/west_commands/runners/nrf_common.py @@ -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: diff --git a/scripts/west_commands/runners/nrfjprog.py b/scripts/west_commands/runners/nrfjprog.py index c2fc2635caf..fd0a47e5dc4 100644 --- a/scripts/west_commands/runners/nrfjprog.py +++ b/scripts/west_commands/runners/nrfjprog.py @@ -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) diff --git a/scripts/west_commands/runners/nrfutil.py b/scripts/west_commands/runners/nrfutil.py index ea670a8f555..e7efda9ac5a 100644 --- a/scripts/west_commands/runners/nrfutil.py +++ b/scripts/west_commands/runners/nrfutil.py @@ -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)