Setting the default config in the Makefile so that it builds the exact same
[goodfet] / firmware / apps / jtag / jtag430x2.c
1 /*! \file jtag430x2.c
2   \author Travis Goodspeed <travis at radiantmachines.com>
3   \brief MSP430X2 JTAG (20-bit)
4 */
5
6 #include "platform.h"
7 #include "command.h"
8 #include "jtag430.h"
9 #include "jtag430x2.h"
10
11 void jtag430x2_handle_fn( uint8_t const app,
12                                                   uint8_t const verb,
13                                                   uint32_t const len);
14
15
16 // define the jtag430x2 app's app_t
17 app_t const jtag430x2_app = {
18
19         /* app number */
20         JTAG430X2,
21
22         /* handle fn */
23         jtag430x2_handle_fn,
24
25         /* name */
26         "JTAG430X2",
27
28         /* desc */
29         "\tThe JTAG430X2 app extends the basic JTAG app with support\n"
30         "\tfor 20-bit MSP430 devices.\n"
31 };
32
33
34 unsigned char jtagid;
35
36 //! Get the JTAG ID
37 unsigned char jtag430x2_jtagid(){
38   jtag430_resettap();
39   return jtagid=jtag_ir_shift8(IR_BYPASS);
40 }
41 //! Start JTAG, take pins
42 unsigned char jtag430x2_start(){
43   jtagsetup();
44   
45   //Known-good starting position.
46   //Might be unnecessary.
47   SETTST;
48   SETRST;
49   
50   delay(0xFFFF);
51   
52   //Entry sequence from Page 67 of SLAU265A for 4-wire MSP430 JTAG
53   CLRRST;
54   delay(20);//10
55   CLRTST;
56
57   delay(10);//5
58   SETTST;
59   msdelay(10);//5
60   SETRST;
61   P5DIR&=~RST;
62   
63   delay(0xFFFF);
64   
65   //Perform a reset and disable watchdog.
66   return jtag430x2_jtagid();
67 }
68
69 //! Grab the core ID.
70 unsigned int jtag430_coreid(){
71   jtag_ir_shift8(IR_COREIP_ID);
72   return jtag_dr_shift16(0);
73 }
74
75 //! Grab the device ID.
76 unsigned long jtag430_deviceid(){
77   jtag_ir_shift8(IR_DEVICE_ID);
78   return jtag_dr_shift20(0);
79 }
80
81
82 //! Write data to address
83 void jtag430x2_writemem(unsigned long adr,
84                         unsigned int data){
85   jtag_ir_shift8(IR_CNTRL_SIG_CAPTURE);
86   if(jtag_dr_shift16(0) & 0x0301){
87     CLRTCLK;
88     jtag_ir_shift8(IR_CNTRL_SIG_16BIT);
89     if(adr>=0x100)
90       jtag_dr_shift16(0x0500);//word mode
91     else
92       jtag_dr_shift16(0x0510);//byte mode
93     jtag_ir_shift8(IR_ADDR_16BIT);
94     jtag_dr_shift20(adr);
95     
96     SETTCLK;
97     
98     jtag_ir_shift8(IR_DATA_TO_ADDR);
99     jtag_dr_shift16(data);//16 word
100
101     CLRTCLK;
102     jtag_ir_shift8(IR_CNTRL_SIG_16BIT);
103     jtag_dr_shift16(0x0501);
104     SETTCLK;
105
106     CLRTCLK;
107     SETTCLK;
108     //init state
109   }else{
110     while(1) PLEDOUT^=PLEDPIN; //loop if locked up
111   }
112 }
113
114 //! Read data from address
115 unsigned int jtag430x2_readmem(unsigned long adr){
116   unsigned int toret=0;
117   //unsigned int tries=5;
118   
119   while(1){
120     //do{
121     jtag_ir_shift8(IR_CNTRL_SIG_CAPTURE);
122     //}while(!(jtag_dr_shift16(0) & 0x0301));
123     
124     if(jtag_dr_shift16(0) & 0x0301){
125       // Read Memory
126       CLRTCLK;
127       jtag_ir_shift8(IR_CNTRL_SIG_16BIT);
128       
129       //if(adr>=0x100){
130       jtag_dr_shift16(0x0501);//word read
131       //}else{
132       //jtag_dr_shift16(0x0511);//byte read
133       //}
134       
135       jtag_ir_shift8(IR_ADDR_16BIT);
136       jtag_dr_shift20(adr); //20
137       
138       jtag_ir_shift8(IR_DATA_TO_ADDR);
139       SETTCLK;
140       CLRTCLK;
141       toret = jtag_dr_shift16(0x0000);
142       
143       SETTCLK;
144       
145       //Cycle a bit.
146       CLRTCLK;
147       SETTCLK;
148       return toret;
149     }
150   }
151   //return toret;
152 }
153
154 //! Syncs a POR.
155 unsigned int jtag430x2_syncpor(){
156   jtag_ir_shift8(IR_CNTRL_SIG_16BIT);
157   jtag_dr_shift16(0x1501); //JTAG mode
158   while(!(jtag_dr_shift16(0) & 0x200));
159   return jtag430x2_por();
160 }
161
162 //! Executes an MSP430X2 POR
163 unsigned int jtag430x2_por(){
164   unsigned int i = 0;
165   
166   // tick
167   CLRTCLK;
168   SETTCLK;
169
170   jtag_ir_shift8(IR_CNTRL_SIG_16BIT);
171   jtag_dr_shift16(0x0C01);
172   jtag_dr_shift16(0x0401);
173   
174   //cycle
175   for (i = 0; i < 10; i++){
176     CLRTCLK;
177     SETTCLK;
178   }
179   
180   jtag_dr_shift16(0x0501);
181   
182   // tick
183   CLRTCLK;
184   SETTCLK;
185   
186   
187   // Disable WDT
188   jtag430x2_writemem(0x015C, 0x5A80);
189   
190   // check state
191   jtag_ir_shift8(IR_CNTRL_SIG_CAPTURE);
192   if(jtag_dr_shift16(0) & 0x0301)
193     return(1);//ok
194   
195   return 0;//error
196 }
197
198
199 //! Check the fuse.
200 unsigned int jtag430x2_fusecheck(){
201   int i;
202   for(i=0;i<3;i++){
203     jtag_ir_shift8(IR_CNTRL_SIG_CAPTURE);
204     if(jtag_dr_shift16(0xAAAA)==0x5555)
205       return 1;//blown
206   }
207   return 0;//unblown
208 }
209
210
211 //! Handles MSP430X2 JTAG commands.  Forwards others to JTAG.
212 void jtag430x2_handle_fn( uint8_t const app,
213                                                   uint8_t const verb,
214                                                   uint32_t const len)
215 {
216   register char blocks;
217   
218   unsigned int i,val;
219   unsigned long at, l;
220   
221   //jtag430_resettap();
222   
223   if(verb!=START && jtag430mode==MSP430MODE){
224     (*(jtag430_app.handle))(app,verb,len);
225     return;
226   }
227   
228   switch(verb){
229   case START:
230     //Enter JTAG mode.
231     //do 
232     cmddata[0]=jtag430x2_start();
233     //while(cmddata[0]==00 || cmddata[0]==0xFF);
234     
235     //MSP430 or MSP430X
236     if(jtagid==MSP430JTAGID){ 
237       jtag430mode=MSP430MODE;
238       
239       /* So the way this works is that a width of 20 does some
240          backward-compatibility finagling, causing the correct value
241          to be exchanged for addresses on 16-bit chips as well as the
242          new MSP430X chips.  (This has only been verified on the
243          MSP430F2xx family.  TODO verify for others.)
244        */
245
246       drwidth=20;
247       
248       //Perform a reset and disable watchdog.
249       jtag430_por();
250       jtag430_writemem(0x120,0x5a80);//disable watchdog
251       
252       jtag430_haltcpu();
253       
254       jtag430_resettap();
255       txdata(app,verb,1);
256       return;
257     }else if(jtagid==MSP430X2JTAGID){
258       jtag430mode=MSP430X2MODE;
259       drwidth=20;
260     }else{
261       debugstr("JTAG version unknown.");
262       txdata(app,NOK,1);
263       return;
264     }
265     
266     jtag430x2_fusecheck();
267         
268     jtag430x2_syncpor();
269     
270     jtag430_resettap();
271     
272     txdata(app,verb,1);
273     break;
274   case JTAG430_READMEM:
275   case PEEK:
276     blocks=(len>4?cmddata[4]:1);
277     at=cmddatalong[0];
278     
279     l=0x80;
280     txhead(app,verb,l);
281     
282     while(blocks--){
283       for(i=0;i<l;i+=2){
284         jtag430_resettap();
285         delay(10);
286         
287         val=jtag430x2_readmem(at);
288                 
289         at+=2;
290         serial_tx(val&0xFF);
291         serial_tx((val&0xFF00)>>8);
292       }
293     }
294     
295     break;
296   case JTAG430_COREIP_ID:
297     cmddataword[0]=jtag430_coreid();
298     txdata(app,verb,2);
299     break;
300   case JTAG430_DEVICE_ID:
301     cmddatalong[0]=jtag430_deviceid();
302     txdata(app,verb,4);
303     break;
304   case JTAG430_WRITEFLASH:
305   case JTAG430_WRITEMEM:
306   case POKE:
307     jtag430x2_writemem(cmddatalong[0],
308                        cmddataword[2]);
309     cmddataword[0]=jtag430x2_readmem(cmddatalong[0]);
310     txdata(app,verb,2);
311     break;
312
313     //unimplemented functions
314   case JTAG430_HALTCPU:  
315   case JTAG430_RELEASECPU:
316   case JTAG430_SETINSTRFETCH:
317
318   case JTAG430_ERASEFLASH:
319   case JTAG430_SETPC:
320     debugstr("This function is not yet implemented for MSP430X2.");
321     debughex(verb);
322     txdata(app,NOK,0);
323     break;
324   default:
325     (*(jtag_app.handle))(app,verb,len);
326   }
327   jtag430_resettap();
328 }
329