-
Notifications
You must be signed in to change notification settings - Fork 1
/
loader.py
160 lines (116 loc) · 3.55 KB
/
loader.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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import argparse
import os
import time
from serial import Serial
from array import array
def main():
parser = argparse.ArgumentParser(
description='Load application software via UART'
)
parser.add_argument(
'-b', '--base',
dest='base', type=str, required=True,
help='Base address where the software will be loaded, usually in RAM. '
'Supply in hexadecimal format. Minimum 0x0000, maximum 0xFFFF.'
)
parser.add_argument(
'-e', '--exec',
dest='exec', action='store_true', default=False,
help='After loading, execute from base address'
)
parser.add_argument(
'filename',
type=str,
help='Filename that should be loaded. Must be a binary file, not hex.'
)
args = parser.parse_args()
base = int(args.base, 16)
exec = args.exec
filename = args.filename
if not (0 <= base <= 0xFFFF):
raise ValueError(
'Base has invalid value. Minimum 0x0000, maximum 0xFFFF.'
)
filesize = os.stat(filename).st_size
if not (1 <= filesize <= 0xFFFF):
raise ValueError(
'Size of file is invalid. Minimum 1 byte, maximum 65536.'
)
if base + filesize > 0xFFFF:
raise ValueError(
'Base address plus file size would cause an address overflow.'
)
base_le = (base & 0xFF) << 8 | (base & 0xFF00) >> 8
filesize_le = (filesize & 0xFF) << 8 | (filesize & 0xFF00) >> 8
rom = array('B')
with open(filename, 'rb') as f:
rom.fromfile(f, filesize)
data = [
3,
(filesize & 0xFF), (filesize & 0xFF00) >> 8,
(base & 0xFF), (base & 0xFF00) >> 8
] + list(rom)
if exec is True:
data += [
4,
(base & 0xFF), (base & 0xFF00) >> 8
]
data = bytes(data)
ser = Serial(
'/dev/cu.usbserial-FT94JP1H',
baudrate=57600,
timeout=1
)
if ser.in_waiting > 0:
ser.read(size=ser.in_waiting)
# Wait for serial loader to be available
print('Waiting for serial loader availability: ', end='', flush=True)
failed = 0
while True:
ser.write(bytes([0x01]))
ser.flush()
try:
if ord(ser.read(size=1)) == 64:
print(' OK')
break
except TypeError:
failed += 1
print('.', end='', flush=True)
if failed == 10:
print(' Failed after too many attempts')
return
start = time.time()
print('Transferring %d bytes to 0x%4.4X: ' % (filesize, base), end='', flush=True)
ser.write(data)
ser.flush()
failed = 0
while True:
try:
if ord(ser.read(size=1)) == 33:
break
except TypeError:
failed += 1
print('.', end='', flush=True)
if failed == 5:
print(' Failed: transfer not acknowledged')
return
duration = time.time() - start
print(' Done in %.3fs' % duration)
failed = 0
if exec is True:
print('Executing from 0x%4.4X: ' % base, end='', flush=True)
while True:
try:
if ord(ser.read(size=1)) == 43:
break
except TypeError:
failed += 1
print('.', end='', flush=True)
if failed == 2:
print(' Failed: execution not acknowledged')
return
print(' OK')
ser.close()
return
if __name__ == '__main__':
main()