All pastes #488265 Raw Edit

Anonymous

public python v1 · immutable
·published 2007-05-14 22:22 UTC
rendered paste body
#!/usr/bin/pythonimport serial,threading,Queue,struct,sys,arrayclass BotLoadIOException(Exception):    passclass TimeoutException(BotLoadIOException):    passclass ProtocolException(BotLoadIOException):    passclass StateException(BotLoadIOException):    passclass CommandQueue:    def __init__(self, serial):        self.serial = serial        self.cmdqueue = Queue.Queue()        self.error = None        self.errorFetched = False        self.finished = False        self.finishedFetched = False        self.abortRequested = False        self.discarded = 0        self.parentThread = threading.currentThread()        self.thread = threading.Thread(target=self._service_thread)        self.queueEmpty = threading.Event()        self.queueEmpty.set()        self.queueItems = 0        self.queueItemsLock = threading.Lock()    def _service_thread(self):        while self.error == None and not self.finished and not self.abortRequested and self.parentThread.isAlive():            try:                cmd, final = self.cmdqueue.get(True,0.4)                try:                    try:                        self._send_command(final, cmd)                        if final:                            self.finished = True                    except BotLoaderException,e:                        self.error = e                finally:                    self._updateQueueLength(-1)            except Queue.Empty:                try:                    self._send_command(False, "N")                except BotLoaderException,e:                    self.error = e        if self.abortRequested or not self.parentThread.isAlive():            return        while (self.error != None and self.errorFetched == False) or (self.finished and self.finishedFetched == False):            try:                self.cmdqueue.get(True,0.1)                self._updateQueueLength(-1)                self.discarded += 1            except Queue.Empty:                pass                    def _send_command(self, final, cmd):        self.serial.write(cmd)        if not final:            res = self.serial.read(1)            if len(res) != 1:                raise TimeoutException("Timeout in command '%s' (0x%02X)"%(cmd[0],ord(cmd[0])))            if res != "K":                if res == "!":                    raise ProtocolException("CRC Error in command '%s' (0x%02X)"%(cmd[0],ord(cmd[0])))                elif res == "?":                    raise ProtocolException("Unrecognized command '%s' (0x%02X)"%(cmd[0],ord(cmd[0])))                else:                    raise ProtocolException("Unknown error: %s (0x%02X) in command '%s' (0x%02X)"%(res,ord(res),cmd[0],ord(cmd[0])))    def _updateQueueLength(self, delta):        self.queueItemsLock.acquire()        self.queueItems += delta        if self.queueItems > 0:            self.queueEmpty.clear()        else:            self.queueEmpty.set()        self.queueItemsLock.release()            def start(self):        self.thread.start()    def sendCommand(self, cmd, final, blocking=True):        if blocking:            self.join()        if self.finishedFetched:            raise StateException("Dialog finished, no further commands allowed")        if self.errorFetched:            raise StateException("Errors occured, no further commands allowed")        self._updateQueueLength(1)        self.cmdqueue.put((cmd,final),True)        if blocking:            self.join()    def join(self):        self.queueEmpty.wait()        if self.error != None:            self.errorFetched = True            raise self.error        if self.finished == True:            self.finishedFetched = True    def finished(self):        return self.finishedFetched    def errorOccured(self):        return self.errorFetched    def abort(self):        self.abortRequested = True        self.thread.join()class BotLoaderInterface:    def __init__(self, port, retries=10):        self.retries = retries        if isinstance(port,serial.Serial):            self.serial = port        else:            self.serial = serial.Serial(port,115200,timeout=0.5)    def start(self,retries=None):        if retries == None:            retries = self.retries        rnum = 0        valid = False        picid = 0        try:            while rnum < retries:                sys.stdout.write("\x0dConnecting to bootloader (attempt %d of %d)..."%(rnum+1,retries))                sys.stdout.flush()                self.serial.write("BL")                res = self.serial.read(1000000)                if len(res) >= 3 and res[-1]=="K":                    valid = True                    picid = struct.unpack("<H",res[-3:-1])                    sys.stdout.write(" Connected, device is 0x%04X"%picid)                    break                rnum += 1        finally:            print        if not valid:            raise TimeoutException("Maximum retries reached while connecting to bootloader")        if picid != 0x1105:            raise ValueError("Unsupported PIC: %04X",picid)        self.serial.timeout = 0.5        self.queue = CommandQueue(self.serial)        self.queue.start()        self.picid = picid        return picid    def abort(self):        self.queue.abort()        self.serial.close()    def runUser(self):        self.queue.sendCommand("R", True)    def writeEEPROM(self, address, data):        if not 0x00 <= address <= 0xFF:            raise ValueError("EEPROM address out of range: 0x%X"%address)        if not 0x00 <= data <= 0xFF:            raise ValueError("EEPROM data out of range: %d"%data)        crc = (-(address+data))&0xFF        cmd = struct.pack("cBBB","E",address,data,crc)        self.queue.sendCommand(cmd, False)    def writeConfig(self, address, data):        if not 0x300000 <= address <= 0x30000F:            raise ValueError("CONFIG address out of range: 0x%X"%address)        if not 0x00 <= data <= 0xFF:            raise ValueError("CONFIG data out of range: %d"%data)        addu = (address>>16) & 0xFF        addh = (address>>8) & 0xFF        addl = address & 0xFF        crc = (-(addu+addh+addl+data))&0xFF        cmd = struct.pack("cBBBBB","C",addu,addh,addl,data,crc)        self.queue.sendCommand(cmd, False)    def writeFlash(self, address, data):        if not 0 <= address <= 0x7FC0:            raise ValueError("Flash address out of range: 0x%X"%address)        if address&0x40 != 0:            raise ValueError("Flash address not aligned: 0x%X"%address)        if len(data) != 0x40:            raise ValueError("Flash data length != 64: %d"%len(data))        for a,i in enumerate(data):            if not 0x00 <= i <= 0xFF:                raise ValueError("Flash data out of range: %d (address 0x%04X)"%(i,address+a))                addu = (address>>16) & 0xFF        addh = (address>>8) & 0xFF        addl = address & 0xFF        crc = (-(addu+addh+addl+sum(data)))&0xFF        cmd = struct.pack("cBBB","F",addu,addh,addl)        cmd += array.array("B",data+[crc]).tostring()        self.queue.sendCommand(cmd, False)