X-Git-Url: http://git.rot13.org/?p=goodfet;a=blobdiff_plain;f=client%2FGoodFETARM.py;h=45ab3f91107edb012255e1f0ad530cff3365a72d;hp=33058203ed6e81d31132147bc14585e3cbae78bd;hb=f1115f89754a6482731b77cf2bf71bb7534f9a28;hpb=b7a6e00b7d75a7f29401c2aeeb2e19cbd622d678 diff --git a/client/GoodFETARM.py b/client/GoodFETARM.py index 3305820..45ab3f9 100644 --- a/client/GoodFETARM.py +++ b/client/GoodFETARM.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# GoodFET Client Library +# GoodFET ARM Client Library # # # Good luck with alpha / beta code. @@ -8,6 +8,16 @@ import sys, binascii, struct import atlasutils.smartprint as asp +from GoodFET import GoodFET +from intelhex import IntelHex + +platforms = { + "at91sam7": {0:(0x100000, "Flash before remap, SRAM after remap"), + 0x100000: (0x100000, "Internal Flash"), + 0x200000: (0x100000, "Internal SRAM"), + }, + } + #Global Commands READ = 0x00 @@ -40,10 +50,6 @@ RESUMECPU = 0x8d DEBUG_INSTR = 0x8e # STEP_INSTR = 0x8f # STEP_REPLACE = 0x90 # -READ_CODE_MEMORY = 0x91 # ?? -WRITE_FLASH_PAGE = 0x92 # ?? -READ_FLASH_PAGE = 0x93 # ?? -MASS_ERASE_FLASH = 0x94 # ?? PROGRAM_FLASH = 0x95 LOCKCHIP = 0x96 # ?? CHIP_ERASE = 0x97 # can do? @@ -54,23 +60,128 @@ GET_SPSR = 0x9a SET_SPSR = 0x9b SET_MODE_THUMB = 0x9c SET_MODE_ARM = 0x9d +SET_IR = 0x9e +WAIT_DBG = 0x9f +SHIFT_DR = 0xa0 +SETWATCH0 = 0xa1 +SETWATCH1 = 0xa2 -from GoodFET import GoodFET -from intelhex import IntelHex +PM_usr = 0b10000 +PM_fiq = 0b10001 +PM_irq = 0b10010 +PM_svc = 0b10011 +PM_abt = 0b10111 +PM_und = 0b11011 +PM_sys = 0b11111 +proc_modes = { + PM_usr: ("User Processor Mode", "usr", "Normal program execution mode"), + PM_fiq: ("FIQ Processor Mode", "fiq", "Supports a high-speed data transfer or channel process"), + PM_irq: ("IRQ Processor Mode", "irq", "Used for general-purpose interrupt handling"), + PM_svc: ("Supervisor Processor Mode", "svc", "A protected mode for the operating system"), + PM_irq: ("Abort Processor Mode", "irq", "Implements virtual memory and/or memory protection"), + PM_und: ("Undefined Processor Mode", "und", "Supports software emulation of hardware coprocessor"), + PM_sys: ("System Processor Mode", "sys", "Runs privileged operating system tasks (ARMv4 and above)"), +} + +PSR_bits = [ + None, + None, + None, + None, + None, + "Thumb", + "nFIQ_int", + "nIRQ_int", + "nImprDataAbort_int", + "BIGendian", + None, + None, + None, + None, + None, + None, + "GE_0", + "GE_1", + "GE_2", + "GE_3", + None, + None, + None, + None, + "Jazelle", + None, + None, + "Q (DSP-overflow)", + "oVerflow", + "Carry", + "Zero", + "Neg", + ] +ARM_INSTR_NOP = 0xe1a00000L +ARM_INSTR_BX_R0 = 0xe12fff10L +ARM_INSTR_STR_Rx_r14 = 0xe58f0000L # from atmel docs +ARM_READ_REG = ARM_INSTR_STR_Rx_r14 +ARM_INSTR_LDR_Rx_r14 = 0xe59f0000L # from atmel docs +ARM_WRITE_REG = ARM_INSTR_LDR_Rx_r14 +ARM_INSTR_LDR_R1_r0_4 = 0xe4901004L +ARM_READ_MEM = ARM_INSTR_LDR_R1_r0_4 +ARM_INSTR_STR_R1_r0_4 = 0xe4801004L +ARM_WRITE_MEM = ARM_INSTR_STR_R1_r0_4 +ARM_INSTR_MRS_R0_CPSR = 0xe10f0000L +ARM_INSTR_MSR_cpsr_cxsf_R0 =0xe12ff000L +ARM_INSTR_STMIA_R14_r0_rx = 0xE88E0000L # add up to 65k to indicate which registers... +ARM_STORE_MULTIPLE = ARM_INSTR_STMIA_R14_r0_rx +ARM_INSTR_SKANKREGS = 0xE88F7fffL +ARM_INSTR_CLOBBEREGS = 0xE89F7fffL +ARM_INSTR_B_PC = 0xea000000L +ARM_INSTR_BX_PC = 0xe1200010L # need to set r0 to the desired address +THUMB_INSTR_STR_R0_r0 = 0x60006000L +THUMB_INSTR_MOV_R0_PC = 0x46b846b8L +THUMB_INSTR_BX_PC = 0x47784778L +THUMB_INSTR_NOP = 0x1c001c00L +ARM_REG_PC = 15 + +ARM7TDMI_IR_EXTEST = 0x0 +ARM7TDMI_IR_SCAN_N = 0x2 +ARM7TDMI_IR_SAMPLE = 0x3 +ARM7TDMI_IR_RESTART = 0x4 +ARM7TDMI_IR_CLAMP = 0x5 +ARM7TDMI_IR_HIGHZ = 0x7 +ARM7TDMI_IR_CLAMPZ = 0x9 +ARM7TDMI_IR_INTEST = 0xC +ARM7TDMI_IR_IDCODE = 0xE +ARM7TDMI_IR_BYPASS = 0xF + + +def PSRdecode(psrval): + output = [ "(%s mode)"%proc_modes[psrval&0x1f][1] ] + for x in xrange(5,32): + if psrval & (1<>8)&0xff, (reg>>16)&0xff, reg>>24]) - self.writecmd(0x13,SET_REGISTERS,16*4,regarry) + for x in xrange(15): + if (1<>8)&0xff, (val>>16)&0xff, val>>24]) def ARMcmd(self,phrase): self.writecmd(0x13,READ,len(phrase),phrase) val=ord(self.data[0]) print "Got %02x" % val return val - def ARMdebuginstr(self,instr): - if type (instr) == int: + def ARMdebuginstr(self,instr,bkpt): + if type (instr) == int or type(instr) == long: instr = struct.pack(">8)&0xff,(data>>16)&0xff,(data>>24)&0xff]) + return self.data + def ARMwaitDBG(self, timeout=0xff): + self.writecmd(0x13,WAIT_DBG,2,[timeout&0xf,timeout>>8]) + return self.data + def ARMrestart(self): + self.ARMset_IR(ARM7TDMI_IR_RESTART) + def ARMset_watchpoint0(self, addr, addrmask, data, datamask, ctrl, ctrlmask): + self.data = [] + self.data.extend(chop(addr,4)) + self.data.extend(chop(addrmask,4)) + self.data.extend(chop(data,4)) + self.data.extend(chop(datamask,4)) + self.data.extend(chop(ctrl,4)) + self.data.extend(chop(ctrlmask,4)) + self.writecmd(0x13,SETWATCH0,24,self.data) + return self.data + def ARMset_watchpoint1(self, addr, addrmask, data, datamask, ctrl, ctrlmask): + self.data = [] + self.data.extend(chop(addr,4)) + self.data.extend(chop(addrmask,4)) + self.data.extend(chop(data,4)) + self.data.extend(chop(datamask,4)) + self.data.extend(chop(ctrl,4)) + self.data.extend(chop(ctrlmask,4)) + self.writecmd(0x13,SETWATCH1,24,self.data) + return self.data + def ARMreadMem(self, adr, wrdcount): + retval = [] + r0 = self.ARMget_register(0); # store R0 and R1 + r1 = self.ARMget_register(1); + print >>sys.stderr,("CPSR:\t%x"%self.ARMget_regCPSR()) + for word in range(adr, adr+(wrdcount*4), 4): + self.ARMset_register(0, word); # write address into R0 + self.ARM_nop(0) + self.ARM_nop(1) + self.ARMdebuginstr(ARM_READ_MEM, 0); # push LDR R1, [R0], #4 into instruction pipeline (autoincrements for consecutive reads) + self.ARM_nop(0) + self.ARMrestart() + self.ARMwaitDBG() + print self.ARMget_register(1) + + + # FIXME: this may end up changing te current debug-state. should we compare to current_dbgstate? + #print repr(self.data[4]) + if (len(self.data)>4 and self.data[4] == '\x00'): + print >>sys.stderr,("FAILED TO READ MEMORY/RE-ENTER DEBUG MODE") + raise Exception("FAILED TO READ MEMORY/RE-ENTER DEBUG MODE") + return (-1); + else: + retval.append( self.ARMget_register(1) ) # read memory value from R1 register + print >>sys.stderr,("CPSR: %x\t\tR0: %x\t\tR1: %x"%(self.ARMget_regCPSR(),self.ARMget_register(0),self.ARMget_register(1))) + self.ARMset_register(1, r1); # restore R0 and R1 + self.ARMset_register(0, r0); + return retval + + def ARMpeekcodewords(self,adr,words): """Read the contents of code memory at an address.""" self.data=[adr&0xff, (adr>>8)&0xff, (adr>>16)&0xff, (adr>>24)&0xff, words&0xff, (words>>8)&0xff, (words>>16)&0xff, (words>>24)&0xff ] - self.writecmd(0x13,PEEK,2,self.data) + self.writecmd(0x13,READ_CODE_MEMORY,8,self.data) retval = [] retval.append(self.serialport.read(words*4)) #retval = struct.unpack(">8, (adr&0xff0000)>>16, (adr&0xff000000)>>24] - self.writecmd(0x13, PEEK, 2, self.data) + self.data=[ adr&0xff, (adr>>8)&0xff, (adr>>16)&0xff, (adr>>24)&0xff ] + self.writecmd(0x13, PEEK, 4, self.data) + #retval.append(self.serialport.read(words*4)) retval = struct.unpack(">8, val] - self.writecmd(0x13, POKE, 3, self.data) + self.data=[adr&0xff, (adr>>8)&0xff, (adr>>16)&0xff, (adr>>24)&0xff, val&0xff, (val>>8)&0xff, (val>>16)&0xff, (val>>24)&0xff ] + self.writecmd(0x13, POKE, 8, self.data) retval = struct.unpack(">8)&0xFF, - (adr>>16)&0xFF, - (adr>>24)&0xFF] - print "Flashing buffer to 0x%06x" % adr - self.writecmd(0x13,MASS_FLASH_PAGE,4,data) + #def ARMstep_instr(self): + # """Step one instruction.""" + # self.writecmd(0x13,STEP_INSTR,0,self.data) + #def ARMflashpage(self,adr): + # """Flash 2kB a page of flash from 0xF000 in XDATA""" + # data=[adr&0xFF, + # (adr>>8)&0xFF, + # (adr>>16)&0xFF, + # (adr>>24)&0xFF] + # print "Flashing buffer to 0x%06x" % adr + # self.writecmd(0x13,MASS_FLASH_PAGE,4,data) def writecmd(self, app, verb, count=0, data=[]): """Write a command and some data to the GoodFET.""" @@ -305,3 +492,4 @@ class GoodFETARM(GoodFET): self.readcmd() +