Browse Source

Add main function

This commit adds a main function to the alpaca_isp package, which will
eventually allow flashing microcontrollers from the command line but for
now mostly parses command-line arguments.  There's more work to do
before I can get on with the real flashing (microcontroller-specific
stuff, Intel HEX stuff).
Clara Hobbs 6 years ago
parent
commit
e766623cb6
2 changed files with 98 additions and 4 deletions
  1. 79
    4
      alpaca_isp/__init__.py
  2. 19
    0
      alpaca_isp/__main__.py

+ 79
- 4
alpaca_isp/__init__.py View File

16
 __author__ = "Clayton G. Hobbs"
16
 __author__ = "Clayton G. Hobbs"
17
 __version__ = "0"
17
 __version__ = "0"
18
 
18
 
19
+import argparse
19
 import struct
20
 import struct
21
+import sys
20
 import time
22
 import time
21
 from enum import Enum
23
 from enum import Enum
22
 
24
 
23
 import serial
25
 import serial
24
 
26
 
25
 
27
 
28
+_DEFAULT_BAUDRATE = 115200
29
+_DEFAULT_CLOCK = 12000
30
+_DEFAULT_TIMEOUT = 0.1
31
+
32
+
26
 class LPC:
33
 class LPC:
27
     """Interface for LPC in-system programming"""
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
         self._serport = serport
38
         self._serport = serport
31
         self._baudrate = baudrate
39
         self._baudrate = baudrate
32
         self._clock = clock
40
         self._clock = clock
97
         time.sleep(delay)
105
         time.sleep(delay)
98
         self._uart.rts = False
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
         # Synchronize with the MCU
115
         # Synchronize with the MCU
103
         while True:
116
         while True:
104
             # Send a ?
117
             # Send a ?
105
             self._uart.write(b"?")
118
             self._uart.write(b"?")
106
             self._uart.flush()
119
             self._uart.flush()
107
             if verbose:
120
             if verbose:
108
-                print("?")
121
+                print(".", end="", flush=True)
109
             # Receive a response
122
             # Receive a response
110
             try:
123
             try:
111
                 s = self._readline()
124
                 s = self._readline()
112
             except RecvTimeout:
125
             except RecvTimeout:
126
+                if max_tries is not None:
127
+                    max_tries -= 1
128
+                    if max_tries <= 0:
129
+                        raise
113
                 continue
130
                 continue
114
             # If we got the right response, break
131
             # If we got the right response, break
115
             if s == b"Synchronized\r\n":
132
             if s == b"Synchronized\r\n":
336
 
353
 
337
 class RecvTimeout(ISPError):
354
 class RecvTimeout(ISPError):
338
     """Timeout while receiving a command"""
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()

+ 19
- 0
alpaca_isp/__main__.py View File

1
+# Copyright 2017 Clayton G. Hobbs
2
+# 
3
+# Licensed under the Apache License, Version 2.0 (the "License");
4
+# you may not use this file except in compliance with the License.
5
+# You may obtain a copy of the License at
6
+# 
7
+# http://www.apache.org/licenses/LICENSE-2.0
8
+# 
9
+# Unless required by applicable law or agreed to in writing, software
10
+# distributed under the License is distributed on an "AS IS" BASIS,
11
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+# See the License for the specific language governing permissions and
13
+# limitations under the License.
14
+"""Alpaca ISP command line tool"""
15
+
16
+import alpaca_isp
17
+
18
+if __name__ == "__main__":
19
+    alpaca_isp.main()

Loading…
Cancel
Save