X-Git-Url: http://git.rot13.org/?p=goodfet;a=blobdiff_plain;f=firmware%2Fapps%2Fjtag%2Fjtag430x2.c;h=f499de2ce47a7f98dc08faaeb36a53d35460a5b6;hp=5e76aa522f7d2842c3bb8bdf59a440027303af03;hb=5c029aa0c4f7573d9fa49beefe6e887dee2b25f9;hpb=2b654b579b948558edecc63dd7ab3aa4543f050d diff --git a/firmware/apps/jtag/jtag430x2.c b/firmware/apps/jtag/jtag430x2.c index 5e76aa5..f499de2 100644 --- a/firmware/apps/jtag/jtag430x2.c +++ b/firmware/apps/jtag/jtag430x2.c @@ -1,10 +1,6 @@ /*! \file jtag430x2.c \author Travis Goodspeed - - This is an implementation of the MSP430X2 JTAG protocol - for the GoodFET project at http://goodfet.sf.net/ - - See the license file for details of proper use. + \brief MSP430X2 JTAG (20-bit) */ #include "platform.h" @@ -31,12 +27,12 @@ unsigned char jtag430x2_start(){ //Entry sequence from Page 67 of SLAU265A for 4-wire MSP430 JTAG CLRRST; - delay(10); + delay(20);//10 CLRTST; - delay(5); + delay(10);//5 SETTST; - msdelay(5); + msdelay(10);//5 SETRST; P5DIR&=~RST; @@ -60,10 +56,10 @@ unsigned long jtag430_deviceid(){ //! Write data to address -unsigned int jtag430x2_writemem(unsigned long adr, - unsigned long data){ +void jtag430x2_writemem(unsigned long adr, + unsigned int data){ jtag_ir_shift8(IR_CNTRL_SIG_CAPTURE); - if(jtag_ir_shift8(0) & 0x0301){ + if(jtag_dr_shift16(0) & 0x0301){ CLRTCLK; jtag_ir_shift8(IR_CNTRL_SIG_16BIT); if(adr>=0x100) @@ -94,71 +90,182 @@ unsigned int jtag430x2_writemem(unsigned long adr, //! Read data from address unsigned int jtag430x2_readmem(unsigned long adr){ unsigned int toret=0; - - jtag_ir_shift8(IR_CNTRL_SIG_CAPTURE); - if(jtag_dr_shift16(0) & 0x0301){ - // Read Memory - CLRTCLK; - jtag_ir_shift8(IR_CNTRL_SIG_16BIT); - if(adr>=0x100){ - jtag_dr_shift16(0x0501);//word read - }else{ - jtag_dr_shift16(0x0511);//byte read + //unsigned int tries=5; + + while(1){ + do{ + jtag_ir_shift8(IR_CNTRL_SIG_CAPTURE); + }while(!(jtag_dr_shift16(0) & 0x0301)); + + if(jtag_dr_shift16(0) & 0x0301){ + // Read Memory + CLRTCLK; + jtag_ir_shift8(IR_CNTRL_SIG_16BIT); + if(adr>=0x100){ + jtag_dr_shift16(0x0501);//word read + }else{ + jtag_dr_shift16(0x0511);//byte read + } + + jtag_ir_shift8(IR_ADDR_16BIT); + jtag_dr_shift20(adr); //20 + + jtag_ir_shift8(IR_DATA_TO_ADDR); + SETTCLK; + CLRTCLK; + toret = jtag_dr_shift16(0x0000); + + SETTCLK; + + //Cycle a bit. + CLRTCLK; + SETTCLK; + return toret; } - jtag_ir_shift8(IR_ADDR_16BIT); - jtag_dr_shift20(adr); //20 + } + //return toret; +} - jtag_ir_shift8(IR_DATA_TO_ADDR); - SETTCLK; - CLRTCLK; - toret = jtag_dr_shift16(0x0000); - - SETTCLK; - // one or more cycle, so CPU is driving correct MAB +//! Syncs a POR. +unsigned int jtag430x2_syncpor(){ + jtag_ir_shift8(IR_CNTRL_SIG_16BIT); + jtag_dr_shift16(0x1501); //JTAG mode + while(!(jtag_dr_shift16(0) & 0x200)); + return jtag430x2_por(); +} + +//! Executes an MSP430X2 POR +unsigned int jtag430x2_por(){ + unsigned int i = 0; + + // tick + CLRTCLK; + SETTCLK; + jtag_ir_shift8(IR_CNTRL_SIG_16BIT); + jtag_dr_shift16(0x0C01); + jtag_dr_shift16(0x0401); + + //cycle + for (i = 0; i < 10; i++){ CLRTCLK; SETTCLK; - // Processor is now again in Init State - }else{ - return 0xDEAD; } - return toret; + jtag_dr_shift16(0x0501); + + // tick + CLRTCLK; + SETTCLK; + + + // Disable WDT + jtag430x2_writemem(0x015C, 0x5A80); + + // check state + jtag_ir_shift8(IR_CNTRL_SIG_CAPTURE); + if(jtag_dr_shift16(0) & 0x0301) + return(1);//ok + + return 0;//error } -//! Handles classic MSP430 JTAG commands. Forwards others to JTAG. +//! Check the fuse. +unsigned int jtag430x2_fusecheck(){ + int i; + for(i=0;i<3;i++){ + jtag_ir_shift8(IR_CNTRL_SIG_CAPTURE); + if(jtag_dr_shift16(0xAAAA)==0x5555) + return 1;//blown + } + return 0;//unblown +} + + +//! Handles MSP430X2 JTAG commands. Forwards others to JTAG. void jtag430x2handle(unsigned char app, - unsigned char verb, - unsigned char len){ - jtag430_resettap(); + unsigned char verb, + unsigned long len){ + register char blocks; + + unsigned int i,val; + unsigned long at; + + //jtag430_resettap(); + + if(verb!=START && jtag430mode==MSP430MODE){ + jtag430handle(app,verb,len); + return; + } + switch(verb){ case START: //Enter JTAG mode. - do cmddata[0]=jtag430x2_start(); - while(cmddata[0]==00 || cmddata[0]==0xFF); + //do + cmddata[0]=jtag430x2_start(); + //while(cmddata[0]==00 || cmddata[0]==0xFF); //MSP430 or MSP430X if(jtagid==MSP430JTAGID){ jtag430mode=MSP430MODE; - drwidth=16; + + /* So the way this works is that a width of 20 does some + backward-compatibility finagling, causing the correct value + to be exchanged for addresses on 16-bit chips as well as the + new MSP430X chips. (This has only been verified on the + MSP430F2xx family. TODO verify for others.) + */ + + drwidth=20; + + //Perform a reset and disable watchdog. + jtag430_por(); + jtag430_writemem(0x120,0x5a80);//disable watchdog + + jtag430_haltcpu(); + + jtag430_resettap(); + txdata(app,verb,1); + return; }else if(jtagid==MSP430X2JTAGID){ jtag430mode=MSP430X2MODE; drwidth=20; }else{ + debugstr("JTAG version unknown."); txdata(app,NOK,1); return; } - //TAP setup, fuse check - //jtag430_resettap(); + jtag430x2_fusecheck(); + + jtag430x2_syncpor(); + + jtag430_resettap(); + txdata(app,verb,1); break; case JTAG430_READMEM: case PEEK: - //cmddataword[0]=jtag430x2_readmem(cmddataword[0]); - cmddataword[0]=jtag430x2_readmem(cmddatalong[0]); - txdata(app,verb,2); + blocks=(len>4?cmddata[4]:1); + at=cmddatalong[0]; + + len=0x80; + txhead(app,verb,len); + + while(blocks--){ + for(i=0;i>8); + } + } + break; case JTAG430_COREIP_ID: cmddataword[0]=jtag430_coreid(); @@ -168,19 +275,24 @@ void jtag430x2handle(unsigned char app, cmddatalong[0]=jtag430_deviceid(); txdata(app,verb,4); break; - case JTAG430_HALTCPU: - case JTAG430_RELEASECPU: - case JTAG430_SETINSTRFETCH: + case JTAG430_WRITEMEM: case POKE: - jtag430x2_writemem(cmddataword[0], - cmddataword[1]); - cmddataword[0]=jtag430x2_readmem(cmddataword[0]); + jtag430x2_writemem(cmddatalong[0], + cmddataword[2]); + cmddataword[0]=jtag430x2_readmem(cmddatalong[0]); txdata(app,verb,2); break; + + //unimplemented functions + case JTAG430_HALTCPU: + case JTAG430_RELEASECPU: + case JTAG430_SETINSTRFETCH: case JTAG430_WRITEFLASH: case JTAG430_ERASEFLASH: case JTAG430_SETPC: + txdata(app,NOK,0); + break; default: jtaghandle(app,verb,len); }