97db51bb408d78218da050a03835ea7e1a513b2c
[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     TCKTOCK;
40     /* read MISO on trailing edge */
41     byte |= READMISO;
42   }
43   RESTORETCLK;
44   
45   // exit state
46   TCKTOCK;
47   // update state
48   CLRTMS;
49   TCKTOCK;
50   
51   return byte;
52 }
53
54 //! Shift n bits in and out.
55 unsigned long jtagtransn(unsigned long word,
56                          unsigned int bitcount){
57   unsigned int bit;
58   //0x8000
59   unsigned long high=0x8000;
60   
61   if(bitcount==20)
62     high=0x80000;
63   if(bitcount==16)
64     high= 0x8000;
65   
66   SAVETCLK;
67   
68   for (bit = 0; bit < bitcount; bit++) {
69     /* write MOSI on trailing edge of previous clock */
70     if (word & high)
71       {SETMOSI;}
72     else
73       {CLRMOSI;}
74     word <<= 1;
75     
76     if(bit==bitcount-1)
77       SETTMS;//TMS high on last bit to exit.
78     
79     TCKTOCK;
80     /* read MISO on trailing edge */
81     word |= READMISO;
82   }
83   
84   if(bitcount==20){
85     word = ((word << 16) | (word >> 4)) & 0x000FFFFF;
86   }
87   
88   RESTORETCLK;
89   
90   // exit state
91   TCKTOCK;
92   // update state
93   CLRTMS;
94   TCKTOCK;
95   
96   return word;
97 }
98
99
100 //! Stop JTAG, release pins
101 void jtag_stop(){
102   P5OUT=0;
103   P4OUT=0;
104 }
105
106 unsigned int drwidth=20;
107 //! Shift all bits of the DR.
108 unsigned long jtag_dr_shift20(unsigned long in){
109   // idle
110   SETTMS;
111   TCKTOCK;
112   // select DR
113   CLRTMS;
114   TCKTOCK;
115   // capture IR
116   TCKTOCK;
117   
118   // shift DR, then idle
119   return(jtagtransn(in,20));
120 }
121
122
123 //! Shift 16 bits of the DR.
124 unsigned int jtag_dr_shift16(unsigned int in){
125   // idle
126   SETTMS;
127   TCKTOCK;
128   // select DR
129   CLRTMS;
130   TCKTOCK;
131   // capture IR
132   TCKTOCK;
133   
134   // shift DR, then idle
135   return(jtagtransn(in,16));
136 }
137
138
139 //! Shift 8 bits of the IR.
140 unsigned char jtag_ir_shift8(unsigned char in){
141   // idle
142   SETTMS;
143   TCKTOCK;
144   // select DR
145   TCKTOCK;
146   // select IR
147   CLRTMS;
148   TCKTOCK;
149   // capture IR
150   TCKTOCK;
151   
152   // shift IR, then idle.
153   return(jtagtrans8(in));
154 }
155
156 //! Handles a monitor command.
157 void jtaghandle(unsigned char app,
158                unsigned char verb,
159                unsigned long len){
160   switch(verb){
161     //START handled by specific JTAG
162   case STOP:
163     jtag_stop();
164     txdata(app,verb,0);
165     break;
166   case SETUP:
167     jtagsetup();
168     txdata(app,verb,0);
169     break;
170   case JTAG_IR_SHIFT:
171     cmddata[0]=jtag_ir_shift8(cmddata[0]);
172     txdata(app,verb,1);
173     break;
174   case JTAG_DR_SHIFT:
175     cmddataword[0]=jtag_dr_shift16(cmddataword[0]);
176     txdata(app,verb,2);
177     break;
178   default:
179     txdata(app,NOK,0);
180   }
181 }
182
183