Preliminary support for PIC24F chips with tblpag at an odd address; finally updated...
[goodfet] / client / goodfet.pic
index 4250635..40de634 100755 (executable)
@@ -9,7 +9,7 @@
 #
 # Scott Livingston  <slivingston at caltech.edu>
 #
-# March, April 2010.
+# March-June 2010.
 
 
 import sys
@@ -24,8 +24,54 @@ from intelhex import IntelHex
 PICAPP = 0x34
 MONITORAPP = 0x00
 NOK = 0x7E
+
+VERB_CMDLIST = 0x88
+
+# 0x32 is the normal address of the TBLPAG register. On some PICs,
+# though, it appears at 0x54 (see DS39970B). Affected PIC families
+# include: PIC24FJxxx{DA1,DA2,GB2,GA3}xx
+tblpag = 0x32
+
 dev_table = { 0x00EE : "dsPIC33FJ128GP708",
-              0x00EF : "dsPIC33FJ128GP710" }
+              0x00EF : "dsPIC33FJ128GP710",
+              0x080A : "PIC24HJ12GP201",
+              0x080B : "PIC24HJ12GP202",
+              0x0444 : "PIC24FJ16GA002",
+              0x044C : "PIC24FJ16GA004",
+              0x0445 : "PIC24FJ32GA002",
+              0x044D : "PIC24FJ32GA004",
+              0x0446 : "PIC24FJ48GA002",
+              0x044E : "PIC24FJ48GA004",
+              0x0447 : "PIC24FJ64GA002",
+              0x044F : "PIC24FJ64GA004",
+              0x0405 : "PIC24FJ64GA006",
+              0x0408 : "PIC24FJ64GA008",
+              0x040B : "PIC24FJ64GA010",
+              0x0406 : "PIC24FJ96GA006",
+              0x0409 : "PIC24FJ96GA008",
+              0x040C : "PIC24FJ96GA010",
+              0x0407 : "PIC24FJ128GA006",
+              0x040A : "PIC24FJ128GA008",
+              0x040D : "PIC24FJ128GA010",
+              0x4109 : "PIC24FJ128DA106",
+              0x410D : "PIC24FJ256DA106",
+              0x410B : "PIC24FJ128DA110",
+              0x410F : "PIC24FJ256DA110",
+              0x4108 : "PIC24FJ128DA206",
+              0x410C : "PIC24FJ256DA206",
+              0x410A : "PIC24FJ128DA210",
+              0x410E : "PIC24FJ256DA210",
+              0x46C0 : "PIC24FJ64GA306",
+              0x46C4 : "PIC24FJ64GA308",
+              0x46C8 : "PIC24FJ64GA310",
+              0x46C2 : "PIC24FJ128GA306",
+              0x46C6 : "PIC24FJ128GA308",
+              0x46CA : "PIC24FJ128GA310",
+              0x4100 : "PIC24FJ128GB206",
+              0x4104 : "PIC24FJ256GB206",
+              0x4102 : "PIC24FJ128GB210",
+              0x4106 : "PIC24FJ256GB210",
+              }
 cfg_table = { 0xF80000 : "FBS",
               0xF80002 : "FSS",
               0xF80004 : "FGS",
@@ -61,6 +107,84 @@ Assumes ICSP session already started."""
         stopICSP()
         exit(-1)
 
+class PicResponseThunk(object):
+    """A holder for a response value from the PIC, eg from a REGOUT
+    command.
+
+    To retrieve the value, simply call the object. If the value has
+    not yet been retrieved, any pending commands in the command buffer
+    will be executed. You can determine whether the response has been
+    recieved by calling the have_response function.
+    
+    Objects of this class should only be created by the PicCmdBuffer
+    class"""
+
+    def __init__(self, cmdbuf):
+        self.holder = cmdbuf
+        self.value = None
+
+    def _set_value(self, value):
+        self.value = value
+    def have_response(self):
+        return self.value is not None
+    def __call__(self):
+        if self.value is None:
+            self.holder.force()
+        assert self.value is not None
+        return self.value
+
+class PicCmdBuffer(object):
+    def __init__(self, client):
+        self.client = client
+        self.buffered_commands = []
+        self.response_buffer = []
+        data = client.writecmd(MONITORAPP, 0xc2)
+        assert data is not None and len(data) is 2
+        # buffer size is the size of the goodfet's recieve buffer, in
+        # instructions
+        self.buffer_size = (ord(data[0]) + (ord(data[1]) << 8)) >> 2
+    def force(self):
+        assert len(self.buffered_commands) <= self.buffer_size
+        command = ''.join(self.buffered_commands)
+        self.buffered_commands = []
+        #print "Running: " + command.encode('hex')
+        data = self.client.writecmd(PICAPP, VERB_CMDLIST,
+                                    len(command), map(ord, command))
+        #print "Recieved: " + data.encode('hex')
+        assert len(data) == (len(self.response_buffer) + 1) * 2
+        orig_data = data
+        checksum = 0
+        for resp in self.response_buffer:
+            wd, data = data[0:2],data[2:]
+            val = ord(wd[0]) + (ord(wd[1]) << 8)
+            checksum += val
+            resp._set_value(val)
+        assert len(data) == 2
+        checksum += ord(data[0]) + (ord(data[1]) << 8)
+        checksum &= 0xffff
+        assert checksum == 0
+        self.response_buffer = []
+    def _add_command(self, command, data):
+        assert command in (0,1)
+        assert (data >> 24) == 0
+        full_cmd = [chr(command)]
+        for i in (0,1,2):
+            full_cmd.append(chr((data >> (8*i)) & 0xff))
+        if len(self.buffered_commands) >= self.buffer_size:
+            self.force()
+        self.buffered_commands.append(''.join(full_cmd))
+    def SIX(self, *insns):
+        """Run a list of instructions"""
+        for insn in insns:
+            self._add_command(0, insn)
+        return self
+    def REGOUT(self):
+        "Read the VISI register. Returns a PicResponseThunk"
+        thunk = PicResponseThunk(self)
+        self.response_buffer.append(thunk)
+        self._add_command(1, 0)
+        return thunk
+    
 def build_instr_stream( cmd_li ):
     """Given a list of instruction words, returns a list of bytes of
 the same, in little endian ordering."""
@@ -122,6 +246,86 @@ def dumpVISI():
     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
+                     0x880000 | tblpag << 3, # 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).
@@ -160,11 +364,12 @@ Returns [-1] on failure."""
 #############
 
 if len(sys.argv) == 1:
-    print "Usage: %s verb [objects]\n" % sys.argv[0]
+    print "Usage: %s [-alt_tblpag] 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 reset" % sys.argv[0]
     print "%s program $foo.hex" % sys.argv[0]
     print "%s verify $foo.hex" % sys.argv[0]
     print "%s write 0x$address 0x$value" % sys.argv[0]
@@ -175,7 +380,9 @@ if len(sys.argv) == 1:
     print "%s regout" % sys.argv[0]
     print """
 Note: use - for stdout.
-Warning: only supports dsPIC33F/PIC24H (maybe)...
+      use -alt_tblpag for PIC24FJxxx{DA1,DA2,GB2,GA3}xx with tblpag at 0x54
+Warning: only formally supports dsPIC33F/PIC24H,
+         but read/write flash memory works with PIC24F ...
 """
     sys.exit()
 
@@ -184,38 +391,66 @@ client = GoodFET()
 client.verbose = False # Dump activity to terminal
 client.serInit( timeout=10 ) # UART comm timeout (in seconds)
 
+if sys.argv[1] == "-alt_tblpag":
+    del sys.argv[1]
+    tblpag = 0x54
 
 # Handle each possible PIC verb in turn
-
 if sys.argv[1] == "devid": #0x81
     print "Requesting Application ID, DEVID and hardware revision..."
-    data = client.writecmd( PICAPP, 0x81, 0 )
-    
-    if len(data) > 0:
-        appid = ord(data[0])
-    else:
-        appid = -1
-    if len(data) > 2:
-        devid = ord(data[1]) + (ord(data[2]) << 8)
-    else:
-        devid = -1
-    if len(data) > 4:
-        hwrev = ord(data[3]) + (ord(data[4]) << 8)
-    else:
-        hwrev = -1
-    print "Application ID:   0x%02X" % appid
-    if dev_table.has_key( devid ):
-        print "DEVID:          0x%04X  (%s)" % ( devid, dev_table[devid] )
-    else:
-        print "DEVID:          0x%04X  (unknown)" %  devid
-    print "revision:       0x%04X"% hwrev
+    startICSP()
+    cmdbuf = PicCmdBuffer(client)
+    cmdbuf.SIX(0x040200, # GOTO 0x200
+               0x000000, # NOP
+               0x200FF0, # MOV #0xff, W0
+               0x880000 | tblpag << 3, # MOV W0, TBLPAG
+               0x200006, # MOV #0x0000, W6
+               0x207847, # MOV #VISI, W7
+               0x000000, # NOP
+               0xBA0B96, # TBLRDL [W6],[W7]
+               0x000000, # NOP
+               0x000000) # NOP
+    devid = cmdbuf.REGOUT()
+    cmdbuf.SIX(0x200026, # MOV #0x0002, W6
+               0x000000, # NOP
+               0xBA0B96, # TBLRDL [W6],[W7]
+               0x000000, # NOP
+               0x000000) # NOP
+    devidrev = cmdbuf.REGOUT()
+    cmdbuf.SIX(0x200800, # MOV #0x80, W0
+               0x880000 | tblpag << 3, # MOV W0, TBLPAG
+               0x207F00, # MOV #0x07F0, W6
+               0x000000, # NOP
+               0xBA0B96, # TBLRDL [W6],[W7]
+               0x000000, # NOP
+               0x000000) # NOP
+    appid = cmdbuf.REGOUT()
+    print "Application ID:   0x%02x" % appid()
+    print "DEVID:            0x%04x  (%s)" % (
+        devid(), dev_table.get(devid(), "unknown"))
+    print "Revision:  0x%04x" % devidrev()
+    stopICSP()
     #print "\n(Note that -1 indicates failure to read a value.)"
 
+elif sys.argv[1] == "test":
+    startICSP()
+    cmdbuf = PicCmdBuffer(client)
+    cmdbuf.SIX(0x2BEEF6, # MOV #0xBEEF, W6
+               0x000000,
+               0x780B86, # MOV W6, [W7]
+               0x000000, # NOP
+               0x000000) # NOP
+    assert cmdbuf.REGOUT()() == 0xbeef
+    stopICSP()
+    
+elif sys.argv[1] == "reset":
+    client.writecmd( PICAPP, 0x87, 0 )
+
 elif sys.argv[1] == "config": # Dump configuration registers
     prep_cmd_li = [0x040200, # GOTO 0x0200
                    0x000000, #
                    0x200F80, # MOV #0x00F8, W0
-                   0x880190, # MOV W0, TBLPAG
+                   0x880000 | tblpag << 3, # MOV W0, TBLPAG
                    0xEB0300, # CLR W6
                    0x207847, # MOV #VISI, W7
                    0x000000] # NOP
@@ -262,7 +497,7 @@ elif sys.argv[1] == "program":
                           0x24001A, # MOV $0x4001, W10
                           0x883B0A, # MOV W10, NVMCON
                           0x200000, # + ((addr>>12)&0xff0),  # MOV #addr<23:16>, W0
-                          0x880190, # MOV W0, TBLPAG
+                          0x880000 | tblpag << 3, # MOV W0, TBLPAG
                           0x200007] # + ((addr&0xffff)<<4), # MOV #addr<15:0>, W7
 
     # Load 4 instructions into write latches
