|
@@ -16,17 +16,25 @@
|
16
|
16
|
__author__ = "Clayton G. Hobbs"
|
17
|
17
|
__version__ = "0"
|
18
|
18
|
|
|
19
|
+import argparse
|
19
|
20
|
import struct
|
|
21
|
+import sys
|
20
|
22
|
import time
|
21
|
23
|
from enum import Enum
|
22
|
24
|
|
23
|
25
|
import serial
|
24
|
26
|
|
25
|
27
|
|
|
28
|
+_DEFAULT_BAUDRATE = 115200
|
|
29
|
+_DEFAULT_CLOCK = 12000
|
|
30
|
+_DEFAULT_TIMEOUT = 0.1
|
|
31
|
+
|
|
32
|
+
|
26
|
33
|
class LPC:
|
27
|
34
|
"""Interface for LPC in-system programming"""
|
28
|
35
|
|
29
|
|
- def __init__(self, serport, baudrate=115200, clock=12000, timeout=0.1):
|
|
36
|
+ def __init__(self, serport, baudrate=_DEFAULT_BAUDRATE,
|
|
37
|
+ clock=_DEFAULT_CLOCK, timeout=_DEFAULT_TIMEOUT):
|
30
|
38
|
self._serport = serport
|
31
|
39
|
self._baudrate = baudrate
|
32
|
40
|
self._clock = clock
|
|
@@ -97,19 +105,28 @@ class LPC:
|
97
|
105
|
time.sleep(delay)
|
98
|
106
|
self._uart.rts = False
|
99
|
107
|
|
100
|
|
- def synchronize(self, verbose=False):
|
101
|
|
- """Begin communication with the microcontroller"""
|
|
108
|
+ def synchronize(self, verbose=False, max_tries=None):
|
|
109
|
+ """Begin communication with the microcontroller
|
|
110
|
+
|
|
111
|
+ If verbose is True, prints a . for every synchronization attempt.
|
|
112
|
+ If max_tries is an integer, attempt to synchronize at most that many
|
|
113
|
+ times before failing by raising RecvTimeout.
|
|
114
|
+ """
|
102
|
115
|
# Synchronize with the MCU
|
103
|
116
|
while True:
|
104
|
117
|
# Send a ?
|
105
|
118
|
self._uart.write(b"?")
|
106
|
119
|
self._uart.flush()
|
107
|
120
|
if verbose:
|
108
|
|
- print("?")
|
|
121
|
+ print(".", end="", flush=True)
|
109
|
122
|
# Receive a response
|
110
|
123
|
try:
|
111
|
124
|
s = self._readline()
|
112
|
125
|
except RecvTimeout:
|
|
126
|
+ if max_tries is not None:
|
|
127
|
+ max_tries -= 1
|
|
128
|
+ if max_tries <= 0:
|
|
129
|
+ raise
|
113
|
130
|
continue
|
114
|
131
|
# If we got the right response, break
|
115
|
132
|
if s == b"Synchronized\r\n":
|
|
@@ -336,3 +353,61 @@ class ISPError(IOError):
|
336
|
353
|
|
337
|
354
|
class RecvTimeout(ISPError):
|
338
|
355
|
"""Timeout while receiving a command"""
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+def main():
|
|
359
|
+ """Entry point for Alpaca ISP command line tool"""
|
|
360
|
+ # Make the argument parser
|
|
361
|
+ parser = argparse.ArgumentParser(
|
|
362
|
+ description="Flash an LPC microcontroller")
|
|
363
|
+ parser.add_argument("file", metavar="file", nargs="+", type=str,
|
|
364
|
+ help="Intel HEX file to flash to the microcontroller")
|
|
365
|
+ parser.add_argument("tty", metavar="tty", type=str,
|
|
366
|
+ help="the tty to which the microcontroller is attached")
|
|
367
|
+ parser.add_argument("-b", "--baudrate", type=int,
|
|
368
|
+ default=_DEFAULT_BAUDRATE,
|
|
369
|
+ help="baud rate used for communication (default: %(default)s)")
|
|
370
|
+ parser.add_argument("-c", "--clock-khz", type=int, default=_DEFAULT_CLOCK,
|
|
371
|
+ help="microcontroller's clock frequency in kHz "
|
|
372
|
+ "(default: %(default)s)")
|
|
373
|
+ parser.add_argument("-t", "--timeout", type=float,
|
|
374
|
+ default=_DEFAULT_TIMEOUT,
|
|
375
|
+ help="timeout for reading data from the microcontroller in "
|
|
376
|
+ "seconds (default: %(default)s)")
|
|
377
|
+ parser.add_argument("-e", "--erase", action="store_true",
|
|
378
|
+ help="erase all the microcontroller's flash before flashing")
|
|
379
|
+ parser.add_argument("--no-start", action="store_true",
|
|
380
|
+ help="do not start the microcontroller after flashing")
|
|
381
|
+ parser.add_argument("--try-sync", type=int,
|
|
382
|
+ help="maximum number of tries to synchronize with the "
|
|
383
|
+ "microcontroller")
|
|
384
|
+ parser.add_argument("--control", action="store_true",
|
|
385
|
+ help="control RS232 lines to enter ISP mode (/RST = DTR, /ISP = "
|
|
386
|
+ "RTS)")
|
|
387
|
+ parser.add_argument("--verify", action="store_true",
|
|
388
|
+ help="verify that the data were written correctly after flashing")
|
|
389
|
+
|
|
390
|
+ # Parse arguments
|
|
391
|
+ args = parser.parse_args()
|
|
392
|
+
|
|
393
|
+ # Open the LPC
|
|
394
|
+ lpc = LPC(args.tty, baudrate=args.baudrate, clock=args.clock_khz,
|
|
395
|
+ timeout=args.timeout)
|
|
396
|
+ lpc.open()
|
|
397
|
+
|
|
398
|
+ # Enter ISP mode if we've been asked to do so
|
|
399
|
+ if args.control:
|
|
400
|
+ lpc.enter_isp()
|
|
401
|
+
|
|
402
|
+ # Synchronize with the microcontroller
|
|
403
|
+ print("Synchronizing", end="", flush=True)
|
|
404
|
+ try:
|
|
405
|
+ lpc.synchronize(max_tries=args.try_sync, verbose=True)
|
|
406
|
+ except RecvTimeout:
|
|
407
|
+ print(" failed")
|
|
408
|
+ sys.exit(1)
|
|
409
|
+ print()
|
|
410
|
+
|
|
411
|
+ # TODO: all the interesting stuff
|
|
412
|
+
|
|
413
|
+ lpc.close()
|