diff options
Diffstat (limited to 'util/flash_jlink.py')
-rwxr-xr-x | util/flash_jlink.py | 208 |
1 files changed, 0 insertions, 208 deletions
diff --git a/util/flash_jlink.py b/util/flash_jlink.py deleted file mode 100755 index d2fd4dec15..0000000000 --- a/util/flash_jlink.py +++ /dev/null @@ -1,208 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2020 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Flashes firmware using Segger J-Link. - -This script requires Segger hardware attached via JTAG/SWD. - -See -https://chromium.googlesource.com/chromiumos/platform/ec/+/HEAD/docs/fingerprint/fingerprint-debugging.md#flash -for instructions. -""" - -import argparse -import logging -import os -import shutil -import socket -import subprocess -import sys -import tempfile -import time - - -DEFAULT_SEGGER_REMOTE_PORT = 19020 - -# Commands are documented here: https://wiki.segger.com/J-Link_Commander -JLINK_COMMANDS = ''' -exitonerror 1 -r -loadfile {FIRMWARE} {FLASH_ADDRESS} -r -go -exit -''' - - -class BoardConfig: - def __init__(self, interface, device, flash_address): - self.interface = interface - self.device = device - self.flash_address = flash_address - - -SWD_INTERFACE = 'SWD' -STM32_DEFAULT_FLASH_ADDRESS = '0x8000000' -DRAGONCLAW_CONFIG = BoardConfig(interface=SWD_INTERFACE, device='STM32F412CG', - flash_address=STM32_DEFAULT_FLASH_ADDRESS) -ICETOWER_CONFIG = BoardConfig(interface=SWD_INTERFACE, device='STM32H743ZI', - flash_address=STM32_DEFAULT_FLASH_ADDRESS) - -BOARD_CONFIGS = { - 'dragonclaw': DRAGONCLAW_CONFIG, - 'bloonchipper': DRAGONCLAW_CONFIG, - 'nucleo-f412zg': DRAGONCLAW_CONFIG, - 'dartmonkey': ICETOWER_CONFIG, - 'icetower': ICETOWER_CONFIG, - 'nucleo-dartmonkey': ICETOWER_CONFIG, - 'nucleo-h743zi': ICETOWER_CONFIG, -} - - -def is_tcp_port_open(host: str, tcp_port: int) -> bool: - """Checks if the TCP host port is open.""" - - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.settimeout(2) # 2 Second Timeout - try: - sock.connect((host, tcp_port)) - sock.shutdown(socket.SHUT_RDWR) - except ConnectionRefusedError: - return False - except socket.timeout: - return False - finally: - sock.close() - # Other errors are propagated as odd exceptions. - - # We shutdown and closed the connection, but the server may need a second - # to start listening again. If the following error is seen, this timeout - # should be increased. 300ms seems to be the minimum. - # - # Connecting to J-Link via IP...FAILED: Can not connect to J-Link via \ - # TCP/IP (127.0.0.1, port 19020) - time.sleep(0.5) - return True - - -def create_jlink_command_file(firmware_file, config): - tmp = tempfile.NamedTemporaryFile() - tmp.write(JLINK_COMMANDS.format(FIRMWARE=firmware_file, - FLASH_ADDRESS=config.flash_address).encode( - 'utf-8')) - tmp.flush() - return tmp - - -def flash(jlink_exe, remote, device, interface, cmd_file): - cmd = [ - jlink_exe, - ] - - if remote: - logging.debug(f'Connecting to J-Link over TCP/IP {remote}.') - remote_components = remote.split(':') - if len(remote_components) not in [1, 2]: - logging.debug(f'Given remote "{remote}" is malformed.') - return 1 - - host = remote_components[0] - try: - ip = socket.gethostbyname(host) - except socket.gaierror as e: - logging.error(f'Failed to resolve host "{host}": {e}.') - return 1 - logging.debug(f'Resolved {host} as {ip}.') - port = DEFAULT_SEGGER_REMOTE_PORT - - if len(remote_components) == 2: - try: - port = int(remote_components[1]) - except ValueError: - logging.error( - f'Given remote port "{remote_components[1]}" is malformed.') - return 1 - - remote = f'{ip}:{port}' - - logging.debug(f'Checking connection to {remote}.') - if not is_tcp_port_open(ip, port): - logging.error( - f'JLink server doesn\'t seem to be listening on {remote}.') - logging.error('Ensure that JLinkRemoteServerCLExe is running.') - return 1 - cmd.extend(['-ip', remote]) - - cmd.extend([ - '-device', device, - '-if', interface, - '-speed', 'auto', - '-autoconnect', '1', - '-CommandFile', cmd_file, - ]) - logging.debug('Running command: "%s"', ' '.join(cmd)) - completed_process = subprocess.run(cmd) - logging.debug('JLink return code: %d', completed_process.returncode) - return completed_process.returncode - - -def main(argv: list): - - parser = argparse.ArgumentParser() - - default_jlink = './JLink_Linux_V684a_x86_64/JLinkExe' - if shutil.which(default_jlink) is None: - default_jlink = 'JLinkExe' - parser.add_argument( - '--jlink', '-j', - help='JLinkExe path (default: ' + default_jlink + ')', - default=default_jlink) - - parser.add_argument( - '--remote', '-n', - help='Use TCP/IP host[:port] to connect to a J-Link or ' - 'JLinkRemoteServerCLExe. If unspecified, connect over USB.') - - default_board = 'bloonchipper' - parser.add_argument( - '--board', '-b', - help='Board (default: ' + default_board + ')', - default=default_board) - - default_firmware = os.path.join('./build', default_board, 'ec.bin') - parser.add_argument( - '--image', '-i', - help='Firmware binary (default: ' + default_firmware + ')', - default=default_firmware) - - log_level_choices = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'] - parser.add_argument( - '--log_level', '-l', - choices=log_level_choices, - default='DEBUG' - ) - - args = parser.parse_args(argv) - logging.basicConfig(level=args.log_level) - - if args.board not in BOARD_CONFIGS: - logging.error('Unable to find a config for board: "%s"', args.board) - sys.exit(1) - - config = BOARD_CONFIGS[args.board] - - args.image = os.path.realpath(args.image) - args.jlink = args.jlink - - cmd_file = create_jlink_command_file(args.image, config) - ret_code = flash(args.jlink, args.remote, config.device, config.interface, - cmd_file.name) - cmd_file.close() - return ret_code - - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:])) |