MSP430 JTAG works.
authortravisutk <travisutk@12e2690d-a6be-4b82-a7b7-67c4a43b65c8>
Thu, 18 Jun 2009 18:33:07 +0000 (18:33 +0000)
committertravisutk <travisutk@12e2690d-a6be-4b82-a7b7-67c4a43b65c8>
Thu, 18 Jun 2009 18:33:07 +0000 (18:33 +0000)
git-svn-id: https://svn.code.sf.net/p/goodfet/code/trunk@38 12e2690d-a6be-4b82-a7b7-67c4a43b65c8

client/GoodFET.py [new file with mode: 0755]
client/goodfet [deleted file]
client/goodfet.msp430 [new file with mode: 0755]
firmware/apps/Makefile
firmware/apps/goodfet.c
firmware/apps/jtag/Readme.txt [new file with mode: 0644]
firmware/apps/jtag/jtag430.c [new file with mode: 0644]
firmware/include/command.h
firmware/include/jtag.h
firmware/lib/command.c

diff --git a/client/GoodFET.py b/client/GoodFET.py
new file mode 100755 (executable)
index 0000000..387eeab
--- /dev/null
@@ -0,0 +1,164 @@
+#!/usr/bin/env python
+# GoodFET Client Library
+# 
+# (C) 2009 Travis Goodspeed <travis at radiantmachines.com>
+#
+# This code is ugly as sin, for bootstrapping the firmware only.
+# Rewrite cleanly as soon as is convenient.
+
+import sys, time, string, cStringIO, struct
+sys.path.append("/usr/lib/tinyos")
+import serial
+
+
+class GoodFET:
+    def __init__(self, *args, **kargs):
+        print "inited\n";
+        self.data=[0];
+    def timeout(self):
+        print "timout\n";
+    def serInit(self, port):
+        """Open the serial port"""
+        self.serialport = serial.Serial(
+            port,
+            9600,
+            parity = serial.PARITY_NONE
+            )
+        #Drop DTR, which is !RST, low to begin the app.
+        self.serialport.setDTR(0);
+        self.serialport.flushInput()
+        self.serialport.flushOutput()
+        
+        #Read and handle the initial command.
+        time.sleep(1);
+        self.readcmd(); #Read the first command.
+        if(self.verb!=0x7F):
+            print "Verb is wrong.  Incorrect firmware?";
+        
+        
+    def writecmd(self, app, verb, count, data):
+        """Write a command and some data to the GoodFET."""
+        self.serialport.write(chr(app));
+        self.serialport.write(chr(verb));
+        self.serialport.write(chr(count));
+        #print "count=%02x, len(data)=%04x" % (count,len(data));
+        if count!=0:
+            for d in data:
+                self.serialport.write(chr(d));
+        self.readcmd();  #Uncomment this later, to ensure a response.
+    def readcmd(self):
+        """Read a reply from the GoodFET."""
+        self.app=ord(self.serialport.read(1));
+        self.verb=ord(self.serialport.read(1));
+        self.count=ord(self.serialport.read(1));
+        if self.count>0:
+            self.data=self.serialport.read(self.count);
+        #print "READ %02x %02x %02x " % (self.app, self.verb, self.count);
+        
+    #Monitor stuff
+    def peekbyte(self,address):
+        """Read a byte of memory from the monitor."""
+        self.data=[address&0xff,address>>8];
+        self.writecmd(0,0x02,2,self.data);
+        #self.readcmd();
+        return ord(self.data[0]);
+    def peekword(self,address):
+        """Read a word of memory from the monitor."""
+        return self.peekbyte(address)+(self.peekbyte(address+1)<<8);
+    def pokebyte(self,address,value):
+        """Set a byte of memory by the monitor."""
+        self.data=[address&0xff,address>>8,value];
+        self.writecmd(0,0x03,3,self.data);
+        return ord(self.data[0]);
+    
+    def monitortest(self):
+        """Self-test several functions through the monitor."""
+        print "Performing monitor self-test.";
+        
+        if self.peekword(0x0c00)!=0x0c04:
+            print "ERROR Fetched wrong value from 0x0c04.";
+        self.pokebyte(0x0021,0); #Drop LED
+        if self.peekbyte(0x0021)!=0:
+            print "ERROR, P1OUT not cleared.";
+        self.pokebyte(0x0021,1); #Light LED
+        
+        print "Self-test complete.";
+    
+    def spisetup(self):
+        """Moved the FET into the SPI application."""
+        print "Initializing SPI.";
+        self.writecmd(1,0x10,0,self.data); #SPI/SETUP
+        #self.readcmd();
+    def spitrans8(self,byte):
+        """Read and write 8 bits by SPI."""
+        self.data=[byte];
+        self.writecmd(1,0,1,self.data);    #SPI exchange
+        #self.readcmd();
+        
+        if self.app!=1 or self.verb!=0:
+            print "Error in SPI transaction; app=%02x, verb=%02x" % (self.app, self.verb);
+        return ord(self.data[0]);
+    def MSP430setup(self):
+        """Move the FET into the MSP430 JTAG application."""
+        print "Initializing MSP430.";
+        self.writecmd(0x11,0x10,0,self.data);
+    def MSP430peek(self,adr):
+        """Read the contents of memory at an address."""
+        self.data=[adr&0xff, (adr&0xff00)>>8];
+        self.writecmd(0x11,0x02,2,self.data);
+        return ord(self.data[0])+(ord(self.data[1])<<8);
+    def MSP430poke(self,adr,val):
+        """Read the contents of memory at an address."""
+        self.data=[adr&0xff, (adr&0xff00)>>8, val&0xff, (val&0xff00)>>8];
+        self.writecmd(0x11,0x03,4,self.data);
+        return;# ord(self.data[0])+(ord(self.data[1])<<8);
+    
+    def MSP430start(self):
+        """Start debugging."""
+        self.writecmd(0x11,0x20,0,self.data);
+    def MSP430haltcpu(self):
+        """Halt the CPU."""
+        self.writecmd(0x11,0xA0,0,self.data);
+    def MSP430releasecpu(self):
+        """Resume the CPU."""
+        self.writecmd(0x11,0xA1,0,self.data);
+
+    def MSP430shiftir8(self,ins):
+        """Shift the 8-bit Instruction Register."""
+        data=[ins];
+        self.writecmd(0x11,0x80,1,data);
+        return ord(self.data[0]);
+    def MSP430shiftdr16(self,dat):
+        """Shift the 16-bit Data Register."""
+        data=[dat&0xFF,(dat&0xFF00)>>8];
+        self.writecmd(0x11,0x81,2,data);
+        return ord(self.data[0])#+(ord(self.data[1])<<8);
+    def MSP430setinstrfetch(self):
+        """Set the instruction fetch mode."""
+        self.writecmd(0x11,0xC1,0,self.data);
+        return self.data[0];
+    def MSP430test(self):
+        """Test MSP430 JTAG.  Requires that a chip be attached."""
+        self.MSP430setup();
+        self.MSP430start();
+        self.MSP430haltcpu();
+        
+        ident=self.MSP430peek(0x0ff0);
+        print "Target identifies as %04x." % ident;
+        if ident==0xffff:
+            print "Is anything connected?";
+        print "Testing RAM.";
+        temp=self.MSP430peek(0x0200);
+        self.MSP430poke(0x0200,0xdead);
+        if(self.MSP430peek(0x0200)!=0xdead):
+            print "Poke of 0x0200 did not set to 0xDEAD properly.";
+            exit;
+        self.MSP430poke(0x0200,temp); #restore old value.
+        self.MSP430releasecpu();
+        
+    def MSP430dumpbsl(self):
+        i=0xC00;
+        while i<0x1000:
+            print "%04x %04x" % (i, self.MSP430peek(i));
+            i+=2;
+
diff --git a/client/goodfet b/client/goodfet
deleted file mode 100755 (executable)
index 78171b7..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-#!/usr/bin/env python
-# GoodFET Client Application
-# 
-# (C) 2009 Travis Goodspeed <travis at radiantmachines.com>
-#
-# This code is ugly as sin, for bootstrapping the firmware only.
-# Rewrite cleanly as soon as is convenient.
-
-import sys, time, string, cStringIO, struct
-sys.path.append("/usr/lib/tinyos")
-import serial
-
-
-class Client:
-    def __init__(self, *args, **kargs):
-        print "inited\n";
-    def timeout(self):
-        print "timout\n";
-    def serInit(self, port):
-        """Open the serial port"""
-        self.serialport = serial.Serial(
-            port,
-            9600,
-            parity = serial.PARITY_NONE
-            )
-        #Drop DTR, which is !RST, low to begin the app.
-        self.serialport.setDTR(0);
-        self.serialport.flushInput()
-        self.serialport.flushOutput()
-        
-        #Read and handle the initial command.
-        time.sleep(1);
-        client.readcmd(); #Read the first command.
-        if(self.verb!=0x7F):
-            print "Verb is wrong.  Incorrect firmware?";
-        
-        
-    def writecmd(self, app, verb, count, data):
-        """Write a command and some data to the GoodFET."""
-        self.serialport.write(chr(app));
-        self.serialport.write(chr(verb));
-        self.serialport.write(chr(count));
-        #print "count=%02x, len(data)=%04x" % (count,len(data));
-        if count!=0:
-            for d in data:
-                self.serialport.write(chr(d));
-        self.readcmd();  #Uncomment this later, to ensure a response.
-    def readcmd(self):
-        """Read a reply from the GoodFET."""
-        self.app=ord(self.serialport.read(1));
-        self.verb=ord(self.serialport.read(1));
-        self.count=ord(self.serialport.read(1));
-        if self.count>0:
-            self.data=self.serialport.read(self.count);
-        #print "%02x %02x %02x" % (self.app, self.verb, self.count);
-    
-    #Monitor stuff
-    def peekbyte(self,address):
-        """Read a byte of memory from the monitor."""
-        self.data=[address&0xff,address>>8];
-        self.writecmd(0,0x02,2,self.data);
-        #self.readcmd();
-        return ord(self.data[0]);
-    def peekword(self,address):
-        """Read a word of memory from the monitor."""
-        return self.peekbyte(address)+(self.peekbyte(address+1)<<8);
-    def pokebyte(self,address,value):
-        """Set a byte of memory by the monitor."""
-        self.data=[address&0xff,address>>8,value];
-        self.writecmd(0,0x03,3,self.data);
-        return ord(self.data[0]);
-    
-    def monitortest(self):
-        """Self-test several functions through the monitor."""
-        print "Performing self-test.";
-        
-        if self.peekword(0x0c00)!=0x0c04:
-            print "ERROR Fetched wrong value from 0x0c04.";
-        self.pokebyte(0x0021,0); #Drop LED
-        if self.peekbyte(0x0021)!=0:
-            print "ERROR, P1OUT not cleared.";
-        self.pokebyte(0x0021,1); #Light LED
-        
-        print "Self-test complete.";
-    
-    def spisetup(self):
-        """Moved the FET into the SPI application."""
-        print "Initializing SPI.";
-        self.writecmd(1,0x10,0,self.data); #SPI/SETUP
-        #self.readcmd();
-    def spitrans8(self,byte):
-        """Read and write 8 bits by SPI."""
-        self.data=[byte];
-        self.writecmd(1,0,1,self.data);    #SPI exchange
-        #self.readcmd();
-        
-        if self.app!=1 or self.verb!=0:
-            print "Error in SPI transaction; app=%02x, verb=%02x" % (self.app, self.verb);
-        return ord(self.data[0]);
-
-client=Client();
-client.serInit("/dev/ttyUSB0")
-
-client.monitortest();
-
-client.spisetup();
-while 1:
-    print "%02x" % client.spitrans8(5);
-    time.sleep(0.1);
diff --git a/client/goodfet.msp430 b/client/goodfet.msp430
new file mode 100755 (executable)
index 0000000..8a17a26
--- /dev/null
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+
+from GoodFET import GoodFET;
+
+
+client=GoodFET();
+client.serInit("/dev/ttyUSB0")
+
+client.MSP430test();
+#client.MSP430dumpbsl();
+
+# client.MSP430setup();
+# client.MSP430start();
+# client.MSP430haltcpu();
+# ident=client.MSP430peek(0x0ff0);
+# print "Target identifies as %04x." % ident;
+
index 1ffeb5a..40114b3 100644 (file)
@@ -1,6 +1,6 @@
 
 PORT=/dev/ttyUSB0
 
 PORT=/dev/ttyUSB0
