blob: 08051fa823ae66edd2822fc32eac981db5618a3a [file] [log] [blame]
# Copyright (c) 2018 Foundries.io
# Copyright (c) 2019 Nordic Semiconductor ASA.
# Copyright (c) 2020-2021 Gerson Fernando Budke <nandojve@gmail.com>
#
# SPDX-License-Identifier: Apache-2.0
import argparse
import os
import platform
from unittest.mock import patch, call
import pytest
from runners.bossac import BossacBinaryRunner
from conftest import RC_KERNEL_BIN
if platform.system() != 'Linux':
pytest.skip("skipping Linux-only bossac tests", allow_module_level=True)
TEST_BOSSAC_PORT = 'test-bossac-serial'
TEST_BOSSAC_SPEED = '1200'
TEST_OFFSET = 1234
TEST_FLASH_ADDRESS = 5678
TEST_BOARD_NAME = "my_board"
EXPECTED_COMMANDS = [
['stty', '-F', TEST_BOSSAC_PORT, 'raw', 'ispeed', '115200',
'ospeed', '115200', 'cs8', '-cstopb', 'ignpar', 'eol', '255',
'eof', '255'],
['bossac', '-p', TEST_BOSSAC_PORT, '-R', '-e', '-w', '-v',
'-b', RC_KERNEL_BIN],
]
EXPECTED_COMMANDS_WITH_SPEED = [
['stty', '-F', TEST_BOSSAC_PORT, 'raw', 'ispeed', TEST_BOSSAC_SPEED,
'ospeed', TEST_BOSSAC_SPEED, 'cs8', '-cstopb', 'ignpar', 'eol', '255',
'eof', '255'],
['bossac', '-p', TEST_BOSSAC_PORT, '-R', '-e', '-w', '-v',
'-b', RC_KERNEL_BIN],
]
EXPECTED_COMMANDS_WITH_OFFSET = [
['stty', '-F', TEST_BOSSAC_PORT, 'raw', 'ispeed', '115200',
'ospeed', '115200', 'cs8', '-cstopb', 'ignpar', 'eol', '255',
'eof', '255'],
['bossac', '-p', TEST_BOSSAC_PORT, '-R', '-e', '-w', '-v',
'-b', RC_KERNEL_BIN, '-o', str(TEST_OFFSET)],
]
EXPECTED_COMMANDS_WITH_FLASH_ADDRESS = [
[
'stty', '-F', TEST_BOSSAC_PORT, 'raw', 'ispeed', '115200',
'ospeed', '115200', 'cs8', '-cstopb', 'ignpar', 'eol', '255',
'eof', '255'
],
[
'bossac', '-p', TEST_BOSSAC_PORT, '-R', '-e', '-w', '-v',
'-b', RC_KERNEL_BIN, '-o', str(TEST_FLASH_ADDRESS),
],
]
EXPECTED_COMMANDS_WITH_EXTENDED = [
[
'stty', '-F', TEST_BOSSAC_PORT, 'raw', 'ispeed', '1200',
'ospeed', '1200', 'cs8', '-cstopb', 'ignpar', 'eol', '255',
'eof', '255'
],
[
'bossac', '-p', TEST_BOSSAC_PORT, '-R', '-e', '-w', '-v',
'-b', RC_KERNEL_BIN, '-o', str(TEST_FLASH_ADDRESS),
],
]
# SAM-BA ROM without offset
# No code partition Kconfig
# No zephyr,code-partition (defined on DT)
DOTCONFIG_STD = f'''
CONFIG_BOARD="{TEST_BOARD_NAME}"
CONFIG_FLASH_LOAD_OFFSET=0x162e
'''
# SAM-BA ROM/FLASH with offset
DOTCONFIG_COND1 = f'''
CONFIG_BOARD="{TEST_BOARD_NAME}"
CONFIG_USE_DT_CODE_PARTITION=y
CONFIG_HAS_FLASH_LOAD_OFFSET=y
CONFIG_FLASH_LOAD_OFFSET=0x162e
'''
# SAM-BA ROM/FLASH without offset
# No code partition Kconfig
DOTCONFIG_COND2 = f'''
CONFIG_BOARD="{TEST_BOARD_NAME}"
CONFIG_HAS_FLASH_LOAD_OFFSET=y
CONFIG_FLASH_LOAD_OFFSET=0x162e
'''
# SAM-BA Extended Arduino with offset
DOTCONFIG_COND3 = f'''
CONFIG_BOARD="{TEST_BOARD_NAME}"
CONFIG_USE_DT_CODE_PARTITION=y
CONFIG_BOOTLOADER_BOSSA_ARDUINO=y
CONFIG_HAS_FLASH_LOAD_OFFSET=y
CONFIG_FLASH_LOAD_OFFSET=0x162e
'''
# SAM-BA Extended Adafruit with offset
DOTCONFIG_COND4 = f'''
CONFIG_BOARD="{TEST_BOARD_NAME}"
CONFIG_USE_DT_CODE_PARTITION=y
CONFIG_BOOTLOADER_BOSSA_ADAFRUIT_UF2=y
CONFIG_HAS_FLASH_LOAD_OFFSET=y
CONFIG_FLASH_LOAD_OFFSET=0x162e
'''
# SAM-BA omit offset
DOTCONFIG_COND5 = f'''
CONFIG_BOARD="{TEST_BOARD_NAME}"
CONFIG_USE_DT_CODE_PARTITION=y
CONFIG_HAS_FLASH_LOAD_OFFSET=y
CONFIG_FLASH_LOAD_OFFSET=0x0
'''
# SAM-BA Legacy Mode
DOTCONFIG_COND6 = f'''
CONFIG_BOARD="{TEST_BOARD_NAME}"
CONFIG_USE_DT_CODE_PARTITION=y
CONFIG_BOOTLOADER_BOSSA_LEGACY=y
CONFIG_HAS_FLASH_LOAD_OFFSET=y
CONFIG_FLASH_LOAD_OFFSET=0x162e
'''
def adjust_runner_config(runner_config, tmpdir, dotconfig):
# Adjust a RunnerConfig object, 'runner_config', by
# replacing its build directory with 'tmpdir' after writing
# the contents of 'dotconfig' to tmpdir/zephyr/.config.
zephyr = tmpdir / 'zephyr'
zephyr.mkdir()
with open(zephyr / '.config', 'w') as f:
f.write(dotconfig)
return runner_config._replace(build_dir=os.fspath(tmpdir))
def require_patch(program):
assert program in ['bossac', 'stty']
os_path_isfile = os.path.isfile
def os_path_isfile_patch(filename):
if filename == RC_KERNEL_BIN:
return True
return os_path_isfile(filename)
@patch('runners.bossac.BossacBinaryRunner.supports',
return_value=False)
@patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
return_value=None)
@patch('runners.core.ZephyrBinaryRunner.require',
side_effect=require_patch)
@patch('runners.core.ZephyrBinaryRunner.check_call')
def test_bossac_init(cc, req, get_cod_par, sup, runner_config, tmpdir):
"""
Test commands using a runner created by constructor.
Requirements:
Any SDK
Configuration:
ROM bootloader
CONFIG_USE_DT_CODE_PARTITION=n
without zephyr,code-partition
Input:
none
Output:
no --offset
"""
runner_config = adjust_runner_config(runner_config, tmpdir, DOTCONFIG_STD)
runner = BossacBinaryRunner(runner_config, port=TEST_BOSSAC_PORT)
with patch('os.path.isfile', side_effect=os_path_isfile_patch):
runner.run('flash')
assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS]
@patch('runners.bossac.BossacBinaryRunner.supports',
return_value=False)
@patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
return_value=None)
@patch('runners.core.ZephyrBinaryRunner.require',
side_effect=require_patch)
@patch('runners.core.ZephyrBinaryRunner.check_call')
def test_bossac_create(cc, req, get_cod_par, sup, runner_config, tmpdir):
"""
Test commands using a runner created from command line parameters.
Requirements:
Any SDK
Configuration:
ROM bootloader
CONFIG_USE_DT_CODE_PARTITION=n
without zephyr,code-partition
Input:
--bossac-port
Output:
no --offset
"""
args = ['--bossac-port', str(TEST_BOSSAC_PORT)]
parser = argparse.ArgumentParser()
BossacBinaryRunner.add_parser(parser)
arg_namespace = parser.parse_args(args)
runner_config = adjust_runner_config(runner_config, tmpdir, DOTCONFIG_STD)
runner = BossacBinaryRunner.create(runner_config, arg_namespace)
with patch('os.path.isfile', side_effect=os_path_isfile_patch):
runner.run('flash')
assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS]
@patch('runners.bossac.BossacBinaryRunner.supports',
return_value=False)
@patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
return_value=None)
@patch('runners.core.ZephyrBinaryRunner.require',
side_effect=require_patch)
@patch('runners.core.ZephyrBinaryRunner.check_call')
def test_bossac_create_with_speed(cc, req, get_cod_par, sup, runner_config, tmpdir):
"""
Test commands using a runner created from command line parameters.
Requirements:
Any SDK
Configuration:
ROM bootloader
CONFIG_USE_DT_CODE_PARTITION=n
without zephyr,code-partition
Input:
--bossac-port
--speed
Output:
no --offset
"""
args = ['--bossac-port', str(TEST_BOSSAC_PORT),
'--speed', str(TEST_BOSSAC_SPEED)]
parser = argparse.ArgumentParser()
BossacBinaryRunner.add_parser(parser)
arg_namespace = parser.parse_args(args)
runner_config = adjust_runner_config(runner_config, tmpdir, DOTCONFIG_STD)
runner = BossacBinaryRunner.create(runner_config, arg_namespace)
with patch('os.path.isfile', side_effect=os_path_isfile_patch):
runner.run('flash')
assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS_WITH_SPEED]
@patch('runners.bossac.BossacBinaryRunner.supports',
return_value=True)
@patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
return_value=True)
@patch('runners.core.ZephyrBinaryRunner.require',
side_effect=require_patch)
@patch('runners.core.ZephyrBinaryRunner.check_call')
def test_bossac_create_with_flash_address(cc, req, get_cod_par, sup,
runner_config, tmpdir):
"""
Test command with offset parameter
Requirements:
SDK >= 0.12.0
Configuration:
Any bootloader
CONFIG_USE_DT_CODE_PARTITION=y
with zephyr,code-partition
Input:
--bossac-port
Output:
--offset
"""
args = [
'--bossac-port',
str(TEST_BOSSAC_PORT),
]
parser = argparse.ArgumentParser()
BossacBinaryRunner.add_parser(parser)
arg_namespace = parser.parse_args(args)
runner_config = adjust_runner_config(runner_config, tmpdir,
DOTCONFIG_COND1)
runner = BossacBinaryRunner.create(runner_config, arg_namespace)
with patch('os.path.isfile', side_effect=os_path_isfile_patch):
runner.run('flash')
assert cc.call_args_list == [
call(x) for x in EXPECTED_COMMANDS_WITH_FLASH_ADDRESS
]
@patch('runners.bossac.BossacBinaryRunner.supports',
return_value=False)
@patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
return_value=True)
@patch('runners.core.ZephyrBinaryRunner.require',
side_effect=require_patch)
@patch('runners.core.ZephyrBinaryRunner.check_call')
def test_bossac_create_with_omit_address(cc, req, bcfg_ini, sup,
runner_config, tmpdir):
"""
Test command that will omit offset because CONFIG_FLASH_LOAD_OFFSET is 0.
This case is valid for ROM bootloaders that define image start at 0 and
define flash partitions, to use the storage capabilities, for instance.
Requirements:
Any SDK
Configuration:
ROM bootloader
CONFIG_USE_DT_CODE_PARTITION=y
with zephyr,code-partition
Input:
--bossac-port
Output:
no --offset
"""
runner_config = adjust_runner_config(runner_config, tmpdir,
DOTCONFIG_COND5)
runner = BossacBinaryRunner(runner_config, port=TEST_BOSSAC_PORT)
with patch('os.path.isfile', side_effect=os_path_isfile_patch):
runner.run('flash')
assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS]
@patch('runners.bossac.BossacBinaryRunner.supports',
return_value=True)
@patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
return_value=True)
@patch('runners.core.ZephyrBinaryRunner.require',
side_effect=require_patch)
@patch('runners.core.ZephyrBinaryRunner.check_call')
def test_bossac_create_with_arduino(cc, req, get_cod_par, sup,
runner_config, tmpdir):
"""
Test SAM-BA extended protocol with Arduino variation
Requirements:
SDK >= 0.12.0
Configuration:
Extended bootloader
CONFIG_USE_DT_CODE_PARTITION=y
CONFIG_BOOTLOADER_BOSSA_ARDUINO=y
with zephyr,code-partition
Input:
--bossac-port
Output:
--offset
"""
runner_config = adjust_runner_config(runner_config, tmpdir,
DOTCONFIG_COND3)
runner = BossacBinaryRunner(runner_config, port=TEST_BOSSAC_PORT)
with patch('os.path.isfile', side_effect=os_path_isfile_patch):
runner.run('flash')
assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS_WITH_EXTENDED]
@patch('runners.bossac.BossacBinaryRunner.supports',
return_value=True)
@patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
return_value=True)
@patch('runners.core.ZephyrBinaryRunner.require',
side_effect=require_patch)
@patch('runners.core.ZephyrBinaryRunner.check_call')
def test_bossac_create_with_adafruit(cc, req, get_cod_par, sup,
runner_config, tmpdir):
"""
Test SAM-BA extended protocol with Adafruit UF2 variation
Requirements:
SDK >= 0.12.0
Configuration:
Extended bootloader
CONFIG_USE_DT_CODE_PARTITION=y
CONFIG_BOOTLOADER_BOSSA_ADAFRUIT_UF2=y
with zephyr,code-partition
Input:
--bossac-port
Output:
--offset
"""
runner_config = adjust_runner_config(runner_config, tmpdir,
DOTCONFIG_COND4)
runner = BossacBinaryRunner(runner_config, port=TEST_BOSSAC_PORT)
with patch('os.path.isfile', side_effect=os_path_isfile_patch):
runner.run('flash')
assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS_WITH_EXTENDED]
@patch('runners.bossac.BossacBinaryRunner.supports',
return_value=True)
@patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
return_value=True)
@patch('runners.core.ZephyrBinaryRunner.require',
side_effect=require_patch)
@patch('runners.core.ZephyrBinaryRunner.check_call')
def test_bossac_create_with_legacy(cc, req, get_cod_par, sup,
runner_config, tmpdir):
"""
Test SAM-BA legacy protocol
Requirements:
Any SDK
Configuration:
Extended bootloader
CONFIG_USE_DT_CODE_PARTITION=y
CONFIG_BOOTLOADER_BOSSA_LEGACY=y
with zephyr,code-partition
Input:
--bossac-port
Output:
no --offset
"""
runner_config = adjust_runner_config(runner_config, tmpdir,
DOTCONFIG_COND6)
runner = BossacBinaryRunner(runner_config, port=TEST_BOSSAC_PORT)
with patch('os.path.isfile', side_effect=os_path_isfile_patch):
runner.run('flash')
assert cc.call_args_list == [call(x) for x in EXPECTED_COMMANDS]
@patch('runners.bossac.BossacBinaryRunner.supports',
return_value=False)
@patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
return_value=True)
@patch('runners.core.ZephyrBinaryRunner.require',
side_effect=require_patch)
@patch('runners.core.ZephyrBinaryRunner.check_call')
def test_bossac_create_with_oldsdk(cc, req, get_cod_par, sup,
runner_config, tmpdir):
"""
Test old SDK and ask user to upgrade
Requirements:
SDK <= 0.12.0
Configuration:
Any bootloader
CONFIG_USE_DT_CODE_PARTITION=y
with zephyr,code-partition
Input:
Output:
Abort
"""
runner_config = adjust_runner_config(runner_config, tmpdir,
DOTCONFIG_COND1)
runner = BossacBinaryRunner(runner_config)
with pytest.raises(RuntimeError) as rinfo:
with patch('os.path.isfile', side_effect=os_path_isfile_patch):
runner.run('flash')
assert str(rinfo.value) == "This version of BOSSA does not support the" \
" --offset flag. Please upgrade to a newer" \
" Zephyr SDK version >= 0.12.0."
@patch('runners.bossac.BossacBinaryRunner.supports',
return_value=False)
@patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
return_value=None)
@patch('runners.core.ZephyrBinaryRunner.require',
side_effect=require_patch)
@patch('runners.core.ZephyrBinaryRunner.check_call')
def test_bossac_create_error_missing_dt_info(cc, req, get_cod_par, sup,
runner_config, tmpdir):
"""
Test SAM-BA offset wrong configuration. No chosen code partition.
Requirements:
Any SDK
Configuration:
Any bootloader
CONFIG_USE_DT_CODE_PARTITION=y
with zephyr,code-partition (missing)
Input:
Output:
Abort
"""
runner_config = adjust_runner_config(runner_config, tmpdir,
DOTCONFIG_COND1)
runner = BossacBinaryRunner(runner_config)
with pytest.raises(RuntimeError) as rinfo:
with patch('os.path.isfile', side_effect=os_path_isfile_patch):
runner.run('flash')
assert str(rinfo.value) == "The device tree zephyr,code-partition" \
" chosen node must be defined."
@patch('runners.bossac.BossacBinaryRunner.supports',
return_value=False)
@patch('runners.bossac.BossacBinaryRunner.get_chosen_code_partition_node',
return_value=True)
@patch('runners.core.ZephyrBinaryRunner.require',
side_effect=require_patch)
@patch('runners.core.ZephyrBinaryRunner.check_call')
def test_bossac_create_error_missing_kconfig(cc, req, get_cod_par, sup,
runner_config, tmpdir):
"""
Test SAM-BA offset wrong configuration. No CONFIG_USE_DT_CODE_PARTITION
Kconfig definition.
Requirements:
Any SDK
Configuration:
Any bootloader
CONFIG_USE_DT_CODE_PARTITION=y (missing)
with zephyr,code-partition
Input:
Output:
Abort
"""
runner_config = adjust_runner_config(runner_config, tmpdir,
DOTCONFIG_COND2)
runner = BossacBinaryRunner(runner_config)
with pytest.raises(RuntimeError) as rinfo:
with patch('os.path.isfile', side_effect=os_path_isfile_patch):
runner.run('flash')
assert str(rinfo.value) == \
"There is no CONFIG_USE_DT_CODE_PARTITION Kconfig defined at " \
+ TEST_BOARD_NAME + "_defconfig file.\n This means that" \
" zephyr,code-partition device tree node should not be defined." \
" Check Zephyr SAM-BA documentation."