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