From b56d6ca1c76c774fd8372df1ff8430136774f13e Mon Sep 17 00:00:00 2001 From: Virgil Dupras Date: Sun, 8 Dec 2019 08:32:19 -0500 Subject: [PATCH] Rewrite uploadb.py in perl I know, this is silly, but I'm moving tools to something a bit closer to the system. I consider perl to be more system-like than python for a simple reason: perl is part of the OpenBSD base system and python is not. Also, I'm learning perl and using this as an opportunity. --- tools/uploadb.pl | 79 ++++++++++++++++++++++++++++++++++++++++++++++++ tools/uploadb.py | 79 ------------------------------------------------ 2 files changed, 79 insertions(+), 79 deletions(-) create mode 100755 tools/uploadb.pl delete mode 100755 tools/uploadb.py diff --git a/tools/uploadb.pl b/tools/uploadb.pl new file mode 100755 index 0000000..fb308d8 --- /dev/null +++ b/tools/uploadb.pl @@ -0,0 +1,79 @@ +#!/usr/bin/perl +# Push specified file to specified device **running the BASIC shell** and verify +# that the sent contents is correct. +use strict; +use Fcntl; + +if (@ARGV != 3) { + print "Usage: ./uploadb.pl device memptr filename\n"; + exit 1; +} + +my ($device, $memptr, $fname) = @ARGV; + +if (hex($memptr) >= 0x10000) { die "memptr is out of range"; } + +if (! -e $fname) { die "${fname} does not exist"; } +my $fsize = -s $fname; +my $maxsize = 0x10000 - hex($memptr); +if ($fsize > $maxsize) { die "File too big. ${maxsize} bytes max"; } + +my $fh; +unless (open($fh, '<', $fname)) { die "Can't open $fname"; } + +my $devh; +unless (sysopen($devh, $device, O_RDWR|O_NOCTTY)) { die "Can't open $device"; } + +sub sendcmd { + # The serial link echoes back all typed characters and expects us to read + # them. We have to send each char one at a time. + my $junk; + foreach my $char (split //, shift) { + syswrite $devh, $char; + sysread $devh, $junk, 1; + } + syswrite $devh, "\n"; + sysread $devh, $junk, 2; # send back \r\n +} + +sendcmd("m=0x${memptr}"); + +my $rd; +sysread $devh, $rd, 2; # read prompt + +# disable buffering +$| = 1; + +while (sysread $fh, my $char, 1) { + print "."; + for (my $i=0; $i<5; $i++) { # try 5 times + sendcmd("getc"); + syswrite $devh, $char; + sysread $devh, $rd, 2; # read prompt + sendcmd("print a"); + my $s = ""; + while (1) { + sysread $devh, $rd, 1; + if ($rd !~ /\d/) { last; } + $s .= $rd; + } + sysread $devh, $rd, 3; # read prompt + if ($s == ord($char)) { + last; + } else { + if ($i < 4) { + print "Mismatch at byte ${i}! ${s} != ${ord($char)}. Retrying.\n"; + } else { + die "Maximum retries reached, abort.\n"; + } + } + } + sendcmd("poke m a"); + sysread $devh, $rd, 2; # read prompt + sendcmd("m=m+1"); + sysread $devh, $rd, 2; # read prompt +} + +print "Done!\n"; +close $fh; +close $devh; diff --git a/tools/uploadb.py b/tools/uploadb.py deleted file mode 100755 index 74c7e22..0000000 --- a/tools/uploadb.py +++ /dev/null @@ -1,79 +0,0 @@ -#!/usr/bin/env python3 - -# Push specified file to specified device **running the BASIC shell** and verify -# that the sent contents is correct. - -import argparse -import os -import sys - -def sendcmd(fd, cmd): - # The serial link echoes back all typed characters and expects us to read - # them. We have to send each char one at a time. - if isinstance(cmd, str): - cmd = cmd.encode() - for c in cmd: - os.write(fd, bytes([c])) - os.read(fd, 1) - os.write(fd, b'\n') - os.read(fd, 2) # sends back \r\n - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument('device') - parser.add_argument('memptr') - parser.add_argument('filename') - args = parser.parse_args() - - try: - memptr = int('0x' + args.memptr, 0) - except ValueError: - print("memptr are has to be hexadecimal without prefix.") - return 1 - if memptr >= 0x10000: - print("memptr out of range.") - return 1 - maxsize = 0x10000 - memptr - st = os.stat(args.filename) - if st.st_size > maxsize: - print("File too big. 0x{:04x} bytes max".format(maxsize)) - return 1 - fd = os.open(args.device, os.O_RDWR) - with open(args.filename, 'rb') as fp: - fcontents = fp.read() - sendcmd(fd, f'm=0x{memptr:04x}') - os.read(fd, 2) # read prompt - - for i, c in enumerate(fcontents): - c = bytes([c]) - print('.', end='', flush=True) - for _ in range(5): # try 5 times - sendcmd(fd, 'getc') - os.write(fd, c) - os.read(fd, 2) # read prompt - sendcmd(fd, 'print a') - s = b'' - while True: - r = os.read(fd, 1) # putc result - if not r.isdigit(): - break - s += r - os.read(fd, 3) # read prompt - if int(s) == c[0]: - break - else: - print(f"Mismatch at byte {i}! {c} != {r}. Retrying") - else: - print("Maximum retries reached, abort") - return 1 - sendcmd(fd, 'poke m a') - os.read(fd, 2) # read prompt - sendcmd(fd, 'm=m+1') - os.read(fd, 2) # read prompt - print("Done!") - os.close(fd) - return 0 - -if __name__ == '__main__': - sys.exit(main())