cf9199d90fbca16c6ced460f7cb9fd2aa352fa59
[goodfet] / firmware / apps / jtag / jtag.c
1 /*! \file jtag.c
2   \author Travis Goodspeed <travis at radiantmachines.com>
3   
4   This is an implementation of the low-level JTAG functions
5   for the GoodFET project at http://goodfet.sf.net/
6   
7   See the license file for details of proper use.
8 */
9
10
11 #include "platform.h"
12 #include "command.h"
13 #include "jtag.h"
14
15
16 //! Set up the pins for JTAG mode.
17 void jtagsetup(){
18   P5DIR|=MOSI+SCK+TMS;
19   P5DIR&=~MISO;
20   P5OUT|=0xFFFF;
21   P5OUT=0;
22   P4DIR|=TST;
23   P2DIR|=RST;
24   msdelay(100);
25 }
26
27 int savedtclk=0;
28 //! Shift 8 bits in and out.
29 unsigned char jtagtrans8(unsigned char byte){
30   unsigned int bit;
31   SAVETCLK;
32   for (bit = 0; bit < 8; bit++) {
33     /* write MOSI on trailing edge of previous clock */
34     if (byte & 0x80)
35       {SETMOSI;}
36     else
37       {CLRMOSI;}
38     byte <<= 1;
39     
40     if(bit==7)
41       SETTMS;//TMS high on last bit to exit.
42     
43     CLRTCK;
44     SETTCK;
45      /* read MISO on trailing edge */
46     byte |= READMISO;
47   }
48   RESTORETCLK;
49   
50   // exit state
51   CLRTCK;
52   SETTCK;
53   // update state
54   CLRTMS;
55   CLRTCK;
56   SETTCK;
57   
58   return byte;
59 }
60
61 //! Shift n bits in and out.
62 unsigned long jtagtransn(unsigned long word,
63                          unsigned int bitcount){
64   unsigned int bit;
65   //0x8000
66   unsigned long high;
67   
68   if(bitcount==20)
69     high=0x80000;
70   if(bitcount==16)
71     high= 0x8000;
72   
73   SAVETCLK;
74   
75   for (bit = 0; bit < bitcount; bit++) {
76     /* write MOSI on trailing edge of previous clock */
77     if (word & high)
78       {SETMOSI;}
79     else
80       {CLRMOSI;}
81     word <<= 1;
82     
83     if(bit==bitcount-1)
84       SETTMS;//TMS high on last bit to exit.
85     
86     CLRTCK;
87     SETTCK;
88     /* read MISO on trailing edge */
89     word |= READMISO;
90   }
91   
92   if(bitcount==20){
93     word = ((word << 16) | (word >> 4)) & 0x000FFFFF;
94   }
95   
96   RESTORETCLK;
97   
98   // exit state
99   CLRTCK;
100   SETTCK;
101   // update state
102   CLRTMS;
103   CLRTCK;
104   SETTCK;
105   
106   return word;
107 }
108
109 /*
110 //! Shift 16 bits in and out.
111 unsigned int jtagtrans16(unsigned int word){ //REMOVEME
112   unsigned int bit;
113   SAVETCLK;
114   
115   for (bit = 0; bit < 16; bit++) {
116     // write MOSI on trailing edge of previous clock 
117     if (word & 0x8000)
118       {SETMOSI;}
119     else
120       {CLRMOSI;}
121     word <<= 1;
122     
123     if(bit==15)
124       SETTMS;//TMS high on last bit to exit.
125     
126     CLRTCK;
127     SETTCK;
128     // read MISO on trailing edge 
129     word |= READMISO;
130   }
131   RESTORETCLK;
132   
133   // exit state
134   CLRTCK;
135   SETTCK;
136   // update state
137   CLRTMS;
138   CLRTCK;
139   SETTCK;
140   
141   return word;
142 }*/
143
144 //! Stop JTAG, release pins
145 void jtag_stop(){
146   P5OUT=0;
147   P4OUT=0;
148 }
149
150 unsigned int drwidth=20;
151 //! Shift all bits of the DR.
152 unsigned long jtag_dr_shift20(unsigned long in){
153   // idle
154   SETTMS;
155   CLRTCK;
156   SETTCK;
157   // select DR
158   CLRTMS;
159   CLRTCK;
160   SETTCK;
161   // capture IR
162   CLRTCK;
163   SETTCK;
164   
165   // shift DR, then idle
166   return(jtagtransn(in,20));
167 }
168
169
170 //! Shift 16 bits of the DR.
171 unsigned int jtag_dr_shift16(unsigned int in){
172   // idle
173   SETTMS;
174   CLRTCK;
175   SETTCK;
176   // select DR
177   CLRTMS;
178   CLRTCK;
179   SETTCK;
180   // capture IR
181   CLRTCK;
182   SETTCK;
183   
184   // shift DR, then idle
185   return(jtagtransn(in,16));
186 }
187
188
189 //! Shift 8 bits of the IR.
190 unsigned char jtag_ir_shift8(unsigned char in){
191   // idle
192   SETTMS;
193   CLRTCK;
194   SETTCK;
195   // select DR
196   CLRTCK;
197   SETTCK;
198   // select IR
199   CLRTMS;
200   CLRTCK;
201   SETTCK;
202   // capture IR
203   CLRTCK;
204   SETTCK;
205   
206   // shift IR, then idle.
207   return(jtagtrans8(in));
208 }
209
210 //! Handles a monitor command.
211 void jtaghandle(unsigned char app,
212                unsigned char verb,
213                unsigned char len){
214   switch(verb){
215     //START handled by specific JTAG
216   case STOP:
217     jtag_stop();
218     txdata(app,verb,0);
219     break;
220   case SETUP:
221     jtagsetup();
222     txdata(app,verb,0);
223     break;
224   case JTAG_IR_SHIFT:
225     cmddata[0]=jtag_ir_shift8(cmddata[0]);
226     txdata(app,verb,1);
227     break;
228   case JTAG_DR_SHIFT:
229     cmddataword[0]=jtag_dr_shift16(cmddataword[0]);
230     txdata(app,verb,2);
231     break;
232   default:
233     txdata(app,NOK,0);
234   }
235 }
236
237