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