-BSL=tos-bsl --invert-reset --invert-test -c $(PORT)
+BSL=tos-bsl --invert-reset --invert-test -c $(PORT) --speed=38400
 
 #mcu=msp430x1611
 mcu=msp430x1612
 
 #mcu=msp430x1611
 mcu=msp430x1612
@@ -10,7 +10,7 @@ GCCINC=-T ../ldscripts/161x.x
 
 CC=msp430-gcc -g -mmcu=$(mcu) -DGCC $(GCCINC) -I ../include
 
 
 CC=msp430-gcc -g -mmcu=$(mcu) -DGCC $(GCCINC) -I ../include
 
-apps= monitor/monitor.c spi/spi.c i2c/i2c.c chipcon/chipcon.c jtag/jtag.c
+apps= monitor/monitor.c spi/spi.c i2c/i2c.c chipcon/chipcon.c jtag/jtag.c jtag/jtag430.c
 libs= ../lib/msp430f1612.c ../lib/command.c
 app=goodfet
 
 libs= ../lib/msp430f1612.c ../lib/command.c
 app=goodfet
 
@@ -18,10 +18,12 @@ all: $(app)
 
 goodfet.hex: goodfet
 
 
 goodfet.hex: goodfet
 
+run:
+       ../../client/goodfet.msp430
 
 install: $(app)
 
 install: $(app)
