1528e7c920925e0eea84d9348c50ed6a26218087
[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   unsigned int i,val;
179   unsigned long at, l;
180   
181   //jtag430_resettap();
182   
183   if(verb!=START && jtag430mode==MSP430MODE){
184     (*(jtag430_app.handle))(app,verb,len);
185     return;
186   }
187   
188   switch(verb){
189   case START:
190     //Enter JTAG mode.
191     //do 
192     cmddata[0]=jtag430x2_start();
193     //while(cmddata[0]==00 || cmddata[0]==0xFF);
194     
195     //MSP430 or MSP430X
196     if(jtagid==MSP430JTAGID){ 
197       //debugstr("ERROR, using JTAG430X2 instead of JTAG430!");
198       jtag430mode=MSP430MODE;
199       
200       /* So the way this works is that a width of 20 does some
201          backward-compatibility finagling, causing the correct value
202          to be exchanged for addresses on 16-bit chips as well as the
203          new MSP430X chips.  (This has only been verified on the
204          MSP430F2xx family.  TODO verify for others.)
205       */
206       
207       drwidth=20;
208       
209       //Perform a reset and disable watchdog.
210       jtag430_por();
211       jtag430_writemem(0x120,0x5a80);//disable watchdog
212       
213       jtag430_haltcpu();
214       
215       jtag430_resettap();
216       txdata(app,verb,1);
217       
218       return;
219     }else if(jtagid==MSP430X2JTAGID){
220       jtag430mode=MSP430X2MODE;
221       drwidth=20;
222     }else{
223       debugstr("JTAG version unknown.");
224       txdata(app,NOK,1);
225       return;
226     }
227     
228     
229     
230     jtag430x2_fusecheck();
231         
232     jtag430x2_syncpor();
233     
234     jtag430_resettap();
235     
236     txdata(app,verb,1);
237     break;
238   case JTAG430_READMEM:
239   case PEEK:
240     at=cmddatalong[0];
241     
242     //Fetch large blocks for bulk fetches,
243     //small blocks for individual peeks.
244     if(len>5)
245       l=(cmddataword[2]);//always even.
246     else
247       l=2;
248     l&=~1;//clear lsbit
249     
250     if(l<2) l=2;
251     
252     txhead(app,verb,l);
253     for(i=0;i<l;i+=2){
254       //jtag430_resettap();
255       //delay(10);
256       
257       val=jtag430x2_readmem(at);
258       
259       at+=2;
260       serial_tx(val&0xFF);
261       serial_tx((val&0xFF00)>>8);
262     }
263     
264     break;
265   case JTAG430_COREIP_ID:
266     cmddataword[0]=jtag430_coreid();
267     txdata(app,verb,2);
268     break;
269   case JTAG430_DEVICE_ID:
270     cmddatalong[0]=jtag430_deviceid();
271     txdata(app,verb,4);
272     break;
273   case JTAG430_WRITEFLASH:
274   case JTAG430_WRITEMEM:
275   case POKE:
276     jtag430x2_writemem(cmddatalong[0],
277                        cmddataword[2]);
278     cmddataword[0]=jtag430x2_readmem(cmddatalong[0]);
279     txdata(app,verb,2);
280     break;
281
282     //unimplemented functions
283   case JTAG430_HALTCPU:
284     //jtag430x2_haltcpu();
285     debugstr("Warning, not trying to halt for lack of code.");
286     txdata(app,verb,0);
287     break;
288   case JTAG430_RELEASECPU:
289   case JTAG430_SETINSTRFETCH:
290
291   case JTAG430_ERASEFLASH:
292   case JTAG430_SETPC:
293     debugstr("This function is not yet implemented for MSP430X2.");
294     debughex(verb);
295     txdata(app,NOK,0);
296     break;
297   default:
298     (*(jtag_app.handle))(app,verb,len);
299   }
300   jtag430_resettap();
301 }
302