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