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