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)