jtagarm: added jtag_trans_many and supporting firmware and client functions/protocol...
[goodfet] / firmware / apps / jtag / jtagarm7.c
index 6587de1..5310d62 100644 (file)
@@ -33,8 +33,9 @@ unsigned long last_instr = -1;
 unsigned char last_sysstate = 0;
 unsigned char last_ir = -1;
 unsigned char last_scanchain = -1;
-unsigned char tapstate = 15;
 unsigned char current_dbgstate = -1;
+unsigned char g_jtag_ir_size = 4;
+unsigned char g_jtagarm_scan_n_bitsize = 4;
 //unsigned char last_halt_debug_state = -1;
 //unsigned long last_halt_pc = -1;
 
@@ -45,9 +46,9 @@ GoodFET  ->  7TDMI 20-pin connector (HE-10 connector)
   3               5  (TDI)
   5               7  (TMS)
   7               9  (TCK)
-  8               15 (nRST)
   9               4,6,8,10,12,14,16,18,20 (GND)
-  11              17/3 (nTRST)  (different sources suggest 17 or 3 alternately)
+  11              15 (nRST)
+  //  no longer...  (11              17/3 (nTRST)  (different sources suggest 17 or 3 alternately))
 ********************************/
 
 /**** 14-pin Connection Information (pin1 is on top-right for both connectors)****
@@ -57,9 +58,9 @@ GoodFET  ->  7TDMI 14-pin connector
   3               5  (TDI)
   5               7  (TMS)
   7               9  (TCK)
-  8               12 (nRST)
   9               2,4,6,8,10,14 (GND)
-  11              3 (nTRST)
+  11              12 (nRST)
+  //  no longer... (11              3 (nTRST))
 
 http://hri.sourceforge.net/tools/jtag_faq_org.html
 ********************************/
@@ -91,8 +92,7 @@ u8 jtagarm_shift_ir(u8 ir, u8 flags){
   if (last_ir != ir){
        jtag_capture_ir();
        jtag_shift_register();
-    retval = jtag_trans_n(ir, 4, LSB|flags); 
-    tapstate = RunTest_Idle;
+    retval = jtag_trans_n(ir, g_jtag_ir_size, LSB|flags); 
     last_ir = ir;
   }
   return retval;
@@ -112,8 +112,7 @@ state” to the “Select DR” state each time the “Update” state is reache
     last_scanchain = chain;
        jtag_capture_dr();
        jtag_shift_register();
-    retval = jtag_trans_n(chain, 4, LSB | NORETIDLE);
-    tapstate = Update_DR;
+    retval = jtag_trans_n(chain, g_jtagarm_scan_n_bitsize, LSB | NORETIDLE);
   }
   jtagarm_shift_ir(testmode, NORETIDLE); 
   return(retval);
@@ -123,29 +122,27 @@ state” to the “Select DR” state each time the “Update” state is reache
 /************************* EmbeddedICE Primitives ****************************/
 //! shifter for writing to chain2 (EmbeddedICE). 
 unsigned long eice_write(unsigned char reg, unsigned long data){
-  unsigned long retval, temp;
+  unsigned long retval;
   jtagarm7tdmi_scan(2, ARM7TDMI_IR_INTEST);
   jtag_capture_dr();
   jtag_shift_register();
   retval = jtag_trans_n(data, 32, LSB| NOEND| NORETIDLE);         // send in the data - 32-bits lsb
-  temp = jtag_trans_n(reg, 5, LSB| NOEND| NORETIDLE);             // send in the register address - 5 bits lsb
+  jtag_trans_n(reg, 5, LSB| NOEND| NORETIDLE);             // send in the register address - 5 bits lsb
   jtag_trans_n(1, 1, LSB);                                        // send in the WRITE bit
-  tapstate = RunTest_Idle;
   return(retval); 
 }
 
 //! shifter for reading from chain2 (EmbeddedICE).
 unsigned long eice_read(unsigned char reg){               // PROVEN
-  unsigned long temp, retval;
+  unsigned long retval;
   jtagarm7tdmi_scan(2, ARM7TDMI_IR_INTEST);
   jtag_capture_dr();
   jtag_shift_register(); // send in the register address - 5 bits LSB
-  temp = jtag_trans_n(reg, 5, LSB| NOEND| NORETIDLE);
+  jtag_trans_n(reg, 5, LSB| NOEND| NORETIDLE);
   jtag_trans_n(0L, 1, LSB);                                       // clear TDI to select "read only"
   jtag_capture_dr();
   jtag_shift_register(); // Now shift out the 32 bits
   retval = jtag_trans_n(0L, 32, LSB);                             // atmel arm jtag docs pp.10-11: LSB first
-  tapstate = RunTest_Idle;
   return(retval);
   
 }
