|
|
@@ -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)
|