Min 4 лет назад
Родитель
Сommit
c8c7d8d587
1 измененных файлов с 51 добавлено и 20 удалено
  1. 51 20
      programmer.py

+ 51 - 20
programmer.py

@@ -1,6 +1,7 @@
 import serial
 from array import array
 
+
 class Program:
     def __init__(self, intelhex):
         self.program = b''
@@ -73,12 +74,25 @@ class PSoC1Prog:
 
     def __init__(self, serial_port):
         self.ser = serial.Serial(port=serial_port, baudrate=9600, timeout=0.1, write_timeout=1)
-        self.ser.write(b'\n')
-        x = self.ser.read_until(b'> ')
+        self.__get_resp(msg=b'> ')
+
+    def __get_resp(self, msg=b'\r\n> '):
+        """
+        When serial is started programmer might be reset,
+        which takes some time (around 1.4s) to reinitialise and respond.
+        This function waits for initial response.
+        """
+        res = self.ser.read_until(msg)
+        i = 0
+        while len(res) == 0:
+            i += 1
+            res = self.ser.read_until(msg)
+            if i > 50:
+                raise TimeoutError("Programmer response timeout")
+        return res.strip(msg)
 
     def reinitialise(self):
         self.ser.write(b'i')
-        res = self.ser.read_until('\r\n> ')
 
     def reset_device(self):
         self.ser.write(b'r')
@@ -87,12 +101,12 @@ class PSoC1Prog:
     def get_device_id(self):
         self.ser.write(b'd')
         res = self.ser.read_until('\r\n> ')
-        return int(res[:-4], 16)
+        return int(res.strip(b'\r\n> '), 16)
 
     def get_firmware_id(self):
         self.ser.write(b'f')
         res = self.ser.read_until('\r\n> ')
-        return res[:-4]
+        return res.strip(b'\r\n> ')
 
     def erase_memory(self):
         self.ser.write(b'e')
@@ -101,7 +115,12 @@ class PSoC1Prog:
     def read_checksum(self):
         self.ser.write(b'c')
         res = self.ser.read_until('\r\n> ')
-        return int(res[:-4], 16).to_bytes(2, 'big')
+        return int(res.strip(b'\r\n> '), 16).to_bytes(2, 'big')
+
+    def read_firmware(self):
+        self.ser.write(b'f')
+        res = self.ser.read_until('\r\n> ')
+        return int(res.strip(b'\r\n> '), 16).to_bytes(2, 'big')
 
     def read_memory(self, n=64, offset=0x80):
         # read n x 64 memory blocks
@@ -111,7 +130,7 @@ class PSoC1Prog:
             x = self.ser.read_until('\r\n> ')
             block = self._read_blk()
             blocks += block
-            print(f"\rReading 0x{i.to_bytes(1, 'big').hex()} [{(i+1)/64*100:.2f}%]", end='')
+            print(f"\rReading 0x{i.to_bytes(1, 'big').hex()} [{(i + 1) / 64 * 100:.2f}%]", end='')
         print('')
         return blocks
 
@@ -135,11 +154,11 @@ class PSoC1Prog:
 
     def write_program(self, data):
         self.erase_memory()
-        for i in range(len(data)//64):
-            self._write_blk(data[i*64:(i+1)*64])
+        for i in range(len(data) // 64):
+            self._write_blk(data[i * 64:(i + 1) * 64])
             self.ser.write(b'w' + array('B', [i]).tobytes())
             x = self.ser.read_until('\r\n> ')
-            print(f"\rWriting 0x{i.to_bytes(1, 'big').hex()} [{(i+1)/64*100:.2f}%]", end='')
+            print(f"\rWriting 0x{i.to_bytes(1, 'big').hex()} [{(i + 1) / 64 * 100:.2f}%]", end='')
         print('')
 
     def write_secure(self, data):
@@ -157,15 +176,16 @@ if __name__ == '__main__':
 
     parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter)
     parser.add_argument("port", help="Serial port")
-    parser.add_argument("cmd", choices=['flash', 'checksum', 'device', 'read', 'erase', 'reset'], 
-        help="Command to run\n" +
-        "flash - write .hex to device\n" +
-        "checksum - returns program checksum from device\n" +
-        "device - returns device name or identification hex\n" +
-        "read - dumps device program to file\n" +
-        "erase - deletes all devices program memory\n" +
-        "reset - restarts device\n"
-    )
+    parser.add_argument("cmd", choices=['flash', 'checksum', 'device', 'read', 'erase', 'reset', 'fw'],
+                        help="Command to run\n" +
+                             "flash - write .hex to device\n" +
+                             "checksum - returns program checksum from device\n" +
+                             "device - returns device name or identification hex\n" +
+                             "read - dumps device program to file\n" +
+                             "erase - deletes all devices program memory\n" +
+                             "reset - restarts device\n" +
+                             "fw - programmer firmware version\n"
+                        )
     parser.add_argument("-i", "--input", help="Input intel hex file for flashing")
     parser.add_argument("-o", "--output", help="Output binary for memory dump")
     parser.add_argument("--offset", type=int, default=0x80, help="Memory dump read address offset")
@@ -202,7 +222,15 @@ if __name__ == '__main__':
                 exit(1)
         print("PSoC1_Prog: success")
     elif args.cmd == 'checksum':
-        print(prog.read_checksum().hex())
+        if args.input is None:
+            print(prog.read_checksum().hex())
+            exit(0)
+        ifile = Program(args.input)
+        csum = prog.read_checksum()
+        if csum != ifile.checksum:
+            print(f"PSoC1_Prog: checksum mismatch, device={csum.hex()} file={ifile.checksum.hex()}", file=sys.stderr)
+            exit(1)
+        print(f"PSoC1_Prog: checksum match {csum.hex()}")
     elif args.cmd == 'device':
         print(prog.get_device_name())
     elif args.cmd == 'read':
@@ -218,6 +246,9 @@ if __name__ == '__main__':
     elif args.cmd == 'reset':
         prog.reset_device()
         exit(0)
+    elif args.cmd == 'fw':
+        print(prog.read_firmware().hex())
+        exit(0)
     if args.reset:
         prog.reset_device()
     exit(0)