From cb7a703564c14019308fed3f11bf38879d29939a Mon Sep 17 00:00:00 2001 From: Dreaded_X Date: Mon, 21 Sep 2020 21:50:19 +0200 Subject: [PATCH] Upload.py can now upload to the sdcard and did some reorganization --- bin/create_disk | 1 + bin/upload | 101 +-------- scripts/__pycache__/mojo.cpython-38.pyc | Bin 0 -> 5365 bytes create_img.py => scripts/create_disk.py | 23 +- scripts/mojo.py | 282 ++++++++++++++++++++++++ scripts/upload.py | 133 +++++++++++ 6 files changed, 430 insertions(+), 110 deletions(-) create mode 120000 bin/create_disk mode change 100755 => 120000 bin/upload create mode 100644 scripts/__pycache__/mojo.cpython-38.pyc rename create_img.py => scripts/create_disk.py (79%) create mode 100755 scripts/mojo.py create mode 100755 scripts/upload.py diff --git a/bin/create_disk b/bin/create_disk new file mode 120000 index 0000000..27d47ba --- /dev/null +++ b/bin/create_disk @@ -0,0 +1 @@ +../scripts/create_disk.py \ No newline at end of file diff --git a/bin/upload b/bin/upload deleted file mode 100755 index b75832d..0000000 --- a/bin/upload +++ /dev/null @@ -1,100 +0,0 @@ -#!/usr/bin/env python3 -import serial -import os -import sys -import time -import argparse -import math - -def progressbar(it, prefix="", size=60, file=sys.stdout): - count = len(it) - def show(j): - x = int(size*j/count) - file.write("%s[%s%s] %i/%i\r" % (prefix, "#"*x, "."*(size-x), j, count)) - file.flush() - show(0) - for i, item in enumerate(it): - yield item - show(i+1) - file.write("\n") - file.flush() - -def rom_upload(filename): - # ser = serial.Serial("COM3", timeout=1, write_timeout=1) - ser = serial.Serial("/dev/ttyUSB0", timeout=1, write_timeout=1, baudrate=115200) - if ser.is_open: - # Clear out any existing input - ser.write(b'\n') - time.sleep(0.002) - - # Send the upload command - ser.write(b'#') - time.sleep(0.002) - ser.write(b'u') - time.sleep(0.002) - ser.write(b'\n') - time.sleep(0.002) - - size = os.path.getsize(filename) - ser.write([size & 0xFF]) - time.sleep(0.002) - ser.write([(size >> 8) & 0xFF]) - time.sleep(0.002) - - with open(filename, "rb") as f: - for i in progressbar(range(size), "Upload: ", 40): - byte = f.read(1) - ser.write(byte) - time.sleep(0.002) - - ser.close() - - else: - print("Failed to open serial port") - -def bload_upload(filename): - # ser = serial.Serial("COM3", timeout=1, write_timeout=1) - ser = serial.Serial("/dev/ttyUSB0", timeout=1, write_timeout=1, baudrate=115200) - if ser.is_open: - size = os.path.getsize(filename) - - print("Size: {} ({} pages)".format(size, math.ceil(size/256))) - - input("Press enter to start upload") - - with open(filename, "rb") as f: - for i in progressbar(range(size), "Upload: ", 40): - byte = f.read(1) - ser.write(byte) - - if byte == b'#': - time.sleep(0.002) - ser.write(b'#') - time.sleep(0.002) - ser.write(b'\n') - - time.sleep(0.002) - - ser.close() - - else: - print("Failed to open serial port") - -def main(): - parser = argparse.ArgumentParser(description="Upload binaries to the z80 computer.") - parser.add_argument("filename", help="file to upload") - parser.add_argument("--rom", dest="rom", action="store_const", const=True, default=False, help="Upload binary to rom") - parser.add_argument("--bload", dest="bload", action="store_const", const=True, default=False, help="Upload binary to bload") - - args = parser.parse_args() - - if (args.rom): - rom_upload(args.filename) - elif (args.bload): - bload_upload(args.filename) - else: - print("You needs to specify a target") - - -if "__main__": - main() diff --git a/bin/upload b/bin/upload new file mode 120000 index 0000000..0b34209 --- /dev/null +++ b/bin/upload @@ -0,0 +1 @@ +../scripts/upload.py \ No newline at end of file diff --git a/scripts/__pycache__/mojo.cpython-38.pyc b/scripts/__pycache__/mojo.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2ac152f5cc4cf82771a7858325919ba1f129efe9 GIT binary patch literal 5365 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 S*iU0@+$e06Duw%n%D(`7=V=`P literal 0 HcmV?d00001 diff --git a/create_img.py b/scripts/create_disk.py similarity index 79% rename from create_img.py rename to scripts/create_disk.py index 350592a..024c513 100755 --- a/create_img.py +++ b/scripts/create_disk.py @@ -7,10 +7,6 @@ blockSize = 16384 maxDirs = 128 dirBlocks = 1 -# @todo Currently the tool assumes your are running in a subfolder from z80 - -out = open('../tools/disk.img', 'wb') - def addBootloader(name): loader = open(name, 'rb') b = loader.read() @@ -88,12 +84,19 @@ def addFile(filename, n, t): seekBlock(fileCounter) out.write(b) +def main(): + # @todo We need to make this configurable using the command line so we can create disk images per project + global out + out = open('../tools/disk.img', 'wb') -addBootloader('../cpm/.build/loader.bin') -addOS('../cpm/.build/cpm22.bin', '../cpm/.build/bios.bin') + addBootloader('../cpm/.build/loader.bin') + addOS('../cpm/.build/cpm22.bin', '../cpm/.build/bios.bin') -initDirs() + initDirs() -addFile("../cpm/.build/MONITOR.COM", "MONITOR", "COM") -addFile("../cpm/bin/STAT.COM", "STAT", "COM") -addFile("../xed/.build/XED.COM", "XED", "COM") + addFile("../cpm/.build/MONITOR.COM", "MONITOR", "COM") + addFile("../cpm/bin/STAT.COM", "STAT", "COM") + addFile("../xed/.build/XED.COM", "XED", "COM") + +if __name__ == "__main__": + main() diff --git a/scripts/mojo.py b/scripts/mojo.py new file mode 100755 index 0000000..1234bc0 --- /dev/null +++ b/scripts/mojo.py @@ -0,0 +1,282 @@ +#!/usr/bin/env python3 +###------------------------------------------------------------------------- +### Mojo.py is a bitstream uploader for the mojo v2 board +### author Matthew O'Gorman +### copyright 2013 Matthew O'Gorman +### version 2.0 +### ### License : This program is free software, distributed under the terms of +### the GNU General Public License Version 3. See the COPYING file +### at the top of the source tree. +###------------------------------------------------------------------------- + +import time +import sys +import argparse +import serial + +# Try to rename process to something more friendly than python mojo.py +try: + import setproctitle + + setproctitle.setproctitle("mojo") +except ImportError as error: + pass + + +def main(): + Version = "Mojo v2.0 is licensed under the GPLv3 copyright 2013 Matthew O'Gorman" + + parser = argparse.ArgumentParser(description="Mojo bitstream loader v2") + group = parser.add_mutually_exclusive_group(required=True) + group.add_argument( + "bitstream", + metavar="BITSTREAM", + nargs="?", + help="Bitstream file to upload to the Mojo.", + ) + group.add_argument( + "-i", + "--install", + metavar="BITSTREAM", + dest="install", + action="store", + help="Bitstream file to upload to the Mojo", + ) + parser.add_argument( + "-r", + "--ram", + dest="ram", + action="store_const", + const=True, + default=False, + help="Install bitstream file only to ram", + ) + # not currently supported by the default firmware of the board + # group.add_argument('-c', '--copy', metavar='BITSTREAM', dest='copy', action='append', nargs='?', + # help='Bitstream file to copy from the Mojo [Default: %(default)s]', default=['mojo.bin']) + + # group.add_argument('-o', '--only_verify', metavar='BITSTREAM', dest='only_verify', action='store', + # help='Read flash of Mojo only to verify against bitstream.') + # group.add_argument('-r', '--reboot', dest='reboot', action='store_const', + # const=True, default=False, + # help='Reboot mojo board.') + parser.add_argument( + "-v", + "--verbose", + dest="verbose", + action="store_const", + const=True, + default=False, + help="Enable verbose output to cli.", + ) + parser.add_argument( + "-V", + "--version", + dest="version", + action="store_const", + const=True, + default=False, + help="Display version number of mojo.", + ) + parser.add_argument( + "-n", + "--no-verify", + dest="no_verify", + action="store_const", + const=True, + default=False, + help="Do not verify the operation to the Mojo.", + ) + group.add_argument( + "-e", + "--erase", + dest="erase", + action="store_const", + const=True, + default=False, + help="Erase flash on Mojo.", + ) + parser.add_argument( + "-d", + "--device", + dest="mojo_tty", + action="store", + default="/dev/mojo", + help="Address of the serial port for the mojo [Default: %(default)s]", + ) + parser.add_argument( + "-p", + "--progress", + dest="progress", + action="store_const", + const=True, + default=False, + help="Display progress bar while uploading.", + ) + + args = parser.parse_args() + + if args.version: + print(Version) + sys.exit(0) + + # Serial code + try: + ser = serial.Serial(args.mojo_tty, 19200, timeout=20) + except: + print("No serial port found named " + args.mojo_tty) + sys.exit(1) + + # if (not args.bitstream and not args.install and not args.copy and not args.erase and not args.only_verify and not args.reboot): + if not args.bitstream and not args.install and not args.erase: + print(parser.print_help()) + sys.exit(1) + if args.erase: + if args.verbose: + print("Preparing to erase") + erase_mojo(ser, args.verbose) + sys.exit(0) + if args.bitstream: + install_mojo( + ser, args.bitstream, args.verbose, args.no_verify, args.ram, args.progress + ) + sys.exit(0) + if args.install: + install_mojo( + ser, args.install, args.verbose, args.no_verify, args.ram, args.progress + ) + sys.exit(0) + + +def display_progress(p, width=30): + if p > 1: + p = 1 + if p < 0: + p = 0 + bar_width = int(width * p) + rem_bar_width = int(width - bar_width) + sys.stdout.write( + "\r[" + ("#" * bar_width) + (" " * rem_bar_width) + ("] (%d%%)" % int(100 * p)) + ) + sys.stdout.flush() + + +def install_mojo(ser, bitstream, verbose, no_verify, ram, progress): + file = open(bitstream, "rb") + bits = file.read() + length = len(bits) + reboot_mojo(ser, verbose) + + if ram: + ser.write(b"R") + ret = ser.read(1) + if verbose and ret == b"R": + print("Mojo is ready to recieve bitstream and write it to RAM") + elif ret != b"R": + print("Mojo did not respond correctly! Make sure the port is correct") + sys.exit(1) + + if not ram and no_verify: + ser.write(b"F") + ret = ser.read(1) + if verbose and ret == b"R": + print("Mojo is ready to recieve bitstream and write it to FLASH") + elif ret != b"R": + print("Mojo did not respond correctly! Make sure the port is correct") + sys.exit(1) + + if not ram and not no_verify: + ser.write(b"V") + ret = ser.read(1) + if verbose and ret == b"R": + print("Mojo is ready to recieve bitstream, write it to FLASH and verify it afterwards") + elif ret != b"R": + print("Mojo did not respond correctly! Make sure the port is correct") + sys.exit(1) + + buf = length.to_bytes(4, byteorder="little") + ser.write(buf) + ret = ser.read(1) + if verbose and ret == b"O": + print("Mojo acknowledged size of bitstream. Writing bitstream") + elif ret != b"O": + print("Mojo failed to acknowledge size of bitstream. Did not write") + sys.exit(1) + + if progress: + for i, bit in enumerate(bits): + ser.write(bit.to_bytes(1, byteorder="little")) + display_progress(float(i + 1) / length) + sys.stdout.write("\n") + else: + ser.write(bits) + + ret = ser.read(1) + if verbose and ret == b"D": + print("Mojo has been flashed") + elif ret != b"D": + print("Mojo failed to flash correctly") + sys.exit(1) + + if not ram and not no_verify: + ser.write(b"S") + if verbose: + print("Verifying Mojo") + ret = ser.read(1) + if ret == b"\xAA" and verbose: + print("First Byte was valid getting flash size.") + elif ret != b"\xAA": + print("Flash does not contain valid start byte.") + sys.exit(1) + ret = ser.read(4) + flash_length = int.from_bytes(ret, byteorder='little') - 5 + if flash_length == length and verbose: + print("Flash and local bitstream match file size.") + elif flash_length != length: + print("Flash is not same size as local bitstream.") + sys.exit(1) + ret = ser.read(length) + if ret == bits and verbose: + print("Flash and local bitstream are a match.") + elif ret != bits: + print("Flash and local bitstream do not match.") + sys.exit(1) + if not ram: + ser.write(b"L") + ret = ser.read(1) + if verbose and ret == b"D": + print("Mojo has been loaded bitsream") + elif ret != b"D": + print("Mojo failed to load bitstream") + sys.exit(1) + return + + +def reboot_mojo(ser, verbose): + ser.setDTR(True) + time.sleep(0.005) + for i in range(0, 5): + ser.setDTR(False) + time.sleep(0.005) + ser.setDTR(True) + time.sleep(0.005) + if verbose: + print("Rebooting Mojo") + return + + +def erase_mojo(ser, verbose): + reboot_mojo(ser, verbose) + ser.write(b"E") + ret = ser.read(1) + if verbose and ret == b"D": + print("Erased mojo successfully.") + elif ret != b"D": + print("Failed to erase Mojo. Error code: " + ret) + sys.exit(1) + ser.close() + sys.exit(0) + return + + +# main() diff --git a/scripts/upload.py b/scripts/upload.py new file mode 100755 index 0000000..14117bd --- /dev/null +++ b/scripts/upload.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python3 +import serial +import os +import subprocess +import sys +import time +import argparse +import math + +import mojo + +def progressbar(it, prefix="", size=60, file=sys.stdout): + count = len(it) + def show(j): + x = int(size*j/count) + file.write("%s[%s%s] %i/%i\r" % (prefix, "#"*x, "."*(size-x), j, count)) + file.flush() + show(0) + for i, item in enumerate(it): + yield item + show(i+1) + file.write("\n") + file.flush() + +def upload_rom(filename): + # ser = serial.Serial("COM3", timeout=1, write_timeout=1) + ser = serial.Serial("/dev/ttyUSB0", timeout=1, write_timeout=1, baudrate=115200) + if ser.is_open: + # Clear out any existing input + ser.write(b'\n') + time.sleep(0.002) + + # Send the upload command + ser.write(b'#') + time.sleep(0.002) + ser.write(b'u') + time.sleep(0.002) + ser.write(b'\n') + time.sleep(0.002) + + size = os.path.getsize(filename) + ser.write([size & 0xFF]) + time.sleep(0.002) + ser.write([(size >> 8) & 0xFF]) + time.sleep(0.002) + + with open(filename, "rb") as f: + for i in progressbar(range(size), "Upload: ", 40): + byte = f.read(1) + ser.write(byte) + time.sleep(0.002) + + ser.close() + + else: + print("Failed to open serial port") + +def upload_bload(filename): + # ser = serial.Serial("COM3", timeout=1, write_timeout=1) + ser = serial.Serial("/dev/ttyUSB0", timeout=1, write_timeout=1, baudrate=115200) + if ser.is_open: + size = os.path.getsize(filename) + + print("Size: {} ({} pages)".format(size, math.ceil(size/256))) + + input("Press enter to start upload") + + with open(filename, "rb") as f: + for i in progressbar(range(size), "Upload: ", 40): + byte = f.read(1) + ser.write(byte) + + if byte == b'#': + time.sleep(0.002) + ser.write(b'#') + time.sleep(0.002) + ser.write(b'\n') + + time.sleep(0.002) + + ser.close() + + else: + print("Failed to open serial port") + +def upload_sd(filename): + if os.geteuid() == 0: + print("Running as root") + file_in = open(filename, "rb") + file_out = open("/dev/sdb", "wb") + + file_out.write(file_in.read()) + else: + print("Reqeusting root permission") + subprocess.call(["sudo", "python3", *sys.argv]) + sys.exit() + + +# @todo For now we just wrap the existing mojo.py tool +# At some point we should rewrite it from scratch +def upload_mojo(filename): + # Serial code + try: + ser = serial.Serial("/dev/ttyACM0", 19200, timeout=20) + except: + print("No serial port found named /dev/ttyACM0") + sys.exit(1) + + mojo.install_mojo(ser, filename, True, False, False, True) + +def main(): + parser = argparse.ArgumentParser(description="Upload binaries to the z80 computer.") + parser.add_argument("filename", help="file to upload") + parser.add_argument("--rom", dest="rom", action="store_const", const=True, default=False, help="Upload binary to rom") + parser.add_argument("--bload", dest="bload", action="store_const", const=True, default=False, help="Upload binary to bload") + parser.add_argument("--mojo", dest="mojo", action="store_const", const=True, default=False, help="Upload binary to mojo") + parser.add_argument("--sd", dest="sd", action="store_const", const=True, default=False, help="Upload binary to sd card") + + args = parser.parse_args() + + if (args.rom): + upload_rom(args.filename) + elif (args.bload): + upload_bload(args.filename) + elif (args.mojo): + upload_mojo(args.filename) + elif (args.sd): + upload_sd(args.filename) + else: + print("You needs to specify a target") + +if __name__ == "__main__": + main()