X-Git-Url: http://git.rot13.org/?p=goodfet;a=blobdiff_plain;f=firmware%2Fapps%2Fjtag%2Fjtag430x2.c;h=265dae08b1ecb0fbc64f213341f75818d7046f03;hp=e25a90525f0d7357702b9d1317284e66dbe25763;hb=6d6a522d3adf0ddd18d30f24fd6bba0cc3547041;hpb=3e4369fde16445c994da1b1efb332704aad0716d diff --git a/firmware/apps/jtag/jtag430x2.c b/firmware/apps/jtag/jtag430x2.c index e25a905..265dae0 100644 --- a/firmware/apps/jtag/jtag430x2.c +++ b/firmware/apps/jtag/jtag430x2.c @@ -1,146 +1,268 @@ /*! \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" #include "command.h" -#include "jtag.h" +#include "jtag430.h" +#include "jtag430x2.h" -unsigned char jtagid; +void jtag430x2_handle_fn( uint8_t const app, + uint8_t const verb, + uint32_t const len); -//! Get the JTAG ID -unsigned char jtag430x2_jtagid(){ - jtag430_resettap(); - return jtagid=jtag_ir_shift8(IR_BYPASS); -} -//! Start JTAG, take pins -unsigned char jtag430x2_start(){ - jtagsetup(); + +// define the jtag430x2 app's app_t +app_t const jtag430x2_app = { + /* app number */ + JTAG430X2, - //Known-good starting position. - //Might be unnecessary. - SETTST; - SETRST; + /* handle fn */ + jtag430x2_handle_fn, - delay(0xFFFF); + /* name */ + "JTAG430X2", - //Entry sequence from Page 67 of SLAU265A for 4-wire MSP430 JTAG - CLRRST; - delay(10); - CLRTST; + /* desc */ + "\tThe JTAG430X2 app extends the basic JTAG app with support\n" + "\tfor 20-bit MSP430X2 devices, such as the MSP430F5xx Family.\n" +}; - delay(5); - SETTST; - msdelay(5); - SETRST; - P5DIR&=~RST; - - delay(0xFFFF); - - //Perform a reset and disable watchdog. - return jtag430x2_jtagid(); -} +//! Grab the core ID. unsigned int jtag430_coreid(){ jtag_ir_shift8(IR_COREIP_ID); return jtag_dr_shift16(0); } +//! Grab the device ID. unsigned long jtag430_deviceid(){ jtag_ir_shift8(IR_DEVICE_ID); - return jtag_dr_shift(0); + return jtag_dr_shift20(0); } -//! Set the program counter. -void jtag430x2_setpc(unsigned long pc){ - unsigned short Mova; - unsigned short Pc_l; - - Mova = 0x0080; - Mova += (unsigned short)((pc>>8) & 0x00000F00); - Pc_l = (unsigned short)((pc & 0xFFFF)); - // Check Full-Emulation-State at the beginning +//! Write data to address +void jtag430x2_writemem(unsigned long adr, + unsigned int data){ jtag_ir_shift8(IR_CNTRL_SIG_CAPTURE); if(jtag_dr_shift16(0) & 0x0301){ - // MOVA #imm20, PC + CLRTCLK; + jtag_ir_shift8(IR_CNTRL_SIG_16BIT); + if(adr>=0x100) + jtag_dr_shift16(0x0500);//word mode + else + jtag_dr_shift16(0x0510);//byte mode + jtag_ir_shift8(IR_ADDR_16BIT); + jtag_dr_shift20(adr); + + SETTCLK; + + jtag_ir_shift8(IR_DATA_TO_ADDR); + jtag_dr_shift16(data);//16 word + + CLRTCLK; + jtag_ir_shift8(IR_CNTRL_SIG_16BIT); + jtag_dr_shift16(0x0501); + SETTCLK; + + CLRTCLK; + SETTCLK; + //init state + }else{ + while(1) PLEDOUT^=PLEDPIN; //loop if locked up + } +} + +//! Read data from address +unsigned int jtag430x2_readmem(unsigned long adr){ + unsigned int toret=0; + //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; - // take over bus control during clock LOW phase - jtag_ir_shift8(IR_DATA_16BIT); - SETTCLK; - jtag_dr_shift16(Mova); jtag_ir_shift8(IR_CNTRL_SIG_16BIT); - jtag_dr_shift16(0x1400); - jtag_ir_shift8(IR_DATA_16BIT); - CLRTCLK; + + //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; - jtag_dr_shift16(Pc_l); CLRTCLK; + toret = jtag_dr_shift16(0x0000); + SETTCLK; - jtag_dr_shift16(0x4303); + + //Cycle a bit. CLRTCLK; - jtag_ir_shift8(IR_ADDR_CAPTURE); - jtag_dr_shift(0x00000); + SETTCLK; + return toret; + } } + //return toret; } -//! Read data from address -unsigned int jtag430x2_readmem(unsigned int adr){ - unsigned int toret; +//! 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; - //SETPC_430Xv2(StartAddr); + // 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; + } + jtag_dr_shift16(0x0501); - jtag_ir_shift8(IR_ADDR_CAPTURE); - - jtag_ir_shift8(IR_DATA_QUICK); - - SETTCLK; + + // tick CLRTCLK; - toret = jtag_dr_shift16(0);//read - + 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 toret; + return 0;//error +} + + +//! 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 classic MSP430 JTAG commands. Forwards others to JTAG. -void jtag430x2handle(unsigned char app, - unsigned char verb, - unsigned char len){ +//! Handles MSP430X2 JTAG commands. Forwards others to JTAG. +void jtag430x2_handle_fn( uint8_t const app, + uint8_t const verb, + uint32_t const len) +{ + register char blocks; + + unsigned int i,val; + unsigned long at, l; + + //jtag430_resettap(); + + if(verb!=START && jtag430mode==MSP430MODE){ + (*(jtag430_app.handle))(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){ + //debugstr("ERROR, using JTAG430X2 instead of JTAG430!"); 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]); - txdata(app,verb,2); + at=cmddatalong[0]; + + //Fetch large blocks for bulk fetches, + //small blocks for individual peeks. + if(len>5) + l=(cmddataword[2]);//always even. + else + l=2; + l&=~1;//clear lsbit + + if(l<2) l=2; + + txhead(app,verb,l); + for(i=0;i>8); + } + break; case JTAG430_COREIP_ID: cmddataword[0]=jtag430_coreid(); @@ -150,16 +272,33 @@ void jtag430x2handle(unsigned char app, cmddatalong[0]=jtag430_deviceid(); txdata(app,verb,4); break; + case JTAG430_WRITEFLASH: + case JTAG430_WRITEMEM: + case POKE: + jtag430x2_writemem(cmddatalong[0], + cmddataword[2]); + cmddataword[0]=jtag430x2_readmem(cmddatalong[0]); + txdata(app,verb,2); + break; + + //unimplemented functions case JTAG430_HALTCPU: + //jtag430x2_haltcpu(); + debugstr("Warning, not trying to halt for lack of code."); + txdata(app,verb,0); + break; case JTAG430_RELEASECPU: case JTAG430_SETINSTRFETCH: - case JTAG430_WRITEMEM: - case POKE: - case JTAG430_WRITEFLASH: + case JTAG430_ERASEFLASH: case JTAG430_SETPC: + debugstr("This function is not yet implemented for MSP430X2."); + debughex(verb); + txdata(app,NOK,0); + break; default: - jtaghandle(app,verb,len); + (*(jtag_app.handle))(app,verb,len); } jtag430_resettap(); } +