Bringing back MSP430X2 JTAG. Not there yet.
[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     blocks=(len>4?cmddata[4]:1);
224     at=cmddatalong[0];
225     
226     l=0x80;
227     txhead(app,verb,l);
228     
229     while(blocks--){
230       for(i=0;i<l;i+=2){
231         jtag430_resettap();
232         delay(10);
233         
234         val=jtag430x2_readmem(at);
235                 
236         at+=2;
237         serial_tx(val&0xFF);
238         serial_tx((val&0xFF00)>>8);
239       }
240     }
241     
242     break;
243   case JTAG430_COREIP_ID:
244     cmddataword[0]=jtag430_coreid();
245     txdata(app,verb,2);
246     break;
247   case JTAG430_DEVICE_ID:
248     cmddatalong[0]=jtag430_deviceid();
249     txdata(app,verb,4);
250     break;
251   case JTAG430_WRITEFLASH:
252   case JTAG430_WRITEMEM:
253   case POKE:
254     jtag430x2_writemem(cmddatalong[0],
255                        cmddataword[2]);
256     cmddataword[0]=jtag430x2_readmem(cmddatalong[0]);
257     txdata(app,verb,2);
258     break;
259
260     //unimplemented functions
261   case JTAG430_HALTCPU:  
262   case JTAG430_RELEASECPU:
263   case JTAG430_SETINSTRFETCH:
264
265   case JTAG430_ERASEFLASH:
266   case JTAG430_SETPC:
267     debugstr("This function is not yet implemented for MSP430X2.");
268     debughex(verb);
269     txdata(app,NOK,0);
270     break;
271   default:
272     (*(jtag_app.handle))(app,verb,len);
273   }
274   jtag430_resettap();
275 }
276