-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathneorv32load.py
102 lines (88 loc) · 3.39 KB
/
neorv32load.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# ------------------------------------------------------------------------------
# neorv32load
#
# Cross-platform compatible firmware download tool for use with the NEORV32
# bootloader.
# Targeted project: The NEORV32 RISC-V Processor by S. Nolting
# (https://github.com/stnolting/neorv32)
#
#
# Copyright © 2021 islandc_
# https://github.com/islandcontroller/neorv32load/
#
import argparse
import serial
def process_args() -> argparse.Namespace:
"""Helper function to set up command line argument parser and process arguments
Returns:
argparse.Namespace: Processed options
"""
parser = argparse.ArgumentParser(description='Script for uploading an application image via bootloader UART')
parser.add_argument('port', type=str, help='Serial/COM port, as required for the host OS (e.g. \"/dev/ttyUSB0\", \"COM3\" etc.)')
parser.add_argument('file', type=argparse.FileType('rb'), help='Application image in bootloader format (e.g. \"neorv32_exe.bin\")')
parser.add_argument('-b', dest='baud', type=int, default=19200, help='Serial baud rate (defaults to 19200)')
parser.add_argument('-t', dest='timeout', type=int, default=3, help='Line timeout in seconds (defaults to 3)')
parser.add_argument('-v', action='store_true', help='Print verbose output')
parser.add_argument('--keep', action='store_true', help='Keep port open after download and print RX')
parser.add_argument('--legacy', action='store_true', dest='legacy_loader', help='Target uses old bootloader (\"#\" as command character)')
return parser.parse_args()
if __name__ == "__main__":
device_ready: bool = False
upload_ok: bool = False
args: argparse.Namespace = process_args()
start_symbol = b'#' if args.legacy_loader else b'u'
with serial.Serial(port=args.port, baudrate=args.baud, timeout=args.timeout) as s:
# Immediately try to enter upload mode
print(f"Entering upload mode (sending \"{start_symbol.decode('ascii')}\")")
s.write(start_symbol)
# Wait until device is ready
line = s.readline()
while line:
if args.v:
print(line)
if (args.legacy_loader and 'Bootloader' in str(line)) or (not args.legacy_loader and 'CMD:' in str(line)):
print('Re-sending upload command')
s.write(start_symbol)
if 'neorv32_exe.bin' in str(line):
device_ready = True
break
line = s.readline()
# Evaluate wait result, abort if timeout
if not device_ready:
print('Aborting upload')
exit()
else:
print('Starting upload')
# Send binary file content
d = args.file.read()
s.write(d)
print(f"{len(d)} bytes sent")
s.flush()
# Await upload ACK from device
line = s.readline()
while line:
if args.v:
print(line)
if 'OK' in str(line):
upload_ok = True
break
line = s.readline()
# Evaluate wait result, abort if upload failed
if not upload_ok:
print('Upload failed')
exit()
else:
print('Upload successful')
# Start program execution after download
if (not args.legacy_loader):
print('Start program execution')
s.write(b'e')
s.flush()
# Optional: print serial RX until timeout
if args.keep:
print('Printing RX')
line = s.readline()
while line:
print(line)
line = s.readline()
print('Closed')