Upload.py can now upload to the sdcard and did some reorganization

This commit is contained in:
Dreaded_X 2020-09-21 21:50:19 +02:00
parent 077b2a295e
commit cb7a703564
6 changed files with 430 additions and 110 deletions

1
bin/create_disk Symbolic link
View File

@ -0,0 +1 @@
../scripts/create_disk.py

View File

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

1
bin/upload Symbolic link
View File

@ -0,0 +1 @@
../scripts/upload.py

Binary file not shown.

View File

@ -7,10 +7,6 @@ blockSize = 16384
maxDirs = 128 maxDirs = 128
dirBlocks = 1 dirBlocks = 1
# @todo Currently the tool assumes your are running in a subfolder from z80
out = open('../tools/disk.img', 'wb')
def addBootloader(name): def addBootloader(name):
loader = open(name, 'rb') loader = open(name, 'rb')
b = loader.read() b = loader.read()
@ -88,6 +84,10 @@ def addFile(filename, n, t):
seekBlock(fileCounter) seekBlock(fileCounter)
out.write(b) 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') addBootloader('../cpm/.build/loader.bin')
addOS('../cpm/.build/cpm22.bin', '../cpm/.build/bios.bin') addOS('../cpm/.build/cpm22.bin', '../cpm/.build/bios.bin')
@ -97,3 +97,6 @@ initDirs()
addFile("../cpm/.build/MONITOR.COM", "MONITOR", "COM") addFile("../cpm/.build/MONITOR.COM", "MONITOR", "COM")
addFile("../cpm/bin/STAT.COM", "STAT", "COM") addFile("../cpm/bin/STAT.COM", "STAT", "COM")
addFile("../xed/.build/XED.COM", "XED", "COM") addFile("../xed/.build/XED.COM", "XED", "COM")
if __name__ == "__main__":
main()

282
scripts/mojo.py Executable file
View File

@ -0,0 +1,282 @@
#!/usr/bin/env python3
###-------------------------------------------------------------------------
### Mojo.py is a bitstream uploader for the mojo v2 board
### author Matthew O'Gorman <mog@rldn.net>
### 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()

133
scripts/upload.py Executable file
View File

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