From 6691b6920cb99c6f4d7129fcd5758ab2828073e2 Mon Sep 17 00:00:00 2001 From: Nicolas Schodet Date: Thu, 17 Jun 2010 00:44:56 +0200 Subject: add bootloader control program --- tools/bootloader.py | 187 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 tools/bootloader.py (limited to 'tools/bootloader.py') diff --git a/tools/bootloader.py b/tools/bootloader.py new file mode 100644 index 0000000..7432191 --- /dev/null +++ b/tools/bootloader.py @@ -0,0 +1,187 @@ +# binwatch - Tiny binary wristwatch. {{{ +# +# Copyright (C) 2010 Nicolas Schodet +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# Contact : +# Web: http://ni.fr.eu.org/ +# Email: +# }}} */ +"""binwatch bootloader control.""" +import struct +import dev2.twi + +class ProtocolError (RuntimeError): + pass + +class Bootloader: + + INFO = 0 + START = 1 + READ = 2 + PAGE_WRITE = 3 + READ_FUSES = 4 + + def __init__ (self, address, serial): + """Initialise and set address and serial object to use.""" + self.address = address + self.twi = dev2.twi.Twi (serial) + + def _command (self, command, fmt, rfmt, *params): + """Send a command and check response. + + - command: command to send. + - fmt: command format (see struct). + - rfmt: response format. + - params: command parameters. + + Will return unpacked response or None on error.""" + s = struct.pack (' flash_size: + raise RuntimeError ("flash too small") + # Program pages. + for page in xrange (0, len (data), page_size): + bootloader.page_write (page, page_size, data[page:page + page_size]) + if progress: + progress ('program', page + page_size, len (data)) + # Verify. + if verify: + for page in xrange (0, len (data), page_size): + r = bootloader.read (page, page_size) + if page == 0: + match = r[2:] == data[page + 2:page + page_size] + else: + match = r == data[page:page + page_size] + if not match: + raise RuntimeError ( + "verification mismatch at address 0x04x" % page) + if progress: + progress ('verify', page + page_size, len (data)) + +def dump (bootloader, progress = None): + """Dump all flash data using bootloader.""" + # Get bootloader parameters. + _, page_size, flash_size = bootloader.info () + data = [ ] + for page in xrange (0, flash_size, page_size): + r = bootloader.read (page, page_size) + data.append (r) + if progress: + progress ('dump', page + page_size, flash_size) + return ''.join (data) + +def progress (step, current, total): + """Print current progress.""" + print "\r%s: %3d%%" % (step, current * 100 / total), + if current == total: + print '' + import sys + sys.stdout.flush () + +def command (args = None): + """Implement command line interface.""" + # Parse options. + import optparse + parser = optparse.OptionParser () + parser.add_option ('-d', '--dump', + help = "dump flash to FILE", metavar = 'FILE') + parser.add_option ('-f', '--flash', + help = "flash from FILE", metavar = 'FILE') + parser.add_option ('-s', '--start', action = 'store_true', + help = "start application program") + parser.add_option ('-i', '--info', action = 'store_true', + help = "get page and flash size") + parser.add_option ('-t', '--tty', + help = "tty connected to dev2", metavar = 'TTY') + parser.add_option ('-a', '--address', type = 'int', default = 0xb8, + help = "define bootloader slave address", metavar = 'ADDR') + (options, extra) = parser.parse_args (args = args) + if extra: + parser.error ("extra unused arguments") + if options.tty is None: + parser.error ("no tty to open") + # Apply. + import serial + try: + s = serial.Serial (options.tty) + bl = Bootloader (options.address, s) + if options.info: + print bl.info () + if options.dump is not None: + f = open (options.dump, 'w') + f.write (dump (bl, progress = progress)) + f.close () + if options.flash is not None: + flash (bl, open (options.flash).read (), progress = progress) + if options.start: + bl.start () + except Exception, e: + import sys + print >> sys.stderr, e.message + sys.exit (1) + +if __name__ == '__main__': + command () -- cgit v1.2.3