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>
This commit is contained in:
Gerson Fernando Budke 2021-09-17 18:29:36 -03:00 committed by Christopher Friedt
parent d435340f1b
commit 0de934b2a7
6 changed files with 160 additions and 0 deletions

View file

@ -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

View file

@ -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)

View file

@ -31,6 +31,7 @@ _names = [
'dediprog',
'dfu',
'esp32',
'gd32isp',
'hifive1',
'intel_s1000',
'jlink',

View file

@ -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)

View file

@ -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]

View file

@ -21,6 +21,7 @@ def test_runner_imports():
'dediprog',
'dfu-util',
'esp32',
'gd32isp',
'hifive1',
'intel_s1000',
'jlink',