tools/upload.py: support files larger than 0xff bytes
This commit is contained in:
parent
d40940a1ff
commit
df5549ae76
@ -2,7 +2,7 @@
|
||||
|
||||
Collapse OS likely runs from ROM code. If you need to fiddle with your machine
|
||||
more deeply, you will want to send arbitrary code to it and run it. You can do
|
||||
so with the shell's `load` and `call` commands.
|
||||
so with the shell's `poke` and `call` commands.
|
||||
|
||||
For example, let's say that you want to run this simple code that you have
|
||||
sitting on your "modern" machine and want to execute on your running Collapse OS
|
||||
@ -22,7 +22,7 @@ Now, we'll send that code to address `0xa000`:
|
||||
|
||||
> mptr a000
|
||||
A000
|
||||
> load 8 (resulting binary is 8 bytes long)
|
||||
> poke 8 (resulting binary is 8 bytes long)
|
||||
|
||||
Now, at this point, it's a bit delicate. To pipe your binary to your serial
|
||||
connection, you have to close `screen` with CTRL+A then `:quit` to free your
|
||||
@ -31,7 +31,7 @@ tty device. Then, you can run:
|
||||
cat tosend.bin > /dev/ttyUSB0 (or whatever is your device)
|
||||
|
||||
You can then re-open your connection with screen. You'll have a blank screen,
|
||||
but if the number of characters sent corresponds to what you gave `load`, then
|
||||
but if the number of characters sent corresponds to what you gave `poke`, then
|
||||
Collapse OS will be waiting for a new command. Go ahead, verify that the
|
||||
transfer was successful with:
|
||||
|
||||
@ -62,16 +62,19 @@ Success!
|
||||
|
||||
The serial connection is not always 100% reliable and a bad byte can slip in
|
||||
when you push your code and that's not fun when you try to debug your code (is
|
||||
this bad behavior caused by my logic or by a bad serial upload?).
|
||||
this bad behavior caused by my logic or by a bad serial upload?). Moreover,
|
||||
sending contents bigger than `0xff` bytes can be a hassle.
|
||||
|
||||
To this end, there is a `upload.py` file in `tools/` that takes care of loading
|
||||
the file and verify the contents. So, instead of doing `load 8` followed by
|
||||
your `cat` above, you would have done:
|
||||
the file and verify the contents. So, instead of doing `mptr a000` followed by
|
||||
`poke 8` followed by your `cat` above, you would have done:
|
||||
|
||||
./upload.py /dev/ttyUSB0 tosend.bin
|
||||
./upload.py /dev/ttyUSB0 a000 tosend.bin
|
||||
|
||||
This emits `load` and `peek` commands and fail appropriately if the `peek`
|
||||
doesn't match sent contents. Very handy.
|
||||
This emits `mptr`, `poke` and `peek` commands and fail appropriately if the
|
||||
`peek` doesn't match sent contents. If the file is larger than `0xff` bytes,
|
||||
repeat the process until the whole file was sent (file must fit in memory space
|
||||
though, of course). Very handy.
|
||||
|
||||
## Labels in RAM code
|
||||
|
||||
|
@ -24,41 +24,60 @@ def sendcmd(fd, cmd):
|
||||
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 > 0xff:
|
||||
print("File too big. 0xff bytes max")
|
||||
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)
|
||||
sendcmd(fd, 'poke {:x}'.format(st.st_size).encode())
|
||||
print("Poking...")
|
||||
with open(args.filename, 'rb') as fp:
|
||||
fcontents = fp.read()
|
||||
for c in fcontents:
|
||||
os.write(fd, bytes([c]))
|
||||
# Let's give the machine a bit of time to breathe. We ain't in a
|
||||
# hurry now, are we?
|
||||
time.sleep(0.0001)
|
||||
print("Poked")
|
||||
os.read(fd, 5)
|
||||
print("Peeking back...")
|
||||
sendcmd(fd, 'peek {:x}'.format(st.st_size).encode())
|
||||
peek = b''
|
||||
while len(peek) < st.st_size * 2:
|
||||
peek += os.read(fd, 1)
|
||||
time.sleep(0.0001)
|
||||
while True:
|
||||
fcontents = fp.read(0xff)
|
||||
if not fcontents:
|
||||
break
|
||||
print("Seeking...")
|
||||
sendcmd(fd, 'mptr {:04x}'.format(memptr).encode())
|
||||
os.read(fd, 9)
|
||||
sendcmd(fd, 'poke {:x}'.format(len(fcontents)).encode())
|
||||
print("Poking...")
|
||||
for c in fcontents:
|
||||
os.write(fd, bytes([c]))
|
||||
# Let's give the machine a bit of time to breathe. We ain't in a
|
||||
# hurry now, are we?
|
||||
time.sleep(0.0001)
|
||||
print("Poked")
|
||||
os.read(fd, 5)
|
||||
print("Peeking back...")
|
||||
sendcmd(fd, 'peek {:x}'.format(len(fcontents)).encode())
|
||||
peek = b''
|
||||
while len(peek) < len(fcontents) * 2:
|
||||
peek += os.read(fd, 1)
|
||||
time.sleep(0.0001)
|
||||
os.read(fd, 5)
|
||||
print("Got {}".format(peek.decode()))
|
||||
print("Comparing...")
|
||||
for i, c in enumerate(fcontents):
|
||||
hexfmt = '{:02X}'.format(c).encode()
|
||||
if hexfmt != peek[:2]:
|
||||
print("Mismatch at byte {}! {} != {}".format(i, peek[:2], hexfmt))
|
||||
return 1
|
||||
peek = peek[2:]
|
||||
print("All good!")
|
||||
memptr += len(fcontents)
|
||||
print("Done!")
|
||||
os.close(fd)
|
||||
print("Got {}".format(peek.decode()))
|
||||
print("Comparing...")
|
||||
for i, c in enumerate(fcontents):
|
||||
hexfmt = '{:02X}'.format(c).encode()
|
||||
if hexfmt != peek[:2]:
|
||||
print("Mismatch at byte {}! {} != {}".format(i, peek[:2], hexfmt))
|
||||
return 1
|
||||
peek = peek[2:]
|
||||
print("All good!")
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
Loading…
Reference in New Issue
Block a user