scripts: runner: Introduce gd32isp flash runner Add GigaDevice ISP console flash runner. This tool enable uses ROM bootloader to flash devices using serial port. The GD32_ISP_Console tool can be found at http://www.gd32mcu.com/download/down/document_id/175/path_type/1 Signed-off-by: Gerson Fernando Budke <gerson.budke@atl-electronics.com>
diff --git a/CODEOWNERS b/CODEOWNERS index df2803d..529ab87 100644 --- a/CODEOWNERS +++ b/CODEOWNERS
@@ -645,6 +645,8 @@ /scripts/twister @nashif /scripts/series-push-hook.sh @erwango /scripts/west_commands/ @mbolivar-nordic +/scripts/west_commands/runners/gd32isp.py @mbolivar-nordic @nandojve +/scripts/west_commands/tests/test_gd32isp.py @mbolivar-nordic @nandojve /scripts/west-commands.yml @mbolivar-nordic /scripts/zephyr_module.py @tejlmand /scripts/uf2conv.py @petejohanson
diff --git a/boards/common/gd32isp.board.cmake b/boards/common/gd32isp.board.cmake new file mode 100644 index 0000000..426d0a2 --- /dev/null +++ b/boards/common/gd32isp.board.cmake
@@ -0,0 +1,5 @@ +# Copyright (c) 2021, ATL Electronics +# SPDX-License-Identifier: Apache-2.0 + +board_set_flasher_ifnset(gd32isp) +board_finalize_runner_args(gd32isp)
diff --git a/scripts/west_commands/runners/__init__.py b/scripts/west_commands/runners/__init__.py index eb4816a..3aa8392 100644 --- a/scripts/west_commands/runners/__init__.py +++ b/scripts/west_commands/runners/__init__.py
@@ -31,6 +31,7 @@ 'dediprog', 'dfu', 'esp32', + 'gd32isp', 'hifive1', 'intel_s1000', 'jlink',
diff --git a/scripts/west_commands/runners/gd32isp.py b/scripts/west_commands/runners/gd32isp.py new file mode 100644 index 0000000..4f2a1b1 --- /dev/null +++ b/scripts/west_commands/runners/gd32isp.py
@@ -0,0 +1,80 @@ +# Copyright (c) 2021, ATL-Electronics +# SPDX-License-Identifier: Apache-2.0 + +'''GigaDevice ISP tool (gd32isp) runner for serial boot ROM''' + +from runners.core import ZephyrBinaryRunner, RunnerCaps + +DEFAULT_GD32ISP_CLI = 'GD32_ISP_Console' +DEFAULT_GD32ISP_PORT = '/dev/ttyUSB0' +DEFAULT_GD32ISP_SPEED = '57600' +DEFAULT_GD32ISP_ADDR = '0x08000000' + +class Gd32ispBinaryRunner(ZephyrBinaryRunner): + '''Runner front-end for gd32isp.''' + + def __init__(self, cfg, device, + isp=DEFAULT_GD32ISP_CLI, + port=DEFAULT_GD32ISP_PORT, + speed=DEFAULT_GD32ISP_SPEED, + addr=DEFAULT_GD32ISP_ADDR): + super().__init__(cfg) + self.device = device + self.isp = isp + self.port = port + self.speed = speed + self.addr = addr + + @classmethod + def name(cls): + return 'gd32isp' + + @classmethod + def capabilities(cls): + return RunnerCaps(commands={'flash'}) + + @classmethod + def do_add_parser(cls, parser): + # Required: + parser.add_argument('--device', required=True, + help='device part number') + + # Optional: + parser.add_argument('--isp', default=DEFAULT_GD32ISP_CLI, + help='path to gd32 isp console program') + parser.add_argument('--port', default=DEFAULT_GD32ISP_PORT, + help='serial port to use, default is ' + + str(DEFAULT_GD32ISP_PORT)) + parser.add_argument('--speed', default=DEFAULT_GD32ISP_SPEED, + help='serial port speed to use, default is ' + + DEFAULT_GD32ISP_SPEED) + parser.add_argument('--addr', default=DEFAULT_GD32ISP_ADDR, + help='flash address, default is ' + + DEFAULT_GD32ISP_ADDR) + + @classmethod + def do_create(cls, cfg, args): + return Gd32ispBinaryRunner(cfg, + device=args.device, + isp=args.isp, + port=args.port, + speed=args.speed, + addr=args.addr) + + def do_run(self, command, **kwargs): + self.require(self.isp) + self.ensure_output('bin') + + cmd_flash = [self.isp, + '-c', + '--pn', self.port, + '--br', self.speed, + '--sb', '1', + '-i', self.device, + '-e', + '--all', + '-d', + '--a', self.addr, + '--fn', self.cfg.bin_file] + + self.check_call(cmd_flash)
diff --git a/scripts/west_commands/tests/test_gd32isp.py b/scripts/west_commands/tests/test_gd32isp.py new file mode 100644 index 0000000..14631af --- /dev/null +++ b/scripts/west_commands/tests/test_gd32isp.py
@@ -0,0 +1,71 @@ +# Copyright (c) 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.gd32isp import Gd32ispBinaryRunner +from conftest import RC_KERNEL_BIN + +if platform.system() != 'Linux': + pytest.skip("skipping Linux-only gd32isp tests", allow_module_level=True) + +TEST_GD32ISP_CLI = 'GD32_ISP_Console' +TEST_GD32ISP_CLI_T = 'GD32_ISP_CLI' +TEST_GD32ISP_DEV = 'test-gd32test' +TEST_GD32ISP_PORT = 'test-gd32isp-serial' +TEST_GD32ISP_SPEED = '2000000' +TEST_GD32ISP_ADDR = '0x08765430' + +EXPECTED_COMMANDS_DEFAULT = [ + [TEST_GD32ISP_CLI, '-c', '--pn', '/dev/ttyUSB0', '--br', '57600', + '--sb', '1', '-i', TEST_GD32ISP_DEV, '-e', '--all', '-d', + '--a', '0x08000000', '--fn', RC_KERNEL_BIN], +] + +EXPECTED_COMMANDS = [ + [TEST_GD32ISP_CLI_T, '-c', '--pn', TEST_GD32ISP_PORT, + '--br', TEST_GD32ISP_SPEED, + '--sb', '1', '-i', TEST_GD32ISP_DEV, '-e', '--all', '-d', + '--a', TEST_GD32ISP_ADDR, '--fn', RC_KERNEL_BIN], +] + +def require_patch(program): + assert program in [TEST_GD32ISP_CLI, TEST_GD32ISP_CLI_T] + +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.core.ZephyrBinaryRunner.require', side_effect=require_patch) +@patch('runners.core.ZephyrBinaryRunner.check_call') +def test_gd32isp_init(cc, req, runner_config): + runner = Gd32ispBinaryRunner(runner_config, TEST_GD32ISP_DEV) + 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_DEFAULT] + + +@patch('runners.core.ZephyrBinaryRunner.require', side_effect=require_patch) +@patch('runners.core.ZephyrBinaryRunner.check_call') +def test_gd32isp_create(cc, req, runner_config): + args = ['--device', TEST_GD32ISP_DEV, + '--port', TEST_GD32ISP_PORT, + '--speed', TEST_GD32ISP_SPEED, + '--addr', TEST_GD32ISP_ADDR, + '--isp', TEST_GD32ISP_CLI_T] + parser = argparse.ArgumentParser() + Gd32ispBinaryRunner.add_parser(parser) + arg_namespace = parser.parse_args(args) + runner = Gd32ispBinaryRunner.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]
diff --git a/scripts/west_commands/tests/test_imports.py b/scripts/west_commands/tests/test_imports.py index 079f6b7..5ebec4f 100644 --- a/scripts/west_commands/tests/test_imports.py +++ b/scripts/west_commands/tests/test_imports.py
@@ -21,6 +21,7 @@ 'dediprog', 'dfu-util', 'esp32', + 'gd32isp', 'hifive1', 'intel_s1000', 'jlink',