@@ -354,7 +589,7 @@ elif sys.argv[1] == "program":
                      0x24000A, # MOV #0x4000, W10
                      0x883B0A, # MOV W10, NVMCON
                      0x200F80, # MOV #0xF8, W0
-                     0x880190, # MOV W0, TBLPAG
+                     0x880000 | tblpag<< 3, # MOV W0, TBLPAG
                      0x200000 + ((proghex[addr]&0x00ff)<<4), # MOV #new_val<7:0>, W0
                      0xBB0B80, # TBLWTL W0, [W7]
                      0x000000, # NOP
@@ -384,61 +619,35 @@ elif sys.argv[1] == "verify":
         print "Error while attempting to read from %s" % sys.argv[2]
         exit(-1)
 
-    readpm_cmd_li = [0x040200, # GOTO 0x0200
-                     0x000000, #
-                     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[:2] + [readpm_cmd_li[2]+((addr_pm&0xff0000)>>12)]
-                 + [readpm_cmd_li[3]] + [readpm_cmd_li[4]+((addr_pm&0xffff)<<4)]
-                 + readpm_cmd_li[5:] )
-        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.
 
 
@@ -461,7 +670,7 @@ elif sys.argv[1] == "write":
                 0x24003A, # MOV $0x4003, W10
                 0x883B0A, # MOV W10, NVMCON
                 0x200000 + ((addr>>12)&0xff0),  # MOV #addr<23:16>, W0
