#!/usr/bin/python # # spreadspace pic utils # # # Copyright (C) 2011 Christian Pointner # # This file is part of spreadspace pic utils. # # spreadspace pic utils 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 3 of the License, or # any later version. # # spreadspace pic utils 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 spreadspace pic utils. If not, see . # '''spreadspace simple pic downloader.''' VERSION_MAJ = 0 VERSION_MIN = 1 ### HEX File Magic def load_hex(file): from intelhex import IntelHex fin = file if fin == '-': fin = sys.stdin elif not os.path.isfile(fin): print "ERROR: File not found: %s" % fin sys.exit(1) codedata = {} ih = IntelHex(fin) for a in ih.addresses(): if a/2 not in codedata.keys(): codedata[a/2] = 0 if a%2 == 0: codedata[a/2] += ih[a] else: codedata[a/2] += (ih[a] << 8) return codedata def get_lowest_flash_addr(codedata, fss): lowest_code_addr = sorted(codedata.keys())[0] return lowest_code_addr - (lowest_code_addr%fss) def get_highest_flash_addr(codedata, fss): highest_code_addr = sorted(codedata.keys())[-1] return highest_code_addr + (fss - highest_code_addr%fss) def create_flash_image(codedata, fss, sa, ea): img = ( sa, [0xFFFF]*(ea-sa) ) for a,d in codedata.items(): img[1][a-sa] = d return img def create_flash_segments(codedata, fss): sa = get_lowest_flash_addr(codedata, fss) ea = get_highest_flash_addr(codedata, fss) img = create_flash_image(codedata, fss, sa, ea) for i in xrange(0, ea, fss): slice = img[1][i:i+fss] if not all( (elem == 0xFFFF) for elem in slice): yield (i, slice) ### Interface to Bootloader def open_serial(device, baud): import os import tty import termios import serial print "opening %s (%s Baud)" % (device, baud) try: dev = serial.Serial(port=device, baudrate=baud, timeout=3) dev.flushInput() dev.flushOutput() return dev except (ValueError, serial.SerialException), msg: print "ERROR: opening serial device: %s" % msg sys.exit(3) def calc_csum(str): cs = 0 for c in str: cs ^= c return cs def exec_command(dev, cmd, param, answer): import struct return_codes = { 0: "OK", 1: "invalid command", 2: "bad checksum", 3: "not implemented", 4: "flash write error", 5: "address invalid", 6: "address prohibited", 7: "value out of bounds" } dev.flushInput() dev.flushOutput() cstr = bytearray(struct.pack(' 0: tmp = bytearray() tmp += dev.read(answer_len) if len(tmp) < answer_len: print "ERROR: timeout while reading response (expected %d bytes, got %d)" % (answer_len, len(tmp)) sys.exit(4) astr += tmp if 0 != calc_csum(astr): print "ERROR: checksum error" sys.exit(4) return struct.unpack_from(answer, astr, 3) ### Commands def identify(dev): data = exec_command(dev, 1, '', ' 1: raise getopt.GetoptError('Too many arguments') except getopt.GetoptError, msg: print "ERROR: %s" % msg print usage sys.exit(2) dev = open_serial(device, baudrate) codedata = load_hex(args[0]) id = identify(dev) # for segment in create_flash_segments(codedata, id['fss']): # print "%05X: %s" % (segment[0], ''.join('%04X'%i for i in segment[1]))