runners: nrfjprog: boilerplate and recover rework
Rework the runner to improve various issues. Every board.cmake file for an nRF SoC target is repeating boilerplate needed for the nrfjprog runner's --nrf-family argument. The information we need to decide the --nrf-family is already available in Kconfig, so just get it from there instead. Keep the --nrf-family argument around for compatibility, though. This cuts boilerplate burden for board maintainers. We also need to revisit how this runner handles recovery to fix it in nRF53 and keep things consistent everywhere else. To cleanly handle additional readback protection features in nRF53, add a --recover option that does an 'nrfjprog --recover' before flashing. Keep the behavior consistent across SoCs by supporting it on those too. Because this is expected to be a bit tricky for users to understand, check if a --recover is needed if the 'nrfjprog --program' fails because of protection, and tell the user how to fix it. Finally, instead of performing a separate 'nrfjprog --eraseall', just give --chiperase to 'nrfjprog --program' process's arguments instead of --sectorerase. This is cleaner, resulting in fewer subprocesses and avoiding an extra chip reset. Having a separate 'west flash --recover' option doubles the number of test cases if we want to keep exhaustively enumerating them. That doesn't feel worthwhile, so update the test cases by picking a representative subset of the possibilities. Each test now has enough state that it's worth wrapping it up in a named tuple for readability. Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
This commit is contained in:
parent
065722fef0
commit
6628a16e4d
36 changed files with 396 additions and 260 deletions
|
@ -1,6 +1,5 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF91")
|
||||
board_runner_args(jlink "--device=cortex-m33" "--speed=4000")
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(pyocd "--target=nrf51")
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF51")
|
||||
board_runner_args(jlink "--device=nrf51" "--speed=4000")
|
||||
|
||||
include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF52" "--softreset")
|
||||
board_runner_args(nrfjprog "--softreset")
|
||||
board_runner_args(jlink "--device=nrf52" "--speed=4000")
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF52" "--softreset")
|
||||
board_runner_args(nrfjprog "--softreset")
|
||||
board_runner_args(jlink "--device=nrf52" "--speed=4000")
|
||||
board_runner_args(pyocd "--target=nrf52833" "--frequency=4000000")
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF52" "--softreset")
|
||||
board_runner_args(nrfjprog "--softreset")
|
||||
board_runner_args(jlink "--device=nrf52" "--speed=4000")
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF52" "--softreset")
|
||||
board_runner_args(nrfjprog "--softreset")
|
||||
board_runner_args(jlink "--device=nrf52" "--speed=4000")
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF91")
|
||||
board_runner_args(jlink "--device=cortex-m33" "--speed=4000")
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
# Copyright (c) 2019 Atmark Techno, Inc.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF52")
|
||||
board_runner_args(jlink "--device=nrf52" "--speed=4000")
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
board_runner_args(nrfjprog "--nrf-family=NRF52" "--softreset")
|
||||
board_runner_args(nrfjprog "--softreset")
|
||||
board_runner_args(jlink "--device=nrf52" "--speed=4000")
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF52")
|
||||
board_runner_args(jlink "--device=nrf52" "--speed=4000")
|
||||
board_runner_args(pyocd "--target=nrf52840" "--frequency=4000000")
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF51")
|
||||
board_runner_args(jlink "--device=nrf51" "--speed=4000")
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF51")
|
||||
board_runner_args(jlink "--device=nrf51" "--speed=4000")
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF51")
|
||||
board_runner_args(jlink "--device=nrf51" "--speed=4000")
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF52")
|
||||
board_runner_args(jlink "--device=nrf52" "--speed=4000")
|
||||
board_runner_args(pyocd "--target=nrf52820" "--frequency=4000000")
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF52")
|
||||
board_runner_args(jlink "--device=nrf52" "--speed=4000")
|
||||
board_runner_args(pyocd "--target=nrf52833" "--frequency=4000000")
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF52" "--softreset")
|
||||
board_runner_args(nrfjprog "--softreset")
|
||||
include(${ZEPHYR_BASE}/boards/common/blackmagicprobe.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF52")
|
||||
board_runner_args(jlink "--device=nrf52" "--speed=4000")
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF52")
|
||||
board_runner_args(jlink "--device=nrf52" "--speed=4000")
|
||||
board_runner_args(pyocd "--target=nrf52840" "--frequency=4000000")
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF52")
|
||||
board_runner_args(jlink "--device=nrf52" "--speed=4000")
|
||||
board_runner_args(pyocd "--target=nrf52840" "--frequency=4000000")
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF52")
|
||||
board_runner_args(jlink "--device=nrf52" "--speed=4000")
|
||||
board_runner_args(pyocd "--target=nrf52" "--frequency=4000000")
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF52")
|
||||
board_runner_args(jlink "--device=nrf52" "--speed=4000")
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF52")
|
||||
board_runner_args(jlink "--device=nrf52" "--speed=4000")
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF52")
|
||||
board_runner_args(jlink "--device=nrf52" "--speed=4000")
|
||||
board_runner_args(pyocd "--target=nrf52" "--frequency=4000000")
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
|
|
|
@ -6,12 +6,10 @@ endif()
|
|||
|
||||
if((CONFIG_BOARD_NRF5340PDK_NRF5340_CPUAPP OR CONFIG_BOARD_NRF5340PDK_NRF5340_CPUAPPNS) OR
|
||||
(CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP OR CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPPNS))
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF53" "--tool-opt=--coprocessor CP_APPLICATION")
|
||||
board_runner_args(jlink "--device=nrf5340_xxaa_app" "--speed=4000")
|
||||
endif()
|
||||
|
||||
if(CONFIG_BOARD_NRF5340PDK_NRF5340_CPUNET OR CONFIG_BOARD_NRF5340DK_NRF5340_CPUNET)
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF53" "--tool-opt=--coprocessor CP_NETWORK")
|
||||
board_runner_args(jlink "--device=nrf5340_xxaa_net" "--speed=4000")
|
||||
endif()
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
# Copyright (c) 2020 InnBlue
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF91")
|
||||
board_runner_args(jlink "--device=cortex-m33" "--speed=4000")
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
# Copyright (c) 2020 InnBlue
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF91")
|
||||
board_runner_args(jlink "--device=cortex-m33" "--speed=4000")
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF52")
|
||||
board_runner_args(jlink "--device=nrf52" "--speed=4000")
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
|
||||
|
|
|
@ -4,7 +4,6 @@ if(CONFIG_BOARD_NRF9160DK_NRF9160NS)
|
|||
set(TFM_PUBLIC_KEY_FORMAT "full")
|
||||
endif()
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF91")
|
||||
board_runner_args(jlink "--device=cortex-m33" "--speed=4000")
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(pyocd "--target=nrf52840" "--frequency=4000000")
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF52")
|
||||
board_runner_args(jlink "--device=nrf52" "--speed=4000")
|
||||
include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(pyocd "--target=nrf52840" "--frequency=4000000")
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF52")
|
||||
board_runner_args(jlink "--device=nrf52" "--speed=4000")
|
||||
include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(pyocd "--target=nrf52840" "--frequency=4000000")
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF52")
|
||||
board_runner_args(jlink "--device=nrf52" "--speed=4000")
|
||||
include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF52" "--softreset")
|
||||
board_runner_args(nrfjprog "--softreset")
|
||||
board_runner_args(jlink "--device=nrf52" "--speed=4000")
|
||||
board_runner_args(pyocd "--target=nrf52840" "--frequency=4000000")
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
# Copyright (c) 2020 Ruuvi Innovations Ltd (Oy)
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF52")
|
||||
board_runner_args(jlink "--device=nrf52" "--speed=4000")
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF52" "--softreset")
|
||||
board_runner_args(nrfjprog "--softreset")
|
||||
board_runner_args(jlink "--device=nrf52" "--speed=4000")
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
|
||||
|
|
|
@ -7,10 +7,11 @@
|
|||
|
||||
import os
|
||||
import shlex
|
||||
import subprocess
|
||||
import sys
|
||||
from re import fullmatch, escape
|
||||
|
||||
from runners.core import ZephyrBinaryRunner, RunnerCaps
|
||||
from runners.core import ZephyrBinaryRunner, RunnerCaps, BuildConfiguration
|
||||
|
||||
try:
|
||||
from intelhex import IntelHex
|
||||
|
@ -33,19 +34,22 @@ def has_region(regions, hex_file):
|
|||
except FileNotFoundError:
|
||||
return False
|
||||
|
||||
# https://infocenter.nordicsemi.com/index.jsp?topic=%2Fug_nrf_cltools%2FUG%2Fcltools%2Fnrf_nrfjprogexe_return_codes.html&cp=9_1_3_1
|
||||
UnavailableOperationBecauseProtectionError = 16
|
||||
|
||||
class NrfJprogBinaryRunner(ZephyrBinaryRunner):
|
||||
'''Runner front-end for nrfjprog.'''
|
||||
|
||||
def __init__(self, cfg, family, softreset, snr, erase=False,
|
||||
tool_opt=[], force=False):
|
||||
tool_opt=[], force=False, recover=False):
|
||||
super().__init__(cfg)
|
||||
self.hex_ = cfg.hex_file
|
||||
self.family = family
|
||||
self.softreset = softreset
|
||||
self.snr = snr
|
||||
self.erase = erase
|
||||
self.erase = bool(erase)
|
||||
self.force = force
|
||||
self.recover = bool(recover)
|
||||
|
||||
self.tool_opt = []
|
||||
for opts in [shlex.split(opt) for opt in tool_opt]:
|
||||
|
@ -61,9 +65,10 @@ class NrfJprogBinaryRunner(ZephyrBinaryRunner):
|
|||
|
||||
@classmethod
|
||||
def do_add_parser(cls, parser):
|
||||
parser.add_argument('--nrf-family', required=True,
|
||||
parser.add_argument('--nrf-family',
|
||||
choices=['NRF51', 'NRF52', 'NRF53', 'NRF91'],
|
||||
help='family of nRF MCU')
|
||||
help='''MCU family; still accepted for
|
||||
compatibility only''')
|
||||
parser.add_argument('--softreset', required=False,
|
||||
action='store_true',
|
||||
help='use reset instead of pinreset')
|
||||
|
@ -76,16 +81,23 @@ class NrfJprogBinaryRunner(ZephyrBinaryRunner):
|
|||
parser.add_argument('--force', required=False,
|
||||
action='store_true',
|
||||
help='Flash even if the result cannot be guaranteed.')
|
||||
parser.add_argument('--recover', required=False,
|
||||
action='store_true',
|
||||
help='''erase all user available non-volatile
|
||||
memory and disable read back protection before
|
||||
flashing (erases flash for both cores on nRF53)''')
|
||||
|
||||
@classmethod
|
||||
def do_create(cls, cfg, args):
|
||||
return NrfJprogBinaryRunner(cfg, args.nrf_family, args.softreset,
|
||||
args.snr, erase=args.erase,
|
||||
tool_opt=args.tool_opt, force=args.force)
|
||||
tool_opt=args.tool_opt, force=args.force,
|
||||
recover=args.recover)
|
||||
|
||||
def ensure_snr(self):
|
||||
if not self.snr or "*" in self.snr:
|
||||
self.snr = self.get_board_snr(self.snr or "*")
|
||||
self.snr = self.snr.lstrip("0")
|
||||
|
||||
def get_boards(self):
|
||||
snrs = self.check_output(['nrfjprog', '--ids'])
|
||||
|
@ -150,68 +162,144 @@ class NrfJprogBinaryRunner(ZephyrBinaryRunner):
|
|||
|
||||
return snrs[value - 1]
|
||||
|
||||
def do_run(self, command, **kwargs):
|
||||
self.require('nrfjprog')
|
||||
def ensure_family(self):
|
||||
# Ensure self.family is set.
|
||||
|
||||
self.ensure_snr()
|
||||
if self.family is not None:
|
||||
return
|
||||
|
||||
commands = []
|
||||
board_snr = self.snr.lstrip("0")
|
||||
|
||||
if not os.path.isfile(self.hex_):
|
||||
raise ValueError('Cannot flash; hex file ({}) does not exist. '.
|
||||
format(self.hex_) +
|
||||
'Try enabling CONFIG_BUILD_OUTPUT_HEX.')
|
||||
|
||||
program_cmd = ['nrfjprog', '--program', self.hex_, '-f', self.family,
|
||||
'--snr', board_snr] + self.tool_opt
|
||||
|
||||
self.logger.info('Flashing file: {}'.format(self.hex_))
|
||||
if self.erase:
|
||||
commands.extend([
|
||||
['nrfjprog',
|
||||
'--eraseall',
|
||||
'-f', self.family,
|
||||
'--snr', board_snr],
|
||||
program_cmd
|
||||
])
|
||||
if self.build_conf.get('CONFIG_SOC_SERIES_NRF51X', False):
|
||||
self.family = 'NRF51'
|
||||
elif self.build_conf.get('CONFIG_SOC_SERIES_NRF52X', False):
|
||||
self.family = 'NRF52'
|
||||
elif self.build_conf.get('CONFIG_SOC_SERIES_NRF53X', False):
|
||||
self.family = 'NRF53'
|
||||
elif self.build_conf.get('CONFIG_SOC_SERIES_NRF91X', False):
|
||||
self.family = 'NRF91'
|
||||
else:
|
||||
if self.family == 'NRF51':
|
||||
commands.append(program_cmd + ['--sectorerase'])
|
||||
elif self.family == 'NRF52':
|
||||
commands.append(program_cmd + ['--sectoranduicrerase'])
|
||||
raise RuntimeError(f'unknown nRF; update {__file__}')
|
||||
|
||||
def check_force_uicr(self):
|
||||
# On SoCs without --sectoranduicrerase, we want to fail by
|
||||
# default if the application contains UICR data and we're not sure
|
||||
# that the flash will succeed.
|
||||
|
||||
# A map from SoCs which need this check to their UICR address
|
||||
# ranges. If self.family isn't in here, do nothing.
|
||||
uicr_ranges = {
|
||||
'NRF53': ((0x00FF8000, 0x00FF8800),
|
||||
(0x01FF8000, 0x01FF8800)),
|
||||
'NRF91': ((0x00FF8000, 0x00FF8800),),
|
||||
}
|
||||
|
||||
if self.family not in uicr_ranges:
|
||||
return
|
||||
|
||||
uicr = uicr_ranges[self.family]
|
||||
|
||||
if not self.force and has_region(uicr, self.hex_):
|
||||
# Hex file has UICR contents.
|
||||
raise RuntimeError(
|
||||
'The hex file contains data placed in the UICR, which '
|
||||
'needs a full erase before reprogramming. Run west '
|
||||
'flash again with --force or --erase.')
|
||||
|
||||
def recover_target(self):
|
||||
if self.family == 'NRF53':
|
||||
self.logger.info(
|
||||
'Recovering and erasing flash memory for both the network '
|
||||
'and application cores.')
|
||||
else:
|
||||
self.logger.info('Recovering and erasing all flash memory.')
|
||||
|
||||
if self.family == 'NRF53':
|
||||
self.check_call(['nrfjprog', '--recover', '-f', self.family,
|
||||
'--coprocessor', 'CP_NETWORK',
|
||||
'--snr', self.snr])
|
||||
|
||||
self.check_call(['nrfjprog', '--recover', '-f', self.family,
|
||||
'--snr', self.snr])
|
||||
|
||||
def program_hex(self):
|
||||
# Get the nrfjprog command use to actually program self.hex_.
|
||||
self.logger.info('Flashing file: {}'.format(self.hex_))
|
||||
|
||||
# What type of erase argument should we pass to nrfjprog?
|
||||
if self.erase:
|
||||
erase_arg = '--chiperase'
|
||||
else:
|
||||
if self.family == 'NRF52':
|
||||
erase_arg = '--sectoranduicrerase'
|
||||
else:
|
||||
uicr = {
|
||||
'NRF53': ((0x00FF8000, 0x00FF8800),
|
||||
(0x01FF8000, 0x01FF8800)),
|
||||
'NRF91': ((0x00FF8000, 0x00FF8800),),
|
||||
}[self.family]
|
||||
erase_arg = '--sectorerase'
|
||||
|
||||
if not self.force and has_region(uicr, self.hex_):
|
||||
# Hex file has UICR contents.
|
||||
raise RuntimeError(
|
||||
'The hex file contains data placed in the UICR, which '
|
||||
'needs a full erase before reprogramming. Run west '
|
||||
'flash again with --force or --erase.')
|
||||
if self.family == 'NRF53':
|
||||
if self.build_conf.get('CONFIG_SOC_NRF5340_CPUAPP', False):
|
||||
coprocessor = 'CP_APPLICATION'
|
||||
elif self.build_conf.get('CONFIG_SOC_NRF5340_CPUNET', False):
|
||||
coprocessor = 'CP_NETWORK'
|
||||
else:
|
||||
# When it's time to update this file, it would probably be best
|
||||
# to handle this by adding common 'SOC_NRF53X_CPUAPP'
|
||||
# and 'SOC_NRF53X_CPUNET' options, so we don't have to
|
||||
# maintain a list of SoCs in this file too.
|
||||
raise RuntimeError(f'unknown nRF53; update {__file__}')
|
||||
coprocessor_args = ['--coprocessor', coprocessor]
|
||||
else:
|
||||
coprocessor_args = []
|
||||
|
||||
# It's important for tool_opt to come last, so it can override
|
||||
# any options that we set here.
|
||||
try:
|
||||
self.check_call(['nrfjprog', '--program', self.hex_, erase_arg,
|
||||
'-f', self.family, '--snr', self.snr] +
|
||||
coprocessor_args + self.tool_opt)
|
||||
except subprocess.CalledProcessError as cpe:
|
||||
if cpe.returncode == UnavailableOperationBecauseProtectionError:
|
||||
if self.family == 'NRF53':
|
||||
family_help = (
|
||||
' Note: your target is an nRF53; all flash memory '
|
||||
'for both the network and application cores will be '
|
||||
'erased prior to reflashing.')
|
||||
else:
|
||||
commands.append(program_cmd + ['--sectorerase'])
|
||||
family_help = (
|
||||
' Note: this will recover and erase all flash memory '
|
||||
'prior to reflashing.')
|
||||
self.logger.error(
|
||||
'Flashing failed because the target '
|
||||
'must be recovered.\n'
|
||||
' To fix, run "west flash --recover" instead.\n' +
|
||||
family_help)
|
||||
raise
|
||||
|
||||
def reset_target(self):
|
||||
if self.family == 'NRF52' and not self.softreset:
|
||||
commands.extend([
|
||||
# Enable pin reset
|
||||
['nrfjprog', '--pinresetenable', '-f', self.family,
|
||||
'--snr', board_snr],
|
||||
])
|
||||
self.check_call(['nrfjprog', '--pinresetenable', '-f', self.family,
|
||||
'--snr', self.snr]) # Enable pin reset
|
||||
|
||||
if self.softreset:
|
||||
commands.append(['nrfjprog', '--reset', '-f', self.family,
|
||||
'--snr', board_snr])
|
||||
self.check_call(['nrfjprog', '--reset', '-f', self.family,
|
||||
'--snr', self.snr])
|
||||
else:
|
||||
commands.append(['nrfjprog', '--pinreset', '-f', self.family,
|
||||
'--snr', board_snr])
|
||||
self.check_call(['nrfjprog', '--pinreset', '-f', self.family,
|
||||
'--snr', self.snr])
|
||||
|
||||
for cmd in commands:
|
||||
self.check_call(cmd)
|
||||
def do_run(self, command, **kwargs):
|
||||
self.require('nrfjprog')
|
||||
self.build_conf = BuildConfiguration(self.cfg.build_dir)
|
||||
if not os.path.isfile(self.hex_):
|
||||
raise RuntimeError(
|
||||
f'Cannot flash; hex file ({self.hex_}) does not exist. '
|
||||
'Try enabling CONFIG_BUILD_OUTPUT_HEX.')
|
||||
|
||||
self.logger.info('Board with serial number {} flashed successfully.'.
|
||||
format(board_snr))
|
||||
self.ensure_snr()
|
||||
self.ensure_family()
|
||||
self.check_force_uicr()
|
||||
|
||||
if self.recover:
|
||||
self.recover_target()
|
||||
self.program_hex()
|
||||
self.reset_target()
|
||||
|
||||
self.logger.info(f'Board with serial number {self.snr} '
|
||||
'flashed successfully.')
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
# Copyright (c) 2018 Foundries.io
|
||||
# Copyright (c) 2020 Nordic Semiconductor ASA
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import typing
|
||||
from unittest.mock import patch, call
|
||||
|
||||
import pytest
|
||||
|
@ -20,205 +22,237 @@ TEST_DEF_SNR = 'test-default-serial-number' # for mocking user input
|
|||
TEST_OVR_SNR = 'test-override-serial-number'
|
||||
|
||||
#
|
||||
# Expected results.
|
||||
# A dictionary mapping test cases to expected results.
|
||||
#
|
||||
# This dictionary maps different configurations to the commands we expect to be
|
||||
# executed for them. Verification is done by mocking the check_call() method,
|
||||
# which is used to run the commands.
|
||||
# The keys are TC objects.
|
||||
#
|
||||
# The key naming scheme is <F><SR><SN><E>, where:
|
||||
#
|
||||
# - F: family, 1 for 'NRF51' or 2 for 'NRF52'
|
||||
# - SR: soft reset, Y for yes, N for pin reset
|
||||
# - SNR: serial number override, Y for yes, N for 'use default'
|
||||
# - E: full chip erase, Y for yes, N for sector / sector and UICR only
|
||||
# The values are the nrfjprog commands we expect to be executed for
|
||||
# each test case. Verification is done by mocking the check_call()
|
||||
# ZephyrBinaryRunner method which is used to run the commands.
|
||||
#
|
||||
|
||||
EXPECTED_COMMANDS = {
|
||||
# NRF51:
|
||||
'1NNN':
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF51', '--snr', TEST_DEF_SNR, '--sectorerase'], # noqa: E501
|
||||
class TC(typing.NamedTuple): # 'TestCase'
|
||||
# NRF51, NRF52, etc.
|
||||
family: str
|
||||
|
||||
# 'APP', 'NET', or None.
|
||||
coprocessor: typing.Optional[str]
|
||||
|
||||
# Run 'nrfjprog --recover' first if True
|
||||
recover: bool
|
||||
|
||||
# Use --reset instead of --pinreset if True
|
||||
softreset: bool
|
||||
|
||||
# --snr TEST_OVR_SNR if True, --snr TEST_DEF_SNR if False
|
||||
snr: bool
|
||||
|
||||
# --chiperase if True,
|
||||
# --sectorerase if False (or --sectoranduicrerase on nRF52)
|
||||
erase: bool
|
||||
|
||||
|
||||
EXPECTED_RESULTS = {
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# NRF51
|
||||
#
|
||||
# family CP recov soft snr erase
|
||||
TC('NRF51', None, False, False, False, False):
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '-f', 'NRF51',
|
||||
'--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF51', '--snr', TEST_DEF_SNR]),
|
||||
|
||||
'1NNY':
|
||||
(['nrfjprog', '--eraseall', '-f', 'NRF51', '--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF51', '--snr', TEST_DEF_SNR], # noqa: E501
|
||||
TC('NRF51', None, False, False, False, True):
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', '-f', 'NRF51',
|
||||
'--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF51', '--snr', TEST_DEF_SNR]),
|
||||
|
||||
'1NYN':
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF51', '--snr', TEST_OVR_SNR, '--sectorerase'], # noqa: E501
|
||||
TC('NRF51', None, False, False, True, False):
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '-f', 'NRF51',
|
||||
'--snr', TEST_OVR_SNR],
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF51', '--snr', TEST_OVR_SNR]),
|
||||
|
||||
'1NYY':
|
||||
(['nrfjprog', '--eraseall', '-f', 'NRF51', '--snr', TEST_OVR_SNR],
|
||||
['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF51', '--snr', TEST_OVR_SNR], # noqa: E501
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF51', '--snr', TEST_OVR_SNR]),
|
||||
|
||||
'1YNN':
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF51', '--snr', TEST_DEF_SNR, '--sectorerase'], # noqa: E501
|
||||
TC('NRF51', None, False, True, False, False):
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '-f', 'NRF51',
|
||||
'--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--reset', '-f', 'NRF51', '--snr', TEST_DEF_SNR]),
|
||||
|
||||
'1YNY':
|
||||
(['nrfjprog', '--eraseall', '-f', 'NRF51', '--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF51', '--snr', TEST_DEF_SNR], # noqa: E501
|
||||
['nrfjprog', '--reset', '-f', 'NRF51', '--snr', TEST_DEF_SNR]),
|
||||
TC('NRF51', None, True, False, False, False):
|
||||
(['nrfjprog', '--recover', '-f', 'NRF51', '--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '-f', 'NRF51',
|
||||
'--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF51', '--snr', TEST_DEF_SNR]),
|
||||
|
||||
'1YYN':
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF51', '--snr', TEST_OVR_SNR, '--sectorerase'], # noqa: E501
|
||||
TC('NRF51', None, True, True, True, True):
|
||||
(['nrfjprog', '--recover', '-f', 'NRF51', '--snr', TEST_OVR_SNR],
|
||||
['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', '-f', 'NRF51',
|
||||
'--snr', TEST_OVR_SNR],
|
||||
['nrfjprog', '--reset', '-f', 'NRF51', '--snr', TEST_OVR_SNR]),
|
||||
|
||||
'1YYY':
|
||||
(['nrfjprog', '--eraseall', '-f', 'NRF51', '--snr', TEST_OVR_SNR],
|
||||
['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF51', '--snr', TEST_OVR_SNR], # noqa: E501
|
||||
['nrfjprog', '--reset', '-f', 'NRF51', '--snr', TEST_OVR_SNR]),
|
||||
|
||||
# NRF52:
|
||||
'2NNN':
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF52', '--snr', TEST_DEF_SNR, '--sectoranduicrerase'], # noqa: E501
|
||||
# -------------------------------------------------------------------------
|
||||
# NRF52
|
||||
#
|
||||
# family CP recov soft snr erase
|
||||
TC('NRF52', None, False, False, False, False):
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '--sectoranduicrerase',
|
||||
'-f', 'NRF52', '--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--pinresetenable', '-f', 'NRF52', '--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF52', '--snr', TEST_DEF_SNR]),
|
||||
|
||||
'2NNY':
|
||||
(['nrfjprog', '--eraseall', '-f', 'NRF52', '--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF52', '--snr', TEST_DEF_SNR], # noqa: E501
|
||||
TC('NRF52', None, False, False, False, True):
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', '-f', 'NRF52',
|
||||
'--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--pinresetenable', '-f', 'NRF52', '--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF52', '--snr', TEST_DEF_SNR]),
|
||||
|
||||
'2NYN':
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF52', '--snr', TEST_OVR_SNR, '--sectoranduicrerase'], # noqa: E501
|
||||
TC('NRF52', None, False, False, True, False):
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '--sectoranduicrerase',
|
||||
'-f', 'NRF52', '--snr', TEST_OVR_SNR],
|
||||
['nrfjprog', '--pinresetenable', '-f', 'NRF52', '--snr', TEST_OVR_SNR],
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF52', '--snr', TEST_OVR_SNR]),
|
||||
|
||||
'2NYY':
|
||||
(['nrfjprog', '--eraseall', '-f', 'NRF52', '--snr', TEST_OVR_SNR],
|
||||
['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF52', '--snr', TEST_OVR_SNR], # noqa: E501
|
||||
['nrfjprog', '--pinresetenable', '-f', 'NRF52', '--snr', TEST_OVR_SNR],
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF52', '--snr', TEST_OVR_SNR]),
|
||||
|
||||
'2YNN':
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF52', '--snr', TEST_DEF_SNR, '--sectoranduicrerase'], # noqa: E501
|
||||
TC('NRF52', None, False, True, False, False):
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '--sectoranduicrerase',
|
||||
'-f', 'NRF52', '--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--reset', '-f', 'NRF52', '--snr', TEST_DEF_SNR]),
|
||||
|
||||
'2YNY':
|
||||
(['nrfjprog', '--eraseall', '-f', 'NRF52', '--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF52', '--snr', TEST_DEF_SNR], # noqa: E501
|
||||
['nrfjprog', '--reset', '-f', 'NRF52', '--snr', TEST_DEF_SNR]),
|
||||
TC('NRF52', None, True, False, False, False):
|
||||
(['nrfjprog', '--recover', '-f', 'NRF52', '--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--program', RC_KERNEL_HEX, '--sectoranduicrerase',
|
||||
'-f', 'NRF52', '--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--pinresetenable', '-f', 'NRF52', '--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF52', '--snr', TEST_DEF_SNR]),
|
||||
|
||||
'2YYN':
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF52', '--snr', TEST_OVR_SNR, '--sectoranduicrerase'], # noqa: E501
|
||||
TC('NRF52', None, True, True, True, True):
|
||||
(['nrfjprog', '--recover', '-f', 'NRF52', '--snr', TEST_OVR_SNR],
|
||||
['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', '-f', 'NRF52',
|
||||
'--snr', TEST_OVR_SNR],
|
||||
['nrfjprog', '--reset', '-f', 'NRF52', '--snr', TEST_OVR_SNR]),
|
||||
|
||||
'2YYY':
|
||||
(['nrfjprog', '--eraseall', '-f', 'NRF52', '--snr', TEST_OVR_SNR],
|
||||
['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF52', '--snr', TEST_OVR_SNR], # noqa: E501
|
||||
['nrfjprog', '--reset', '-f', 'NRF52', '--snr', TEST_OVR_SNR]),
|
||||
# -------------------------------------------------------------------------
|
||||
# NRF53 APP
|
||||
#
|
||||
# family CP recov soft snr erase
|
||||
|
||||
# NRF53:
|
||||
'3NNN':
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF53', '--snr', TEST_DEF_SNR, '--sectorerase'], # noqa: E501
|
||||
TC('NRF53', 'APP', False, False, False, False):
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '-f', 'NRF53',
|
||||
'--snr', TEST_DEF_SNR, '--coprocessor', 'CP_APPLICATION'],
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_DEF_SNR]),
|
||||
|
||||
'3NNY':
|
||||
(['nrfjprog', '--eraseall', '-f', 'NRF53', '--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF53', '--snr', TEST_DEF_SNR], # noqa: E501
|
||||
TC('NRF53', 'APP', False, False, False, True):
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', '-f', 'NRF53',
|
||||
'--snr', TEST_DEF_SNR, '--coprocessor', 'CP_APPLICATION'],
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_DEF_SNR]),
|
||||
|
||||
'3NYN':
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF53', '--snr', TEST_OVR_SNR, '--sectorerase'], # noqa: E501
|
||||
TC('NRF53', 'APP', False, False, True, False):
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '-f', 'NRF53',
|
||||
'--snr', TEST_OVR_SNR, '--coprocessor', 'CP_APPLICATION'],
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_OVR_SNR]),
|
||||
|
||||
'3NYY':
|
||||
(['nrfjprog', '--eraseall', '-f', 'NRF53', '--snr', TEST_OVR_SNR],
|
||||
['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF53', '--snr', TEST_OVR_SNR], # noqa: E501
|
||||
TC('NRF53', 'APP', False, True, False, False):
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '-f', 'NRF53',
|
||||
'--snr', TEST_DEF_SNR, '--coprocessor', 'CP_APPLICATION'],
|
||||
['nrfjprog', '--reset', '-f', 'NRF53', '--snr', TEST_DEF_SNR]),
|
||||
|
||||
TC('NRF53', 'APP', True, False, False, False):
|
||||
(['nrfjprog', '--recover', '-f', 'NRF53', '--coprocessor', 'CP_NETWORK',
|
||||
'--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--recover', '-f', 'NRF53', '--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '-f', 'NRF53',
|
||||
'--snr', TEST_DEF_SNR, '--coprocessor', 'CP_APPLICATION'],
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_DEF_SNR]),
|
||||
|
||||
TC('NRF53', 'APP', True, True, True, True):
|
||||
(['nrfjprog', '--recover', '-f', 'NRF53', '--coprocessor', 'CP_NETWORK',
|
||||
'--snr', TEST_OVR_SNR],
|
||||
['nrfjprog', '--recover', '-f', 'NRF53', '--snr', TEST_OVR_SNR],
|
||||
['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', '-f', 'NRF53',
|
||||
'--snr', TEST_OVR_SNR, '--coprocessor', 'CP_APPLICATION'],
|
||||
['nrfjprog', '--reset', '-f', 'NRF53', '--snr', TEST_OVR_SNR]),
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# NRF53 NET
|
||||
#
|
||||
# family CP recov soft snr erase
|
||||
|
||||
TC('NRF53', 'NET', False, False, False, False):
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '-f', 'NRF53',
|
||||
'--snr', TEST_DEF_SNR, '--coprocessor', 'CP_NETWORK'],
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_DEF_SNR]),
|
||||
|
||||
TC('NRF53', 'NET', False, False, False, True):
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', '-f', 'NRF53',
|
||||
'--snr', TEST_DEF_SNR, '--coprocessor', 'CP_NETWORK'],
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_DEF_SNR]),
|
||||
|
||||
TC('NRF53', 'NET', False, False, True, False):
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '-f', 'NRF53',
|
||||
'--snr', TEST_OVR_SNR, '--coprocessor', 'CP_NETWORK'],
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_OVR_SNR]),
|
||||
|
||||
'3YNN':
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF53', '--snr', TEST_DEF_SNR, '--sectorerase'], # noqa: E501
|
||||
TC('NRF53', 'NET', False, True, False, False):
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '-f', 'NRF53',
|
||||
'--snr', TEST_DEF_SNR, '--coprocessor', 'CP_NETWORK'],
|
||||
['nrfjprog', '--reset', '-f', 'NRF53', '--snr', TEST_DEF_SNR]),
|
||||
|
||||
'3YNY':
|
||||
(['nrfjprog', '--eraseall', '-f', 'NRF53', '--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF53', '--snr', TEST_DEF_SNR], # noqa: E501
|
||||
['nrfjprog', '--reset', '-f', 'NRF53', '--snr', TEST_DEF_SNR]),
|
||||
TC('NRF53', 'NET', True, False, False, False):
|
||||
(['nrfjprog', '--recover', '-f', 'NRF53', '--coprocessor', 'CP_NETWORK',
|
||||
'--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--recover', '-f', 'NRF53', '--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '-f', 'NRF53',
|
||||
'--snr', TEST_DEF_SNR, '--coprocessor', 'CP_NETWORK'],
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_DEF_SNR]),
|
||||
|
||||
'3YYN':
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF53', '--snr', TEST_OVR_SNR, '--sectorerase'], # noqa: E501
|
||||
TC('NRF53', 'NET', True, True, True, True):
|
||||
(['nrfjprog', '--recover', '-f', 'NRF53', '--coprocessor', 'CP_NETWORK',
|
||||
'--snr', TEST_OVR_SNR],
|
||||
['nrfjprog', '--recover', '-f', 'NRF53', '--snr', TEST_OVR_SNR],
|
||||
['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', '-f', 'NRF53',
|
||||
'--snr', TEST_OVR_SNR, '--coprocessor', 'CP_NETWORK'],
|
||||
['nrfjprog', '--reset', '-f', 'NRF53', '--snr', TEST_OVR_SNR]),
|
||||
|
||||
'3YYY':
|
||||
(['nrfjprog', '--eraseall', '-f', 'NRF53', '--snr', TEST_OVR_SNR],
|
||||
['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF53', '--snr', TEST_OVR_SNR], # noqa: E501
|
||||
['nrfjprog', '--reset', '-f', 'NRF53', '--snr', TEST_OVR_SNR]),
|
||||
|
||||
# NRF91:
|
||||
'9NNN':
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF91', '--snr', TEST_DEF_SNR, '--sectorerase'], # noqa: E501
|
||||
# -------------------------------------------------------------------------
|
||||
# NRF91
|
||||
#
|
||||
# family CP recov soft snr erase
|
||||
TC('NRF91', None, False, False, False, False):
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '-f', 'NRF91',
|
||||
'--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF91', '--snr', TEST_DEF_SNR]),
|
||||
|
||||
'9NNY':
|
||||
(['nrfjprog', '--eraseall', '-f', 'NRF91', '--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF91', '--snr', TEST_DEF_SNR], # noqa: E501
|
||||
TC('NRF91', None, False, False, False, True):
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', '-f', 'NRF91',
|
||||
'--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF91', '--snr', TEST_DEF_SNR]),
|
||||
|
||||
'9NYN':
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF91', '--snr', TEST_OVR_SNR, '--sectorerase'], # noqa: E501
|
||||
TC('NRF91', None, False, False, True, False):
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '-f', 'NRF91',
|
||||
'--snr', TEST_OVR_SNR],
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF91', '--snr', TEST_OVR_SNR]),
|
||||
|
||||
'9NYY':
|
||||
(['nrfjprog', '--eraseall', '-f', 'NRF91', '--snr', TEST_OVR_SNR],
|
||||
['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF91', '--snr', TEST_OVR_SNR], # noqa: E501
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF91', '--snr', TEST_OVR_SNR]),
|
||||
|
||||
'9YNN':
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF91', '--snr', TEST_DEF_SNR, '--sectorerase'], # noqa: E501
|
||||
TC('NRF91', None, False, True, False, False):
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '-f', 'NRF91',
|
||||
'--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--reset', '-f', 'NRF91', '--snr', TEST_DEF_SNR]),
|
||||
|
||||
'9YNY':
|
||||
(['nrfjprog', '--eraseall', '-f', 'NRF91', '--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF91', '--snr', TEST_DEF_SNR], # noqa: E501
|
||||
['nrfjprog', '--reset', '-f', 'NRF91', '--snr', TEST_DEF_SNR]),
|
||||
TC('NRF91', None, True, False, False, False):
|
||||
(['nrfjprog', '--recover', '-f', 'NRF91', '--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '-f', 'NRF91',
|
||||
'--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF91', '--snr', TEST_DEF_SNR]),
|
||||
|
||||
'9YYN':
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF91', '--snr', TEST_OVR_SNR, '--sectorerase'], # noqa: E501
|
||||
TC('NRF91', None, True, True, True, True):
|
||||
(['nrfjprog', '--recover', '-f', 'NRF91', '--snr', TEST_OVR_SNR],
|
||||
['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', '-f', 'NRF91',
|
||||
'--snr', TEST_OVR_SNR],
|
||||
['nrfjprog', '--reset', '-f', 'NRF91', '--snr', TEST_OVR_SNR]),
|
||||
|
||||
'9YYY':
|
||||
(['nrfjprog', '--eraseall', '-f', 'NRF91', '--snr', TEST_OVR_SNR],
|
||||
['nrfjprog', '--program', RC_KERNEL_HEX, '-f', 'NRF91', '--snr', TEST_OVR_SNR], # noqa: E501
|
||||
['nrfjprog', '--reset', '-f', 'NRF91', '--snr', TEST_OVR_SNR]),
|
||||
|
||||
}
|
||||
|
||||
|
||||
def expected_commands(family, softreset, snr, erase):
|
||||
'''Expected NrfJprogBinaryRunner results given parameters.
|
||||
|
||||
Returns a factory function which expects the following arguments:
|
||||
|
||||
- family: string, 'NRF51', 'NRF52' or 'NRF91'
|
||||
- softreset: boolean, controls whether soft reset is performed
|
||||
- snr: string serial number of board, or None
|
||||
- erase: boolean, whether to do a full chip erase or not
|
||||
'''
|
||||
expected_key = '{}{}{}{}'.format(
|
||||
'1' if family == 'NRF51' else '2' if family == 'NRF52' else '3' if family == 'NRF53' else '9', # noqa: E501
|
||||
'Y' if softreset else 'N',
|
||||
'Y' if snr else 'N',
|
||||
'Y' if erase else 'N')
|
||||
|
||||
return EXPECTED_COMMANDS[expected_key]
|
||||
|
||||
|
||||
#
|
||||
# Test cases
|
||||
# Monkey-patches
|
||||
#
|
||||
|
||||
TEST_CASES = [(f, sr, snr, e)
|
||||
for f in ('NRF51', 'NRF52', 'NRF53', 'NRF91')
|
||||
for sr in (False, True)
|
||||
for snr in (TEST_OVR_SNR, None)
|
||||
for e in (False, True)]
|
||||
|
||||
def get_board_snr_patch(glob):
|
||||
return TEST_DEF_SNR
|
||||
|
||||
|
@ -230,51 +264,92 @@ def os_path_isfile_patch(filename):
|
|||
return True
|
||||
return os.path.isfile(filename)
|
||||
|
||||
def id_fn(test_case):
|
||||
ret = ''
|
||||
for x in test_case:
|
||||
if x in ('NRF51', 'NRF52', 'NRF53'):
|
||||
ret += x[-1:]
|
||||
def build_configuration(test_case):
|
||||
ret = {
|
||||
f'CONFIG_SOC_SERIES_{test_case.family}X': 'y',
|
||||
}
|
||||
|
||||
# Would need an update if we have more SoCs than nRF5340 supported.
|
||||
if test_case.family == 'NRF53':
|
||||
if test_case.coprocessor == 'APP':
|
||||
ret['CONFIG_SOC_NRF5340_CPUAPP'] = 'y'
|
||||
elif test_case.coprocessor == 'NET':
|
||||
ret['CONFIG_SOC_NRF5340_CPUNET'] = 'y'
|
||||
else:
|
||||
ret += 'Y' if x else 'N'
|
||||
assert False, f'bad nRF53 coprocessor {test_case.coprocessor}'
|
||||
|
||||
return ret
|
||||
|
||||
@pytest.mark.parametrize('test_case', TEST_CASES, ids=id_fn)
|
||||
#
|
||||
# Test functions.
|
||||
#
|
||||
# These are white box tests that rely on the above monkey-patches.
|
||||
#
|
||||
|
||||
def id_fn(test_case):
|
||||
if test_case.coprocessor is None:
|
||||
cp = ''
|
||||
else:
|
||||
cp = f', {test_case.coprocessor}'
|
||||
s = 'soft reset' if test_case.softreset else 'pin reset'
|
||||
sn = 'default snr' if test_case.snr else 'override snr'
|
||||
e = 'chip erase' if test_case.erase else 'sector[anduicr] erase'
|
||||
r = 'recover' if test_case.recover else 'no recover'
|
||||
|
||||
return f'{test_case.family}{cp}, {s}, {sn}, {e}, {r}'
|
||||
|
||||
@pytest.mark.parametrize('test_case', EXPECTED_RESULTS.keys(), ids=id_fn)
|
||||
@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch)
|
||||
@patch('runners.nrfjprog.NrfJprogBinaryRunner.get_board_snr',
|
||||
side_effect=get_board_snr_patch)
|
||||
@patch('runners.nrfjprog.NrfJprogBinaryRunner.check_call')
|
||||
def test_nrfjprog_init(cc, get_snr, req, test_case, runner_config):
|
||||
family, softreset, snr, erase = test_case
|
||||
@patch('runners.nrfjprog.BuildConfiguration')
|
||||
def test_nrfjprog_init(build_conf, check_call, get_snr, require, test_case,
|
||||
runner_config):
|
||||
build_conf.return_value = build_configuration(test_case)
|
||||
expected = EXPECTED_RESULTS[test_case]
|
||||
snr = TEST_OVR_SNR if test_case.snr else None
|
||||
runner = NrfJprogBinaryRunner(runner_config,
|
||||
test_case.family,
|
||||
test_case.softreset,
|
||||
snr,
|
||||
erase=test_case.erase,
|
||||
recover=test_case.recover)
|
||||
|
||||
runner = NrfJprogBinaryRunner(runner_config, family, softreset, snr,
|
||||
erase=erase)
|
||||
with patch('os.path.isfile', side_effect=os_path_isfile_patch):
|
||||
runner.run('flash')
|
||||
assert req.called
|
||||
assert cc.call_args_list == [call(x) for x in
|
||||
expected_commands(*test_case)]
|
||||
assert require.called
|
||||
|
||||
if expected is not None:
|
||||
assert check_call.call_args_list == [call(x) for x in expected]
|
||||
else:
|
||||
assert not check_call.called
|
||||
|
||||
if snr is None:
|
||||
get_snr.assert_called_once_with('*')
|
||||
else:
|
||||
get_snr.assert_not_called()
|
||||
|
||||
@pytest.mark.parametrize('test_case', TEST_CASES, ids=id_fn)
|
||||
@pytest.mark.parametrize('test_case', EXPECTED_RESULTS.keys(), ids=id_fn)
|
||||
@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch)
|
||||
@patch('runners.nrfjprog.NrfJprogBinaryRunner.get_board_snr',
|
||||
side_effect=get_board_snr_patch)
|
||||
@patch('runners.nrfjprog.NrfJprogBinaryRunner.check_call')
|
||||
def test_nrfjprog_create(cc, get_snr, req, test_case, runner_config):
|
||||
family, softreset, snr, erase = test_case
|
||||
@patch('runners.nrfjprog.BuildConfiguration')
|
||||
def test_nrfjprog_create(build_conf, check_call, get_snr, require, test_case,
|
||||
runner_config):
|
||||
build_conf.return_value = build_configuration(test_case)
|
||||
expected = EXPECTED_RESULTS[test_case]
|
||||
|
||||
args = ['--nrf-family', family]
|
||||
if softreset:
|
||||
args = []
|
||||
if test_case.softreset:
|
||||
args.append('--softreset')
|
||||
if snr is not None:
|
||||
args.extend(['--snr', snr])
|
||||
if erase:
|
||||
if test_case.snr:
|
||||
args.extend(['--snr', TEST_OVR_SNR])
|
||||
if test_case.erase:
|
||||
args.append('--erase')
|
||||
if test_case.recover:
|
||||
args.append('--recover')
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
NrfJprogBinaryRunner.add_parser(parser)
|
||||
|
@ -283,10 +358,10 @@ def test_nrfjprog_create(cc, get_snr, req, test_case, runner_config):
|
|||
with patch('os.path.isfile', side_effect=os_path_isfile_patch):
|
||||
runner.run('flash')
|
||||
|
||||
assert req.called
|
||||
assert cc.call_args_list == [call(x) for x in
|
||||
expected_commands(*test_case)]
|
||||
if snr is None:
|
||||
assert require.called
|
||||
assert check_call.call_args_list == [call(x) for x in expected]
|
||||
|
||||
if not test_case.snr:
|
||||
get_snr.assert_called_once_with('*')
|
||||
else:
|
||||
get_snr.assert_not_called()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue