w00t! jtagarm7 committed and included in build.
[goodfet] / firmware / apps / jtag / jtag.c
index cffec3d..cc6ef16 100644 (file)
-//GoodFET JTAG Application
-//Handles basic I/O
+/*! \file jtag.c
+  \author Travis Goodspeed <travis at radiantmachines.com>
+  \brief Low-level JTAG
+*/
 
-//Higher level left to client application.
 
 #include "platform.h"
 #include "command.h"
 #include "jtag.h"
 
 
-
-
 //! Set up the pins for JTAG mode.
-unsigned char jtagsetup(){
+void jtagsetup(){
   P5DIR|=MOSI+SCK+TMS;
   P5DIR&=~MISO;
+  /*
   P5OUT|=0xFFFF;
+  P5OUT=0;
+  */
   P4DIR|=TST;
   P2DIR|=RST;
+  msdelay(100);
+}
+
+/************************** JTAG Primitives ****************************/
+// these have been turned into functions to save flash space
+void jtag_tcktock() {
+  CLRTCK; 
+  PLEDOUT^=PLEDPIN; 
+  SETTCK; 
+  PLEDOUT^=PLEDPIN;
+}
+
+void jtag_goto_shift_ir() {
+  SETTMS;
+  jtag_tcktock();
+  jtag_tcktock();
+  CLRTMS;
+  jtag_tcktock();
+  jtag_tcktock();
+
+}
+void jtag_goto_shift_dr() {
+  SETTMS;
+  jtag_tcktock();
+  CLRTMS;
+  jtag_tcktock();
+  jtag_tcktock();
+}
+
+void jtag_resettap(){
+  SETTMS;
+  jtag_tcktock();
+  jtag_tcktock();
+  jtag_tcktock();
+  jtag_tcktock();
+  jtag_tcktock();  // now in Reset state
+  CLRTMS;
+  jtag_tcktock();  // now in Run-Test/Idle state
 }
 
+
 int savedtclk=0;
+//  NOTE: important: THIS MODULE REVOLVES AROUND RETURNING TO RUNTEST/IDLE, OR THE FUNCTIONAL EQUIVALENT
+//! Shift N bits over TDI/TDO.  May choose LSB or MSB, and select whether to terminate (TMS-high on last bit) and whether to return to RUNTEST/IDLE
+//      flags should be 0 for most uses.  
+//      for the extreme case, flags should be  (NOEND|NORETDLE|LSB)
+//      other edge cases can involve a combination of those three flags
+//
+//      the max bit-size that can be be shifted is 32-bits.  
+//      for longer shifts, use the NOEND flag (which infers NORETIDLE so the additional flag is unnecessary)
+//
+//      NORETIDLE is used for special cases where (as with arm) the debug subsystem does not want to 
+//      return to the RUN-TEST/IDLE state between setting IR and DR
+unsigned long jtagtransn(unsigned long word, unsigned char bitcount, unsigned char flags){            
+  unsigned char bit;
+  unsigned long high = 1L;
+  unsigned long mask;
+
+  //for (bit=(bitcount-1)/8; bit>0; bit--)
+  //  high <<= 8;
+  //high <<= ((bitcount-1)%8);
+  high <<= (bitcount-1);
+
+  mask = high-1;
+
+  SAVETCLK;
+  if (flags & LSB) {
+    for (bit = bitcount; bit > 0; bit--) {
+      /* write MOSI on trailing edge of previous clock */
+      if (word & 1)
+        {SETMOSI;}
+      else
+        {CLRMOSI;}
+      word >>= 1;
+
+      if (bit==1 && !(flags & NOEND))
+        SETTMS;//TMS high on last bit to exit.
+       
+      jtag_tcktock();
+
+      /* read MISO on trailing edge */
+      if (READMISO){
+        word += (high);
+      }
+    }
+  } else {
+    for (bit = bitcount; bit > 0; bit--) {
+      /* write MOSI on trailing edge of previous clock */
+      if (word & high)
+        {SETMOSI;}
+      else
+        {CLRMOSI;}
+      word = (word & mask) << 1;
+
+      if (bit==1 && !(flags & NOEND))
+        SETTMS;//TMS high on last bit to exit.
+
+      jtag_tcktock();
+
+      /* read MISO on trailing edge */
+      word |= (READMISO);
+    }
+  }
+
+  RESTORETCLK;
+  //SETMOSI;
+
+  if (!(flags & NOEND)){
+    // exit state
+    jtag_tcktock();
+    // update state
+    if (!(flags & NORETIDLE)){
+      CLRTMS;
+      jtag_tcktock();
+    }
+  }
+  return word;
+}
+
 //! Shift 8 bits in and out.
 unsigned char jtagtrans8(unsigned char byte){
   unsigned int bit;
@@ -27,65 +146,74 @@ unsigned char jtagtrans8(unsigned char byte){
   for (bit = 0; bit < 8; bit++) {
     /* write MOSI on trailing edge of previous clock */
     if (byte & 0x80)
-      SETMOSI;
+      {SETMOSI;}
     else
-      CLRMOSI;
+      {CLRMOSI;}
     byte <<= 1;
     
     if(bit==7)
       SETTMS;//TMS high on last bit to exit.
     
-    CLRTCK;
-    SETTCK;
-     /* read MISO on trailing edge */
+    TCKTOCK;
+    /* read MISO on trailing edge */
     byte |= READMISO;
   }
   RESTORETCLK;
   
   // exit state
-  CLRTCK;
-  SETTCK;
+  TCKTOCK;
   // update state
   CLRTMS;
-  CLRTCK;
-  SETTCK;
+  TCKTOCK;
   
   return byte;
 }
 
-//! Shift 8 bits in and out.
-unsigned int jtagtrans16(unsigned int word){
+//! Shift n bits in and out.
+/*unsigned long jtagtransn(unsigned long word,
+                        unsigned int bitcount){
   unsigned int bit;
+  //0x8000
+  unsigned long high=0x8000;
+  
+  if(bitcount==20)
+    high=0x80000;
+  if(bitcount==16)
+    high= 0x8000;
+  
   SAVETCLK;
   
-  for (bit = 0; bit < 16; bit++) {
-    /* write MOSI on trailing edge of previous clock */
-    if (word & 0x8000)
-      SETMOSI;
+  for (bit = 0; bit < bitcount; bit++) {
+    // write MOSI on trailing edge of previous clock *
+    if (word & high)
+      {SETMOSI;}
     else
-      CLRMOSI;
+      {CLRMOSI;}
     word <<= 1;
     
-    if(bit==15)
+    if(bit==bitcount-1)
       SETTMS;//TMS high on last bit to exit.
     
-    CLRTCK;
-    SETTCK;
-     /* read MISO on trailing edge */
+    TCKTOCK;
+    // read MISO on trailing edge *
     word |= READMISO;
   }
+  
+  if(bitcount==20){
+    word = ((word << 16) | (word >> 4)) & 0x000FFFFF;
+  }
+  
   RESTORETCLK;
   
   // exit state
-  CLRTCK;
-  SETTCK;
+  TCKTOCK;
   // update state
   CLRTMS;
-  CLRTCK;
-  SETTCK;
+  TCKTOCK;
   
   return word;
 }
+*/
 
 //! Stop JTAG, release pins
 void jtag_stop(){
@@ -93,23 +221,56 @@ void jtag_stop(){
   P4OUT=0;
 }
 
+unsigned int drwidth=16;
+//! Shift all bits of the DR.
+unsigned long jtag_dr_shift20(unsigned long in){
+  // idle
+  SETTMS;
+  TCKTOCK;
+  // select DR
+  CLRTMS;
+  TCKTOCK;
+  // capture IR
+  TCKTOCK;
+  
+  // shift DR, then idle
+  return(jtagtransn(in,20,0));
+}
+
 
 //! Shift 16 bits of the DR.
 unsigned int jtag_dr_shift16(unsigned int in){
   // idle
   SETTMS;
-  CLRTCK;
-  SETTCK;
+  TCKTOCK;
+  // select DR
+  CLRTMS;
+  TCKTOCK;
+  // capture IR
+  TCKTOCK;
+  
+  // shift DR, then idle
+  return(jtagtransn(in,16,0));
+}
+
+//! Shift native width of the DR
+unsigned long jtag_dr_shiftadr(unsigned long in){
+  unsigned long out=0;
+  
+  // idle
+  SETTMS;
+  TCKTOCK;
   // select DR
   CLRTMS;
-  CLRTCK;
-  SETTCK;
+  TCKTOCK;
   // capture IR
-  CLRTCK;
-  SETTCK;
+  TCKTOCK;
 
+  
+  out=jtagtransn(in,drwidth,0);
+  
   // shift DR, then idle
-  return(jtagtrans16(in));
+  return(out);
 }
 
 
@@ -117,18 +278,14 @@ unsigned int jtag_dr_shift16(unsigned int in){
 unsigned char jtag_ir_shift8(unsigned char in){
   // idle
   SETTMS;
-  CLRTCK;
-  SETTCK;
+  TCKTOCK;
   // select DR
-  CLRTCK;
-  SETTCK;
+  TCKTOCK;
   // select IR
   CLRTMS;
-  CLRTCK;
-  SETTCK;
+  TCKTOCK;
   // capture IR
-  CLRTCK;
-  SETTCK;
+  TCKTOCK;
   
   // shift IR, then idle.
   return(jtagtrans8(in));
@@ -137,7 +294,7 @@ unsigned char jtag_ir_shift8(unsigned char in){
 //! Handles a monitor command.
 void jtaghandle(unsigned char app,
               unsigned char verb,
-              unsigned char len){
+              unsigned long len){
   switch(verb){
     //START handled by specific JTAG
   case STOP:
@@ -156,6 +313,10 @@ void jtaghandle(unsigned char app,
     cmddataword[0]=jtag_dr_shift16(cmddataword[0]);
     txdata(app,verb,2);
     break;
+  case JTAG_RESETTAP:
+    jtag_resettap();
+    txdata(app,verb,0);
+    break;
   default:
     txdata(app,NOK,0);
   }