Cleaning MSP430X2 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
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       jtag_dr_shift16(0x0501);//word read
94       
95       jtag_ir_shift8(IR_ADDR_16BIT);
96       jtag_dr_shift20(adr); //20
97       
98       jtag_ir_shift8(IR_DATA_TO_ADDR);
99       SETTCLK;
100       CLRTCLK;
101       toret = jtag_dr_shift16(0x0000);
102       
103       SETTCLK;
104       
105       //Cycle a bit.
106       CLRTCLK;
107       SETTCLK;
108       return toret;
109     }
110     
111     return 0xdead;
112   }
113   //return toret;
114 }
115
116 //! Syncs a POR.
117 unsigned int jtag430x2_syncpor(){
118   jtag_ir_shift8(IR_CNTRL_SIG_16BIT);
119   jtag_dr_shift16(0x1501); //JTAG mode
120   while(!(jtag_dr_shift16(0) & 0x200));  //0x100 or 0x200?
121   return jtag430x2_por();
122 }
123
124 //! Executes an MSP430X2 POR
125 unsigned int jtag430x2_por(){
126   unsigned int i = 0;
127   
128   // tick
129   CLRTCLK;
130   SETTCLK;
131
132   jtag_ir_shift8(IR_CNTRL_SIG_16BIT);
133   jtag_dr_shift16(0x0C01);
134   jtag_dr_shift16(0x0401);
135   
136   //cycle
137   for (i = 0; i < 10; i++){
138     CLRTCLK;
139     SETTCLK;
140   }
141   
142   jtag_dr_shift16(0x0501);
143   
144   // tick
145   CLRTCLK;
146   SETTCLK;
147   
148   
149   // Disable WDT
150   jtag430x2_writemem(0x015C, 0x5A80);
151   
152   // check state
153   jtag_ir_shift8(IR_CNTRL_SIG_CAPTURE);
154   if(jtag_dr_shift16(0) & 0x0301)
155     return(1);//ok
156   
157   return 0;//error
158 }
159
160
161 //! Check the fuse.
162 unsigned int jtag430x2_fusecheck(){
163   int i;
164   for(i=0;i<3;i++){
165     jtag_ir_shift8(IR_CNTRL_SIG_CAPTURE);
166     if(jtag_dr_shift16(0xAAAA)==0x5555)
167       return 1;//blown
168   }
169   return 0;//unblown
170 }
171
172
173 //! Handles MSP430X2 JTAG commands.  Forwards others to JTAG.
174 void jtag430x2_handle_fn( uint8_t const app,
175                                                   uint8_t const verb,
176                                                   uint32_t const len)
177 {
178   register char blocks;
179   
180   unsigned int i,val;
181   unsigned long at, l;
182   
183   //jtag430_resettap();
184   
185   if(verb!=START && jtag430mode==MSP430MODE){
186     (*(jtag430_app.handle))(app,verb,len);
187     return;
188   }
189   
190   switch(verb){
191   case START:
192     //Enter JTAG mode.
193     //do 
194     cmddata[0]=jtag430x2_start();
195     //while(cmddata[0]==00 || cmddata[0]==0xFF);
196     
197     //MSP430 or MSP430X
198     if(jtagid==MSP430JTAGID){ 
199       //debugstr("ERROR, using JTAG430X2 instead of JTAG430!");
200       jtag430mode=MSP430MODE;
201       
202       /* So the way this works is that a width of 20 does some
203          backward-compatibility finagling, causing the correct value
204          to be exchanged for addresses on 16-bit chips as well as the
205          new MSP430X chips.  (This has only been verified on the
206          MSP430F2xx family.  TODO verify for others.)
207       */
208       
209       drwidth=20;
210       
211       //Perform a reset and disable watchdog.
212       jtag430_por();
213       jtag430_writemem(0x120,0x5a80);//disable watchdog
214       
215       jtag430_haltcpu();
216       
217       jtag430_resettap();
218       txdata(app,verb,1);
219       
220       return;
221     }else if(jtagid==MSP430X2JTAGID){
222       jtag430mode=MSP430X2MODE;
223       drwidth=20;
224     }else{
225       debugstr("JTAG version unknown.");
226       txdata(app,NOK,1);
227       return;
228     }
229     
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