summaryrefslogtreecommitdiffstats
path: root/tinyusb/hw/mcu/sony/cxd56/tools/flash_writer.py
diff options
context:
space:
mode:
Diffstat (limited to 'tinyusb/hw/mcu/sony/cxd56/tools/flash_writer.py')
-rwxr-xr-xtinyusb/hw/mcu/sony/cxd56/tools/flash_writer.py580
1 files changed, 580 insertions, 0 deletions
diff --git a/tinyusb/hw/mcu/sony/cxd56/tools/flash_writer.py b/tinyusb/hw/mcu/sony/cxd56/tools/flash_writer.py
new file mode 100755
index 00000000..840f10c3
--- /dev/null
+++ b/tinyusb/hw/mcu/sony/cxd56/tools/flash_writer.py
@@ -0,0 +1,580 @@
+#! /usr/bin/env python3
+
+# Copyright (C) 2018 Sony Semiconductor Solutions Corp.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name NuttX nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+import time
+import sys
+import os
+import struct
+import glob
+import fnmatch
+import errno
+import telnetlib
+import argparse
+import shutil
+import subprocess
+import re
+import xmodem
+
+import_serial_module = True
+
+# When SDK release, plase set SDK_RELEASE as True.
+SDK_RELEASE = False
+
+if SDK_RELEASE :
+ PRINT_RAW_COMMAND = False
+ REBOOT_AT_END = True
+else :
+ PRINT_RAW_COMMAND = True
+ REBOOT_AT_END = True
+
+try:
+ import serial
+except:
+ import_serial_module = False
+
+# supported environment various
+# CXD56_PORT
+# CXD56_TELNETSRV_PORT
+# CXD56_TELNETSRV_IP
+
+PROTOCOL_SERIAL = 0
+PROTOCOL_TELNET = 1
+
+MAX_DOT_COUNT = 70
+
+# configure parameters and default value
+class ConfigArgs:
+ PROTOCOL_TYPE = None
+ SERIAL_PORT = "COM1"
+ SERVER_PORT = 4569
+ SERVER_IP = "localhost"
+ EOL = bytes([10])
+ WAIT_RESET = True
+ AUTO_RESET = False
+ DTR_RESET = False
+ XMODEM_BAUD = 0
+ NO_SET_BOOTABLE = False
+ PACKAGE_NAME = []
+ FILE_NAME = []
+ ERASE_NAME = []
+ PKGSYS_NAME = []
+ PKGAPP_NAME = []
+ PKGUPD_NAME = []
+
+ROM_MSG = [b"Welcome to nash"]
+XMDM_MSG = "Waiting for XMODEM (CRC or 1K) transfer. Ctrl-X to cancel."
+
+class ConfigArgsLoader():
+ def __init__(self):
+ self.parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter)
+ self.parser.add_argument("package_name", help="the name of the package to install", nargs='*')
+ self.parser.add_argument("-f", "--file", dest="file_name", help="save file", action='append')
+ self.parser.add_argument("-e", "--erase", dest="erase_name", help="erase file", action='append')
+
+ self.parser.add_argument("-S", "--sys", dest="pkgsys_name", help="the name of the system package to install", action='append')
+ self.parser.add_argument("-A", "--app", dest="pkgapp_name", help="the name of the application package to install", action='append')
+ self.parser.add_argument("-U", "--upd", dest="pkgupd_name", help="the name of the updater package to install", action='append')
+
+ self.parser.add_argument("-a", "--auto-reset", dest="auto_reset",
+ action="store_true", default=None,
+ help="try to auto reset develop board if possible")
+ self.parser.add_argument("-d", "--dtr-reset", dest="dtr_reset",
+ action="store_true", default=None,
+ help="try to auto reset develop board if possible")
+ self.parser.add_argument("-n", "--no-set-bootable", dest="no_set_bootable",
+ action="store_true", default=None,
+ help="not to set bootable")
+
+ group = self.parser.add_argument_group()
+ group.add_argument("-i", "--server-ip", dest="server_ip",
+ help="the ip address connected to the telnet server")
+ group.add_argument("-p", "--server-port", dest="server_port", type=int,
+ help="the port connected to the telnet server")
+
+ group = self.parser.add_argument_group()
+ group.add_argument("-c", "--serial-port", dest="serial_port", help="the serial port")
+ group.add_argument("-b", "--xmodem-baudrate", dest="xmodem_baud", help="Use the faster baudrate in xmodem")
+
+ mutually_group = self.parser.add_mutually_exclusive_group()
+ mutually_group.add_argument("-t", "--telnet-protocol", dest="telnet_protocol",
+ action="store_true", default=None,
+ help="use the telnet protocol for binary transmission")
+ mutually_group.add_argument("-s", "--serial-protocol", dest="serial_protocol",
+ action="store_true", default=None,
+ help="use the serial port for binary transmission, default options")
+
+ mutually_group2 = self.parser.add_mutually_exclusive_group()
+ mutually_group2.add_argument("-F", "--force-wait-reset", dest="wait_reset",
+ action="store_true", default=None,
+ help="force wait for pressing RESET button")
+ mutually_group2.add_argument("-N", "--no-wait-reset", dest="wait_reset",
+ action="store_false", default=None,
+ help="if possible, skip to wait for pressing RESET button")
+
+ def update_config(self):
+ args = self.parser.parse_args()
+
+ ConfigArgs.PACKAGE_NAME = args.package_name
+ ConfigArgs.FILE_NAME = args.file_name
+ ConfigArgs.ERASE_NAME = args.erase_name
+ ConfigArgs.PKGSYS_NAME = args.pkgsys_name
+ ConfigArgs.PKGAPP_NAME = args.pkgapp_name
+ ConfigArgs.PKGUPD_NAME = args.pkgupd_name
+
+ # Get serial port or telnet server ip etc
+ if args.serial_protocol == True:
+ ConfigArgs.PROTOCOL_TYPE = PROTOCOL_SERIAL
+ elif args.telnet_protocol == True:
+ ConfigArgs.PROTOCOL_TYPE = PROTOCOL_TELNET
+
+ if ConfigArgs.PROTOCOL_TYPE == None:
+ proto = os.environ.get("CXD56_PROTOCOL")
+ if proto is not None:
+ if 's' in proto:
+ ConfigArgs.PROTOCOL_TYPE = PROTOCOL_SERIAL
+ elif 't' in proto:
+ ConfigArgs.PROTOCOL_TYPE = PROTOCOL_TELNET
+
+ if ConfigArgs.PROTOCOL_TYPE == None:
+ ConfigArgs.PROTOCOL_TYPE = PROTOCOL_SERIAL
+
+ if ConfigArgs.PROTOCOL_TYPE == PROTOCOL_SERIAL:
+ if args.serial_port is not None:
+ ConfigArgs.SERIAL_PORT = args.serial_port
+ else:
+ # Get serial port from the environment
+ port = os.environ.get("CXD56_PORT")
+ if port is not None:
+ ConfigArgs.SERIAL_PORT = port
+ else:
+ print("CXD56_PORT is not set, Use " + ConfigArgs.SERIAL_PORT + ".")
+ else:
+ ConfigArgs.PROTOCOL_TYPE = PROTOCOL_TELNET
+ if args.server_port is not None:
+ ConfigArgs.SERVER_PORT = args.server_port
+ else:
+ port = os.environ.get("CXD56_TELNETSRV_PORT")
+ if port is not None:
+ ConfigArgs.SERVER_PORT = port
+ else:
+ print("CXD56_TELNETSRV_PORT is not set, Use " + str(ConfigArgs.SERVER_PORT) + ".")
+ if args.server_ip is not None:
+ ConfigArgs.SERVER_IP = args.server_ip
+ else:
+ ip = os.environ.get("CXD56_TELNETSRV_IP")
+ if ip is not None:
+ ConfigArgs.SERVER_IP = ip
+ else:
+ print("CXD56_TELNETSRV_IP is not set, Use " + ConfigArgs.SERVER_IP + ".")
+
+ if args.xmodem_baud is not None:
+ ConfigArgs.XMODEM_BAUD = args.xmodem_baud
+
+ if args.auto_reset is not None:
+ ConfigArgs.AUTO_RESET = args.auto_reset
+
+ if args.dtr_reset is not None:
+ ConfigArgs.DTR_RESET = args.dtr_reset
+
+ if args.no_set_bootable is not None:
+ ConfigArgs.NO_SET_BOOTABLE = args.no_set_bootable
+
+ if args.wait_reset is not None:
+ ConfigArgs.WAIT_RESET = args.wait_reset
+
+class TelnetDev:
+ def __init__(self):
+ srv_ipaddr = ConfigArgs.SERVER_IP
+ srv_port = ConfigArgs.SERVER_PORT
+ self.recvbuf = b'';
+ try:
+ self.telnet = telnetlib.Telnet(host=srv_ipaddr, port=srv_port, timeout=10)
+ # There is a ack to be sent after connecting to the telnet server.
+ self.telnet.write(b"\xff")
+ except Exception as e:
+ print("Cannot connect to the server %s:%d" % (srv_ipaddr, srv_port))
+ sys.exit(e.args[0])
+
+ def readline(self, size=None):
+ res = b''
+ ch = b''
+ while ch != ConfigArgs.EOL:
+ ch = self.getc_raw(1, timeout=0.1)
+ if ch == b'':
+ return res
+ res += ch
+ return res
+
+ def getc_raw(self, size, timeout=1):
+ res = b''
+ tm = time.monotonic()
+ while size > 0:
+ while self.recvbuf == b'':
+ self.recvbuf = self.telnet.read_eager()
+ if self.recvbuf == b'':
+ if (time.monotonic() - tm) > timeout:
+ return res
+ time.sleep(0.1)
+ res += self.recvbuf[0:1]
+ self.recvbuf = self.recvbuf[1:]
+ size -= 1
+ return res
+
+ def write(self, buffer):
+ self.telnet.write(buffer)
+
+ def discard_inputs(self, timeout=1.0):
+ while True:
+ ch = self.getc_raw(1, timeout=timeout)
+ if ch == b'':
+ break
+
+ def getc(self, size, timeout=1):
+ c = self.getc_raw(size, timeout)
+ return c
+
+ def putc(self, buffer, timeout=1):
+ self.telnet.write(buffer)
+ self.show_progress(len(buffer))
+
+ def reboot(self):
+ # no-op
+ pass
+
+ def set_file_size(self, filesize):
+ self.bytes_transfered = 0
+ self.filesize = filesize
+ self.count = 0
+
+ def show_progress(self, sendsize):
+ if PRINT_RAW_COMMAND:
+ if self.count < MAX_DOT_COUNT:
+ self.bytes_transfered = self.bytes_transfered + sendsize
+ cur_count = int(self.bytes_transfered * MAX_DOT_COUNT / self.filesize)
+ if MAX_DOT_COUNT < cur_count:
+ cur_count = MAX_DOT_COUNT
+ for idx in range(cur_count - self.count):
+ print('#',end='')
+ sys.stdout.flush()
+ self.count = cur_count
+ if self.count == MAX_DOT_COUNT:
+ print("\n")
+
+class SerialDev:
+ def __init__(self):
+ if import_serial_module is False:
+ print("Cannot import serial module, maybe it's not install yet.")
+ print("\n", end="")
+ print("Please install python-setuptool by Cygwin installer.")
+ print("After that use easy_intall command to install serial module")
+ print(" $ cd tool/")
+ print(" $ python3 -m easy_install pyserial-2.7.tar.gz")
+ quit()
+ else:
+ port = ConfigArgs.SERIAL_PORT
+ try:
+ self.serial = serial.Serial(port, baudrate=115200,
+ parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE,
+ bytesize=serial.EIGHTBITS, timeout=0.1)
+ except Exception as e:
+ print("Cannot open port : " + port)
+ sys.exit(e.args[0])
+
+ def readline(self, size=None):
+ return self.serial.readline(size)
+
+ def write(self, buffer):
+ self.serial.write(buffer)
+ self.serial.flush()
+
+ def discard_inputs(self, timeout=1.0):
+ time.sleep(timeout)
+ self.serial.flushInput()
+
+ def getc(self, size, timeout=1):
+ self.serial.timeout = timeout
+ c = self.serial.read(size)
+ self.serial.timeout = 0.1
+ return c
+
+ def putc(self, buffer, timeout=1):
+ self.serial.timeout = timeout
+ self.serial.write(buffer)
+ self.serial.flush()
+ self.serial.timeout = 0.1
+ self.show_progress(len(buffer))
+
+ # Note: windows platform dependent code
+ def putc_win(self, buffer, timeout=1):
+ self.serial.write(buffer)
+ self.show_progress(len(buffer))
+ while True:
+ if self.serial.out_waiting == 0:
+ break
+
+ def setBaudrate(self, baudrate):
+# self.serial.setBaudrate(baudrate)
+ self.serial.baudrate = baudrate
+
+ def reboot(self):
+ # Target Reset by DTR
+ self.serial.setDTR(False)
+ self.serial.setDTR(True)
+ self.serial.setDTR(False)
+
+ def set_file_size(self, filesize):
+ self.bytes_transfered = 0
+ self.filesize = filesize
+ self.count = 0
+
+ def show_progress(self, sendsize):
+ if PRINT_RAW_COMMAND:
+ if self.count < MAX_DOT_COUNT:
+ self.bytes_transfered = self.bytes_transfered + sendsize
+ cur_count = int(self.bytes_transfered * MAX_DOT_COUNT / self.filesize)
+ if MAX_DOT_COUNT < cur_count:
+ cur_count = MAX_DOT_COUNT
+ for idx in range(cur_count - self.count):
+ print('#',end='')
+ sys.stdout.flush()
+ self.count = cur_count
+ if self.count == MAX_DOT_COUNT:
+ print("\n")
+
+class FlashWriter:
+ def __init__(self, protocol_sel=PROTOCOL_SERIAL):
+ if protocol_sel == PROTOCOL_TELNET:
+ self.serial = TelnetDev()
+ else:
+ self.serial = SerialDev()
+
+ def cancel_autoboot(self) :
+ boot_msg = ''
+ self.serial.reboot() # Target reboot before send 'r'
+ while boot_msg == '' :
+ rx = self.serial.readline().strip()
+ self.serial.write(b"r") # Send "r" key to avoid auto boot
+ for msg in ROM_MSG :
+ if msg in rx :
+ boot_msg = msg
+ break
+ while True :
+ rx = self.serial.readline().decode(errors="replace").strip()
+ if "updater" in rx :
+ # Workaround : Sometime first character is dropped.
+ # Send line feed as air shot before actual command.
+ self.serial.write(b"\n") # Send line feed
+ self.serial.discard_inputs()# Clear input buffer to sync
+ return boot_msg.decode(errors="ignore")
+
+ def recv(self):
+ rx = self.serial.readline()
+ if PRINT_RAW_COMMAND :
+ serial_line = rx.decode(errors="replace")
+ if serial_line.strip() != "" and not serial_line.startswith(XMDM_MSG):
+ print(serial_line, end="")
+ return rx
+
+ def wait(self, string):
+ while True:
+ rx = self.recv()
+ if string.encode() in rx:
+ time.sleep(0.1)
+ break
+
+ def wait_for_prompt(self):
+ prompt_pat = re.compile(b"updater")
+ while True:
+ rx = self.recv()
+ if prompt_pat.search(rx):
+ time.sleep(0.1)
+ break
+
+ def send(self, string):
+ self.serial.write(str(string).encode() + b"\n")
+ rx = self.serial.readline()
+ if PRINT_RAW_COMMAND :
+ print(rx.decode(errors="replace"), end="")
+
+ def read_output(self, prompt_text) :
+ output = []
+ while True :
+ rx = self.serial.readline()
+ if prompt_text.encode() in rx :
+ time.sleep(0.1)
+ break
+ if rx != "" :
+ output.append(rx.decode(errors="ignore").rstrip())
+ return output
+
+ def install_files(self, files, command) :
+ if ConfigArgs.XMODEM_BAUD:
+ command += " -b " + ConfigArgs.XMODEM_BAUD
+ if os.name == 'nt':
+ modem = xmodem.XMODEM(self.serial.getc, self.serial.putc_win, 'xmodem1k')
+ else:
+ modem = xmodem.XMODEM(self.serial.getc, self.serial.putc, 'xmodem1k')
+ for file in files:
+ with open(file, "rb") as bin :
+ self.send(command)
+ print("Install " + file)
+ self.wait(XMDM_MSG)
+ print("|0%" +
+ "-" * (int(MAX_DOT_COUNT / 2) - 6) +
+ "50%" +
+ "-" * (MAX_DOT_COUNT - int(MAX_DOT_COUNT / 2) - 5) +
+ "100%|")
+ if ConfigArgs.XMODEM_BAUD:
+ self.serial.setBaudrate(ConfigArgs.XMODEM_BAUD)
+ self.serial.discard_inputs() # Clear input buffer to sync
+ self.serial.set_file_size(os.path.getsize(file))
+ modem.send(bin)
+ if ConfigArgs.XMODEM_BAUD:
+ self.serial.setBaudrate(115200)
+ self.wait_for_prompt()
+
+ def save_files(self, files) :
+ if ConfigArgs.XMODEM_BAUD:
+ command = "save_file -b " + ConfigArgs.XMODEM_BAUD + " -x "
+ else:
+ command = "save_file -x "
+ if os.name == 'nt':
+ modem = xmodem.XMODEM(self.serial.getc, self.serial.putc_win, 'xmodem1k')
+ else:
+ modem = xmodem.XMODEM(self.serial.getc, self.serial.putc, 'xmodem1k')
+ for file in files:
+ with open(file, "rb") as bin :
+ self.send(command + os.path.basename(file))
+ print("Save " + file)
+ self.wait(XMDM_MSG)
+ if ConfigArgs.XMODEM_BAUD:
+ self.serial.setBaudrate(ConfigArgs.XMODEM_BAUD)
+ self.serial.discard_inputs() # Clear input buffer to sync
+ self.serial.set_file_size(os.path.getsize(file))
+ modem.send(bin)
+ if ConfigArgs.XMODEM_BAUD:
+ self.serial.setBaudrate(115200)
+ self.wait_for_prompt()
+ self.send("chmod d+rw " + os.path.basename(file))
+ self.wait_for_prompt()
+
+ def delete_files(self, files) :
+ for file in files :
+ self.delete_binary(file)
+
+ def delete_binary(self, bin_name) :
+ self.send("rm " + bin_name)
+ self.wait_for_prompt()
+
+def main():
+ try:
+ config_loader = ConfigArgsLoader()
+ config_loader.update_config()
+ except:
+ return errno.EINVAL
+
+ # Wait to reset the board
+ writer = FlashWriter(ConfigArgs.PROTOCOL_TYPE)
+
+ do_wait_reset = True
+ if ConfigArgs.AUTO_RESET:
+ if subprocess.call("cd " + sys.path[0] + "; ./reset_board.sh", shell=True) == 0:
+ print("auto reset board sucess!!")
+ do_wait_reset = False
+ bootrom_msg = writer.cancel_autoboot()
+
+ if ConfigArgs.DTR_RESET:
+ do_wait_reset = False
+ bootrom_msg = writer.cancel_autoboot()
+
+ if ConfigArgs.WAIT_RESET == False and do_wait_reset == True:
+ rx = writer.recv()
+ time.sleep(1)
+ for i in range(3):
+ writer.send("")
+ rx = writer.recv()
+ if "updater".encode() in rx:
+ # No need to wait for reset
+ do_wait_reset = False
+ break
+ time.sleep(1)
+
+ if do_wait_reset:
+ # Wait to reset the board
+ print('Please press RESET button on target board')
+ sys.stdout.flush()
+ bootrom_msg = writer.cancel_autoboot()
+
+ # Remove files
+ if ConfigArgs.ERASE_NAME :
+ print(">>> Remove exisiting files ...")
+ writer.delete_files(ConfigArgs.ERASE_NAME)
+
+ # Install files
+ if ConfigArgs.PACKAGE_NAME or ConfigArgs.PKGSYS_NAME or ConfigArgs.PKGAPP_NAME or ConfigArgs.PKGUPD_NAME:
+ print(">>> Install files ...")
+ if ConfigArgs.PACKAGE_NAME :
+ writer.install_files(ConfigArgs.PACKAGE_NAME, "install")
+ if ConfigArgs.PKGSYS_NAME :
+ writer.install_files(ConfigArgs.PKGSYS_NAME, "install")
+ if ConfigArgs.PKGAPP_NAME :
+ writer.install_files(ConfigArgs.PKGAPP_NAME, "install")
+ if ConfigArgs.PKGUPD_NAME :
+ writer.install_files(ConfigArgs.PKGUPD_NAME, "install -k updater.key")
+
+ # Save files
+ if ConfigArgs.FILE_NAME :
+ print(">>> Save files ...")
+ writer.save_files(ConfigArgs.FILE_NAME)
+
+ # Set auto boot
+ if not ConfigArgs.NO_SET_BOOTABLE:
+ print(">>> Save Configuration to FlashROM ...")
+ writer.send("set bootable M0P")
+ writer.wait_for_prompt()
+
+ # Sync all cached data to flash
+ writer.send("sync")
+ writer.wait_for_prompt()
+
+ if REBOOT_AT_END :
+ print("Restarting the board ...")
+ writer.send("reboot")
+
+ return 0
+
+if __name__ == "__main__":
+ try:
+ sys.exit(main())
+ except KeyboardInterrupt:
+ print("Canceled by keyboard interrupt.")
+ pass