JTAG pinout detector

Dependencies:   mbed

Committer:
igorsk
Date:
Wed Jul 14 23:20:48 2010 +0000
Revision:
0:948e97043afb

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
igorsk 0:948e97043afb 1 /*
igorsk 0:948e97043afb 2 * JTAG pinout detector
igorsk 0:948e97043afb 3 * Version 0.1
igorsk 0:948e97043afb 4 * 2010-07-15
igorsk 0:948e97043afb 5 *
igorsk 0:948e97043afb 6 * Copyright (c) 2010 Igor Skochinsky
igorsk 0:948e97043afb 7 *
igorsk 0:948e97043afb 8 * This software is provided 'as-is', without any express or implied
igorsk 0:948e97043afb 9 * warranty. In no event will the authors be held liable for any damages
igorsk 0:948e97043afb 10 * arising from the use of this software.
igorsk 0:948e97043afb 11 *
igorsk 0:948e97043afb 12 * Permission is granted to anyone to use this software for any purpose,
igorsk 0:948e97043afb 13 * including commercial applications, and to alter it and redistribute it
igorsk 0:948e97043afb 14 * freely, subject to the following restrictions:
igorsk 0:948e97043afb 15 *
igorsk 0:948e97043afb 16 * 1. The origin of this software must not be misrepresented; you must not
igorsk 0:948e97043afb 17 * claim that you wrote the original software. If you use this software
igorsk 0:948e97043afb 18 * in a product, an acknowledgment in the product documentation would be
igorsk 0:948e97043afb 19 * appreciated but is not required.
igorsk 0:948e97043afb 20 *
igorsk 0:948e97043afb 21 * 2. Altered source versions must be plainly marked as such, and must not be
igorsk 0:948e97043afb 22 * misrepresented as being the original software.
igorsk 0:948e97043afb 23 *
igorsk 0:948e97043afb 24 * 3. This notice may not be removed or altered from any source
igorsk 0:948e97043afb 25 * distribution.
igorsk 0:948e97043afb 26 */
igorsk 0:948e97043afb 27
igorsk 0:948e97043afb 28
igorsk 0:948e97043afb 29 /*
igorsk 0:948e97043afb 30
igorsk 0:948e97043afb 31 The overall idea:
igorsk 0:948e97043afb 32 1) choose any 2 pins as TMS and TCK
igorsk 0:948e97043afb 33 2) using them, reset TAP and then shift DR, while observing the state of all other pins
igorsk 0:948e97043afb 34 3) for every pin that received anything like a TAP ID (i.e. bit 0 is 1):
igorsk 0:948e97043afb 35 4) using the pin as TDI, feed in a known pattern into the TAP
igorsk 0:948e97043afb 36 5) keep shifting and monitor the rest of the pins
igorsk 0:948e97043afb 37 6) if any of the remaining pins received the pattern, it is TDO
igorsk 0:948e97043afb 38
igorsk 0:948e97043afb 39 Current algorithm assumes chain length of 1
igorsk 0:948e97043afb 40
igorsk 0:948e97043afb 41 */
igorsk 0:948e97043afb 42
igorsk 0:948e97043afb 43 #include "mbed.h"
igorsk 0:948e97043afb 44
igorsk 0:948e97043afb 45
igorsk 0:948e97043afb 46 // pin description structure
igorsk 0:948e97043afb 47 struct PinInfo
igorsk 0:948e97043afb 48 {
igorsk 0:948e97043afb 49 DigitalInOut pin;
igorsk 0:948e97043afb 50 const char *name;
igorsk 0:948e97043afb 51 };
igorsk 0:948e97043afb 52
igorsk 0:948e97043afb 53 // define the pins to use for bruteforcing
igorsk 0:948e97043afb 54 PinInfo g_pins[] = {
igorsk 0:948e97043afb 55 {p21, "pin 21", },
igorsk 0:948e97043afb 56 {p22, "pin 22", },
igorsk 0:948e97043afb 57 {p23, "pin 23", },
igorsk 0:948e97043afb 58 {p24, "pin 24", },
igorsk 0:948e97043afb 59 {p25, "pin 25", },
igorsk 0:948e97043afb 60 };
igorsk 0:948e97043afb 61
igorsk 0:948e97043afb 62 #define NPINS sizeof(g_pins)/sizeof(g_pins[0])
igorsk 0:948e97043afb 63
igorsk 0:948e97043afb 64 // indexes of found pins
igorsk 0:948e97043afb 65 int pin_TCK = -1;
igorsk 0:948e97043afb 66 int pin_TMS = -1;
igorsk 0:948e97043afb 67 int pin_TDO = -1;
igorsk 0:948e97043afb 68 int pin_TDI = -1;
igorsk 0:948e97043afb 69
igorsk 0:948e97043afb 70 inline const char *pinname(int pinno)
igorsk 0:948e97043afb 71 {
igorsk 0:948e97043afb 72 return pinno == -1 ? "unknown" : g_pins[pinno].name;
igorsk 0:948e97043afb 73 }
igorsk 0:948e97043afb 74
igorsk 0:948e97043afb 75 // print current layout
igorsk 0:948e97043afb 76 inline void printpins()
igorsk 0:948e97043afb 77 {
igorsk 0:948e97043afb 78 printf("TCK: %s, TMS: %s, TDO: %s, TDI: %s\n",
igorsk 0:948e97043afb 79 pinname(pin_TCK), pinname(pin_TMS), pinname(pin_TDO), pinname(pin_TDI));
igorsk 0:948e97043afb 80 }
igorsk 0:948e97043afb 81
igorsk 0:948e97043afb 82 // set pin with a given index
igorsk 0:948e97043afb 83 inline void setpin(int pinno, int value)
igorsk 0:948e97043afb 84 {
igorsk 0:948e97043afb 85 g_pins[pinno].pin.write(value != 0);
igorsk 0:948e97043afb 86 }
igorsk 0:948e97043afb 87
igorsk 0:948e97043afb 88 // read pin with a given index
igorsk 0:948e97043afb 89 inline int getpin(int pinno)
igorsk 0:948e97043afb 90 {
igorsk 0:948e97043afb 91 return g_pins[pinno].pin.read();
igorsk 0:948e97043afb 92 }
igorsk 0:948e97043afb 93
igorsk 0:948e97043afb 94 // make a pin output pin
igorsk 0:948e97043afb 95 inline void makeoutput(int pinno)
igorsk 0:948e97043afb 96 {
igorsk 0:948e97043afb 97 g_pins[pinno].pin.output();
igorsk 0:948e97043afb 98 }
igorsk 0:948e97043afb 99
igorsk 0:948e97043afb 100 // make a pin input pin
igorsk 0:948e97043afb 101 inline void makeinput(int pinno)
igorsk 0:948e97043afb 102 {
igorsk 0:948e97043afb 103 g_pins[pinno].pin.input();
igorsk 0:948e97043afb 104 }
igorsk 0:948e97043afb 105
igorsk 0:948e97043afb 106 // init all pins as inputs
igorsk 0:948e97043afb 107 void InitGPIO()
igorsk 0:948e97043afb 108 {
igorsk 0:948e97043afb 109 for (int i=0; i<NPINS; i++)
igorsk 0:948e97043afb 110 makeinput(i);
igorsk 0:948e97043afb 111 }
igorsk 0:948e97043afb 112
igorsk 0:948e97043afb 113 // feed in one tms pulse with given value
igorsk 0:948e97043afb 114 void clock_tms(int tms)
igorsk 0:948e97043afb 115 {
igorsk 0:948e97043afb 116 //TMS is sampled by TAP on the rising edge of TCK, i.e. on change from 0 to 1
igorsk 0:948e97043afb 117 //so the proper sequence is TCK=0; TMS=value; TCK=1
igorsk 0:948e97043afb 118 setpin(pin_TCK, 0);
igorsk 0:948e97043afb 119 setpin(pin_TMS, tms);
igorsk 0:948e97043afb 120 //printpins(1);
igorsk 0:948e97043afb 121 //Delay(1);
igorsk 0:948e97043afb 122 setpin(pin_TCK, 1);
igorsk 0:948e97043afb 123 //printpins(1);
igorsk 0:948e97043afb 124 setpin(pin_TCK, 0);//to make sure the TDO value gets set
igorsk 0:948e97043afb 125 }
igorsk 0:948e97043afb 126
igorsk 0:948e97043afb 127 // same as above but also set the tdi and return tdo
igorsk 0:948e97043afb 128 int clock_tms_tdi(int tms, int tdi)
igorsk 0:948e97043afb 129 {
igorsk 0:948e97043afb 130 setpin(pin_TCK, 0);
igorsk 0:948e97043afb 131 setpin(pin_TMS, tms);
igorsk 0:948e97043afb 132 setpin(pin_TDI, tdi);
igorsk 0:948e97043afb 133 //printpins(2);
igorsk 0:948e97043afb 134 //Delay(1);
igorsk 0:948e97043afb 135 setpin(pin_TCK, 1);
igorsk 0:948e97043afb 136 //printpins(2);
igorsk 0:948e97043afb 137 setpin(pin_TCK, 0);//to make sure the TDO value gets set
igorsk 0:948e97043afb 138 return getpin(pin_TDO);
igorsk 0:948e97043afb 139 }
igorsk 0:948e97043afb 140
igorsk 0:948e97043afb 141 // the end
igorsk 0:948e97043afb 142 void exit_on_button(char* msg)
igorsk 0:948e97043afb 143 {
igorsk 0:948e97043afb 144 printf(msg);
igorsk 0:948e97043afb 145 while(1);
igorsk 0:948e97043afb 146 }
igorsk 0:948e97043afb 147
igorsk 0:948e97043afb 148 const unsigned int pattern=0xAA55AA55;
igorsk 0:948e97043afb 149
igorsk 0:948e97043afb 150 void try_tdi(int tdi)
igorsk 0:948e97043afb 151 {
igorsk 0:948e97043afb 152 int output;
igorsk 0:948e97043afb 153 if (tdi==pin_TCK || tdi==pin_TMS || tdi==pin_TDO)
igorsk 0:948e97043afb 154 return;
igorsk 0:948e97043afb 155 //at this point we know which pin is TDO
igorsk 0:948e97043afb 156 //so we'll shift a known pattern into all possible TDIs and monitor the TDO
igorsk 0:948e97043afb 157 //since we were shifting in garbage into them during reading the IDCODE,
igorsk 0:948e97043afb 158 //we'll skip the 32 bits of output while we're shifting in the pattern
igorsk 0:948e97043afb 159 pin_TDI = tdi;
igorsk 0:948e97043afb 160 printf("Trying %s as TDI\n", pinname(tdi));
igorsk 0:948e97043afb 161 makeoutput(tdi);
igorsk 0:948e97043afb 162
igorsk 0:948e97043afb 163 printpins();
igorsk 0:948e97043afb 164 //reset TAP (11111)
igorsk 0:948e97043afb 165 puts("Resetting TAP\n");
igorsk 0:948e97043afb 166 clock_tms(1);clock_tms(1);clock_tms(1);clock_tms(1);clock_tms(1);
igorsk 0:948e97043afb 167 //go to Shift DR (0100)
igorsk 0:948e97043afb 168 puts("Go to Shift DR\n");
igorsk 0:948e97043afb 169 clock_tms(0);clock_tms(1);clock_tms(0);clock_tms(0);
igorsk 0:948e97043afb 170 puts("Shifting in pattern.\n");
igorsk 0:948e97043afb 171
igorsk 0:948e97043afb 172 for (int i=0; i<32; i++)
igorsk 0:948e97043afb 173 {
igorsk 0:948e97043afb 174 //printf("%d: ",i);
igorsk 0:948e97043afb 175 clock_tms_tdi(0, pattern & (1<<i));
igorsk 0:948e97043afb 176 //puts(stringbuf);putc('\r');putc('\n');
igorsk 0:948e97043afb 177 }
igorsk 0:948e97043afb 178 printf("Reading in the output.\n");
igorsk 0:948e97043afb 179 //now keep shifting and read output from TDO
igorsk 0:948e97043afb 180 output = 0;
igorsk 0:948e97043afb 181 for (int i=0;i<32;i++)
igorsk 0:948e97043afb 182 {
igorsk 0:948e97043afb 183 //printf("%d: ",i);
igorsk 0:948e97043afb 184 output |= getpin(pin_TDO) << i;
igorsk 0:948e97043afb 185 clock_tms_tdi(0, 0);
igorsk 0:948e97043afb 186 //puts(stringbuf);putc('\r');putc('\n');
igorsk 0:948e97043afb 187 }
igorsk 0:948e97043afb 188 printf("Got %08X (expected %08X)\n", output, pattern);
igorsk 0:948e97043afb 189 if (output==pattern)
igorsk 0:948e97043afb 190 {
igorsk 0:948e97043afb 191 printf("Success! Final pinout:\n");
igorsk 0:948e97043afb 192 printpins();
igorsk 0:948e97043afb 193 exit_on_button("Found!");
igorsk 0:948e97043afb 194 }
igorsk 0:948e97043afb 195 else if (output!=0 && output!=0xFFFFFFFF)
igorsk 0:948e97043afb 196 {
igorsk 0:948e97043afb 197 printf("Got some pattern but not ours...");
igorsk 0:948e97043afb 198 }
igorsk 0:948e97043afb 199 makeinput(tdi);
igorsk 0:948e97043afb 200 }
igorsk 0:948e97043afb 201
igorsk 0:948e97043afb 202 union idcode_reg {
igorsk 0:948e97043afb 203 struct {
igorsk 0:948e97043afb 204 unsigned int res: 1;
igorsk 0:948e97043afb 205 unsigned int manuf_id: 11;
igorsk 0:948e97043afb 206 unsigned int part_no: 16;
igorsk 0:948e97043afb 207 unsigned int version: 4;
igorsk 0:948e97043afb 208 };
igorsk 0:948e97043afb 209 unsigned int reg32;
igorsk 0:948e97043afb 210 };
igorsk 0:948e97043afb 211
igorsk 0:948e97043afb 212 // check if we can see a valid TAP id on any of the pins
igorsk 0:948e97043afb 213 void try_id()
igorsk 0:948e97043afb 214 {
igorsk 0:948e97043afb 215 int outputs[NPINS] = {0};
igorsk 0:948e97043afb 216 printf("Trying TCK %s, TMS %s\n", pinname(pin_TCK), pinname(pin_TMS));
igorsk 0:948e97043afb 217 makeoutput(pin_TCK);
igorsk 0:948e97043afb 218 makeoutput(pin_TMS);
igorsk 0:948e97043afb 219 printpins();
igorsk 0:948e97043afb 220 //reset TAP (11111)
igorsk 0:948e97043afb 221 printf("Resetting TAP\n");
igorsk 0:948e97043afb 222 clock_tms(1);clock_tms(1);clock_tms(1);clock_tms(1);clock_tms(1);
igorsk 0:948e97043afb 223 //go to Shift DR (0100)
igorsk 0:948e97043afb 224 printf("Go to Shift DR\n");
igorsk 0:948e97043afb 225 clock_tms(0);clock_tms(1);clock_tms(0);clock_tms(0);
igorsk 0:948e97043afb 226 //shift out the DR
igorsk 0:948e97043afb 227 printf("Shifting DR\n");
igorsk 0:948e97043afb 228 //printpins(1);
igorsk 0:948e97043afb 229 //puts(stringbuf);putc('\r');putc('\n');
igorsk 0:948e97043afb 230 for (int i=0;i<32;i++)
igorsk 0:948e97043afb 231 {
igorsk 0:948e97043afb 232 //printf("%d: ",i);
igorsk 0:948e97043afb 233 for (int j=0;j<NPINS;j++)
igorsk 0:948e97043afb 234 {
igorsk 0:948e97043afb 235 if (j!=pin_TCK && j!=pin_TMS)
igorsk 0:948e97043afb 236 outputs[j] |= getpin(j) << i;
igorsk 0:948e97043afb 237 }
igorsk 0:948e97043afb 238 clock_tms(0);
igorsk 0:948e97043afb 239 //puts(stringbuf);putc('\r');putc('\n');
igorsk 0:948e97043afb 240 //printpins(1);
igorsk 0:948e97043afb 241 }
igorsk 0:948e97043afb 242 puts("Done. Checking pin outputs.\n");
igorsk 0:948e97043afb 243 bool found = false;
igorsk 0:948e97043afb 244 for (int j=0;j<NPINS;j++)
igorsk 0:948e97043afb 245 {
igorsk 0:948e97043afb 246 if (j==pin_TCK || j==pin_TMS)
igorsk 0:948e97043afb 247 continue;
igorsk 0:948e97043afb 248 //printf("%2d: %08X\n", j, outputs[j]);
igorsk 0:948e97043afb 249 //check for possible ID code: 32 bits captured are not all zeroes or ones and the 0th bit is 1
igorsk 0:948e97043afb 250 if (outputs[j]!=0 && outputs[j]!=0xFFFFFFFF && (outputs[j]&1) )
igorsk 0:948e97043afb 251 {
igorsk 0:948e97043afb 252 found = true;
igorsk 0:948e97043afb 253 union idcode_reg idc;
igorsk 0:948e97043afb 254 idc.reg32 = outputs[j];
igorsk 0:948e97043afb 255 printf("Found a possible TDO on %s. ID code reply is %08X (manufacturer: %02X, part no.: %02X, version: %X)\n",
igorsk 0:948e97043afb 256 pinname(j), outputs[j], idc.manuf_id, idc.part_no, idc.version);
igorsk 0:948e97043afb 257 pin_TDO = j;
igorsk 0:948e97043afb 258 for (int k=0;k<NPINS;k++)
igorsk 0:948e97043afb 259 try_tdi(k);
igorsk 0:948e97043afb 260 }
igorsk 0:948e97043afb 261 }
igorsk 0:948e97043afb 262 if ( !found )
igorsk 0:948e97043afb 263 printf("Didn't find any good reply...\n");
igorsk 0:948e97043afb 264 makeinput(pin_TCK);
igorsk 0:948e97043afb 265 makeinput(pin_TMS);
igorsk 0:948e97043afb 266 }
igorsk 0:948e97043afb 267
igorsk 0:948e97043afb 268 // try the selected pins
igorsk 0:948e97043afb 269 void try_comb(int v[], int maxk)
igorsk 0:948e97043afb 270 {
igorsk 0:948e97043afb 271 //for (int i=0; i<maxk; i++) printf ("%i ", v[i]);
igorsk 0:948e97043afb 272 //printf ("\n");
igorsk 0:948e97043afb 273 pin_TCK = v[0];
igorsk 0:948e97043afb 274 pin_TMS = v[1];
igorsk 0:948e97043afb 275 try_id();
igorsk 0:948e97043afb 276 pin_TCK = v[1];
igorsk 0:948e97043afb 277 pin_TMS = v[0];
igorsk 0:948e97043afb 278 try_id();
igorsk 0:948e97043afb 279 }
igorsk 0:948e97043afb 280
igorsk 0:948e97043afb 281 // source: http://userweb.cs.utexas.edu/users/djimenez/utsa/cs3343/lecture25.html
igorsk 0:948e97043afb 282 void combinations(int v[], int start, int n, int k, int maxk)
igorsk 0:948e97043afb 283 {
igorsk 0:948e97043afb 284 int i;
igorsk 0:948e97043afb 285 /* k here counts through positions in the maxk-element v.
igorsk 0:948e97043afb 286 * if k >= maxk, then the v is complete and we can use it.
igorsk 0:948e97043afb 287 */
igorsk 0:948e97043afb 288 if ( k >= maxk )
igorsk 0:948e97043afb 289 {
igorsk 0:948e97043afb 290 try_comb(v, maxk);
igorsk 0:948e97043afb 291 return;
igorsk 0:948e97043afb 292 }
igorsk 0:948e97043afb 293
igorsk 0:948e97043afb 294 /* for this k'th element of the v, try all start..n
igorsk 0:948e97043afb 295 * elements in that position
igorsk 0:948e97043afb 296 */
igorsk 0:948e97043afb 297 for (i=start; i<n; i++)
igorsk 0:948e97043afb 298 {
igorsk 0:948e97043afb 299 v[k] = i;
igorsk 0:948e97043afb 300 /* recursively generate combinations of integers
igorsk 0:948e97043afb 301 * from i+1..n
igorsk 0:948e97043afb 302 */
igorsk 0:948e97043afb 303 combinations (v, i+1, n, k+1, maxk);
igorsk 0:948e97043afb 304 }
igorsk 0:948e97043afb 305 }
igorsk 0:948e97043afb 306
igorsk 0:948e97043afb 307 int main()
igorsk 0:948e97043afb 308 {
igorsk 0:948e97043afb 309 int v[NPINS];
igorsk 0:948e97043afb 310 InitGPIO();
igorsk 0:948e97043afb 311 // try all combinations of 2 pins
igorsk 0:948e97043afb 312 combinations (v, 0, NPINS, 0, 2);
igorsk 0:948e97043afb 313 }