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,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()

+ 19
- 0
alpaca_isp/__main__.py View File

@@ -0,0 +1,19 @@
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