981a0487079444927c27153eb3b9f7bebcfb8c9b
[goodfet] / firmware / apps / jtag / jtag430x2.c
1 /*! \file jtag430x2.c
2   \author Travis Goodspeed <travis at radiantmachines.com>
3   
4   This is an implementation of the MSP430X2 JTAG protocol
5   for the GoodFET project at http://goodfet.sf.net/
6   
7   See the license file for details of proper use.
8 */
9
10 #include "platform.h"
11 #include "command.h"
12 #include "jtag.h"
13
14 unsigned char jtagid;
15
16 //! Get the JTAG ID
17 unsigned char jtag430x2_jtagid(){
18   jtag430_resettap();
19   return jtagid=jtag_ir_shift8(IR_BYPASS);
20 }
21 //! Start JTAG, take pins
22 unsigned char jtag430x2_start(){
23   jtagsetup();
24   
25   //Known-good starting position.
26   //Might be unnecessary.
27   SETTST;
28   SETRST;
29   
30   delay(0xFFFF);
31   
32   //Entry sequence from Page 67 of SLAU265A for 4-wire MSP430 JTAG
33   CLRRST;
34   delay(10);
35   CLRTST;
36
37   delay(5);
38   SETTST;
39   msdelay(5);
40   SETRST;
41   P5DIR&=~RST;
42   
43   delay(0xFFFF);
44   
45   //Perform a reset and disable watchdog.
46   return jtag430x2_jtagid();
47 }
48
49 //! Grab the core ID.
50 unsigned int jtag430_coreid(){
51   jtag_ir_shift8(IR_COREIP_ID);
52   return jtag_dr_shift16(0);
53 }
54
55 //! Grab the device ID.
56 unsigned long jtag430_deviceid(){
57   jtag_ir_shift8(IR_DEVICE_ID);
58   return jtag_dr_shift20(0);
59 }
60
61
62 //! Write data to address
63 void jtag430x2_writemem(unsigned long adr,
64                         unsigned int data){
65   jtag_ir_shift8(IR_CNTRL_SIG_CAPTURE);
66   if(jtag_dr_shift16(0) & 0x0301){
67     CLRTCLK;
68     jtag_ir_shift8(IR_CNTRL_SIG_16BIT);
69     if(adr>=0x100)
70       jtag_dr_shift16(0x0500);//word mode
71     else
72       jtag_dr_shift16(0x0510);//byte mode
73     jtag_ir_shift8(IR_ADDR_16BIT);
74     jtag_dr_shift20(adr);
75     
76     SETTCLK;
77     
78     jtag_ir_shift8(IR_DATA_TO_ADDR);
79     jtag_dr_shift16(data);//16 word
80
81     CLRTCLK;
82     jtag_ir_shift8(IR_CNTRL_SIG_16BIT);
83     jtag_dr_shift16(0x0501);
84     SETTCLK;
85
86     CLRTCLK;
87     SETTCLK;
88     //init state
89   }else{
90     while(1) P1OUT^=1; //loop if locked up
91   }
92 }
93
94 //! Read data from address
95 unsigned int jtag430x2_readmem(unsigned long adr){
96   unsigned int toret=0;
97   unsigned int tries=5;
98   
99   while(1){
100     do{
101       jtag_ir_shift8(IR_CNTRL_SIG_CAPTURE);
102     }while(!(jtag_dr_shift16(0) & 0x0301));
103     
104     if(jtag_dr_shift16(0) & 0x0301){
105       // Read Memory
106       CLRTCLK;
107       jtag_ir_shift8(IR_CNTRL_SIG_16BIT);
108       if(adr>=0x100){
109         jtag_dr_shift16(0x0501);//word read
110       }else{
111         jtag_dr_shift16(0x0511);//byte read
112       }
113       
114       jtag_ir_shift8(IR_ADDR_16BIT);
115       jtag_dr_shift20(adr); //20
116       
117       jtag_ir_shift8(IR_DATA_TO_ADDR);
118       SETTCLK;
119       CLRTCLK;
120       toret = jtag_dr_shift16(0x0000);
121       
122       SETTCLK;
123       
124       //Cycle a bit.
125       CLRTCLK;
126       SETTCLK;
127       return toret;
128     }
129   }
130   //return toret;
131 }
132
133 //! Syncs a POR.
134 unsigned int jtag430x2_syncpor(){
135   jtag_ir_shift8(IR_CNTRL_SIG_16BIT);
136   jtag_dr_shift16(0x1501); //JTAG mode
137   while(!(jtag_dr_shift16(0) & 0x200));
138   return jtag430x2_por();
139 }
140
141 //! Executes an MSP430X2 POR
142 unsigned int jtag430x2_por(){
143   unsigned int i = 0;
144   
145   // tick
146   CLRTCLK;
147   SETTCLK;
148
149   jtag_ir_shift8(IR_CNTRL_SIG_16BIT);
150   jtag_dr_shift16(0x0C01);
151   jtag_dr_shift16(0x0401);
152   
153   //cycle
154   for (i = 0; i < 10; i++){
155     CLRTCLK;
156     SETTCLK;
157   }
158   
159   jtag_dr_shift16(0x0501);
160   
161   // tick
162   CLRTCLK;
163   SETTCLK;
164   
165   
166   // Disable WDT
167   jtag430x2_writemem(0x015C, 0x5A80);
168   
169   // check state
170   jtag_ir_shift8(IR_CNTRL_SIG_CAPTURE);
171   if(jtag_dr_shift16(0) & 0x0301)
172     return(1);//ok
173   
174   return 0;//error
175 }
176
177
178 //! Check the fuse.
179 unsigned int jtag430x2_fusecheck(){
180   int i;
181   for(i=0;i<3;i++){
182     jtag_ir_shift8(IR_CNTRL_SIG_CAPTURE);
183     if(jtag_dr_shift16(0xAAAA)==0x5555)
184       return 1;//blown
185   }
186   return 0;//unblown
187 }
188
189
190 //! Handles MSP430X2 JTAG commands.  Forwards others to JTAG.
191 void jtag430x2handle(unsigned char app,
192                      unsigned char verb,
193                      unsigned char len){
194   register char blocks;
195   
196   unsigned int i,val;
197   unsigned long at;
198   
199   //jtag430_resettap();
200   
201   switch(verb){
202   case START:
203     //Enter JTAG mode.
204     //do 
205       cmddata[0]=jtag430x2_start();
206     //while(cmddata[0]==00 || cmddata[0]==0xFF);
207     
208     //MSP430 or MSP430X
209     if(jtagid==MSP430JTAGID){ 
210       jtag430mode=MSP430MODE;
211       drwidth=16;
212     }else if(jtagid==MSP430X2JTAGID){
213       jtag430mode=MSP430X2MODE;
214       drwidth=20;
215     }else{
216       txdata(app,NOK,1);
217       return;
218     }
219     
220     jtag430x2_fusecheck();
221         
222     jtag430x2_syncpor();
223     
224     jtag430_resettap();
225     
226     txdata(app,verb,1);
227     break;
228   case JTAG430_READMEM:
229   case PEEK:
230     blocks=(len>4?cmddata[4]:1);
231     at=cmddatalong[0];
232     
233     /*
234     cmddataword[0]=jtag430x2_readmem(at);
235     txdata(app,verb,2);
236     break;
237     */
238     
239     len=0x80;
240     serial_tx(app);
241     serial_tx(verb);
242     serial_tx(len);
243     
244     while(blocks--){
245       for(i=0;i<len;i+=2){
246         jtag430_resettap();
247         delay(10);
248         
249         val=jtag430x2_readmem(at);
250                 
251         at+=2;
252         serial_tx(val&0xFF);
253         serial_tx((val&0xFF00)>>8);
254       }
255     }
256     
257     break;
258   case JTAG430_COREIP_ID:
259     cmddataword[0]=jtag430_coreid();
260     txdata(app,verb,2);
261     break;
262   case JTAG430_DEVICE_ID:
263     cmddatalong[0]=jtag430_deviceid();
264     txdata(app,verb,4);
265     break;
266   case JTAG430_HALTCPU:
267     //jtag430x2_haltcpu();
268     break;
269
270   case POKE:
271     jtag430x2_writemem(cmddatalong[0],
272                        cmddataword[2]);
273     cmddataword[0]=jtag430x2_readmem(cmddatalong[0]);
274     txdata(app,verb,2);
275     break;
276   case JTAG430_RELEASECPU:
277     
278   case JTAG430_SETINSTRFETCH:
279   case JTAG430_WRITEMEM:
280   case JTAG430_WRITEFLASH:
281   case JTAG430_ERASEFLASH:
282   case JTAG430_SETPC:
283     txdata(app,NOK,0);
284     break;
285   default:
286     jtaghandle(app,verb,len);
287   }
288   jtag430_resettap();
289 }