mdebug

cortex m series debugger
git clone http://frotz.net/git/mdebug.git
Log | Files | Refs | README | LICENSE

jtag.c (8252B)


      1 /* jtag transport
      2  *
      3  * Copyright 2015 Brian Swetland <swetland@frotz.net>
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 #include <string.h>
     19 #include <stdlib.h>
     20 
     21 #include <fw/types.h>
     22 
     23 #include "debugger.h"
     24 #include "rswdp.h"
     25 #include "jtag.h"
     26 
     27 static const char *JSTATE[17] = {
     28         "RESET", "IDLE", "DRSELECT", "DRCAPTURE",
     29         "DRSHIFT", "DREXIT1", "DRPAUSE", "DREXIT2",
     30         "DRUPDATE", "IRSELECT", "IRCAPTURE", "IRSHIFT",
     31         "IREXIT1", "IRPAUSE", "IREXIT1", "IRUPDATE",
     32 	"UNKNOWN"
     33 };
     34 
     35 static u64 ONES = 0xFFFFFFFFFFFFFFFFUL;
     36 
     37 void jtag_txn_init(jtag_txn *tx) {
     38 	memset(tx, 0, sizeof(jtag_txn));
     39 	tx->state = JTAG_UNKNOWN;
     40 }
     41 
     42 int jtag_txn_exec(jtag_txn *t) {
     43 	unsigned n, off = 0;
     44 	int r;
     45 	if (t->status) {
     46 		return t->status;
     47 	}
     48 	//xprintf(XCORE, "jtag exec %d bits\n", t->txc);
     49 	r = jtag_io(t->txc, t->tms, t->tdi, t->tdo);
     50 	for (n = 0; n < t->rxc; n++) {
     51 		unsigned count = t->bits[n];
     52 		if (t->ptr[n]) {
     53 			unsigned bit = 0;
     54 			u64 x = 0;
     55 			while (count > 0) {
     56 				x |= ((u64) ((t->tdo[off >> 5] >> (off & 31)) & 1)) << bit;
     57 				off++;
     58 				bit++;
     59 				count--;
     60 			}
     61 			*t->ptr[n] = x;
     62 		} else {
     63 			off += count;
     64 		}
     65 	}
     66 	return r;
     67 }
     68 
     69 void jtag_txn_append(jtag_txn *t, unsigned count, u64 tms, u64 tdi, u64 *tdo) {
     70 	unsigned txc = t->txc;
     71 
     72 	if (txc == JTAG_MAX_RESULTS) {
     73 		xprintf(XCORE, "jtag append txn overflow\n");
     74 		t->status = -1;
     75 		return;
     76 	}
     77 	if ((count > 64) || ((JTAG_MAX_BITS - t->bitcount) < count)) {
     78 		xprintf(XCORE, "jtag append bits overflow\n");
     79 		t->status = -1;
     80 		return;
     81 	}
     82 	t->bitcount += count;
     83 
     84 //	xprintf(XCORE, "jtag append %2d bits %016lx %016lx\n", count, tms, tdi);
     85 
     86 	t->ptr[t->rxc] = tdo;
     87 	t->bits[t->rxc] = count;
     88 	t->rxc++;
     89 
     90 	while (count > 0) {
     91 		t->tms[txc >> 5] |= (tms & 1) << (txc & 31);
     92 		t->tdi[txc >> 5] |= (tdi & 1) << (txc & 31);
     93 		tms >>= 1;
     94 		tdi >>= 1;
     95 		count--;
     96 		txc++;
     97 	}
     98 	t->txc = txc;
     99 }
    100 
    101 void jtag_txn_move(jtag_txn *t, unsigned dst) {
    102 	if (t->state == dst) {
    103 		// nothing to do
    104 		return;
    105 	}
    106 	switch (t->state) {
    107 	case JTAG_IDLE:
    108 		if (dst == JTAG_IRSHIFT) {
    109 			// Idle -> SelDR -> SelIR -> CapIR -> ShiftIR
    110 			//      1        1        0        0
    111 			jtag_txn_append(t, 4, 0b0011, 0b1111, NULL);
    112 		} else if (dst == JTAG_DRSHIFT) {
    113 			// Idle -> SelDR -> CapDR -> ShiftDR
    114 			//      1        0        0
    115 			jtag_txn_append(t, 3, 0b001, 0b111, NULL);
    116 		} else {
    117 			goto oops;
    118 		}
    119 		break;
    120 	case JTAG_DRPAUSE:
    121 	case JTAG_IRPAUSE:
    122 		if (dst == JTAG_IRSHIFT) {
    123 			// PauseDR -> Exit2DR -> UpDR -> SelDR -> SelIR -> CapIR -> ShiftIR
    124 			// PauseIR -> Exit2IR -> UpIR -> SelDR -> SelIR -> CapIR -> ShiftIR
    125 			//         1          1       1        1        0        0
    126 			jtag_txn_append(t, 6, 0b001111, 0b111111, NULL);
    127 		} else if (dst == JTAG_DRSHIFT) {
    128 			// PauseDR -> Exit2DR -> UpDR -> SelDR -> CapDR -> ShiftDR
    129 			// PauseIR -> Exit2IR -> UpIR -> SelDR -> CapDR -> ShiftDR
    130 			//         1          1       1        0        0
    131 			jtag_txn_append(t, 5, 0b00111, 0b11111, NULL);
    132 		} else if (dst == JTAG_IDLE) {
    133 			// PauseDR -> Exit2DR -> UpDR -> Idle
    134 			// PauseIR -> Exit2IR -> UpIR -> Idle
    135 			//         1          1       0
    136 			jtag_txn_append(t, 3, 0b011, 0b111, NULL);
    137 		} else {
    138 			goto oops;
    139 		}
    140 		break;
    141 	case JTAG_DREXIT1:
    142 	case JTAG_IREXIT1:
    143 		if (dst == JTAG_IRSHIFT) {
    144 			// Exit1DR -> UpDR -> SelDR -> SelIR -> CapIR -> ShiftIR
    145 			// Exit1IR -> UpIR -> SelDR -> SelIR -> CapIR -> ShiftIR
    146 			//         1       1        1        0        0
    147 			jtag_txn_append(t, 5, 0b00111, 0b11111, NULL);
    148 		} else if (dst == JTAG_DRSHIFT) {
    149 			// Exit1DR -> UpDR -> SelDR -> CapDR -> ShiftDR
    150 			// Exit1IR -> UpIR -> SelDR -> CapDR -> ShiftDR
    151 			//         1       1        0        0
    152 			jtag_txn_append(t, 4, 0b0011, 0b1111, NULL);
    153 		} else if (dst == JTAG_IDLE) {
    154 			// Exit1DR -> UpDR -> Idle
    155 			// Exit1IR -> UpIR -> Idle
    156 			//         1       0
    157 			jtag_txn_append(t, 2, 0b01, 0b11, NULL);
    158 		} else if (dst == JTAG_DRPAUSE) {
    159 			// Exit1DR -> PauseDR
    160 			// Exit1IR -> PauseIR
    161 			//         0
    162 			jtag_txn_append(t, 1, 0b0, 0b1, NULL);
    163 		} else {
    164 			goto oops;
    165 		}
    166 		break;
    167 	default:
    168 oops:
    169 		xprintf(XCORE, "jtag move from %s to %s unsupported\n",
    170 			JSTATE[t->state], JSTATE[dst]);
    171 		t->status = -1;
    172 		t->state = JTAG_UNKNOWN;
    173 		return;
    174 	}
    175 	t->state = dst;
    176 }
    177 
    178 void jtag_cjtag_open(jtag_txn *t) {
    179 	jtag_txn_move(t, JTAG_IDLE);
    180 	// Idle -> SelDR -> CapDR -> Exit1DR -> UpDR             ZBS#1
    181 	//      1        0        1          1
    182 	// UpDR -> SelDR -> CapDR -> Exit1DR -> UpDR             ZBS#2
    183         //      1        0        1          1
    184 	// UpDR -> SelDR -> CapDR -> ShiftDR -> Exit1DR -> UpDR -> Idle   One Bit Scan
    185 	//      1        0        0          1          1       0
    186 	jtag_txn_append(t, 14, 0b01100111011101, 0, NULL);
    187 } 
    188 
    189 void jtag_cjtag_cmd(jtag_txn *t, unsigned cp0, unsigned cp1) {
    190 	jtag_txn_move(t, JTAG_IDLE);
    191 	if ((cp0 > 15) || (cp1 > 15)) {
    192 		xprintf(XCORE, "jtag invalid cjtag parameters %d %d\n", cp0, cp1);
    193 		t->status = -1;
    194 		return;
    195 	}
    196 	if (cp0 == 0) {
    197 		// Idle -> SelDR -> CapDR -> Exit1DR -> UpDR -> Idle
    198 		//      1        0        1          1       0
    199 		jtag_txn_append(t, 5, 0b01101, 0, NULL);
    200 	} else {
    201 		// Idle -> SelDR -> CapDR -> ShiftDR (xN) -> Exit1DR -> UpDR -> Idle
    202 		//      1        0        0               1          1       0
    203 		jtag_txn_append(t, 5 + cp0, ((0b011 << cp0) << 2) | 0b01, 0, NULL);
    204 	}
    205 	if (cp1 == 0) {
    206 		// Idle -> SelDR -> CapDR -> Exit1DR -> UpDR -> Idle
    207 		//      1        0        1          1       0
    208 		jtag_txn_append(t, 5, 0b01101, 0, NULL);
    209 	} else {
    210 		// Idle -> SelDR -> CapDR -> ShiftDR (xN) -> Exit1DR -> UpDR -> Idle
    211 		//      1        0        0               1          1       0
    212 		jtag_txn_append(t, 5 + cp1, ((0b011 << cp1) << 2) | 0b01, 0, NULL);
    213 	}
    214 }
    215 
    216 void jtag_any_to_rti(jtag_txn *t) {
    217 	// 5x TMS=1 is sufficient, but throw a couple more in for luck
    218 	jtag_txn_append(t, 9, 0xFF, 0x1FF, NULL);
    219 	t->state = JTAG_IDLE;
    220 }
    221 
    222 static void _jtag_shiftir(jtag_txn *t, unsigned count, u64 tx, u64 *rx) {
    223 	// all bits but last, tms=0 (stay in ShiftIR), last tms=1 (goto Exit1IR)
    224 	if (t->state != JTAG_IRSHIFT) {
    225 		xprintf(XCORE, "jtag invalid state (%s) in shiftir\n", JSTATE[t->state]);
    226 		t->status = -1;
    227 	}
    228 	if (t->ir_pre) {
    229 		jtag_txn_append(t, t->ir_pre, 0, ONES, NULL);
    230 	}
    231 	if (t->ir_post) {
    232 		u64 tms = 1UL << (t->ir_post - 1);
    233 		jtag_txn_append(t, count, 0, tx, rx);
    234 		jtag_txn_append(t, t->ir_post, tms, ONES, NULL);
    235 	} else {
    236 		u64 tms = 1UL << (count - 1);
    237 		jtag_txn_append(t, count, tms, tx, rx);
    238 	}
    239 	t->state = JTAG_IREXIT1;
    240 }
    241 
    242 static void _jtag_shiftdr(jtag_txn *t, unsigned count, u64 tx, u64 *rx) {
    243 	if (t->state != JTAG_DRSHIFT) {
    244 		xprintf(XCORE, "jtag invalid state (%s) in shiftir\n", JSTATE[t->state]);
    245 		t->status = -1;
    246 	}
    247 	// all bits but last, tms=0 (stay in ShiftDR), last tms=1 (goto Exit1DR)
    248 	if (t->dr_pre) {
    249 		jtag_txn_append(t, t->dr_pre, 0, ONES, NULL);
    250 	}
    251 	if (t->dr_post) {
    252 		u64 tms = 1UL << (t->dr_post - 1);
    253 		jtag_txn_append(t, count, 0, tx, rx);
    254 		jtag_txn_append(t, t->dr_post, tms, ONES, NULL);
    255 	} else {
    256 		u64 tms = 1UL << (count - 1);
    257 		jtag_txn_append(t, count, tms, tx, rx);
    258 	}
    259 	t->state = JTAG_DREXIT1;
    260 }
    261 
    262 void jtag_ir(jtag_txn *t, unsigned count, u64 ir) {
    263 	jtag_txn_move(t, JTAG_IRSHIFT);
    264 	_jtag_shiftir(t, count, ir, NULL);
    265 	jtag_txn_move(t, JTAG_IDLE);
    266 }
    267 
    268 void jtag_dr(jtag_txn *t, unsigned count, u64 dr, u64 *out) {
    269 	jtag_txn_move(t, JTAG_DRSHIFT);
    270 	_jtag_shiftdr(t, count, dr, out);
    271 	jtag_txn_move(t, JTAG_IDLE);
    272 }
    273 
    274 void jtag_ir_p(jtag_txn *t, unsigned count, u64 ir) {
    275 	jtag_txn_move(t, JTAG_IRSHIFT);
    276 	_jtag_shiftir(t, count, ir, NULL);
    277 	jtag_txn_move(t, JTAG_IRPAUSE);
    278 }
    279 
    280 void jtag_dr_p(jtag_txn *t, unsigned count, u64 dr, u64 *out) {
    281 	jtag_txn_move(t, JTAG_DRSHIFT);
    282 	_jtag_shiftdr(t, count, dr, out);
    283 	jtag_txn_move(t, JTAG_DRPAUSE);
    284 }
    285 
    286