-                0x880190, # MOV W0, TBLPAG
+                0x880000 | tblpag << 3, # MOV W0, TBLPAG
                 0x200007 + ((addr&0xffff)<<4), # MOV #addr<15:0>, W7
 
                 # Here we load the instruction into registers W0:W1
@@ -540,7 +749,7 @@ elif sys.argv[1] == "write_config":
                  0x24000A, # MOV #0x4000, W10
                  0x883B0A, # MOV W10, NVMCON
                  0x200F80, # MOV #0xF8, W0
-                 0x880190, # MOV W0, TBLPAG
+                 0x880000 | tblpag << 3, # MOV W0, TBLPAG
                  0x200000 + ((new_val&0xffff)<<4), # MOV #<new_val>, W0
                  0xBB0B80, # TBLWTL W0, [W7]
                  0x000000, # NOP
@@ -570,7 +779,7 @@ elif sys.argv[1] == "read": # Read an address of program memory
     readpm_cmd_li = [0x040200,                         # GOTO 0x0200
                      0x000000,                         #
                      0x200000+((addr & 0xff0000)>>12), # MOV #addr<23:16>, W0
-                     0x880190,                         # MOV W0, TBLPAG
+                     0x880000 | tblpag << 3,                         # MOV W0, TBLPAG
                      0x200006+((addr & 0xffff)<<4),    # MOV #addr<15:0>, W6
                      0xEB0380,                         # CLR W7
                      0xEB0080,                         # CLR W1
@@ -611,82 +820,14 @@ elif sys.argv[1] == "dump": # Read section of program memory
         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
 
@@ -712,7 +853,7 @@ elif sys.argv[1] == "erase": # Bulk (all program memory) or page erase
                         0x24042A, # MOV $0x4042, W10
                         0x883B0A, # MOV W10, NVMCON
                         0x200000+((addr & 0xff0000)>>12), # MOV #addr<23:16>, W0
-                        0x880190, # MOV W0, TBLPAG
+                        0x880000 | tblpag << 3, # MOV W0, TBLPAG
                         0x200001+((addr&0xffff)<<4), # MOV addr<15:0>, W1
                         0x000000, # NOP
                         0xBB0881, # TBLTWL W1, [W1]