From 1169dc6e3b34daf85e5b30183b8fc2979ab952ca Mon Sep 17 00:00:00 2001 From: Michael Hope Date: Wed, 29 Sep 2010 20:01:10 +1300 Subject: Added auto detection of the USB to serial port under Linux and MacOS. --- support/stm32loader.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'support') diff --git a/support/stm32loader.py b/support/stm32loader.py index f717c9a..d8e1f9f 100755 --- a/support/stm32loader.py +++ b/support/stm32loader.py @@ -25,6 +25,7 @@ import sys, getopt import serial import time +import glob try: from progressbar import * @@ -314,7 +315,7 @@ def usage(): -v Verify -r Read -l length Length of read - -p port Serial port (default: /dev/tty.usbserial-ftCYPMYJ) + -p port Serial port (default: first USB-like port in /dev) -b baud Baud speed (default: 115200) -a addr Target address @@ -334,7 +335,7 @@ if __name__ == "__main__": pass conf = { - 'port': '/dev/tty.usbserial-FTD3TMCH', + 'port': 'auto', 'baud': 115200, 'address': 0x08000000, 'erase': 0, @@ -386,6 +387,20 @@ if __name__ == "__main__": else: assert False, "unhandled option" + # Try and find the port automatically + if conf['port'] == 'auto': + ports = [] + + # Get a list of all USB-like names in /dev + for name in ['tty.usbserial', 'ttyUSB']: + ports.extend(glob.glob('/dev/%s*' % name)) + + ports = sorted(ports) + + if ports: + # Found something - take it + conf['port'] = ports[0] + cmd = CommandInterface() cmd.open(conf['port'], conf['baud']) mdebug(10, "Open port %(port)s, baud %(baud)d" % {'port':conf['port'], 'baud':conf['baud']}) -- cgit v1.2.3 From 3b48e2101810db085972a02d682b576076f1f94c Mon Sep 17 00:00:00 2001 From: Michael Hope Date: Wed, 29 Sep 2010 20:06:51 +1300 Subject: Changed the exception handling so that Ctrl-C passes through and isn't treated as a timeout. --- support/stm32loader.py | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) (limited to 'support') diff --git a/support/stm32loader.py b/support/stm32loader.py index d8e1f9f..a817efc 100755 --- a/support/stm32loader.py +++ b/support/stm32loader.py @@ -59,23 +59,24 @@ class CommandInterface: def _wait_for_ask(self, info = ""): + got = self.sp.read(1) + + if not got: + raise CmdException("No response") + # wait for ask - try: - ask = ord(self.sp.read()) - except: - raise CmdException("Can't read port or timeout") + ask = ord(got) + + if ask == 0x79: + # ACK + return 1 else: - if ask == 0x79: - # ACK - return 1 + if ask == 0x1F: + # NACK + raise CmdException("NACK "+info) else: - if ask == 0x1F: - # NACK - raise CmdException("NACK "+info) - else: - # Unknow responce - raise CmdException("Unknow response. "+info+": "+hex(ask)) - + # Unknow responce + raise CmdException("Unknow response. "+info+": "+hex(ask)) def reset(self): self.sp.setDTR(0) @@ -407,7 +408,7 @@ if __name__ == "__main__": try: try: cmd.initChip() - except: + except CmdException: print "Can't init. Ensure that BOOT0 is enabled and reset device" bootversion = cmd.cmdGet() -- cgit v1.2.3 From 97f6b77b580646f5771ff283a3c586045c0e8425 Mon Sep 17 00:00:00 2001 From: Michael Hope Date: Wed, 29 Sep 2010 20:20:32 +1300 Subject: Make the initial chip detection much more robust. --- support/stm32loader.py | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) (limited to 'support') diff --git a/support/stm32loader.py b/support/stm32loader.py index a817efc..7509871 100755 --- a/support/stm32loader.py +++ b/support/stm32loader.py @@ -26,6 +26,7 @@ import sys, getopt import serial import time import glob +import time try: from progressbar import * @@ -54,7 +55,7 @@ class CommandInterface: stopbits=1, xonxoff=0, # enable software flow control rtscts=0, # disable RTS/CTS flow control - timeout=5 # set a timeout value, None for waiting forever + timeout=0.5 # set a timeout value, None for waiting forever ) @@ -62,7 +63,7 @@ class CommandInterface: got = self.sp.read(1) if not got: - raise CmdException("No response") + raise CmdException("No response to %s" % info) # wait for ask ask = ord(got) @@ -73,10 +74,10 @@ class CommandInterface: else: if ask == 0x1F: # NACK - raise CmdException("NACK "+info) + raise CmdException("Chip replied with a NACK during %s" % info) else: - # Unknow responce - raise CmdException("Unknow response. "+info+": "+hex(ask)) + # Unknown responce + raise CmdException("Unrecognised response %x to %s" % (ask, info)) def reset(self): self.sp.setDTR(0) @@ -89,8 +90,21 @@ class CommandInterface: self.sp.setRTS(0) self.reset() - self.sp.write("\x7F") # Syncro - return self._wait_for_ask("Syncro") + # Be a bit more persistant when trying to initialise the chip + stop = time.time() + 5.0 + + while time.time() <= stop: + self.sp.write('\x7f') + + got = self.sp.read() + + # The chip will ACK a sync the very first time and + # NACK it every time afterwards + if got and got in '\x79\x1f': + # Synced up + return + + raise CmdException('No response while trying to sync') def releaseChip(self): self.sp.setRTS(1) -- cgit v1.2.3 From d470dc6daa46f26fc995ec86929e8209c581ea2d Mon Sep 17 00:00:00 2001 From: Michael Hope Date: Wed, 29 Sep 2010 20:21:52 +1300 Subject: Do basic validation on the boot version and chip IDs. --- support/stm32loader.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'support') diff --git a/support/stm32loader.py b/support/stm32loader.py index 7509871..b7fb96c 100755 --- a/support/stm32loader.py +++ b/support/stm32loader.py @@ -426,8 +426,18 @@ if __name__ == "__main__": print "Can't init. Ensure that BOOT0 is enabled and reset device" bootversion = cmd.cmdGet() + mdebug(0, "Bootloader version %X" % bootversion) - mdebug(0, "Chip id `%s'" % str(map(lambda c: hex(ord(c)), cmd.cmdGetID()))) + + if bootversion < 20 or bootversion >= 100: + raise Exception('Unreasonable bootloader version %d' % bootversion) + + id = [ord(x) for x in cmd.cmdGetID()] + mdebug(0, "Chip id '%s'" % ' '.join('0x%x' % x for x in id)) + + if len(id) < 2 or id[0] != 0x04: + raise Exception('Unrecognised chip ID') + # cmd.cmdGetVersion() # cmd.cmdGetID() # cmd.cmdReadoutUnprotect() -- cgit v1.2.3 From 0fcccd921ef306f6c7ba87b063ad037d2c0bd1e8 Mon Sep 17 00:00:00 2001 From: Michael Hope Date: Wed, 29 Sep 2010 20:28:39 +1300 Subject: Added support for programming ELF files without converting first. --- support/stm32loader.py | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) (limited to 'support') diff --git a/support/stm32loader.py b/support/stm32loader.py index b7fb96c..02ca4e8 100755 --- a/support/stm32loader.py +++ b/support/stm32loader.py @@ -27,6 +27,9 @@ import serial import time import glob import time +import tempfile +import os +import subprocess try: from progressbar import * @@ -338,6 +341,34 @@ def usage(): """ % sys.argv[0] +def read(filename): + """Read the file to be programmed and turn it into a binary""" + with open(filename, 'rb') as f: + bytes = f.read() + + if bytes.startswith('\x7FELF'): + # Actually an ELF file. Convert to binary + handle, path = tempfile.mkstemp(suffix='.bin', prefix='stm32loader') + + try: + os.close(handle) + + # Try a couple of options for objcopy + for name in ['arm-none-eabi-objcopy', 'arm-linux-gnueabi-objcopy']: + try: + code = subprocess.call([name, '-Obinary', filename, path]) + + if code == 0: + return read(path) + except OSError: + pass + else: + raise Exception('Error %d while converting to a binary file' % code) + finally: + # Remove the temporary file + os.unlink(path) + else: + return [ord(x) for x in bytes] if __name__ == "__main__": @@ -420,6 +451,9 @@ if __name__ == "__main__": cmd.open(conf['port'], conf['baud']) mdebug(10, "Open port %(port)s, baud %(baud)d" % {'port':conf['port'], 'baud':conf['baud']}) try: + if (conf['write'] or conf['verify']): + data = read(args[0]) + try: cmd.initChip() except CmdException: @@ -444,9 +478,6 @@ if __name__ == "__main__": # cmd.cmdWriteUnprotect() # cmd.cmdWriteProtect([0, 1]) - if (conf['write'] or conf['verify']): - data = map(lambda c: ord(c), file(args[0]).read()) - if conf['erase']: cmd.cmdEraseMemory() -- cgit v1.2.3