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