Reliability patch to Chipcon.
[goodfet] / firmware / apps / chipcon / chipcon.c
index e2fbcb4..28440c4 100644 (file)
@@ -1,17 +1,16 @@
-//GoodFET ChipCon Debugging Application
-//Handles basic I/O for the Chipcon 8051 debugging protocol.
+/*! \file chipcon.c
+  \author Travis Goodspeed
+  \brief Chipcon 8051 debugging.
+*/
 
 
-//Higher level left to client application.
 
 //This is like SPI, except that you read or write, not both.
 
 
 //This is like SPI, except that you read or write, not both.
 
-/** N.B. The READ verb performs a write of all (any) supplied data,
+/* N.B. The READ verb performs a write of all (any) supplied data,
     then reads a single byte reply from the target.  The WRITE verb
     only writes.
 */
 
     then reads a single byte reply from the target.  The WRITE verb
     only writes.
 */
 
-//This is REALLY untested.
-
 #include "platform.h"
 #include "command.h"
 #include "chipcon.h"
 #include "platform.h"
 #include "command.h"
 #include "chipcon.h"
@@ -21,7 +20,7 @@
 #include <iomacros.h>
 
 
 #include <iomacros.h>
 
 
-/** Concerning clock rates,
+/* Concerning clock rates,
     the maximimum clock rates are defined on page 4 of the spec.
     They vary, but are roughly 30MHz.  Raising this clock rate might
     allow for clock glitching, but the GoodFET isn't sufficient fast for that.
     the maximimum clock rates are defined on page 4 of the spec.
     They vary, but are roughly 30MHz.  Raising this clock rate might
     allow for clock glitching, but the GoodFET isn't sufficient fast for that.
@@ -37,7 +36,7 @@
 
 //This could be more accurate.
 //Does it ever need to be?
 
 //This could be more accurate.
 //Does it ever need to be?
-#define CCSPEED 0
+#define CCSPEED 3
 #define CCDELAY(x) delay(x)
 
 #define SETMOSI P5OUT|=MOSI
 #define CCDELAY(x) delay(x)
 
 #define SETMOSI P5OUT|=MOSI
@@ -125,9 +124,12 @@ void ccread(unsigned char len){
 //! Handles a monitor command.
 void cchandle(unsigned char app,
               unsigned char verb,
 //! Handles a monitor command.
 void cchandle(unsigned char app,
               unsigned char verb,
-              unsigned char len){
+              unsigned long len){
+  //Always init.  Might help with buggy lines.
+  ccdebuginit();
+  
   switch(verb){
   switch(verb){
-    //PEEK and POKE will come later.
+    //CC_PEEK and CC_POKE will come later.
   case READ:  //Write a command and return 1-byte reply.
     cccmd(len);
     ccread(1);
   case READ:  //Write a command and return 1-byte reply.
     cccmd(len);
     ccread(1);
@@ -139,12 +141,14 @@ void cchandle(unsigned char app,
     break;
   case START://enter debugger
     ccdebuginit();
     break;
   case START://enter debugger
     ccdebuginit();
+    txdata(app,verb,0);
     break;
   case STOP://exit debugger
     //Take RST low, then high.
     P5OUT&=~RST;
     CCDELAY(CCSPEED);
     P5OUT|=RST;
     break;
   case STOP://exit debugger
     //Take RST low, then high.
     P5OUT&=~RST;
     CCDELAY(CCSPEED);
     P5OUT|=RST;
+    txdata(app,verb,0);
     break;
   case SETUP:
     ccsetup();
     break;
   case SETUP:
     ccsetup();
@@ -166,7 +170,7 @@ void cchandle(unsigned char app,
     break;
   case CC_GET_PC:
     cc_get_pc();
     break;
   case CC_GET_PC:
     cc_get_pc();
-    txdata(app,verb,1);
+    txdata(app,verb,2);
     break;
   case CC_READ_STATUS:
     cc_read_status();
     break;
   case CC_READ_STATUS:
     cc_read_status();
@@ -185,7 +189,8 @@ void cchandle(unsigned char app,
     txdata(app,verb,1);
     break;
   case CC_DEBUG_INSTR:
     txdata(app,verb,1);
     break;
   case CC_DEBUG_INSTR:
-    txdata(app,NOK,0);//TODO add me
+    cc_debug_instr(len);
+    txdata(app,verb,1);
     break;
   case CC_STEP_INSTR:
     cc_step_instr();
     break;
   case CC_STEP_INSTR:
     cc_step_instr();
@@ -202,8 +207,17 @@ void cchandle(unsigned char app,
 
   //Macro commands
   case CC_READ_CODE_MEMORY:
 
   //Macro commands
   case CC_READ_CODE_MEMORY:
+    cmddata[0]=cc_peekcodebyte(cmddataword[0]);
+    txdata(app,verb,1);
+    break;
   case CC_READ_XDATA_MEMORY:
   case CC_READ_XDATA_MEMORY:
+    cmddata[0]=cc_peekdatabyte(cmddataword[0]);
+    txdata(app,verb,1);
+    break;
   case CC_WRITE_XDATA_MEMORY:
   case CC_WRITE_XDATA_MEMORY:
+    cmddata[0]=cc_pokedatabyte(cmddataword[0], cmddata[2]);
+    txdata(app,verb,1);
+    break;
   case CC_SET_PC:
   case CC_CLOCK_INIT:
   case CC_WRITE_FLASH_PAGE:
   case CC_SET_PC:
   case CC_CLOCK_INIT:
   case CC_WRITE_FLASH_PAGE:
@@ -269,7 +283,6 @@ unsigned short cc_get_pc(){
   return cmddataword[0];
 }
 
   return cmddataword[0];
 }
 
-
 //! Set a hardware breakpoint.
 void cc_set_hw_brkpnt(unsigned short adr){
   cmddataword[0]=adr;
 //! Set a hardware breakpoint.
 void cc_set_hw_brkpnt(unsigned short adr){
   cmddataword[0]=adr;
@@ -302,3 +315,111 @@ void cc_step_instr(){
   ccread(1);
   return;
 }
   ccread(1);
   return;
 }
+
+//! Debug an instruction.
+void cc_debug_instr(unsigned char len){
+  //Bottom two bits of command indicate length.
+  unsigned char cmd=0x54+(len&0x3);
+  CCWRITE;
+  cctrans8(cmd);  //Second command code
+  cccmd(len&0x3); //Command itself.
+  ccread(1);
+  return;
+}
+
+//! Debug an instruction, for local use.
+unsigned char cc_debug(unsigned char len,
+             unsigned char a,
+             unsigned char b,
+             unsigned char c){
+  unsigned char cmd=0x54+(len&0x3);//(len&0x3);
+  CCWRITE;
+  cctrans8(0xFF);//resync
+  cctrans8(0xFF);//resync
+  cctrans8(0xFF);//resync
+  cctrans8(0xFF);//resync
+  cctrans8(0xFF);//resync
+  cctrans8(cmd);
+  if(len--)
+    cctrans8(a);
+  if(len--)
+    cctrans8(b);
+  if(len--)
+    cctrans8(c);
+  CCREAD;
+  return cctrans8(0x00);
+}
+
+//! Fetch a byte of code memory.
+unsigned char cc_peekcodebyte(unsigned long adr){
+  /** See page 9 of SWRA124 */
+  unsigned char bank=adr>>15,
+    lb=adr&0xFF,
+    hb=(adr>>8)&0x7F,
+    toret=0;
+  adr&=0x7FFF;
+  
+  //MOV MEMCTR, (bank*16)+1
+  cc_debug(3, 0x75, 0xC7, (bank<<4) + 1);
+  //MOV DPTR, address
+  cc_debug(3, 0x90, hb, lb);
+  
+  //for each byte
+  //CLR A
+  cc_debug(2, 0xE4, 0, 0);
+  //MOVC A, @A+DPTR;
+  toret=cc_debug(3, 0x93, 0, 0);
+  //INC DPTR
+  //cc_debug(1, 0xA3, 0, 0);
+  
+  return toret;
+}
+
+
+//! Set a byte of data memory.
+unsigned char cc_pokedatabyte(unsigned int adr,
+                          unsigned char val){
+  unsigned char
+    hb=(adr&0xFF00)>>8,
+    lb=adr&0xFF;
+  
+  //MOV DPTR, adr
+  cc_debug(3, 0x90, hb, lb);
+  //MOV A, val
+  cc_debug(2, 0x74, val, 0);
+  //MOVX @DPTR, A
+  cc_debug(1, 0xF0, 0, 0);
+  
+  return 0;
+  /*
+DEBUG_INSTR(IN: 0x90, HIBYTE(address), LOBYTE(address), OUT: Discard);
+for (n = 0; n < count; n++) {
+    DEBUG_INSTR(IN: 0x74, inputArray[n], OUT: Discard);
+    DEBUG_INSTR(IN: 0xF0, OUT: Discard);
+    DEBUG_INSTR(IN: 0xA3, OUT: Discard);
+}
+   */
+}
+
+//! Fetch a byte of data memory.
+unsigned char cc_peekdatabyte(unsigned int adr){
+  unsigned char
+    hb=(adr&0xFF00)>>8,
+    lb=adr&0xFF,
+    toret;
+
+  //MOV DPTR, adr
+  cc_debug(3, 0x90, hb, lb);
+  //MOVX A, @DPTR
+  //Must be 2, perhaps for clocking?
+  toret=cc_debug(3, 0xE0, 0, 0);
+  return toret;
+  
+    /*
+DEBUG_INSTR(IN: 0x90, HIBYTE(address), LOBYTE(address), OUT: Discard);
+for (n = 0; n < count; n++) {
+    DEBUG_INSTR(IN: 0xE0, OUT: outputArray[n]);
+    DEBUG_INSTR(IN: 0xA3, OUT: Discard);
+}
+  */
+}