X-Git-Url: http://git.rot13.org/?p=goodfet;a=blobdiff_plain;f=client%2Fgoodfet.pic;h=5158912f6f12b833adb8ca4fdda58d5d379c4db4;hp=66f08a1d8355de3fb2f4d1433dcaf324c32d5ad7;hb=1f8e984b38e60a3b2aa0609864f05250cc8df673;hpb=dbcedaa279472080a2585e959a3146f3c5859556 diff --git a/client/goodfet.pic b/client/goodfet.pic index 66f08a1..5158912 100755 --- a/client/goodfet.pic +++ b/client/goodfet.pic @@ -1,12 +1,19 @@ #!/usr/bin/env python # PIC client (currently only supports dsPIC33F/PIC24H.) # +# Note that a verify operation only considers addresses specified in +# the given Intel hex file ($foo.hex). +# +# sixfile expects a plain text file, one instruction per line. +# +# # Scott Livingston # # March, April 2010. import sys +import time from GoodFET import GoodFET from intelhex import IntelHex @@ -33,6 +40,8 @@ cfg_table = { 0xF80000 : "FBS", 0xF80016 : "FUID3", "width" : 7 } # For pretty printing. +#cfg_bitmask_table = { + ############# # Functions: @@ -139,21 +148,22 @@ Returns [-1] on failure.""" ############# if len(sys.argv) == 1: - print "Usage: %s verb [objects]" % sys.argv[0] - print "Warning: only supports dsPIC33F/PIC24H (maybe)...\n" + print "Usage: %s verb [objects]\n" % sys.argv[0] print "%s devid" % sys.argv[0] print "%s read 0x$addr" % sys.argv[0] print "%s dump $foo.hex [0x$start 0x$stop] [pretty]" % sys.argv[0] print "%s config" % sys.argv[0] print "%s program $foo.hex" % sys.argv[0] - print "%s write $0xADDRESS $0xVALUE" % sys.argv[0] - print "%s write_config $REG_NAME [$0x0000]" % sys.argv[0] + print "%s verify $foo.hex" % sys.argv[0] + print "%s write 0x$address 0x$value" % sys.argv[0] + print "%s write_config 0x$reg_address (or $reg_name) [$0x0000]" % sys.argv[0] print "%s erase [0x$page]" % sys.argv[0] # bulk or page erase print "%s six [instruction]" % sys.argv[0] - print "%s sixfile [foo.txt] (NOTE: plaintext, one instruction per line.)" % sys.argv[0] + print "%s sixfile [$foo.txt]" % sys.argv[0] print "%s regout" % sys.argv[0] print """ Note: use - for stdout. +Warning: only supports dsPIC33F/PIC24H (maybe)... """ sys.exit() @@ -190,8 +200,6 @@ if sys.argv[1] == "devid": #0x81 #print "\n(Note that -1 indicates failure to read a value.)" elif sys.argv[1] == "config": # Dump configuration registers - startICSP() - prep_cmd_li = [0x040200, # GOTO 0x0200 0x040200, # GOTO 0x0200 0x000000, # NOP @@ -203,6 +211,7 @@ elif sys.argv[1] == "config": # Dump configuration registers rd_cmd_li = [0xBA0BB6, # TBLRDL [W6++], [W7] 0x000000, # NOP 0x000000] # NOP + startICSP() print "Dumping configuration registers..." for instr in prep_cmd_li: data = client.writecmd( PICAPP, 0x82, 3, [instr & 0xff, @@ -321,122 +330,76 @@ elif sys.argv[1] == "program": status = readNVMCON() stopICSP() - exit(0) - - - ##################### - # TESTING - # Generic code to write 4 instruction words to program memory. - # This is filled in as we step through given code values to write. - # Remainder (of total number of instruction words divided by 64) - # is then handled specially. - # - # Note that we do not erase flash memory before programming here! - # The user must do so herself. - wr_pm64_li = [0x040200, # GOTO 0x0200 - 0x040200, # GOTO 0x0200 - 0x000000, # NOP - - 0x24001A, # MOV $0x4001, W10 - 0x883B0A, # MOV W10, NVMCON - - 0x200000,# + ((addr>>12)&0xff0), # MOV #addr<23:16>, W0 - 0x880190, # MOV W0, TBLPAG - 0x200007,# + ((addr&0xffff)<<4), # MOV #addr<15:0>, W7 - - # Here we load the 4 instructions into registers W0:W5 - 0x200000,# + ((new_words[0]&0xffff)<<4), - 0x200001,# + ((new_words[1]&0xffff)<<4), - 0x200002,# + ((new_words[2]&0xffff)<<4), - 0x200003,# + ((new_words[3]&0xffff)<<4), - 0x200004,# + ((new_words[4]&0xffff)<<4), - 0x200005,# + ((new_words[5]&0xffff)<<4), - - 0xEB0300, # CLR W6 - 0x000000, # NOP - 0xBB0BB6, # TBLWTL [W6++], [W7] - 0x000000, # NOP - 0x000000, # NOP - 0xBBDBB6, # TBLWTH.B [W6++], [W7++] - 0x000000, # NOP - 0x000000, # NOP - 0xBBEBB6, # TBLWTH.B [W6++], [++W7] - 0x000000, # NOP - 0x000000, # NOP - 0xBB1BB6, # TBLWTL [W6++], [W7++] - 0x000000, # NOP - 0x000000, # NOP - 0xBB0BB6, # TBLWTL [W6++], [W7] - 0x000000, # NOP - 0x000000, # NOP - 0xBBDBB6, # TBLWTH.B [W6++], [W7++] - 0x000000, # NOP - 0x000000, # NOP - 0xBBEBB6, # TBLWTH.B [W6++], [++W7] - 0x000000, # NOP - 0x000000, # NOP - 0xBB1BB6, # TBLWTL [W6++], [W7++] - 0x000000, # NOP - 0x000000, # NOP - - 0xA8E761, # BSET NVMCON, #WR - 0x000000, # NOP - 0x000000, # NOP - 0x000000, # NOP - 0x000000] # NOP - ph_addrs = proghex.addresses() - for r in range(len(ph_addrs)): # Find last non-configuration register address - if ph_addrs[len(ph_addrs)-r-1]/2 < 0xF80000: - break - - for addr in range(0,ph_addrs[len(ph_addrs)-r-1]/2+128,128): - addr_highb_cmd = 0x200000 + ((addr>>12)&0xff0) - addr_loww_cmd = 0x200007 + ((addr&0xffff)<<4) - instr_li = [] - for k in range(4): - instr_li.append( proghex[addr*2+k*4] ) - instr_li[-1] |= proghex[addr*2+k*4+1] << 8 - instr_li[-1] |= proghex[addr*2+k*4+2] << 16 - packed_instr_li = instr2words( instr_li ) - words_cmd = [0x200000+k+((packed_instr_li[k]&0xffff)<<4) for k in range(6)] - runlist( wr_pm64_li[:5] + [addr_highb_cmd] + [wr_pm64_li[6]] - + [addr_loww_cmd] + words_cmd - + wr_pm64_li[14:] ) - status = readNVMCON() - while status & 0x8000: - client.writecmd( PICAPP, 0x82, 3, [0x00,0x00,0x00] ) - status = readNVMCON() - if r > 0: - for addr in ph_addrs[len(ph_addrs)-r:]: - if addr % 4 != 0: - continue - print "0x%06X <-- 0x%06X" % (addr/2, proghex[addr]) - wr_cfg_li = [0x040200, # GOTO 0x0200 - 0x040200, # GOTO 0x0200 - 0x000000, # NOP - 0x200007 + ((addr<<3)&0xffff0), # MOV #addr<15:0>, W7 - 0x24000A, # MOV #0x4000, W10 - 0x883B0A, # MOV W10, NVMCON - 0x200F80, # MOV #0xF8, W0 - 0x880190, # MOV W0, TBLPAG - 0x200000 + ((proghex[addr]&0x00ff)<<4), # MOV #new_val<7:0>, W0 - 0xBB0B80, # TBLWTL W0, [W7] - 0x000000, # NOP - 0x000000, # NOP - 0xA8E761, # BSET NVMCON, #WR - 0x000000, # NOP - 0x000000, # NOP - 0x000000, # NOP - 0x000000] # NOP - runlist( wr_cfg_li ) - status = readNVMCON() - while status & 0x8000: - client.writecmd( PICAPP, 0x82, 3, [0x00,0x00,0x00] ) - status = readNVMCON() + + +elif sys.argv[1] == "verify": + if len(sys.argv) != 3: + print "Error: an Intel HEX file with which to compare must be given." + exit(1) + + try: + proghex = IntelHex( sys.argv[2] ) + except IOError: + print "Error while attempting to read from %s" % sys.argv[2] + exit(-1) + + readpm_cmd_li = [0x040200, # GOTO 0x0200 + 0x040200, # GOTO 0x0200 + 0x000000, # NOP + 0x200000, # MOV #addr_pm<23:16>, W0 + 0x880190, # MOV W0, TBLPAG + 0x200006, # MOV #addr_pm<15:0>, W6 + 0xEB0380, # CLR W7 + 0xEB0080, # CLR W1 + 0x000000, # NOP + 0xBA1B96, # TBLRDL [W6], [W7++] + 0x000000, # NOP + 0x000000, # NOP + 0xBACB96, # TBLRDH.B [W6], [W7] + 0x000000, # NOP + 0x000000] # NOP + + print "WARNING: verifying config registers not yet supported." + + startICSP() + + # Step through addresses in HEX file and compare to those in target PIC + for addr in proghex.addresses(): + # Ignore non-aligned steps + if addr % 4 != 0: + continue + + # Configuration registers must be treated separately + if (addr>>1) >= 0xf80000 and (addr>>1) <= 0xf80017: + # Need to read datasheets to see which bits are masked. + # Then add dictionary to handle this. + # (Straightforward but tedious.) + continue + else: + # Build instruction from 3 separate bytes + instr = proghex[addr] + instr |= proghex[addr+1] << 8 + instr |= proghex[addr+2] << 16 + + # Change HEX file address to actual program memory address + addr_pm = addr >> 1 + + runlist( readpm_cmd_li[:3] + [readpm_cmd_li[3]+((addr_pm&0xff0000)>>12)] + + [readpm_cmd_li[4]] + [readpm_cmd_li[5]+((addr_pm&0xffff)<<4)] + + readpm_cmd_li[6:] ) + loww = readreg(0) # Read W0, which has lower 16 bits + highb = readreg(1) # Read W1, which has high 8 bits + result = (highb<<16) | loww + + # Compare; fail if mismatch + if instr != result: + print "Fail at address 0x%06X: found 0x%06X, expected 0x%06X." % (addr_pm, result, instr ) + stopICSP() + exit(-1) stopICSP() - exit(0) -##################### + + print "PASSED" # Be verbose. elif sys.argv[1] == "write": @@ -524,10 +487,13 @@ elif sys.argv[1] == "write_config": new_val = 0xFF # Assume new value else: new_val = int(float.fromhex(sys.argv[3])) - if sys.argv[2] not in cfg_table.values(): - print "Given register, %s, not recognized." % sys.argv[2] - exit(1) - reg_addr = cfg_table.keys()[cfg_table.values().index(sys.argv[2])] + try: + reg_addr = int(float.fromhex(sys.argv[2])) + except ValueError: + if sys.argv[2] not in cfg_table.values(): + print "Given register, %s, not recognized." % sys.argv[2] + exit(1) + reg_addr = cfg_table.keys()[cfg_table.values().index(sys.argv[2])] wr_cfg_li = [0x040200, # GOTO 0x0200 0x040200, # GOTO 0x0200 @@ -606,20 +572,37 @@ elif sys.argv[1] == "dump": # Read section of program memory # Assume all of program memory (including unimplemented sections, # which will be read as zeroes. start_addr = 0x0 - stop_addr = 0xFFFFFE # - - readpm_cmd_li = [0x200000, # MOV #addr<23:16>, W0 - 0x880190, # MOV W0, TBLPAG - 0x200006, # MOV #addr<15:0>, W6 - 0xEB0380, # CLR W7 - 0xEB0080, # CLR W1 - 0x000000, # NOP - 0xBA1B96, # TBLRDL [W6], [W7++] - 0x000000, # NOP - 0x000000, # NOP - 0xBACB96, # TBLRDH.B [W6], [W7] - 0x000000, # NOP - 0x000000] # NOP + stop_addr = 0xFFFFFE + + readpm_cmd_li = [0x200000, # MOV #addr<23:16>, W0 + 0x880190, # MOV W0, TBLPAG + 0x200006, # MOV #addr<15:0>, W6 + 0xEB0380, # CLR W7 + 0x000000, # NOP + 0xBA1B96, # TBLRDL [W6], [W7++] + 0x000000, # NOP + 0x000000, # NOP + 0xBADBB6, # TBLRDH.B [W6++], [W7++] + 0x000000, # NOP + 0x000000, # NOP + 0xBADBD6, # TBLRDH.B [++W6], [W7++] + 0x000000, # NOP + 0x000000, # NOP + 0xBA1BB6, # TBLRDL [W6++], [W7++] + 0x000000, # NOP + 0x000000, # NOP + 0xBA1B96, # TBLRDL [W6], [W7++] + 0x000000, # NOP + 0x000000, # NOP + 0xBADBB6, # TBLRDH.B [W6++], [W7++] + 0x000000, # NOP + 0x000000, # NOP + 0xBADBD6, # TBLRDH.B [++W6], [W7++] + 0x000000, # NOP + 0x000000, # NOP + 0xBA0BB6, # TBLRDL [W6++], [W7] + 0x000000, # NOP + 0x000000] # NOP dumphex = IntelHex() @@ -630,18 +613,35 @@ elif sys.argv[1] == "dump": # Read section of program memory client.writecmd( PICAPP, 0x82, 3, [0x00,0x02,0x04] ) #GOTO 0x200 (reset) client.writecmd( PICAPP, 0x82, 3, [0x00,0x02,0x04] ) #GOTO 0x200 (reset) client.writecmd( PICAPP, 0x82, 3, [0x00,0x00,0x00] ) #NOP (pump clock) - for addr in range( start_addr, stop_addr+2, 2 ): - specify_addr_cmd = [readpm_cmd_li[0] + ((addr & 0xff0000)>>12), - readpm_cmd_li[1], - readpm_cmd_li[2] + ((addr & 0xffff)<<4)] + + last_highb = -1 # Only set TBLPAG when needed. + packed_instr_list = [0,0,0,0,0,0] # For packing 4 (24-bit) instructions in 6 (16-bit) words + for addr in range( start_addr&0xfffff8, stop_addr+8, 8 ): + if (addr>>16)&0xff != last_highb: + last_highb = (addr>>16)&0xff; + specify_addr_cmd = [readpm_cmd_li[0] + ((addr & 0xff0000)>>12), + readpm_cmd_li[1], + readpm_cmd_li[2] + ((addr & 0xffff)<<4)] + else: + specify_addr_cmd = [readpm_cmd_li[2] + ((addr & 0xffff)<<4)] runlist( specify_addr_cmd + readpm_cmd_li[3:] ) - loww = readreg(0) # Read W0, which has lower 16 bits - highb = readreg(1) # Read W1, which has high 8 bits - result = (highb<<16) | loww - dumphex.puts( (addr&0xffffff)*2, - chr(result&0xff)+chr((result>>8)&0xff)+chr((result>>16)&0xff)+chr(0) ) - if print_term: - print "0x%06X 0x%06X" % (addr,result) + + for reg_num in range(6): # Read W0:5, to get packed instructions + packed_instr_list[reg_num] = readreg( reg_num ) + instr_list = words2instr( packed_instr_list ) + + for offset in range(4): # Print result + if addr+offset*2 < start_addr: + continue + if addr+offset*2 > stop_addr: + break + dumphex.puts( ((addr+offset*2)&0xffffff)*2, + chr(instr_list[offset]&0xff) + +chr((instr_list[offset]>>8)&0xff) + +chr((instr_list[offset]>>16)&0xff) + +chr(0) ) + if print_term: + print "0x%06X 0x%06X" % (addr+offset*2,instr_list[offset]) if not print_term: if fname == "-": @@ -651,7 +651,7 @@ elif sys.argv[1] == "dump": # Read section of program memory stopICSP() -elif sys.argv[1] == "erase": # Bulk erase (all program memory) +elif sys.argv[1] == "erase": # Bulk (all program memory) or page erase if len(sys.argv) == 3: addr = int(float.fromhex(sys.argv[2])) @@ -670,6 +670,7 @@ elif sys.argv[1] == "erase": # Bulk erase (all program memory) 0x000000, # NOP 0x000000] # NOP else: # Page erase + print "Erasing page of 0x%06X" % addr erase_cmd_li = [0x040200, # GOTO 0x0200 0x040200, # GOTO 0x0200 0x000000, # NOP @@ -677,7 +678,7 @@ elif sys.argv[1] == "erase": # Bulk erase (all program memory) 0x883B0A, # MOV W10, NVMCON 0x200000+((addr & 0xff0000)>>12), # MOV #addr<23:16>, W0 0x880190, # MOV W0, TBLPAG - 0x200001+((addr&0xffff)<<4), # MOV 0x0, W1 + 0x200001+((addr&0xffff)<<4), # MOV addr<15:0>, W1 0x000000, # NOP 0xBB0881, # TBLTWL W1, [W1] 0x000000, # NOP