-       $(BSL) -e -p $(app) 
-       $(BSL) -P $(app) -r
+       $(BSL) -e -p $(app).hex 
+       $(BSL) -P $(app).hex -r
 $(app): $(app).c $(libs) $(apps)
 $(app).hex: $(app)
        msp430-objcopy goodfet -O ihex goodfet.hex
 $(app): $(app).c $(libs) $(apps)
 $(app).hex: $(app)
        msp430-objcopy goodfet -O ihex goodfet.hex
index 19feb63..a8d5b7a 100644 (file)
@@ -48,6 +48,9 @@ void handle(unsigned char app,
   case JTAG:\r
     jtaghandle(app,verb,len);\r
     break;\r
   case JTAG:\r
     jtaghandle(app,verb,len);\r
     break;\r
+  case JTAG430:\r
+    jtag430handle(app,verb,len);\r
+    break;\r
   default:\r
     txdata(app,NOK,0);\r
     break;\r
   default:\r
     txdata(app,NOK,0);\r
     break;\r
diff --git a/firmware/apps/jtag/Readme.txt b/firmware/apps/jtag/Readme.txt
new file mode 100644 (file)
index 0000000..862cb48
--- /dev/null
@@ -0,0 +1,5 @@
+GoodFET JTAG Applications
+by Travis Goodspeed
+
+Most MSP430 macros come from definitions in SLAU265A.
+
diff --git a/firmware/apps/jtag/jtag430.c b/firmware/apps/jtag/jtag430.c
new file mode 100644 (file)
index 0000000..03541c1
--- /dev/null
@@ -0,0 +1,209 @@
+
+#include "platform.h"
+#include "command.h"
+#include "jtag.h"
+
+
+//! Set the program counter.
+void jtag430_setpc(unsigned int adr){
+  jtag_ir_shift8(IR_CNTRL_SIG_16BIT);
+  jtag_dr_shift16(0x3401);// release low byte
+  jtag_ir_shift8(IR_DATA_16BIT);
+  jtag_dr_shift16(0x4030);//Instruction to load PC
+  CLRTCLK;
+  SETTCLK;
+  jtag_dr_shift16(adr);// Value for PC
+  CLRTCLK;
+  jtag_ir_shift8(IR_ADDR_CAPTURE);
+  SETTCLK;
+  CLRTCLK ;// Now PC is set to "PC_Value"
+  jtag_ir_shift8(IR_CNTRL_SIG_16BIT);
+  jtag_dr_shift16(0x2401);// low byte controlled by JTAG
+}
+
+//! Halt the CPU
+void jtag430_haltcpu(){
+  //jtag430_setinstrfetch();
+  
+  jtag_ir_shift8(IR_DATA_16BIT);
+  jtag_dr_shift16(0x3FFF);//JMP $+0
+  
+  CLRTCLK;
+  jtag_ir_shift8(IR_CNTRL_SIG_16BIT);
+  jtag_dr_shift16(0x2409);//set JTAG_HALT bit
+  SETTCLK;
+}
+
+//! Release the CPU
+void jtag430_releasecpu(){
+  CLRTCLK;
+  jtag_ir_shift8(IR_CNTRL_SIG_16BIT);
+  jtag_dr_shift16(0x2401);
+  jtag_ir_shift8(IR_ADDR_CAPTURE);
+  SETTCLK;
+}
+
+//! Read data from address
+unsigned int jtag430_readmem(unsigned int adr){
+  unsigned int toret;
+  
+  CLRTCLK;
+  jtag_ir_shift8(IR_CNTRL_SIG_16BIT);
+  if(adr>0xFF)
+    jtag_dr_shift16(0x2409);//word read
+  else
+    jtag_dr_shift16(0x2419);//byte read
+  jtag_ir_shift8(IR_ADDR_16BIT);
+  jtag_dr_shift16(adr);//address
+  jtag_ir_shift8(IR_DATA_TO_ADDR);
+  SETTCLK;
+
+  CLRTCLK;
+  toret=jtag_dr_shift16(0x0000);//16 bit return
+  
+  return toret;
+}
+
+//! Write data to address.
+void jtag430_writemem(unsigned int adr, unsigned int data){
+  CLRTCLK;
+  jtag_ir_shift8(IR_CNTRL_SIG_16BIT);
+  if(adr>0xFF)
+    jtag_dr_shift16(0x2408);//word write
+  else
+    jtag_dr_shift16(0x2418);//byte write
+  jtag_ir_shift8(IR_ADDR_16BIT);
+  jtag_dr_shift16(adr);
+  jtag_ir_shift8(IR_DATA_TO_ADDR);
+  jtag_dr_shift16(data);
+  SETTCLK;
+  
+}
+
+//! Write data to address.
+void jtag430_writeflash(unsigned int adr, unsigned int data){
+  //TODO; this is complicated.
+}
+
+
+//! Reset the TAP state machine.
+void jtag430_resettap(){
+  int i;
+  // Settle output
+  SETTMS;
+  SETTDI;
+  SETTCK;
+
+  // Navigate to reset state.
+  // Should be at least six.
+  for(i=0;i<4;i++){
+    CLRTCK;
+    SETTCK;
+  }
+
+  // test-logic-reset
+  CLRTCK;
+  CLRTMS;
+  SETTCK;
+  SETTMS;
+  // idle
+
+    
+  /* sacred, by spec.
+     Sometimes this isn't necessary. */
+  // fuse check
+  CLRTMS;
+  delay(50);
+  SETTMS;
+  CLRTMS;
+  delay(50);
+  SETTMS;
+  /**/
+  
+}
+
+//! Start JTAG, take pins
+void jtag430_start(){
+  jtagsetup();
+  
+  //Known-good starting position.
+  //Might be unnecessary.
+  SETTST;
+  SETRST;
+  delay(0xFFFF);
+  
+  //Entry sequence from Page 67 of SLAU265A for 4-wire MSP430 JTAG
+  CLRRST;
+  delay(100);
+  CLRTST;
+  delay(50);
+  SETTST;
+  delay(50);
+  SETRST;
+  P5DIR&=~RST;
+  delay(0xFFFF);
+}
+
+//! Set CPU to Instruction Fetch
+void jtag430_setinstrfetch(){
+  jtag_ir_shift8(IR_CNTRL_SIG_CAPTURE);
+
+  // Wait until instruction fetch state.
+  while(1){
+    if (jtag_dr_shift16(0x0000) & 0x0080)
+      return;
+    CLRTCLK;
+    SETTCLK;
+  }
+}
+
+//! Handles unique MSP430 JTAG commands.  Forwards others to JTAG.
+void jtag430handle(unsigned char app,
+                  unsigned char verb,
+                  unsigned char len){
+  unsigned char i;
+  switch(verb){
+  case START:
+    //Enter JTAG mode.
+    jtag430_start();
+    //TAP setup, fuse check
+    jtag430_resettap();
+    txdata(app,verb,0);
+    break;
+  case JTAG430_HALTCPU:
+    jtag430_haltcpu();
+    txdata(app,verb,0);
+    break;
+  case JTAG430_RELEASECPU:
+    jtag430_releasecpu();
+    txdata(app,verb,0);
+    break;
+  case JTAG430_SETINSTRFETCH:
+    jtag430_setinstrfetch();
+    txdata(app,verb,0);
+    break;
+
+    
+  case JTAG430_READMEM:
+  case PEEK:
+    cmddataword[0]=jtag430_readmem(cmddataword[0]);
+    txdata(app,verb,2);
+    break;
+  case JTAG430_WRITEMEM:
+  case POKE:
+    jtag430_writemem(cmddataword[0],cmddataword[1]);
+    txdata(app,verb,0);
+    break;
+  case JTAG430_WRITEFLASH:
+    jtag430_writeflash(cmddataword[0],cmddataword[1]);
+    txdata(app,verb,0);
+    break;
+  case JTAG430_SETPC:
+    jtag430_setpc(cmddataword[0]);
+    txdata(app,verb,0);
+    break;
+  default:
+    jtaghandle(app,verb,len);
+  }
+}
+
index 2c722c3..0c65462 100644 (file)
@@ -40,6 +40,21 @@ extern unsigned char cmddata[256];
 #define CC_MASS_ERASE_FLASH 0x97
 #define CC_PROGRAM_FLASH 0x98
 
 #define CC_MASS_ERASE_FLASH 0x97
 #define CC_PROGRAM_FLASH 0x98
 
+//JTAG commands
+#define JTAG_IR_SHIFT 0x80
+#define JTAG_DR_SHIFT 0x81
+#define JTAG_DR_SHIFT20 0x91
+
+//JTAG430 commands
+#define JTAG430_HALTCPU 0xA0
+#define JTAG430_RELEASECPU 0xA1
+#define JTAG430_SETINSTRFETCH 0xC1
+#define JTAG430_SETPC 0xC2
+#define JTAG430_WRITEMEM 0xE0
+#define JTAG430_WRITEFLASH 0xE1
+#define JTAG430_READMEM 0xE2
+
+
 //! Handle a command.  Defined in goodfet.c
 void handle(unsigned char app,
            unsigned char verb,
 //! Handle a command.  Defined in goodfet.c
 void handle(unsigned char app,
            unsigned char verb,
index 6f9b6dc..17833d6 100644 (file)
@@ -1,6 +1,105 @@
 
 
+#include <signal.h>
+#include <io.h>
+#include <iomacros.h>
+
+
+// Generic Commands
 
 //! Shift 8 bits of the IR.
 unsigned char jtag_ir_shift8(unsigned char);
 //! Shift 16 bits of the DR.
 
 //! Shift 8 bits of the IR.
 unsigned char jtag_ir_shift8(unsigned char);
 //! Shift 16 bits of the DR.
-unsigned int jtag_dr_shift16(unsigned int in);
+unsigned int jtag_dr_shift16(unsigned int);
+//! Stop JTAG, release pins
+void jtag_stop();
+
+
+// JTAG430 Commands
+
+//! Start JTAG, unique to the '430.
+void jtag430_start();
+//! Reset the TAP state machine, check the fuse.
+void jtag430_resettap();
+
+//High-level Macros follow
+//! Write data to address.
+void jtag430_writemem(unsigned int adr, unsigned int data);
+//! Read data from address
+unsigned int jtag430_readmem(unsigned int adr);
+//! Halt the CPU
+void jtag430_haltcpu();
+//! Release the CPU
+void jtag430_releasecpu();
+//! Set CPU to Instruction Fetch
+void jtag430_setinstrfetch();
+//! Set the program counter.
+void jtag430_setpc(unsigned int adr);
+//! Write data to address.
+void jtag430_writeflash(unsigned int adr, unsigned int data);
+
+//Pins.  Both SPI and JTAG names are acceptable.
+//#define SS   BIT0
+#define MOSI BIT1
+#define MISO BIT2
+#define SCK  BIT3
+
+#define TMS BIT0
+#define TDI BIT1
+#define TDO BIT2
+#define TCK BIT3
+
+#define TCLK TDI
+
+//These are not on P5
+#define RST BIT6
+#define TST BIT0
+
+//This could be more accurate.
+//Does it ever need to be?
+#define JTAGSPEED 20
+#define JTAGDELAY(x) delay(x)
+
+#define SETMOSI P5OUT|=MOSI
+#define CLRMOSI P5OUT&=~MOSI
+#define SETCLK P5OUT|=SCK
+#define CLRCLK P5OUT&=~SCK
+#define READMISO (P5IN&MISO?1:0)
+#define SETTMS P5OUT|=TMS
+#define CLRTMS P5OUT&=~TMS
+#define SETTCK P5OUT|=TCK
+#define CLRTCK P5OUT&=~TCK
+#define SETTDI P5OUT|=TDI
+#define CLRTDI P5OUT&=~TDI
+
+#define SETTST P4OUT|=TST
+#define CLRTST P4OUT&=~TST
+#define SETRST P2OUT|=RST
+#define CLRRST P2OUT&=~RST
+
+#define SETTCLK SETTDI
+#define CLRTCLK CLRTDI
+
+extern int savedtclk;
+#define SAVETCLK savedtclk=P5OUT&TCLK;
+#define RESTORETCLK if(savedtclk) P5OUT|=TCLK; else P5OUT&=~TCLK
+
+//JTAG commands, bit-swapped
+#define IR_CNTRL_SIG_16BIT         0xC8   // 0x13
+#define IR_CNTRL_SIG_CAPTURE       0x28   // 0x14
+#define IR_CNTRL_SIG_RELEASE       0xA8   // 0x15
+// Instructions for the JTAG Fuse
+#define IR_PREPARE_BLOW            0x44   // 0x22
+#define IR_EX_BLOW                 0x24   // 0x24
+// Instructions for the JTAG data register
+#define IR_DATA_16BIT              0x82   // 0x41
+#define IR_DATA_QUICK              0xC2   // 0x43
+// Instructions for the JTAG PSA mode
+#define IR_DATA_PSA                0x22   // 0x44
+#define IR_SHIFT_OUT_PSA           0x62   // 0x46
+// Instructions for the JTAG address register
+#define IR_ADDR_16BIT              0xC1   // 0x83
+#define IR_ADDR_CAPTURE            0x21   // 0x84
+#define IR_DATA_TO_ADDR            0xA1   // 0x85
+// Bypass instruction
+#define IR_BYPASS                  0xFF   // 0xFF
+
index 44a853d..9a9421d 100644 (file)
@@ -19,5 +19,5 @@ void txdata(unsigned char app,
 //! Delay for a count.
 void delay(unsigned int count){
   volatile unsigned int i=count;
 //! Delay for a count.
 void delay(unsigned int count){
   volatile unsigned int i=count;
-  while(i--);
+  while(i--) asm("nop");
 }
 }