@@ -155,13 +152,14 @@ unsigned long jtagarm7tdmi_instr_primitive(unsigned long instr, char breakpt){
   unsigned long retval = 0;
   jtagarm7tdmi_scan(1, ARM7TDMI_IR_INTEST);
 
-  //debughex32(instr);
-  if (last_instr != instr && last_sysstate != breakpt){
+  //if (!(last_instr == instr && last_sysstate == breakpt))
+  {
          jtag_capture_dr();
          jtag_shift_register();
     // if the next instruction is to run using MCLK (master clock), set TDI
     if (breakpt)
       {
+      //debugstr("--breakpt flag set");
       SETMOSI;
       } 
     else
@@ -172,16 +170,40 @@ unsigned long jtagarm7tdmi_instr_primitive(unsigned long instr, char breakpt){
     
     // Now shift in the 32 bits
     retval = jtag_trans_n(instr, 32, 0);    // Must return to RUN-TEST/IDLE state for instruction to enter pipeline, and causes debug clock.
-    tapstate = RunTest_Idle;
     last_instr = instr;
     last_sysstate = breakpt;
-  } else
+  }
+  return(retval);
+}
+
+//! push an instruction into the pipeline
+unsigned long jtagarm_instr_primitive(unsigned char *instr, char breakpt){ 
+  unsigned long retval = 0;
+  jtagarm7tdmi_scan(1, ARM7TDMI_IR_INTEST);
+
+  //if (!(last_instr == instr && last_sysstate == breakpt))
+  {
+         jtag_capture_dr();
+         jtag_shift_register();
+
+    // if the next instruction is to run using MCLK (master clock), set TDI
+    if (breakpt)
+      { SETMOSI; } 
+    else
+      { CLRMOSI; }
     jtag_tcktock();
+    
+    // Now shift in the 32 bits
+    retval = jtag_trans_many(instr, 32, 0);    // Must return to RUN-TEST/IDLE state for instruction to enter pipeline, and causes debug clock.
+    last_instr = *instr;
+    last_sysstate = breakpt;
+  }
   return(retval);
 }
 
 u32 jtagarm7tdmi_nop(u8 brkpt){
     //  WARNING: current_dbgstate must be up-to-date before calling this function!!!!!
+    //debugstr("jtagarm7tdmi_nop");
     if (current_dbgstate & JTAG_ARM7TDMI_DBG_TBIT)
         return jtagarm7tdmi_instr_primitive(THUMB_INSTR_NOP, brkpt);
     return jtagarm7tdmi_instr_primitive(ARM_INSTR_NOP, brkpt);
@@ -191,6 +213,7 @@ u32 jtagarm7tdmi_nop(u8 brkpt){
 
 //! Retrieve a 32-bit Register value
 unsigned long jtagarm7_get_reg_prim(unsigned long instr){
+  //debugstr("jtagarm7_get_reg_prim");
   jtagarm7tdmi_nop( 0);
   jtagarm7tdmi_instr_primitive(instr, 0);
   jtagarm7tdmi_nop( 0);
@@ -220,10 +243,8 @@ void jtagarm7_thumb_swap_reg(unsigned char dir, unsigned long reg){
   jtagarm7tdmi_nop( 0);
   if (dir){
     jtagarm7tdmi_instr_primitive((unsigned long)(THUMB_INSTR_MOV_LoHi | (reg) | (reg<<16)), 0);
-    //debughex32((unsigned long)(THUMB_INSTR_MOV_LoHi | (reg) | (reg<<16)));
   } else {
     jtagarm7tdmi_instr_primitive((unsigned long)(THUMB_INSTR_MOV_HiLo | (reg<<3) | (reg<<19)), 0);
-    //debughex32((unsigned long)(THUMB_INSTR_MOV_HiLo | (reg<<3) | (reg<<19)));
   }
   jtagarm7tdmi_nop( 0);
   jtagarm7tdmi_nop( 0);
@@ -233,6 +254,9 @@ void jtagarm7_thumb_swap_reg(unsigned char dir, unsigned long reg){
 unsigned long jtagarm7tdmi_get_register(unsigned long reg) {                                // PROVEN - 100827
   unsigned long retval=0L, instr, r0;
   current_dbgstate = eice_read(EICE_DBGSTATUS);
+  //debugstr("current_dbgstate:");
+  //debughex32(current_dbgstate);
+
   if (current_dbgstate & JTAG_ARM7TDMI_DBG_TBIT){
     if (reg > 7){
       //debugstr("debug: jtagarm7tdmi_get_register: thumb reg > 15");
@@ -243,10 +267,14 @@ unsigned long jtagarm7tdmi_get_register(unsigned long reg) {
       jtagarm7_set_reg_prim( THUMB_WRITE_REG, 0, r0);       // restore r0
       return retval;
     } else {
+      //debugstr("debug: jtagarm7tdmi_get_register: thumb reg < 15");
       instr = (unsigned long)(THUMB_READ_REG | (unsigned long)reg | (unsigned long)(reg<<16L));
     }
   } else
+  {
+    //debugstr("debug: jtagarm7tdmi_get_register: arm");
     instr = (reg<<12L) | ARM_READ_REG;    // STR Rx, [R14] 
+  }
   return jtagarm7_get_reg_prim(instr);
 }
 
@@ -295,6 +323,14 @@ void jtagarm7_handle_fn( uint8_t const app,
     jtagarm7tdmi_start();
     txdata(app,verb,0);
     break;
+  case JTAGARM7_SCAN_N_SIZE:
+    g_jtagarm_scan_n_bitsize = cmddata[0];
+    txdata(app,verb,1);
+    break;
+  case JTAGARM7_IR_SIZE:
+    g_jtag_ir_size = cmddata[0];
+    txdata(app,verb,1);
+    break;
   case JTAG_IR_SHIFT:
     cmddataword[0] = jtagarm_shift_ir(cmddata[0], cmddata[1]);
     txdata(app,verb,1);
@@ -302,9 +338,45 @@ void jtagarm7_handle_fn( uint8_t const app,
   case JTAG_DR_SHIFT:
        jtag_capture_dr();
        jtag_shift_register();
-    cmddatalong[0] = jtag_trans_n(cmddatalong[1],cmddata[0],cmddata[1]);
-    tapstate = (cmddata[1]&NORETIDLE)>0?Update_DR:RunTest_Idle;
-    txdata(app,verb,4);
+    val = cmddata[0];
+    if (cmddata[0] > 32)
+    {
+        //debughex32(cmddatalong[0]);
+        //debughex32(cmddatalong[1]);
+        cmddatalong[1] = jtag_trans_n(cmddatalong[2], val - 32 ,cmddata[1] | NOEND |NORETIDLE);
+        cmddatalong[0] = jtag_trans_n(cmddatalong[2], 32, cmddata[1]);
+    }
+    else
+    {
+        //debughex32(cmddatalong[0]);
+        cmddatalong[0] = jtag_trans_n(cmddatalong[1], val, cmddata[1]);
+    }
+    txdata(app,verb,val/8);
+    break;
+  case JTAG_DR_SHIFT_MORE:
+    // assumes you just executed JTAG_DR_SHIFT with NOEND flag set
+    debugstr("JTAG_DR_SHIFT_MORE");
+    val = cmddata[0];
+    if (cmddata[0] > 32)
+    {
+        //debughex32(cmddatalong[0]);
+        //debughex32(cmddatalong[1]);
+        cmddatalong[1] = jtag_trans_n(cmddatalong[2], val - 32 ,cmddata[1] | NOEND |NORETIDLE);
+        cmddatalong[0] = jtag_trans_n(cmddatalong[2], 32, cmddata[1]);
+    }
+    else
+    {
+        debughex32(cmddatalong[0]);
+        cmddatalong[0] = jtag_trans_n(cmddatalong[1], val, cmddata[1]);
+    }
+    txdata(app,verb,val/8);
+    break;
+  case JTAG_DR_SHIFT_MANY:
+       jtag_capture_dr();
+       jtag_shift_register();
+    val = cmddata[0];
+    jtag_trans_many(&cmddata[2], val, cmddata[1] );
+    txdata(app,verb,((val+7)/8)+2);
     break;
   case JTAGARM7_CHAIN0:
     jtagarm7tdmi_scan(0, ARM7TDMI_IR_INTEST);
@@ -318,7 +390,6 @@ void jtagarm7_handle_fn( uint8_t const app,
     cmddatalong[2] = jtag_trans_n(cmddataword[4], 9, MSB| NOEND| NORETIDLE);
     cmddatalong[1] = jtag_trans_n(cmddatalong[1], 32, MSB| NOEND| NORETIDLE);
     cmddatalong[3] = jtag_trans_n(cmddatalong[3], 32, MSB);
-    tapstate = RunTest_Idle;
     txdata(app,verb,16);
     break;
   case JTAGARM7_SCANCHAIN1:
@@ -326,6 +397,10 @@ void jtagarm7_handle_fn( uint8_t const app,
     cmddatalong[0] = jtagarm7tdmi_instr_primitive(cmddatalong[0],cmddata[4]);
     txdata(app,verb,4);
     break;
+  case JTAGARM_SCAN1_MANY:
+    cmddatalong[0] = jtagarm_instr_primitive(&cmddata[1],cmddata[0]);
+    txdata(app,verb,4);
+    break;
   case JTAGARM7_EICE_READ:
     cmddatalong[0] = eice_read(cmddata[0]);
     txdata(app,verb,0x4);
@@ -346,9 +421,12 @@ void jtagarm7_handle_fn( uint8_t const app,
   case JTAG_RESET_TARGET:
     //FIXME: BORKEN
     debugstr("RESET TARGET");
-    CLRTST;
+    //debughex((P3OUT&RST));
+    CLRRST;
+    //debughex((P3OUT&RST));
     delay(cmddataword[0]);
-    SETTST;
+    SETRST;
+    //debughex((P3OUT&RST));
     txdata(app,verb,4);
     break;
 
@@ -367,4 +445,162 @@ void jtagarm7_handle_fn( uint8_t const app,
   }
 }
 
+#define min(x,y) ( (x>y) ? y : x )
+#define max(x,y) ( (x>y) ? x : y )
 
+uint8_t* jtag_trans_many(uint8_t *data, 
+                     uint8_t bitcount, 
+                     enum eTransFlags flags) 
+{
+       uint8_t bit;
+       uint16_t high;
+       uint16_t mask;
+       uint16_t hmask;
+       uint8_t bitnum = 0;
+
+       if (!in_state(SHIFT_IR | SHIFT_DR))
+       {
+               debugstr("jtag_trans_n from invalid TAP state");
+               return 0;
+       }
+
+       SAVETCLK;
+
+       if (flags & LSB) 
+       {
+        high = (1L << (min(bitcount,8) - 1));
+        mask = high - 1;
+        hmask = (high<<1) - 1;
+                debugstr(" starting shift:");
+                //debughex(bit);
+                debughex(high);
+                //debughex(hmask);
+                debughex(mask);
+                debughex(*data);
+
+               for (bit = bitcount; bit > 0; bit--,bitnum++) 
+               {
+            if (bitnum == 8)
+            {
+                high = (1L << (min(bit,8) - 1));
+                hmask = (high<<1) - 1;
+                mask = high - 1;
+                bitnum = 0;
+
+                debugstr("");
+                //debughex(bit);
+                debughex(high);
+                //debughex(hmask);
+                debughex(mask);
+                debughex(*data);
+                data ++;
+
+            }
+                       /* write MOSI on trailing edge of previous clock */
+                       if (*data & 1)
+                       {
+                               SETMOSI;
+                       }
+                       else
+                       {
+                               CLRMOSI;
+                       }
+                       *data >>= 1;
+
+                       if ((bit == 1) && !(flags & NOEND))
+                               SETTMS; //TMS high on last bit to exit.
+
+                       jtag_tcktock();
+
+                       if ((bit == 1) && !(flags & NOEND))
+                               jtag_state <<= 1; // Exit1-DR or Exit1-IR
+
+                       /* read MISO on trailing edge */
+                       if (READMISO)
+                       {
+                debugstr("MISO: 1");
+                               *data |= (high);
+                       }
+            else
+            {
+                debugstr("MISO: 0");
+            }
+            debughex(*data);
+
+               }
+        debughex(*data);
+        *data &= hmask;
+       } 
+       else 
+       {
+        // MSB... we need to start at the end of the byte array
+        data += (bitcount/8);
+        bitnum = bitcount % 8;
+        high = (1L << (max(bitnum,8) - 1));
+        mask = high - 1;
+        hmask = (high<<1) - 1;
+
+               for (bit = bitcount; bit > 0; bit--,bitnum--) 
+               {
+                       /* write MOSI on trailing edge of previous clock */
+                       if (*data & high)
+                       {
+                               SETMOSI;
+                       }
+                       else
+                       {
+                               CLRMOSI;
+                       }
+                       *data = (*data & mask) << 1;
+
+                       if ((bit==1) && !(flags & NOEND))
+                               SETTMS; //TMS high on last bit to exit.
+
+                       jtag_tcktock();
+
+                       if ((bit == 1) && !(flags & NOEND))
+                               jtag_state <<= 1; // Exit1-DR or Exit1-IR
+
+                       /* read MISO on trailing edge */
+                       *data |= (READMISO);
+
+            if (bitnum == 0)
+            {
+                high = (1L << (min(bit,8) - 1));
+                mask = high - 1;
+                hmask = (high<<1) - 1;
+                bitnum = 8;
+                data --;
+            }
+               }
+       }
+       
+       //This is needed for 20-bit MSP430 chips.
+       //Might break another 20-bit chip, if one exists.
+    //
+    //UGH... this needs to be fixed...  doesn't work with char*
+/*     if(bitcount==20){
+         *data = ((*data << 16) | (*data >> 4)) & 0x000FFFFF;
+       }*/
+       
+       RESTORETCLK;
+
+       if (!(flags & NOEND))
+       {
+               // exit state
+               jtag_tcktock();
+
+               jtag_state <<= 3; // Update-DR or Update-IR
+
+               // update state
+               if (!(flags & NORETIDLE))
+               {
+                       CLRTMS;
+                       jtag_tcktock();
+
+                       jtag_state = RUN_TEST_IDLE;
+               }
+       }
+
+       return &data[2];
+}