Some bits of Spy-Bi-Wire support, thanks to Mark Rages. (Not yet complete.)
[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
12 //! Set up the pins for JTAG mode.
13 void jtagsetup(){
14   P5DIR|=MOSI+SCK+TMS;
15   P5DIR&=~MISO;
16   P5OUT|=0xFFFF;
17   P5OUT=0;
18   P4DIR|=TST;
19   P2DIR|=RST;
20   msdelay(100);
21 }
22
23 int savedtclk=0;
24 //! Shift 8 bits in and out.
25 unsigned char jtagtrans8(unsigned char byte){
26   unsigned int bit;
27   SAVETCLK;
28   for (bit = 0; bit < 8; bit++) {
29     /* write MOSI on trailing edge of previous clock */
30     if (byte & 0x80)
31       {SETMOSI;}
32     else
33       {CLRMOSI;}
34     byte <<= 1;
35     
36     if(bit==7)
37       SETTMS;//TMS high on last bit to exit.
38     
39     CLRTCK;
40     SETTCK;
41      /* read MISO on trailing edge */
42     byte |= READMISO;
43   }
44   RESTORETCLK;
45   
46   // exit state
47   CLRTCK;
48   SETTCK;
49   // update state
50   CLRTMS;
51   CLRTCK;
52   SETTCK;
53   
54   return byte;
55 }
56
57 //! Shift n bits in and out.
58 unsigned long jtagtransn(unsigned long word,
59                          unsigned int bitcount){
60   unsigned int bit;
61   //0x8000
62   unsigned long high=0x8000;
63   
64   if(bitcount==20)
65     high=0x80000;
66   if(bitcount==16)
67     high= 0x8000;
68   
69   SAVETCLK;
70   
71   for (bit = 0; bit < bitcount; bit++) {
72     /* write MOSI on trailing edge of previous clock */
73     if (word & high)
74       {SETMOSI;}
75     else
76       {CLRMOSI;}
77     word <<= 1;
78     
79     if(bit==bitcount-1)
80       SETTMS;//TMS high on last bit to exit.
81     
82     CLRTCK;
83     SETTCK;
84     /* read MISO on trailing edge */
85     word |= READMISO;
86   }
87   
88   if(bitcount==20){
89     word = ((word << 16) | (word >> 4)) & 0x000FFFFF;
90   }
91   
92   RESTORETCLK;
93   
94   // exit state
95   CLRTCK;
96   SETTCK;
97   // update state
98   CLRTMS;
99   CLRTCK;
100   SETTCK;
101   
102   return word;
103 }
104
105
106 //! Stop JTAG, release pins
107 void jtag_stop(){
108   P5OUT=0;
109   P4OUT=0;
110 }
111
112 unsigned int drwidth=20;
113 //! Shift all bits of the DR.
114 unsigned long jtag_dr_shift20(unsigned long in){
115   // idle
116   SETTMS;
117   CLRTCK;
118   SETTCK;
119   // select DR
120   CLRTMS;
121   CLRTCK;
122   SETTCK;
123   // capture IR
124   CLRTCK;
125   SETTCK;
126   
127   // shift DR, then idle
128   return(jtagtransn(in,20));
129 }
130
131
132 //! Shift 16 bits of the DR.
133 unsigned int jtag_dr_shift16(unsigned int in){
134   // idle
135   SETTMS;
136   CLRTCK;
137   SETTCK;
138   // select DR
139   CLRTMS;
140   CLRTCK;
141   SETTCK;
142   // capture IR
143   CLRTCK;
144   SETTCK;
145   
146   // shift DR, then idle
147   return(jtagtransn(in,16));
148 }
149
150
151 //! Shift 8 bits of the IR.
152 unsigned char jtag_ir_shift8(unsigned char in){
153   // idle
154   SETTMS;
155   CLRTCK;
156   SETTCK;
157   // select DR
158   CLRTCK;
159   SETTCK;
160   // select IR
161   CLRTMS;
162   CLRTCK;
163   SETTCK;
164   // capture IR
165   CLRTCK;
166   SETTCK;
167   
168   // shift IR, then idle.
169   return(jtagtrans8(in));
170 }
171
172 //! Handles a monitor command.
173 void jtaghandle(unsigned char app,
174                unsigned char verb,
175                unsigned long len){
176   switch(verb){
177     //START handled by specific JTAG
178   case STOP:
179     jtag_stop();
180     txdata(app,verb,0);
181     break;
182   case SETUP:
183     jtagsetup();
184     txdata(app,verb,0);
185     break;
186   case JTAG_IR_SHIFT:
187     cmddata[0]=jtag_ir_shift8(cmddata[0]);
188     txdata(app,verb,1);
189     break;
190   case JTAG_DR_SHIFT:
191     cmddataword[0]=jtag_dr_shift16(cmddataword[0]);
192     txdata(app,verb,2);
193     break;
194   default:
195     txdata(app,NOK,0);
196   }
197 }
198
199