def read_fuses(self, dev): """Reads the fuse and lock bits from the target and returns them as a named tuple.""" # set up constants buf = [ asm.ldi(29, RFLB | SPMEN), # ldi r29, RFLB | SPMEN asm.ldi(31, 0), # ldi r31, 0 ; (high byte of Z) ] # there are four bytes to read for index in reversed(range(4)): # read fuse/lock bit into r0 buf += [ asm.ldi(30, index), # ldi r31, index ; (low byte of Z) asm.out(dev.reg_spmcsr, 29), # out SPMCSR, r29 ; RFLB | SPMEN asm.lpm(), # lpm ] # move into another register if not reading index 0 if index != 0: buf += [ asm.mov(index, 0), # mov r[index], r0 ] # execute generated code self._exec(buf) # read r0-r3 which now contain the bytes that were read return Fuses(*self.read_regs(0, 4))
def write_flash_page(self, dev, start, data): if start % dev.flash_pagesize != 0: raise DWException("Bad page offset") if len(data) != dev.flash_pagesize: raise DWException("Bad page size") prof = (SimpleProfiler if self.enable_log else DummyProfiler)() prof.step("Starting page write") # set up constants in registers self.write_regs( 26, [ SPMEN, # r26 PGERS | SPMEN, # r27 PGWRT | SPMEN, # r28 CTPB | SPMEN, # r29 start & 0xff, (start >> 8) & 0xff # r30:r31(Z) ]) # clear self-programming buffer prof.step("Write constants") self._exec([ asm.movw(24, 30), # movw r24, r30 asm.out(dev.reg_spmcsr, 29), # out SPMCSR, r29 ; CTPB | SPMEN asm.spm() ]) # spm self.iface.send_break() prof.step("Clear buffer") # erase flash page self._exec([ asm.out(dev.reg_spmcsr, 27), # out SPMCSR, r27 ; PGERS | SPMEN asm.spm(), # spm ]) # wait for erase to complete self.iface.send_break() prof.step("Erase page") # write data to buffer # How many instruction bytes to write at once # The maximum suitable value for this is probably related to USB buffer sizes etc. CHUNK_LEN = 16 for ci in range(0, len(data), CHUNK_LEN): buf = [] for ii in range(ci, ci + CHUNK_LEN, 2): if dev.reg_dwdr: buf += [ asm.in_(dev.reg_dwdr, 0), bytes([data[ii]]), # in r0, DWDR ; (low byte) asm.in_(dev.reg_dwdr, 1), bytes([data[ii + 1]]) ] # in r1, DWDR ; (high byte) else: buf += [ asm.ldi(22, data[ii]), # ldi r22, (low byte) asm.ldi(23, data[ii + 1]), # ldi r23, (high byte) asm.movw(0, 22) ] # movw r0, r22 buf += [ asm.out(dev.reg_spmcsr, 26), # out SPMCSR, r26 ; SPMEN asm.spm(), # spm asm.adiw(30, 2) ] # adiw Z, 2 self._exec(buf) prof.step("Write data") # write buffer to flash self._exec([ asm.movw(30, 24), # movw r30, r24 asm.out(dev.reg_spmcsr, 28), # out SPMCSR, r28 ; PGWRT | SPMEN asm.spm() ]) # spm # wait for write to complete self.iface.send_break() prof.step("Write flash")
def write_flash_page(self, dev, start, data): if start % dev.flash_pagesize != 0: raise DWException("Bad page offset") if len(data) != dev.flash_pagesize: raise DWException("Bad page size") prof = (SimpleProfiler if self.enable_log else DummyProfiler)() prof.step("Starting page write") # set up constants in registers self.write_regs(26, [ SPMEN, # r26 PGERS | SPMEN, # r27 PGWRT | SPMEN, # r28 CTPB | SPMEN, # r29 start & 0xff, (start >> 8) & 0xff # r30:r31(Z) ]) # clear self-programming buffer prof.step("Write constants") self._exec([ asm.movw(24, 30), # movw r24, r30 asm.out(dev.reg_spmcsr, 29), # out SPMCSR, r29 ; CTPB | SPMEN asm.spm()]) # spm self.iface.send_break() prof.step("Clear buffer") # erase flash page self._exec([ asm.out(dev.reg_spmcsr, 27), # out SPMCSR, r27 ; PGERS | SPMEN asm.spm(), # spm ]) # wait for erase to complete self.iface.send_break() prof.step("Erase page") # write data to buffer # How many instruction bytes to write at once # The maximum suitable value for this is probably related to USB buffer sizes etc. CHUNK_LEN = 16 for ci in range(0, len(data), CHUNK_LEN): buf = [] for ii in range(ci, ci + CHUNK_LEN, 2): if dev.reg_dwdr: buf += [ asm.in_(dev.reg_dwdr, 0), bytes([data[ii]]), # in r0, DWDR ; (low byte) asm.in_(dev.reg_dwdr, 1), bytes([data[ii + 1]])] # in r1, DWDR ; (high byte) else: buf += [ asm.ldi(22, data[ii]), # ldi r22, (low byte) asm.ldi(23, data[ii + 1]), # ldi r23, (high byte) asm.movw(0, 22)] # movw r0, r22 buf += [ asm.out(dev.reg_spmcsr, 26), # out SPMCSR, r26 ; SPMEN asm.spm(), # spm asm.adiw(30, 2)] # adiw Z, 2 self._exec(buf) prof.step("Write data") # write buffer to flash self._exec([ asm.movw(30, 24), # movw r30, r24 asm.out(dev.reg_spmcsr, 28), # out SPMCSR, r28 ; PGWRT | SPMEN asm.spm()]) # spm # wait for write to complete self.iface.send_break() prof.step("Write flash")