runners: nrfjprog: workaround for multi-core hex files
The nrfjprog utility is not capable of flashing a hex file which affects the flash memories of both coprocessors of the nRF53 family of SoCs. However, the user is capable of creating such a hex file using the HEX_FILES_TO_MERGE build system variable. An example use case is to build a bluetooth controller application for the network core, then use the zephyr.hex file in that build directory as the HEX_FILES_TO_MERGE argument for a separate Bluetooth application build targeting the app core. Work around this by detecting the situation and doing the right thing by splitting the hex file back up again, even if thats a bit awkward. Splitting the hex into app and network core components allows them to be flashed separately. This is the only way we can get the job done with nrfjprog. This is arguably nicer since there's just one 'west flash' invocation. At least in the use case named above, you wouldn't need to rebuild the controller application very often, so this is a simpler user workflow. Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
This commit is contained in:
parent
795d0577c9
commit
524853ecfa
|
@ -5,6 +5,8 @@
|
|||
|
||||
'''Runner for flashing with nrfjprog.'''
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
import shlex
|
||||
import subprocess
|
||||
import sys
|
||||
|
@ -239,27 +241,22 @@ class NrfJprogBinaryRunner(ZephyrBinaryRunner):
|
|||
else:
|
||||
erase_arg = '--sectorerase'
|
||||
|
||||
# What nrfjprog commands do we need to flash this target?
|
||||
program_commands = []
|
||||
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]
|
||||
# nRF53 requires special treatment due to the extra coprocessor.
|
||||
self.program_hex_nrf53(erase_arg, program_commands)
|
||||
else:
|
||||
coprocessor_args = []
|
||||
# It's important for tool_opt to come last, so it can override
|
||||
# any options that we set here.
|
||||
program_commands.append(['nrfjprog', '--program', self.hex_,
|
||||
erase_arg, '-f', self.family,
|
||||
'--snr', self.snr] +
|
||||
self.tool_opt)
|
||||
|
||||
# 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)
|
||||
for command in program_commands:
|
||||
self.check_call(command)
|
||||
except subprocess.CalledProcessError as cpe:
|
||||
if cpe.returncode == UnavailableOperationBecauseProtectionError:
|
||||
if self.family == 'NRF53':
|
||||
|
@ -278,6 +275,69 @@ class NrfJprogBinaryRunner(ZephyrBinaryRunner):
|
|||
family_help)
|
||||
raise
|
||||
|
||||
def program_hex_nrf53(self, erase_arg, program_commands):
|
||||
# program_hex() helper for nRF53.
|
||||
|
||||
# *********************** NOTE *******************************
|
||||
# self.hex_ can contain code for both the application core and
|
||||
# the network core.
|
||||
#
|
||||
# We can't assume, for example, that
|
||||
# CONFIG_SOC_NRF5340_CPUAPP=y means self.hex_ only contains
|
||||
# data for the app core's flash: the user can put arbitrary
|
||||
# addresses into one of the files in HEX_FILES_TO_MERGE.
|
||||
#
|
||||
# Therefore, on this family, we may need to generate two new
|
||||
# hex files, one for each core, and flash them individually
|
||||
# with the correct '--coprocessor' arguments.
|
||||
#
|
||||
# Kind of hacky, but it works, and nrfjprog is not capable of
|
||||
# flashing to both cores at once. If self.hex_ only affects
|
||||
# one core's flash, then we skip the extra work to save time.
|
||||
# ************************************************************
|
||||
|
||||
def add_program_cmd(hex_file, coprocessor):
|
||||
program_commands.append(
|
||||
['nrfjprog', '--program', hex_file, erase_arg,
|
||||
'-f', 'NRF53', '--snr', self.snr,
|
||||
'--coprocessor', coprocessor] + self.tool_opt)
|
||||
|
||||
full_hex = IntelHex()
|
||||
full_hex.loadfile(self.hex_, format='hex')
|
||||
min_addr, max_addr = full_hex.minaddr(), full_hex.maxaddr()
|
||||
|
||||
# Base address of network coprocessor's flash. From nRF5340
|
||||
# OPS. We should get this from DTS instead if multiple values
|
||||
# are possible, but this is fine for now.
|
||||
net_base = 0x01000000
|
||||
|
||||
if min_addr < net_base <= max_addr:
|
||||
net_hex, app_hex = IntelHex(), IntelHex()
|
||||
|
||||
for start, stop in full_hex.segments():
|
||||
segment_hex = net_hex if start >= net_base else app_hex
|
||||
segment_hex.merge(full_hex[start:stop])
|
||||
|
||||
hex_path = Path(self.hex_)
|
||||
hex_dir, hex_name = hex_path.parent, hex_path.name
|
||||
|
||||
net_hex_file = os.fspath(hex_dir / f'GENERATED_CP_NETWORK_{hex_name}')
|
||||
app_hex_file = os.fspath(
|
||||
hex_dir / f'GENERATED_CP_APPLICATION_{hex_name}')
|
||||
|
||||
self.logger.info(
|
||||
f'{self.hex_} targets both nRF53 coprocessors; '
|
||||
f'splitting it into: {net_hex_file} and {app_hex_file}')
|
||||
|
||||
net_hex.write_hex_file(net_hex_file)
|
||||
app_hex.write_hex_file(app_hex_file)
|
||||
|
||||
add_program_cmd(net_hex_file, 'CP_NETWORK')
|
||||
add_program_cmd(app_hex_file, 'CP_APPLICATION')
|
||||
else:
|
||||
coprocessor = 'CP_NETWORK' if max_addr >= net_base else 'CP_APPLICATION'
|
||||
add_program_cmd(self.hex_, coprocessor)
|
||||
|
||||
def reset_target(self):
|
||||
if self.family == 'NRF52' and not self.softreset:
|
||||
self.check_call(['nrfjprog', '--pinresetenable', '-f', self.family,
|
||||
|
|
1
scripts/west_commands/tests/nrfjprog/README.rst
Normal file
1
scripts/west_commands/tests/nrfjprog/README.rst
Normal file
|
@ -0,0 +1 @@
|
|||
This directory contains test data files for test_nrfjprog.py.
|
|
@ -0,0 +1,5 @@
|
|||
:020000040000FA
|
||||
:0100000001FE
|
||||
:020000040100F9
|
||||
:0100000001FE
|
||||
:00000001FF
|
|
@ -0,0 +1,2 @@
|
|||
:0100000001FE
|
||||
:00000001FF
|
|
@ -0,0 +1,3 @@
|
|||
:020000040100F9
|
||||
:0100000001FE
|
||||
:00000001FF
|
|
@ -5,11 +5,14 @@
|
|||
|
||||
import argparse
|
||||
import os
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import typing
|
||||
from unittest.mock import patch, call
|
||||
|
||||
import pytest
|
||||
|
||||
from runners.core import RunnerConfig
|
||||
from runners.nrfjprog import NrfJprogBinaryRunner
|
||||
from conftest import RC_KERNEL_HEX
|
||||
|
||||
|
@ -21,21 +24,32 @@ from conftest import RC_KERNEL_HEX
|
|||
TEST_DEF_SNR = 'test-default-serial-number' # for mocking user input
|
||||
TEST_OVR_SNR = 'test-override-serial-number'
|
||||
|
||||
# nRF53 flashing is special in that we have different results
|
||||
# depending on the input hex file. For that reason, we test it with
|
||||
# real hex files.
|
||||
TEST_DIR = Path(__file__).parent / 'nrfjprog'
|
||||
NRF5340_APP_ONLY_HEX = os.fspath(TEST_DIR / 'nrf5340_app_only.hex')
|
||||
NRF5340_NET_ONLY_HEX = os.fspath(TEST_DIR / 'nrf5340_net_only.hex')
|
||||
NRF5340_APP_AND_NET_HEX = os.fspath(TEST_DIR / 'nrf5340_app_and_net.hex')
|
||||
|
||||
#
|
||||
# A dictionary mapping test cases to expected results.
|
||||
#
|
||||
# The keys are TC objects.
|
||||
#
|
||||
# The values are the nrfjprog commands we expect to be executed for
|
||||
# The values are usually 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.
|
||||
#
|
||||
# Values can also be callables which take a tmpdir and return the
|
||||
# expected nrfjprog commands. This is needed for nRF53 testing.
|
||||
#
|
||||
|
||||
class TC(typing.NamedTuple): # 'TestCase'
|
||||
# NRF51, NRF52, etc.
|
||||
family: str
|
||||
|
||||
# 'APP', 'NET', or None.
|
||||
# 'APP', 'NET', 'APP+NET', or None.
|
||||
coprocessor: typing.Optional[str]
|
||||
|
||||
# Run 'nrfjprog --recover' first if True
|
||||
|
@ -131,87 +145,182 @@ EXPECTED_RESULTS = {
|
|||
['nrfjprog', '--reset', '-f', 'NRF52', '--snr', TEST_OVR_SNR]),
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# NRF53 APP
|
||||
# NRF53 APP only
|
||||
#
|
||||
# family CP recov soft snr erase
|
||||
|
||||
TC('NRF53', 'APP', False, False, False, False):
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '-f', 'NRF53',
|
||||
'--snr', TEST_DEF_SNR, '--coprocessor', 'CP_APPLICATION'],
|
||||
(['nrfjprog', '--program', NRF5340_APP_ONLY_HEX, '--sectorerase',
|
||||
'-f', 'NRF53', '--snr', TEST_DEF_SNR, '--coprocessor', 'CP_APPLICATION'],
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_DEF_SNR]),
|
||||
|
||||
TC('NRF53', 'APP', False, False, False, True):
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '--chiperase', '-f', 'NRF53',
|
||||
'--snr', TEST_DEF_SNR, '--coprocessor', 'CP_APPLICATION'],
|
||||
(['nrfjprog', '--program', NRF5340_APP_ONLY_HEX, '--chiperase',
|
||||
'-f', 'NRF53', '--snr', TEST_DEF_SNR, '--coprocessor', 'CP_APPLICATION'],
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_DEF_SNR]),
|
||||
|
||||
TC('NRF53', 'APP', False, False, True, False):
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '-f', 'NRF53',
|
||||
'--snr', TEST_OVR_SNR, '--coprocessor', 'CP_APPLICATION'],
|
||||
(['nrfjprog', '--program', NRF5340_APP_ONLY_HEX, '--sectorerase',
|
||||
'-f', 'NRF53', '--snr', TEST_OVR_SNR, '--coprocessor', 'CP_APPLICATION'],
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_OVR_SNR]),
|
||||
|
||||
TC('NRF53', 'APP', False, True, False, False):
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '-f', 'NRF53',
|
||||
'--snr', TEST_DEF_SNR, '--coprocessor', 'CP_APPLICATION'],
|
||||
(['nrfjprog', '--program', NRF5340_APP_ONLY_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', '--program', NRF5340_APP_ONLY_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', '--program', NRF5340_APP_ONLY_HEX, '--chiperase',
|
||||
'-f', 'NRF53', '--snr', TEST_OVR_SNR, '--coprocessor', 'CP_APPLICATION'],
|
||||
['nrfjprog', '--reset', '-f', 'NRF53', '--snr', TEST_OVR_SNR]),
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# NRF53 NET
|
||||
# NRF53 NET only
|
||||
#
|
||||
# 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', '--program', NRF5340_NET_ONLY_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', '--program', NRF5340_NET_ONLY_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', '--program', NRF5340_NET_ONLY_HEX, '--sectorerase',
|
||||
'-f', 'NRF53', '--snr', TEST_OVR_SNR, '--coprocessor', 'CP_NETWORK'],
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_OVR_SNR]),
|
||||
|
||||
TC('NRF53', 'NET', False, True, False, False):
|
||||
(['nrfjprog', '--program', RC_KERNEL_HEX, '--sectorerase', '-f', 'NRF53',
|
||||
'--snr', TEST_DEF_SNR, '--coprocessor', 'CP_NETWORK'],
|
||||
(['nrfjprog', '--program', NRF5340_NET_ONLY_HEX, '--sectorerase',
|
||||
'-f', 'NRF53', '--snr', TEST_DEF_SNR, '--coprocessor', 'CP_NETWORK'],
|
||||
['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', '--program', NRF5340_NET_ONLY_HEX, '--sectorerase',
|
||||
'-f', 'NRF53', '--snr', TEST_DEF_SNR, '--coprocessor', 'CP_NETWORK'],
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_DEF_SNR]),
|
||||
|
||||
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', '--program', NRF5340_NET_ONLY_HEX, '--chiperase',
|
||||
'-f', 'NRF53', '--snr', TEST_OVR_SNR, '--coprocessor', 'CP_NETWORK'],
|
||||
['nrfjprog', '--reset', '-f', 'NRF53', '--snr', TEST_OVR_SNR]),
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# NRF53 APP+NET
|
||||
#
|
||||
# family CP recov soft snr erase
|
||||
|
||||
TC('NRF53', 'APP+NET', False, False, False, False):
|
||||
(lambda tmpdir, infile: \
|
||||
(['nrfjprog',
|
||||
'--program',
|
||||
os.fspath(tmpdir / 'GENERATED_CP_NETWORK_' + Path(infile).name),
|
||||
'--sectorerase', '-f', 'NRF53', '--snr', TEST_DEF_SNR,
|
||||
'--coprocessor', 'CP_NETWORK'],
|
||||
['nrfjprog',
|
||||
'--program',
|
||||
os.fspath(tmpdir / 'GENERATED_CP_APPLICATION_' + Path(infile).name),
|
||||
'--sectorerase', '-f', 'NRF53', '--snr', TEST_DEF_SNR,
|
||||
'--coprocessor', 'CP_APPLICATION'],
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_DEF_SNR])),
|
||||
|
||||
TC('NRF53', 'APP+NET', False, False, False, True):
|
||||
(lambda tmpdir, infile: \
|
||||
(['nrfjprog',
|
||||
'--program',
|
||||
os.fspath(tmpdir / 'GENERATED_CP_NETWORK_' + Path(infile).name),
|
||||
'--chiperase', '-f', 'NRF53', '--snr', TEST_DEF_SNR,
|
||||
'--coprocessor', 'CP_NETWORK'],
|
||||
['nrfjprog',
|
||||
'--program',
|
||||
os.fspath(tmpdir / 'GENERATED_CP_APPLICATION_' + Path(infile).name),
|
||||
'--chiperase', '-f', 'NRF53', '--snr', TEST_DEF_SNR,
|
||||
'--coprocessor', 'CP_APPLICATION'],
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_DEF_SNR])),
|
||||
|
||||
TC('NRF53', 'APP+NET', False, False, True, False):
|
||||
(lambda tmpdir, infile: \
|
||||
(['nrfjprog',
|
||||
'--program',
|
||||
os.fspath(tmpdir / 'GENERATED_CP_NETWORK_' + Path(infile).name),
|
||||
'--sectorerase', '-f', 'NRF53', '--snr', TEST_OVR_SNR,
|
||||
'--coprocessor', 'CP_NETWORK'],
|
||||
['nrfjprog',
|
||||
'--program',
|
||||
os.fspath(tmpdir / 'GENERATED_CP_APPLICATION_' + Path(infile).name),
|
||||
'--sectorerase', '-f', 'NRF53', '--snr', TEST_OVR_SNR,
|
||||
'--coprocessor', 'CP_APPLICATION'],
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_OVR_SNR])),
|
||||
|
||||
TC('NRF53', 'APP+NET', False, True, False, False):
|
||||
(lambda tmpdir, infile: \
|
||||
(['nrfjprog',
|
||||
'--program',
|
||||
os.fspath(tmpdir / 'GENERATED_CP_NETWORK_' + Path(infile).name),
|
||||
'--sectorerase', '-f', 'NRF53', '--snr', TEST_DEF_SNR,
|
||||
'--coprocessor', 'CP_NETWORK'],
|
||||
['nrfjprog',
|
||||
'--program',
|
||||
os.fspath(tmpdir / 'GENERATED_CP_APPLICATION_' + Path(infile).name),
|
||||
'--sectorerase', '-f', 'NRF53', '--snr', TEST_DEF_SNR,
|
||||
'--coprocessor', 'CP_APPLICATION'],
|
||||
['nrfjprog', '--reset', '-f', 'NRF53', '--snr', TEST_DEF_SNR])),
|
||||
|
||||
TC('NRF53', 'APP+NET', True, False, False, False):
|
||||
(lambda tmpdir, infile: \
|
||||
(['nrfjprog', '--recover', '-f', 'NRF53', '--coprocessor', 'CP_NETWORK',
|
||||
'--snr', TEST_DEF_SNR],
|
||||
['nrfjprog', '--recover', '-f', 'NRF53', '--snr', TEST_DEF_SNR],
|
||||
['nrfjprog',
|
||||
'--program',
|
||||
os.fspath(tmpdir / 'GENERATED_CP_NETWORK_' + Path(infile).name),
|
||||
'--sectorerase', '-f', 'NRF53', '--snr', TEST_DEF_SNR,
|
||||
'--coprocessor', 'CP_NETWORK'],
|
||||
['nrfjprog',
|
||||
'--program',
|
||||
os.fspath(tmpdir / 'GENERATED_CP_APPLICATION_' + Path(infile).name),
|
||||
'--sectorerase', '-f', 'NRF53', '--snr', TEST_DEF_SNR,
|
||||
'--coprocessor', 'CP_APPLICATION'],
|
||||
['nrfjprog', '--pinreset', '-f', 'NRF53', '--snr', TEST_DEF_SNR])),
|
||||
|
||||
TC('NRF53', 'APP+NET', True, True, True, True):
|
||||
(lambda tmpdir, infile: \
|
||||
(['nrfjprog', '--recover', '-f', 'NRF53', '--coprocessor', 'CP_NETWORK',
|
||||
'--snr', TEST_OVR_SNR],
|
||||
['nrfjprog', '--recover', '-f', 'NRF53', '--snr', TEST_OVR_SNR],
|
||||
['nrfjprog',
|
||||
'--program',
|
||||
os.fspath(tmpdir / 'GENERATED_CP_NETWORK_' + Path(infile).name),
|
||||
'--chiperase', '-f', 'NRF53', '--snr', TEST_OVR_SNR,
|
||||
'--coprocessor', 'CP_NETWORK'],
|
||||
['nrfjprog',
|
||||
'--program',
|
||||
os.fspath(tmpdir / 'GENERATED_CP_APPLICATION_' + Path(infile).name),
|
||||
'--chiperase', '-f', 'NRF53', '--snr', TEST_OVR_SNR,
|
||||
'--coprocessor', 'CP_APPLICATION'],
|
||||
['nrfjprog', '--reset', '-f', 'NRF53', '--snr', TEST_OVR_SNR])),
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# NRF91
|
||||
#
|
||||
|
@ -259,27 +368,18 @@ def get_board_snr_patch(glob):
|
|||
def require_patch(program):
|
||||
assert program == 'nrfjprog'
|
||||
|
||||
os_path_isfile = os.path.isfile
|
||||
|
||||
def os_path_isfile_patch(filename):
|
||||
if filename == RC_KERNEL_HEX:
|
||||
return True
|
||||
return os.path.isfile(filename)
|
||||
return os_path_isfile(filename)
|
||||
|
||||
def build_configuration(test_case):
|
||||
ret = {
|
||||
return {
|
||||
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:
|
||||
assert False, f'bad nRF53 coprocessor {test_case.coprocessor}'
|
||||
|
||||
return ret
|
||||
|
||||
#
|
||||
# Test functions.
|
||||
#
|
||||
|
@ -298,6 +398,30 @@ def id_fn(test_case):
|
|||
|
||||
return f'{test_case.family}{cp}, {s}, {sn}, {e}, {r}'
|
||||
|
||||
def fix_up_runner_config(test_case, runner_config, tmpdir):
|
||||
# Helper that adjusts the common runner_config fixture for our
|
||||
# nRF53-specific tests that use real hex files.
|
||||
|
||||
if test_case.family != 'NRF53':
|
||||
return runner_config
|
||||
|
||||
config_as_dict = runner_config._asdict()
|
||||
|
||||
if test_case.coprocessor == 'APP':
|
||||
config_as_dict['hex_file'] = NRF5340_APP_ONLY_HEX
|
||||
elif test_case.coprocessor == 'NET':
|
||||
config_as_dict['hex_file'] = NRF5340_NET_ONLY_HEX
|
||||
elif test_case.coprocessor == 'APP+NET':
|
||||
# Since the runner is going to generate files next to its input
|
||||
# file, we need to stash a copy in a tmpdir it can use.
|
||||
outfile = tmpdir / Path(NRF5340_APP_AND_NET_HEX).name
|
||||
shutil.copyfile(NRF5340_APP_AND_NET_HEX, outfile)
|
||||
config_as_dict['hex_file'] = os.fspath(outfile)
|
||||
else:
|
||||
assert False, f'bad test case {test_case}'
|
||||
|
||||
return RunnerConfig(**config_as_dict)
|
||||
|
||||
@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',
|
||||
|
@ -305,7 +429,8 @@ def id_fn(test_case):
|
|||
@patch('runners.nrfjprog.NrfJprogBinaryRunner.check_call')
|
||||
@patch('runners.nrfjprog.BuildConfiguration')
|
||||
def test_nrfjprog_init(build_conf, check_call, get_snr, require, test_case,
|
||||
runner_config):
|
||||
runner_config, tmpdir):
|
||||
runner_config = fix_up_runner_config(test_case, runner_config, tmpdir)
|
||||
build_conf.return_value = build_configuration(test_case)
|
||||
expected = EXPECTED_RESULTS[test_case]
|
||||
snr = TEST_OVR_SNR if test_case.snr else None
|
||||
|
@ -320,10 +445,11 @@ def test_nrfjprog_init(build_conf, check_call, get_snr, require, test_case,
|
|||
runner.run('flash')
|
||||
assert require.called
|
||||
|
||||
if expected is not None:
|
||||
assert check_call.call_args_list == [call(x) for x in expected]
|
||||
if callable(expected):
|
||||
assert (check_call.call_args_list ==
|
||||
[call(x) for x in expected(tmpdir, runner_config.hex_file)])
|
||||
else:
|
||||
assert not check_call.called
|
||||
assert check_call.call_args_list == [call(x) for x in expected]
|
||||
|
||||
if snr is None:
|
||||
get_snr.assert_called_once_with('*')
|
||||
|
@ -337,7 +463,8 @@ def test_nrfjprog_init(build_conf, check_call, get_snr, require, test_case,
|
|||
@patch('runners.nrfjprog.NrfJprogBinaryRunner.check_call')
|
||||
@patch('runners.nrfjprog.BuildConfiguration')
|
||||
def test_nrfjprog_create(build_conf, check_call, get_snr, require, test_case,
|
||||
runner_config):
|
||||
runner_config, tmpdir):
|
||||
runner_config = fix_up_runner_config(test_case, runner_config, tmpdir)
|
||||
build_conf.return_value = build_configuration(test_case)
|
||||
expected = EXPECTED_RESULTS[test_case]
|
||||
|
||||
|
@ -359,7 +486,11 @@ def test_nrfjprog_create(build_conf, check_call, get_snr, require, test_case,
|
|||
runner.run('flash')
|
||||
|
||||
assert require.called
|
||||
assert check_call.call_args_list == [call(x) for x in expected]
|
||||
if callable(expected):
|
||||
assert (check_call.call_args_list ==
|
||||
[call(x) for x in expected(tmpdir, runner_config.hex_file)])
|
||||
else:
|
||||
assert check_call.call_args_list == [call(x) for x in expected]
|
||||
|
||||
if not test_case.snr:
|
||||
get_snr.assert_called_once_with('*')
|
||||
|
|
Loading…
Reference in a new issue