mdebug

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

jtag-dap.c (11701B)


      1 /* jtag-dap.c
      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 <stdio.h>
     19 #include <stdlib.h>
     20 #include <string.h>
     21 
     22 #include <fw/types.h>
     23 #include "debugger.h"
     24 #include "jtag.h"
     25 #include "dap-registers.h"
     26 
     27 #define CSW_ERRORS (DPCSW_STICKYERR | DPCSW_STICKYCMP | DPCSW_STICKYORUN)
     28 #define CSW_ENABLES (DPCSW_CSYSPWRUPREQ | DPCSW_CDBGPWRUPREQ | DPCSW_ORUNDETECT)
     29 
     30 typedef struct DAP {
     31 	jtag_txn *jtag;
     32 	u32 cached_ir;
     33 	u32 ir_pre, ir_post;
     34 	u32 dr_pre, dr_post;
     35 } DAP;
     36 
     37 void dap_init_jtag(DAP *dap) {
     38 	jtag_txn_init(dap->jtag);
     39 	dap->cached_ir = 0xFFFFFFFF;
     40 	dap->jtag->ir_pre = dap->ir_pre;
     41 	dap->jtag->ir_post = dap->ir_post;
     42 	dap->jtag->dr_pre = dap->dr_pre;
     43 	dap->jtag->dr_post = dap->dr_post;
     44 	dap->jtag->state = JTAG_IDLE;
     45 }
     46 
     47 void dap_init(DAP *dap, jtag_txn *t, u32 ir_pre, u32 ir_post, u32 dr_pre, u32 dr_post) {
     48 	dap->jtag = t;
     49 	dap->ir_pre = ir_pre;
     50 	dap->ir_post = ir_post;
     51 	dap->dr_pre = dr_pre;
     52 	dap->dr_post = dr_post;
     53 	dap_init_jtag(dap);
     54 }
     55 
     56 static void q_dap_ir_wr(DAP *dap, u32 ir) {
     57 	if (dap->cached_ir != ir) {
     58 		dap->cached_ir = ir;
     59 		jtag_ir(dap->jtag, 4, ir);
     60 	}
     61 }
     62 
     63 // force ir write even if redundant
     64 // used for a timing hack
     65 static void _q_dap_ir_wr(DAP *dap, u32 ir) {
     66 	dap->cached_ir = ir;
     67 	jtag_ir(dap->jtag, 4, ir);
     68 }
     69 
     70 static void q_dap_dr_io(DAP *dap, u32 bitcount, u64 wdata, u64 *rdata) {
     71 	if (rdata) {
     72 		*rdata = 0;
     73 	}
     74 	jtag_dr(dap->jtag, bitcount, wdata, rdata);
     75 }
     76 
     77 static void q_dap_abort(DAP *dap) {
     78 	jtag_ir(dap->jtag, 4, DAP_IR_ABORT);
     79 	jtag_dr(dap->jtag, 35, 8, NULL);
     80 	dap->cached_ir = 0xFFFFFFFF;
     81 }
     82 
     83 static int dap_commit_jtag(DAP *dap) {
     84 	int r = jtag_txn_exec(dap->jtag);
     85 	dap_init_jtag(dap);
     86 	return r;
     87 }
     88 
     89 // queue a DPCSW status query, commit jtag txn
     90 static int dap_commit(DAP *dap) {
     91 	u64 a, b;
     92 	q_dap_ir_wr(dap, DAP_IR_DPACC);
     93 	q_dap_dr_io(dap, 35, XPACC_RD(DPACC_CSW), &a);
     94 	q_dap_dr_io(dap, 35, XPACC_RD(DPACC_RDBUFF), &b);
     95 	dap->cached_ir = 0xFFFFFFFF;
     96 	if (dap_commit_jtag(dap)) {
     97 		return -1;
     98 	}
     99 #if 0
    100 	xprintf(XCORE, "DP_CSW %08x(%x) RDBUF %08x(%x)\n",
    101 		((u32) (a >> 3)), ((u32) (a & 7)),
    102 		((u32) (b >> 3)), ((u32) (b & 7)));
    103 #endif
    104 	if (XPACC_STATUS(a) != XPACC_OK) {
    105 		xprintf(XCORE, "dap: invalid txn status\n");
    106 		return -1;
    107 	}
    108 	if (XPACC_STATUS(b) != XPACC_OK) {
    109 		xprintf(XCORE, "dap: cannot read status\n");
    110 		return -1;
    111 	}
    112 	b >>= 3;
    113 	if (b & DPCSW_STICKYORUN) {
    114 		xprintf(XCORE, "dap: overrun\n");
    115 		return -1;
    116 	}
    117 	if (b & DPCSW_STICKYERR) {
    118 		xprintf(XCORE, "dap: error\n");
    119 		return -1;
    120 	}
    121 	return 0;
    122 }
    123 
    124 int dap_dp_rd(DAP *dap, u32 addr, u32 *val) {
    125 	u64 u;
    126 	q_dap_ir_wr(dap, DAP_IR_DPACC);
    127 	q_dap_dr_io(dap, 35, XPACC_RD(addr), NULL);
    128 	q_dap_dr_io(dap, 35, XPACC_RD(DPACC_RDBUFF), &u);
    129 	if (dap_commit_jtag(dap)) {
    130 		return -1;
    131 	}
    132 	if (XPACC_STATUS(u) != XPACC_OK) {
    133 		return -1;
    134 	}
    135 	*val = u >> 3;
    136 	return 0;
    137 }
    138 
    139 static void q_dap_dp_wr(DAP *dap, u32 addr, u32 val) {
    140 	q_dap_ir_wr(dap, DAP_IR_DPACC);
    141 	q_dap_dr_io(dap, 35, XPACC_WR(addr, val), NULL);
    142 	//q_dap_dr_io(dap, 35, XPACC_RD(DPACC_RDBUFF), &s->u);
    143 }
    144 
    145 int dap_dp_wr(DAP *dap, u32 addr, u32 val) {
    146 	q_dap_dp_wr(dap, addr, val);
    147 	return dap_commit_jtag(dap);
    148 }
    149 
    150 int dap_ap_rd(DAP *dap, u32 apnum, u32 addr, u32 *val) {
    151 	u64 u;
    152 	q_dap_ir_wr(dap, DAP_IR_DPACC);
    153 	q_dap_dp_wr(dap, DPACC_SELECT, DPSEL_APSEL(apnum) | DPSEL_APBANKSEL(addr));
    154 	q_dap_ir_wr(dap, DAP_IR_APACC);
    155 	q_dap_dr_io(dap, 35, XPACC_RD(addr), NULL);
    156 	q_dap_ir_wr(dap, DAP_IR_DPACC);
    157 	q_dap_dr_io(dap, 35, XPACC_RD(DPACC_RDBUFF), &u);
    158 	// TODO: redundant ir wr
    159 	if (dap_commit(dap)) {
    160 		return -1;
    161 	}
    162 	*val = (u >> 3);
    163 	return 0;
    164 }
    165 
    166 void q_dap_ap_wr(DAP *dap, u32 apnum, u32 addr, u32 val) {
    167 	q_dap_ir_wr(dap, DAP_IR_DPACC);
    168 	q_dap_dp_wr(dap, DPACC_SELECT, DPSEL_APSEL(apnum) | DPSEL_APBANKSEL(addr));
    169 	q_dap_ir_wr(dap, DAP_IR_APACC);
    170 	q_dap_dr_io(dap, 35, XPACC_WR(addr, val), NULL);
    171 }
    172 
    173 int dap_ap_wr(DAP *dap, u32 apnum, u32 addr, u32 val) {
    174 	q_dap_ap_wr(dap, apnum, addr, val);
    175 	return dap_commit(dap);
    176 }
    177 
    178 int dap_mem_wr32(DAP *dap, u32 n, u32 addr, u32 val) {
    179 	if (addr & 3)
    180 		return -1;
    181 	q_dap_ap_wr(dap, n, APACC_CSW,
    182 		0x23000000 | APCSW_DBGSWEN | APCSW_INCR_NONE | APCSW_SIZE32); //XXX
    183 	q_dap_ap_wr(dap, n, APACC_TAR, addr);
    184 	q_dap_ap_wr(dap, n, APACC_DRW, val);
    185 	return dap_commit(dap);
    186 }
    187 
    188 int dap_mem_rd32(DAP *dap, u32 n, u32 addr, u32 *val) {
    189 	if (addr & 3)
    190 		return -1;
    191 	q_dap_ap_wr(dap, n, APACC_CSW,
    192 		0x23000000 | APCSW_DBGSWEN | APCSW_INCR_NONE | APCSW_SIZE32); //XXX
    193 	q_dap_ap_wr(dap, n, APACC_TAR, addr);
    194 	if (dap_ap_rd(dap, n, APACC_DRW, val))
    195 		return -1;
    196 	return 0;
    197 }
    198 
    199 
    200 int dap_attach(DAP *dap) {
    201 	unsigned n;
    202 	u32 x;
    203 
    204 	// make sure we abort any ongoing transactions first
    205 	q_dap_abort(dap);
    206 
    207 	// attempt to power up and clear errors
    208 	for (n = 0; n < 10; n++) {
    209 		if (dap_dp_wr(dap, DPACC_CSW, CSW_ERRORS | CSW_ENABLES))
    210 			continue;
    211 		if (dap_dp_rd(dap, DPACC_CSW, &x))
    212 			continue;
    213 		if (x & CSW_ERRORS)
    214 			continue;
    215 		if (!(x & DPCSW_CSYSPWRUPACK))
    216 			continue;
    217 		if (!(x & DPCSW_CDBGPWRUPACK))
    218 			continue;
    219 		return 0;
    220 	}
    221 	xprintf(XCORE, "dap: attach failed\n");
    222 	return -1;
    223 }
    224 
    225 void dap_clear_errors(DAP *dap) {
    226 	q_dap_dp_wr(dap, DPACC_CSW, CSW_ERRORS | CSW_ENABLES);
    227 }
    228 
    229 static int read4xid(DAP *dap, u32 n, u32 addr, u32 *val) {
    230 	u32 a,b,c,d;
    231 	if (dap_mem_rd32(dap, n, addr + 0x00, &a)) return -1;
    232 	if (dap_mem_rd32(dap, n, addr + 0x04, &b)) return -1;
    233 	if (dap_mem_rd32(dap, n, addr + 0x08, &c)) return -1;
    234 	if (dap_mem_rd32(dap, n, addr + 0x0C, &d)) return -1;
    235 	*val = (a & 0xFF) | ((b & 0xFF) << 8) | ((c & 0xFF) << 16) | ((d & 0xFF) << 24);
    236 	return 0;
    237 }
    238 
    239 static int readinfo(DAP *dap, u32 n, u32 base, u32 *cid, u32 *pid0, u32 *pid1) {
    240 	if (read4xid(dap, n, base + 0xFF0, cid)) return -1;
    241 	if (read4xid(dap, n, base + 0xFE0, pid0)) return -1;
    242 	if (read4xid(dap, n, base + 0xFD0, pid1)) return -1;
    243 	return 0;
    244 }
    245 
    246 static void dumptable(DAP *dap, u32 n, u32 base) {
    247 	u32 cid, pid0, pid1, memtype;
    248 	u32 x, addr;
    249 	int i;
    250 
    251 	xprintf(XCORE, "TABLE   @%08x ", base);
    252 	if (readinfo(dap, n, base, &cid, &pid0, &pid1)) {
    253 		xprintf(XCORE, "<error reading cid & pid>\n");
    254 		return;
    255 	}
    256 	if (dap_mem_rd32(dap, n, base + 0xFCC, &memtype)) {
    257 		xprintf(XCORE, "<error reading memtype>\n");
    258 		return;
    259 	}
    260 	xprintf(XCORE, "CID %08x  PID %08x %08x  %dKB%s\n", cid, pid1, pid0,
    261 		4 * (1 + ((pid1 & 0xF0) >> 4)),
    262 		(memtype & 1) ? "  SYSMEM": "");
    263 	for (i = 0; i < 128; i++) {
    264 		if (dap_mem_rd32(dap, n, base + i * 4, &x)) break;
    265 		if (x == 0) break;
    266 		if ((x & 3) != 3) continue;
    267 		addr = base + (x & 0xFFFFF000);
    268 		if (readinfo(dap, n, addr, &cid, &pid0, &pid1)) {
    269 			xprintf(XCORE, "    <error reading cid & pid>\n");
    270 			continue;
    271 		}
    272 		xprintf(XCORE, "    %02d: @%08x CID %08x  PID %08x %08x  %dKB\n",
    273 			i, addr, cid, pid1, pid0,
    274 			4 * (1 + ((pid1 & 0xF0) >> 4)));
    275 		if (((cid >> 12) & 0xF) == 1) {
    276 			dumptable(dap, n, addr);
    277 		}
    278 	}
    279 }
    280 
    281 int dap_probe(DAP *dap) {
    282 	unsigned n;
    283 	u32 x, y;
    284 
    285 	for (n = 0; n < 256; n++) {
    286 		if (dap_ap_rd(dap, n, APACC_IDR, &x))
    287 			break;
    288 		if (x == 0)
    289 			break;
    290 		y = 0;
    291 		dap_ap_rd(dap, n, APACC_BASE, &y);
    292 		xprintf(XCORE, "AP%d ID=%08x BASE=%08x\n", n, x, y);
    293 		if (y && (y != 0xFFFFFFFF)) {
    294 			dumptable(dap, n, y & 0xFFFFF000);
    295 		}
    296 		if (dap_ap_rd(dap, n, APACC_CSW, &x) == 0)
    297 			xprintf(XCORE, "AP%d CSW=%08x\n", n, x);
    298 	}
    299 	return 0;
    300 }
    301 
    302 static int jtag_error = 0;
    303 
    304 #include "ti-icepick.h"
    305 
    306 #define IDCODE_ARM_M3		0x4ba00477
    307 #define IPCODE_TI_ICEPICK	0x41611cc0
    308 #define IDCODE_CC1310		0x2b9be02f
    309 #define IDCODE_CC2650		0x8b99a02f
    310 
    311 int connect_ti(void) {
    312 	u64 x0, x1;
    313 	int retry = 5;
    314 	jtag_txn t;
    315 
    316 	while (retry > 0) {
    317 		jtag_txn_init(&t);
    318 		jtag_any_to_rti(&t);
    319 
    320 		// Enable 4-wire JTAG
    321 		jtag_ir(&t, 6, 0x3F);
    322 		jtag_cjtag_open(&t);
    323 		jtag_cjtag_cmd(&t, 2, 9);
    324 		jtag_ir(&t, 6, 0x3F);
    325 
    326 		// sit in IDLE for a bit (not sure if useful)
    327 		jtag_txn_append(&t, 64, 0, 0, NULL);
    328 
    329 		// Read IDCODE and IPCODE
    330 		jtag_ir(&t, 6, IP_IR_IDCODE);
    331 		jtag_dr(&t, 32, 0x00000000, &x0);
    332 		jtag_ir(&t, 6, IP_IR_IPCODE);
    333 		jtag_dr(&t, 32, 0x00000000, &x1);
    334 		jtag_txn_exec(&t);
    335 
    336 		if (x1 == IPCODE_TI_ICEPICK) {
    337 			if (x0 == IDCODE_CC1310) {
    338 				break;
    339 			}
    340 			if (x0 == IDCODE_CC2650) {
    341 				break;
    342 			}
    343 			xprintf(XCORE, "wat!\n");
    344 		}
    345 		retry--;
    346 	}
    347 	if (retry == 0) {
    348 		//xprintf(XCORE, "cannot connect (%08x %08x)\n", (u32)x0, (u32)x1);
    349 		return -1;
    350 	}
    351 	xprintf(XSWD, "attach: IDCODE %08x %08x\n", (u32)x0, (u32)x1);
    352 
    353 	jtag_txn_init(&t);
    354 	t.state = JTAG_IDLE;
    355 
    356 	// enable router access
    357 	jtag_ir(&t, 6, IP_IR_CONNECT);
    358 	jtag_dr(&t, 8, IP_CONNECT_WR_KEY, NULL);
    359 
    360 	// add ARM DAP to the scan chain
    361 	jtag_ir(&t, 6, IP_IR_ROUTER);
    362 	jtag_dr_p(&t, 32, IP_RTR_WR | IP_RTR_BLK(IP_BLK_DEBUG_TLCB) |
    363 		IP_RTR_REG(IP_DBG_TAP0) |
    364 		IP_RTR_VAL(IP_DBG_SELECT_TAP | IP_DBG_INHIBIT_SLEEP | IP_DBG_FORCE_ACTIVE), NULL);
    365 
    366 	// commit router changes by going to IDLE state
    367 	jtag_txn_move(&t, JTAG_IDLE);
    368 
    369 	// idle for a few clocks to let the new TAP path settle
    370 	jtag_txn_append(&t, 8, 0, 0, NULL);
    371 	jtag_txn_exec(&t);
    372 
    373 #if 0
    374 	jtag_txn_init(&t);
    375 	t.state = JTAG_IDLE;
    376 	t.ir_pre = 4;
    377 	t.dr_pre = 1;
    378 	jtag_ir(&t, 6, IP_IR_ROUTER);
    379 	jtag_dr(&t, 32, IP_RTR_WR | IP_RTR_BLK(IP_BLK_CONTROL) | IP_RTR_REG(IP_CTL_CONTROL) |
    380 		IP_RTR_VAL(IP_CTL_SYSTEM_RESET), NULL);
    381 	jtag_txn_exec(&t);
    382 #endif
    383 
    384 	// we should now be stable, try to read DAP IDCODE
    385 	jtag_txn_init(&t);
    386 	t.state = JTAG_IDLE;
    387 	t.ir_post = 6;
    388 	t.dr_post = 1;
    389 	jtag_ir(&t, 4, 0xE); // IDCODE
    390 	jtag_dr(&t, 32, 0, &x0);
    391 	jtag_txn_exec(&t);
    392 
    393 	if (x0 != IDCODE_ARM_M3) {
    394 		xprintf(XDATA, "cannot find DAP (%08x)\n", (u32)x0);
    395 		return -1;
    396 	}
    397 
    398 	return 0;
    399 }
    400 
    401 int _attach(void) {
    402 	jtag_txn t;
    403 	DAP dap;
    404 	jtag_error = -1;
    405 	if (connect_ti()) {
    406 		return -1;
    407 	}
    408 	dap_init(&dap, &t, 0, 6, 0, 1);
    409 	if (dap_attach(&dap)) {
    410 		return -1;
    411 	}
    412 	xprintf(XSWD, "attach: JTAG DAP ok\n");
    413 	jtag_error = 0;
    414 	return 0;
    415 }
    416 
    417 static int _mem_rd_32(u32 addr, u32 *val) {
    418 	jtag_txn t;
    419 	DAP dap;
    420 	if ((addr & 3) || jtag_error) {
    421 		return -1;
    422 	}
    423 	dap_init(&dap, &t, 0, 6, 0, 1);
    424 	jtag_error = dap_mem_rd32(&dap, 0, addr, val);
    425 	return jtag_error;
    426 }
    427 
    428 static int _mem_wr_32(u32 addr, u32 val) {
    429 	jtag_txn t;
    430 	DAP dap;
    431 	if ((addr & 3) || jtag_error) {
    432 		return -1;
    433 	}
    434 	dap_init(&dap, &t, 0, 6, 0, 1);
    435 	jtag_error = dap_mem_wr32(&dap, 0, addr, val);
    436 	return jtag_error;
    437 }
    438 
    439 static int _mem_rd_32_c(u32 addr, u32 *data, int count) {
    440 	jtag_txn t;
    441 	DAP dap;
    442 	if ((addr & 3) || jtag_error) {
    443 		return -1;
    444 	}
    445 	dap_init(&dap, &t, 0, 6, 0, 1);
    446 	while (count > 0) {
    447 		if (dap_mem_rd32(&dap, 0, addr, data)) {
    448 			jtag_error = -1;
    449 			return -1;
    450 		}
    451 		addr += 4;
    452 		data++;
    453 		count--;
    454 	}
    455 	return 0;
    456 }
    457 
    458 static int _mem_wr_32_c(u32 addr, u32 *data, int count) {
    459 	jtag_txn t;
    460 	DAP dap;
    461 	if ((addr & 3) || jtag_error) {
    462 		return -1;
    463 	}
    464 	dap_init(&dap, &t, 0, 6, 0, 1);
    465 	while (count > 0) {
    466 		if (dap_mem_wr32(&dap, 0, addr, *data)) {
    467 			jtag_error = -1;
    468 			return -1;
    469 		}
    470 		addr += 4;
    471 		data++;
    472 		count--;
    473 	}
    474 	return 0;
    475 }
    476 
    477 static int _clear_error(void) {
    478 	if (jtag_error) {
    479 		//XXX this is a lighter weight operation in SWDP
    480 		_attach();
    481 	}
    482 	return jtag_error;
    483 }
    484 
    485 static int _error(void) {
    486 	return jtag_error;
    487 }
    488 
    489 debug_transport JTAG_TRANSPORT = {
    490 	.attach = _attach,
    491 	.error = _error,
    492 	.clear_error = _clear_error,
    493 	.mem_rd_32 = _mem_rd_32,
    494 	.mem_wr_32 = _mem_wr_32,
    495 	.mem_rd_32_c = _mem_rd_32_c,
    496 	.mem_wr_32_c = _mem_wr_32_c,
    497 };