A major refactor of the GoodFET firmware build system and apps to give better
[goodfet] / firmware / apps / jtag / jtag.c
1 /*! \file jtag.c
2   \author Travis Goodspeed <travis at radiantmachines.com>
3   \brief Low-level JTAG
4 */
5
6
7 #include "platform.h"
8 #include "command.h"
9 #include "jtag.h"
10
11 #define JTAG_APP
12
13 //! Handles a monitor command.
14 void jtag_handle_fn(uint8_t const app,
15                                         uint8_t const verb,
16                                         uint32_t const len);
17
18 // define the jtag app's app_t
19 app_t const jtag_app = {
20
21         /* app number */
22         JTAG,
23
24         /* handle fn */
25         jtag_handle_fn,
26
27         /* name */
28         "JTAG",
29
30         /* desc */
31         "\tThe JTAG app handles basic JTAG operations such as\n"
32         "\tresetting the TAP, resetting the target, detecting\n"
33         "\tthe instruction register width, shifting bits into\n"
34         "\tboth the instruction and data registers.\n"
35 };
36
37
38 //! Set up the pins for JTAG mode.
39 void jtagsetup(){
40   P5DIR|=MOSI+SCK+TMS;
41   P5DIR&=~MISO;
42   /*
43   P5OUT|=0xFFFF;
44   P5OUT=0;
45   */
46   P4DIR|=TST;
47   P2DIR|=RST;
48   msdelay(100);
49 }
50
51 /************************** JTAG Primitives ****************************/
52 // these have been turned into functions to save flash space
53 void jtag_tcktock() {
54   CLRTCK; 
55   PLEDOUT^=PLEDPIN; 
56   SETTCK; 
57   PLEDOUT^=PLEDPIN;
58 }
59
60 void jtag_goto_shift_ir() {
61   SETTMS;
62   jtag_tcktock();
63   jtag_tcktock();
64   CLRTMS;
65   jtag_tcktock();
66   jtag_tcktock();
67
68 }
69 void jtag_goto_shift_dr() {
70   SETTMS;
71   jtag_tcktock();
72   CLRTMS;
73   jtag_tcktock();
74   jtag_tcktock();
75 }
76
77 void jtag_resettap(){
78   SETTMS;
79   jtag_tcktock();
80   jtag_tcktock();
81   jtag_tcktock();
82   jtag_tcktock();
83   jtag_tcktock();  // now in Reset state
84   CLRTMS;
85   jtag_tcktock();  // now in Run-Test/Idle state
86 }
87
88
89 int savedtclk=0;
90 //  NOTE: important: THIS MODULE REVOLVES AROUND RETURNING TO RUNTEST/IDLE, OR 
91 //  THE FUNCTIONAL EQUIVALENT
92 //! Shift N bits over TDI/TDO.  May choose LSB or MSB, and select whether to 
93 //  terminate (TMS-high on last bit) and whether to return to RUNTEST/IDLE
94 //      flags should be 0 for most uses.  
95 //      for the extreme case, flags should be  (NOEND|NORETDLE|LSB)
96 //      other edge cases can involve a combination of those three flags
97 //
98 //      the max bit-size that can be be shifted is 32-bits.  
99 //      for longer shifts, use the NOEND flag (which infers NORETIDLE so the 
100 //      additional flag is unnecessary)
101 //
102 //      NORETIDLE is used for special cases where (as with arm) the debug 
103 //      subsystem does not want to return to the RUN-TEST/IDLE state between 
104 //      setting IR and DR
105 unsigned long jtagtransn(unsigned long word, 
106                          unsigned char bitcount, 
107                          unsigned char flags) {
108   unsigned char bit;
109   unsigned long high = 1L;
110   unsigned long mask;
111
112   //for (bit=(bitcount-1)/8; bit>0; bit--)
113   //  high <<= 8;
114   //high <<= ((bitcount-1)%8);
115   high <<= (bitcount-1);
116
117   mask = high-1;
118
119   SAVETCLK;
120   if (flags & LSB) {
121     for (bit = bitcount; bit > 0; bit--) {
122       /* write MOSI on trailing edge of previous clock */
123       if (word & 1)
124         {SETMOSI;}
125       else
126         {CLRMOSI;}
127       word >>= 1;
128
129       if (bit==1 && !(flags & NOEND))
130         SETTMS;//TMS high on last bit to exit.
131        
132       jtag_tcktock();
133
134       /* read MISO on trailing edge */
135       if (READMISO){
136         word += (high);
137       }
138     }
139   } else {
140     for (bit = bitcount; bit > 0; bit--) {
141       /* write MOSI on trailing edge of previous clock */
142       if (word & high)
143         {SETMOSI;}
144       else
145         {CLRMOSI;}
146       word = (word & mask) << 1;
147
148       if (bit==1 && !(flags & NOEND))
149         SETTMS;//TMS high on last bit to exit.
150
151       jtag_tcktock();
152
153       /* read MISO on trailing edge */
154       word |= (READMISO);
155     }
156   }
157  
158
159   RESTORETCLK;
160   //SETMOSI;
161
162   if (!(flags & NOEND)){
163     // exit state
164     jtag_tcktock();
165     // update state
166     if (!(flags & NORETIDLE)){
167       CLRTMS;
168       jtag_tcktock();
169     }
170   }
171   return word;
172 }
173
174 //! Shift 8 bits in and out.
175 unsigned char jtagtrans8(unsigned char byte){
176   unsigned int bit;
177   SAVETCLK;
178   for (bit = 0; bit < 8; bit++) {
179     /* write MOSI on trailing edge of previous clock */
180     if (byte & 0x80)
181       {SETMOSI;}
182     else
183       {CLRMOSI;}
184     byte <<= 1;
185     
186     if(bit==7)
187       SETTMS;//TMS high on last bit to exit.
188     
189     TCKTOCK;
190     /* read MISO on trailing edge */
191     byte |= READMISO;
192   }
193   RESTORETCLK;
194   
195   // exit state
196   TCKTOCK;
197   // update state
198   CLRTMS;
199   TCKTOCK;
200   
201   return byte;
202 }
203
204 //! Shift n bits in and out.
205 /*unsigned long jtagtransn(unsigned long word,
206                          unsigned int bitcount){
207   unsigned int bit;
208   //0x8000
209   unsigned long high=0x8000;
210   
211   if(bitcount==20)
212     high=0x80000;
213   if(bitcount==16)
214     high= 0x8000;
215   
216   SAVETCLK;
217   
218   for (bit = 0; bit < bitcount; bit++) {
219     // write MOSI on trailing edge of previous clock *
220     if (word & high)
221       {SETMOSI;}
222     else
223       {CLRMOSI;}
224     word <<= 1;
225     
226     if(bit==bitcount-1)
227       SETTMS;//TMS high on last bit to exit.
228     
229     TCKTOCK;
230     // read MISO on trailing edge *
231     word |= READMISO;
232   }
233   
234   if(bitcount==20){
235     word = ((word << 16) | (word >> 4)) & 0x000FFFFF;
236   }
237   
238   RESTORETCLK;
239   
240   // exit state
241   TCKTOCK;
242   // update state
243   CLRTMS;
244   TCKTOCK;
245   
246   return word;
247 }
248 */
249
250 //! Stop JTAG, release pins
251 void jtag_stop(){
252   P5OUT=0;
253   P4OUT=0;
254 }
255
256 unsigned int drwidth=16;
257 //! Shift all bits of the DR.
258 unsigned long jtag_dr_shift20(unsigned long in){
259   // idle
260   SETTMS;
261   TCKTOCK;
262   // select DR
263   CLRTMS;
264   TCKTOCK;
265   // capture IR
266   TCKTOCK;
267   
268   // shift DR, then idle
269   return(jtagtransn(in,20,0));
270 }
271
272
273 //! Shift 16 bits of the DR.
274 unsigned int jtag_dr_shift16(unsigned int in){
275   // idle
276   SETTMS;
277   TCKTOCK;
278   // select DR
279   CLRTMS;
280   TCKTOCK;
281   // capture IR
282   TCKTOCK;
283   
284   // shift DR, then idle
285   return(jtagtransn(in,16,0));
286 }
287
288 //! Shift native width of the DR
289 unsigned long jtag_dr_shiftadr(unsigned long in){
290   unsigned long out=0;
291   
292   // idle
293   SETTMS;
294   TCKTOCK;
295   // select DR
296   CLRTMS;
297   TCKTOCK;
298   // capture IR
299   TCKTOCK;
300
301   
302   out=jtagtransn(in,drwidth,0);
303   
304   // shift DR, then idle
305   return(out);
306 }
307
308
309 //! Shift 8 bits of the IR.
310 unsigned char jtag_ir_shift8(unsigned char in){
311   // idle
312   SETTMS;
313   TCKTOCK;
314   // select DR
315   TCKTOCK;
316   // select IR
317   CLRTMS;
318   TCKTOCK;
319   // capture IR
320   TCKTOCK;
321   
322   // shift IR, then idle.
323   return(jtagtrans8(in));
324 }
325
326 //! Handles a monitor command.
327 void jtag_handle_fn(uint8_t const app,
328                                         uint8_t const verb,
329                                         uint32_t const len)
330 {
331         switch(verb)
332         {
333                 //START handled by specific JTAG
334         case STOP:
335                 jtag_stop();
336                 txdata(app,verb,0);
337                 break;
338
339         case SETUP:
340                 jtagsetup();
341                 txdata(app,verb,0);
342                 break;
343
344         case JTAG_IR_SHIFT:
345                 cmddata[0]=jtag_ir_shift8(cmddata[0]);
346                 txdata(app,verb,1);
347                 break;
348
349         case JTAG_DR_SHIFT:
350                 cmddataword[0]=jtag_dr_shift16(cmddataword[0]);
351                 txdata(app,verb,2);
352                 break;
353
354         case JTAG_RESETTAP:
355                 jtag_resettap();
356                 txdata(app,verb,0);
357                 break;
358
359         default:
360                 txdata(app,NOK,0);
361         }
362 }
363
364