client.writecmd( PICAPP, 0x82, 3, [0x00,0x00,0x00] ) # NOP (pump clock)
return readVISI()
+def writereg( reg_num, word ):
+ """Write 16-bit word to a working register (i.e., W0, W1, ..., W15)."""
+ instr = 0x200000 + ((word&0xffff)<<4) + (reg_num&0xf)
+ client.writecmd( PICAPP, 0x82, 3, [instr & 0xff,
+ (instr >> 8) & 0xff,
+ (instr >> 16) & 0xff] )
+
def readVISI():
"""Read VISI register; assumes ICSP session already started."""
data = client.writecmd( PICAPP, 0x83, 0 )
runlist( rd_nvmcon_li )
return readVISI()
+def resetPC():
+ """Reset program counter during an active ISCP session."""
+ runlist( [0x040200, # GOTO 0x0200
+ 0x000000] )
+
def startICSP():
#print "Starting dsPIC33F/PIC24H ICSP session..."
data = client.writecmd( PICAPP, 0x84, 0 )
result = readVISI()
print "VISI: 0x%04X" % result
+def dump_pm( start_addr, stop_addr, pretty=False ):
+ """Dump routine, now encapsulated in a function.
+Returns an instance of IntelHex corresponding to result.
+
+Note that we start and stop an ICSP session here! This means an
+existing session will be broken."""
+ 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()
+
+ startICSP()
+
+ print "Reading program memory 0x%06X:0x%06X ..." % ( start_addr, stop_addr )
+ # Prep device
+ 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)
+
+ 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:] )
+
+ 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 pretty:
+ print "0x%06X 0x%06X" % (addr+offset*2,instr_list[offset])
+
+ stopICSP()
+
+ return dumphex
+
+
def instr2words( instr_list ):
"""Convert a list of 4 24-bit instructions to a list of 6 words
(16-bit width).
elif sys.argv[1] == "config": # Dump configuration registers
prep_cmd_li = [0x040200, # GOTO 0x0200
- 0x040200, # GOTO 0x0200
- 0x000000, # NOP
+ 0x000000, #
0x200F80, # MOV #0x00F8, W0
0x880190, # MOV W0, TBLPAG
0xEB0300, # CLR W6
result = readVISI()
addr = 0xF80000+k*2
if cfg_table.has_key( addr ):
- print "0x%06X (%s): 0x%04X" % ( addr,
+ print "0x%06X (%s): 0x%02X" % ( addr,
cfg_table[addr].ljust(cfg_table["width"]),
result )
else:
- print "0x%06X: 0x%04X" % ( addr, result )
+ print "0x%06X: 0x%02X" % ( addr, result )
stopICSP()
except IOError:
print "Error while attempting to read from %s" % sys.argv[2]
exit(-1)
+ ph_addrs = proghex.addresses()
+
+ # Load starting program memory address
+ wr_pm64_li_setaddr = [0x040200, # GOTO 0x0200
+ 0x000000, #
+ 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
+
+ # Load 4 instructions into write latches
+ wr_pm64_li_wrlat = [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
- wr_pm_li = [0x040200, # GOTO 0x0200
- 0x040200, # GOTO 0x0200
- 0x000000, # NOP
-
- 0x24003A, # MOV $0x4003, 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 instruction into registers W0:W1
- 0x200000,# + ((new_words[0]&0xffff)<<4),
- 0x200001,# + ((new_words[1]&0xffff)<<4),
-
- 0xEB0300, # CLR W6
- 0x000000, # NOP
- 0xBB0BB6, # TBLWTL [W6++], [W7]
- 0x000000, # NOP
- 0x000000, # NOP
- 0xBBDBB6, # TBLWTH.B [W6++], [W7++]
- 0x000000, # NOP
- 0x000000, # NOP
-
- 0xA8E761, # BSET NVMCON, #WR
- 0x000000, # NOP
- 0x000000, # NOP
- 0x000000, # NOP
- 0x000000] # NOP
-
+ wr_pm64_li_wr = [0xA8E761, # BSET NVMCON, #WR
+ 0x000000, # NOP
+ 0x000000, # NOP
+ 0x000000, # NOP
+ 0x000000] # NOP
+
startICSP()
-
- 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:
- 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 )
+
+ for last_code_addr in reversed(ph_addrs):
+ if (last_code_addr>>1) < 0xf80000:
+ last_row_addr = (last_code_addr>>1) & 0xffff80
+ break
+ for addr in range((ph_addrs[0]>>1)&0xffff80,last_code_addr+2,128):
+ # Prevent crossing addresses where upper byte
+ # (i.e., address<23:16>) changes.
+ #if addr+126 > 0xffff:
+ # stop_addr = addr | 0xffff
+ #else:
+ # stop_addr = addr+126
+
+ runlist( wr_pm64_li_setaddr[:4]
+ + [0x200000 + ((addr>>12)&0xff0),
+ wr_pm64_li_setaddr[5],
+ 0x200007 + ((addr&0xffff)<<4)] )
+
+ instr_list = [0,0,0,0]
+ for mid_addr in range(addr,addr+126,8):
+ for offset in range(4):
+ if (mid_addr+offset*2)<<1 not in ph_addrs:
+ instr_list[offset] = 0xffffff
+ else:
+ instr_list[offset] = proghex[(mid_addr+offset*2)<<1]
+ instr_list[offset] |= proghex[((mid_addr+offset*2)<<1)+1] << 8
+ instr_list[offset] |= proghex[((mid_addr+offset*2)<<1)+2] << 16
+ packed_instr_list = instr2words( instr_list )
+ runlist( [0x200000 + ((packed_instr_list[0]&0xffff)<<4),
+ 0x200001 + ((packed_instr_list[1]&0xffff)<<4),
+ 0x200002 + ((packed_instr_list[2]&0xffff)<<4),
+ 0x200003 + ((packed_instr_list[3]&0xffff)<<4),
+ 0x200004 + ((packed_instr_list[4]&0xffff)<<4),
+ 0x200005 + ((packed_instr_list[5]&0xffff)<<4)]
+ + wr_pm64_li_wrlat )
+
+ runlist( wr_pm64_li_wr )
+ status = readNVMCON()
+ while status & 0x8000:
+ client.writecmd( PICAPP, 0x82, 3, [0x00,0x00,0x00] )
status = readNVMCON()
- while status & 0x8000:
- client.writecmd( PICAPP, 0x82, 3, [0x00,0x00,0x00] )
- status = readNVMCON()
- continue
- # 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
-
- # Program this instruction word
- addr_highb_cmd = 0x200000 + ((addr_pm>>12)&0xff0)
- addr_loww_cmd = 0x200007 + ((addr_pm&0xffff)<<4)
- instr_loww_cmd = 0x200000 + ((instr&0xffff)<<4)
- instr_highb_cmd = 0x200001 + ((instr>>12)&0xff0)
- runlist( wr_pm_li[:5] + [addr_highb_cmd] + [wr_pm_li[6]]
- + [addr_loww_cmd,
- instr_loww_cmd, instr_highb_cmd]
- + wr_pm_li[10:] )
+ # Configuration registers must be treated separately
+ for addr in ph_addrs[ph_addrs.index(last_code_addr):]:
+ if addr%4 != 0:
+ continue
+ if (addr>>1) > 0xf80017:
+ break
+ wr_cfg_li = [0x040200, # GOTO 0x0200
+ 0x000000, #
+ 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] )
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:
+ if addr % 4 != 0 or (addr>>1) < 0x200:
continue
+ #elif first_addr == None:
+ # first_addr = addr>>1
+ if (addr>>1) >= 0xf80000:
+ break
+ last_addr = addr>>1
+ dumphex = dump_pm( (proghex.addresses()[0]>>1),
+ last_addr )
- # 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
-
+ # Step through addresses in HEX file and compare to those in target PIC
+ for addr in proghex.addresses():
+ if addr>>1 >= 0xF80000:
+ break # verifying config registers not yet supported
# Compare; fail if mismatch
- if instr != result:
- print "Fail at address 0x%06X: found 0x%06X, expected 0x%06X." % (addr_pm, result, instr )
- stopICSP()
+ if proghex[addr] != dumphex[addr]:
+ addr &= addr&0xfffffffc
+ found_instr = dumphex[addr]
+ found_instr |= dumphex[addr+1]<<8
+ found_instr |= dumphex[addr+2]<<16
+ exp_instr = proghex[addr]
+ exp_instr |= proghex[addr+1]<<8
+ exp_instr |= proghex[addr+2]<<16
+ print "Fail at address 0x%06X: found 0x%06X, expected 0x%06X." % ( addr>>1, found_instr, exp_instr )
exit(-1)
- stopICSP()
-
print "PASSED" # Be verbose.
#new_words = instr2words( new_instr_li )
wr_pm_li = [0x040200, # GOTO 0x0200
- 0x040200, # GOTO 0x0200
- 0x000000, # NOP
+ 0x000000, #
0x24003A, # MOV $0x4003, W10
0x883B0A, # MOV W10, NVMCON
reg_addr = cfg_table.keys()[cfg_table.values().index(sys.argv[2])]
wr_cfg_li = [0x040200, # GOTO 0x0200
- 0x040200, # GOTO 0x0200
- 0x000000, # NOP
+ 0x000000, #
0x200007 + ((reg_addr&0xffff)<<4), # MOV #addr<15:0>, W7
0x24000A, # MOV #0x4000, W10
0x883B0A, # MOV W10, NVMCON
addr = int(float.fromhex(sys.argv[2]))
readpm_cmd_li = [0x040200, # GOTO 0x0200
- 0x040200, # GOTO 0x0200
- 0x000000, # NOP
+ 0x000000, #
0x200000+((addr & 0xff0000)>>12), # MOV #addr<23:16>, W0
0x880190, # MOV W0, TBLPAG
0x200006+((addr & 0xffff)<<4), # MOV #addr<15:0>, W6
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
- 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()
-
- startICSP()
-
- print "Reading program memory 0x%06X:0x%06X ..." % ( start_addr, stop_addr )
- # Prep device
- 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)
-
- 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:] )
-
- 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])
-
+ dumphex = dump_pm( start_addr, stop_addr, print_term )
+
if not print_term:
if fname == "-":
dumphex.tofile( sys.stdout, format="hex" )
else:
dumphex.tofile( fname, format="hex" )
- stopICSP()
elif sys.argv[1] == "erase": # Bulk (all program memory) or page erase
if addr is None: # Bulk erase (all of program memory)
erase_cmd_li = [0x040200, # GOTO 0x0200
- 0x040200, # GOTO 0x0200
- 0x000000, # NOP
+ 0x000000, #
0x2404FA, # MOV $0x404F, W10
0x883B0A, # MOV W10, NVMCON
0xA8E761, # BSET NVMCON, #WR
else: # Page erase
print "Erasing page of 0x%06X" % addr
erase_cmd_li = [0x040200, # GOTO 0x0200
- 0x040200, # GOTO 0x0200
- 0x000000, # NOP
+ 0x000000, #
0x24042A, # MOV $0x4042, W10
0x883B0A, # MOV W10, NVMCON
0x200000+((addr & 0xff0000)>>12), # MOV #addr<23:16>, W0