mdebug

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

debugger-commands.c (26768B)


      1 /* debugger-commands.);
      2  *
      3  * Copyright 2011 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 <unistd.h>
     21 #include <string.h>
     22 #include <ctype.h>
     23 #include <stdarg.h>
     24 #include <errno.h>
     25 
     26 #include <fcntl.h>
     27 #include <sys/time.h>
     28 
     29 #include <fw/types.h>
     30 #include <protocol/rswdp.h>
     31 #include "rswdp.h"
     32 #include "arm-v7m.h"
     33 
     34 #include "debugger.h"
     35 #include "lkdebug.h"
     36 
     37 #define _AGENT_HOST_ 1
     38 #include <agent/flash.h>
     39 
     40 extern struct debugger_command debugger_commands[];
     41 
     42 long long now() {
     43 	struct timeval tv;
     44 	gettimeofday(&tv, 0);
     45 	return ((long long) tv.tv_usec) + ((long long) tv.tv_sec) * 1000000LL;
     46 }
     47 
     48 extern int disassemble_thumb2(u32 addr, u16 op0, u16 op1,
     49 		char *text, int len) __attribute__ ((weak));
     50 
     51 int disassemble(u32 addr) {
     52 #if WITH_THUMB2_DISASSEMBLE
     53 	char text[128];
     54 	int r;
     55 	union {
     56 		u32 w[2];
     57 		u16 h[4];
     58 	} mem;
     59 
     60 	if (!disassemble_thumb2)
     61 		return -1;
     62 
     63 	if (addr & 2) {
     64 		if (swdp_ahb_read32(addr & (~3), mem.w, 2))
     65 			return -1;
     66 		r = disassemble_thumb2(addr, mem.h[1], mem.h[2], text, 128);
     67 	} else {
     68 		if (swdp_ahb_read32(addr & (~3), mem.w, 1))
     69 			return -1;
     70 		r = disassemble_thumb2(addr, mem.h[0], mem.h[1], text, 128);
     71 	}
     72 	if (r > 0)
     73 		xprintf(XDATA, "%s\n", text);
     74 	return r;
     75 #else
     76 	return -1;
     77 #endif
     78 }
     79 
     80 int do_exit(int argc, param *argv) {
     81 	exit(0);
     82 	return 0;
     83 }
     84 
     85 int do_attach(int argc, param *argv) {
     86 	if (argc > 0) {
     87 		if (!strcmp(argv[0].s, "pico0")) {
     88 			swdp_targetsel(0x01002927, 1);
     89 			ACTIVE_TRANSPORT = &SWDP_TRANSPORT;
     90 		} else if (!strcmp(argv[0].s, "pico1")) {
     91 			swdp_targetsel(0x11002927, 1);
     92 			ACTIVE_TRANSPORT = &SWDP_TRANSPORT;
     93 		} else if (!strcmp(argv[0].s, "picor")) {
     94 			swdp_targetsel(0xF1002927, 1);
     95 			ACTIVE_TRANSPORT = &SWDP_TRANSPORT;
     96 		} else if (!strcmp(argv[0].s, "swd")) {
     97 			swdp_targetsel(0, 0);
     98 			ACTIVE_TRANSPORT = &SWDP_TRANSPORT;
     99 		} else if (!strcmp(argv[0].s, "swdx")) {
    100 			swdp_targetsel(0xffffffff, 1);
    101 			ACTIVE_TRANSPORT = &SWDP_TRANSPORT;
    102 		} else if (!strcmp(argv[0].s, "jtag")) {
    103 			ACTIVE_TRANSPORT = &JTAG_TRANSPORT;
    104 		} else {
    105 			xprintf(XCORE, "unknown transport '%s'\n", argv[0].s);
    106 		}
    107 	}
    108 	return swdp_reset();
    109 }
    110 
    111 int debug_target(const char* name) {
    112 	if (!strcmp(name,"pico")) {
    113 		xprintf(XDATA, "target: RPxxxx MCUs\n");
    114 		xprintf(XDATA, "target: use 'attach pico0', 'attach pico1' to change cores\n");
    115 		xprintf(XDATA, "target: use 'attach picor' to enter rescue (reset-stop-in-rom)\n");
    116 		swdp_targetsel(0x01002927, 1);
    117 		return 0;
    118 	} else {
    119 		xprintf(XDATA, "target: unknown target '%s'\n", name);
    120 		return -1;
    121 	}
    122 }
    123 
    124 static u32 lastregs[19];
    125 
    126 int do_regs(int argc, param *argv) {
    127 	if (swdp_core_read_all(lastregs))
    128 		return -1;
    129 
    130 	xprintf(XDATA, "r0 %08x r4 %08x r8 %08x ip %08x psr %08x\n",
    131 		lastregs[0], lastregs[4], lastregs[8],
    132 		lastregs[12], lastregs[16]);
    133 	xprintf(XDATA, "r1 %08x r5 %08x r9 %08x sp %08x msp %08x\n",
    134 		lastregs[1], lastregs[5], lastregs[9],
    135 		lastregs[13], lastregs[17]);
    136 	xprintf(XDATA, "r2 %08x r6 %08x 10 %08x lr %08x psp %08x\n",
    137 		lastregs[2], lastregs[6], lastregs[10],
    138 		lastregs[14], lastregs[18]);
    139 	xprintf(XDATA, "r3 %08x r7 %08x 11 %08x pc %08x\n",
    140 		lastregs[3], lastregs[7], lastregs[11],
    141 		lastregs[15]);
    142 	disassemble(lastregs[15]);
    143 	return 0;
    144 }
    145 
    146 int do_stop(int argc, param *argv) {
    147 	swdp_core_halt();
    148 	do_regs(0, 0);
    149 	return 0;
    150 }
    151 
    152 int do_resume(int argc, param *argv) {
    153 	swdp_core_resume();
    154 	return 0;
    155 }
    156 
    157 int do_step(int argc, param *argv) {
    158 	if (argc > 0) {
    159 		u32 pc;
    160 		do {
    161 			swdp_core_step();
    162 			swdp_core_wait_for_halt();
    163 			if (swdp_core_read(15, &pc)) {
    164 				xprintf(XCORE, "step: error\n");
    165 				return -1;
    166 			}
    167 			fflush(stdout);
    168 		} while (pc != argv[0].n);
    169 	} else {
    170 		swdp_core_step();
    171 		swdp_core_wait_for_halt();
    172 	}
    173 	do_regs(0, 0);
    174 	return 0;
    175 }
    176 
    177 struct {
    178 	const char *name;
    179 	unsigned n;
    180 } core_regmap[] = {
    181 	{ "r0", 0 },
    182 	{ "r1", 1 },
    183 	{ "r2", 2 },
    184 	{ "r3", 3 },
    185 	{ "r4", 4 },
    186 	{ "r5", 5 },
    187 	{ "r6", 6 },
    188 	{ "r7", 7 },
    189 	{ "r8", 8 },
    190 	{ "r9", 9 },
    191 	{ "r10", 10 },
    192 	{ "r11", 11 },
    193 	{ "r12", 12 },
    194 	{ "r13", 13 }, { "sp", 13 },
    195 	{ "r14", 14 }, { "lr", 14 },
    196 	{ "r15", 15 }, { "pc", 15 },
    197 	{ "psr", 16 },
    198 	{ "msp", 17 },
    199 	{ "psp", 18 },
    200 };
    201 
    202 int read_memory_word(u32 addr, u32 *value) {
    203 	return swdp_ahb_read(addr, value);
    204 }
    205 
    206 int read_register(const char *name, u32 *value) {
    207 	int n;
    208 	for (n = 0; n < (sizeof(core_regmap) / sizeof(core_regmap[0])); n++) {
    209 		if (!strcasecmp(name, core_regmap[n].name)) {
    210 			if (swdp_core_read(core_regmap[n].n, value))
    211 				return -1;
    212 			return 0;
    213 		}
    214 	}
    215 	return ERROR_UNKNOWN;
    216 }
    217 
    218 int do_dr(int argc, param *argv) {
    219 	unsigned n;
    220 	u32 x = 0xeeeeeeee;
    221 	if (argc < 1)
    222 		return -1;
    223 	for (n = 0; n < (sizeof(core_regmap) / sizeof(core_regmap[0])); n++) {
    224 		if (!strcasecmp(argv[0].s, core_regmap[n].name)) {
    225 			swdp_core_read(core_regmap[n].n, &x);
    226 			xprintf(XDATA, "%s: %08x\n", argv[0].s, x);
    227 			return 0;
    228 		}
    229 	}
    230 	swdp_ahb_read(argv[0].n, &x);
    231 	xprintf(XDATA, "%08x: %08x\n", argv[0].n, x);
    232 	return 0;
    233 }
    234 
    235 int do_wr(int argc, param *argv) {
    236 	unsigned n;
    237 	if (argc < 2)
    238 		return -1;
    239 	for (n = 0; n < (sizeof(core_regmap) / sizeof(core_regmap[0])); n++) {
    240 		if (!strcasecmp(argv[0].s, core_regmap[n].name)) {
    241 			swdp_core_write(core_regmap[n].n, argv[1].n);
    242 			xprintf(XDATA, "%s<<%08x\n", argv[0].s, argv[1].n);
    243 			return 0;
    244 		}
    245 	}
    246 	swdp_ahb_write(argv[0].n, argv[1].n);
    247 	xprintf(XDATA, "%08x<<%08x\n", argv[0].n, argv[1].n);
    248 	return 0;
    249 }
    250 
    251 int do_text(int argc, param *argv) {
    252 	u8 data[1024], *x;
    253 	u32 addr;
    254 
    255 	if (argc < 1)
    256 		return -1;
    257 	addr = argv[0].n;
    258 	memset(data, 0, sizeof(data));
    259 
    260 	if (swdp_ahb_read32(addr, (void*) data, sizeof(data)/4))
    261 		return -1;
    262 
    263 	data[sizeof(data)-1] = 0;
    264 	for (x = data; *x; x++) {
    265 		if ((*x >= ' ') && (*x < 128))
    266 			continue;
    267 		if (*x == '\n')
    268 			continue;
    269 		*x = '.';
    270 	}
    271 	xprintf(XDATA, "%08x: %s\n", addr, (char*) data);
    272 	return 0;
    273 }
    274 
    275 static u32 lastaddr = 0x20000000;
    276 static u32 lastcount = 0x40;
    277 
    278 int do_dw(int argc, param *argv) {
    279 	u32 data[4096];
    280 	u32 addr = lastaddr;
    281 	u32 count = lastcount;
    282 	unsigned n;
    283 
    284 	if (argc > 0) addr = argv[0].n;
    285 	if (argc > 1) count = argv[1].n;
    286 
    287 	memset(data, 0xee, 256 *4);
    288 
    289 	/* word align */
    290 	addr = (addr + 3) & ~3;
    291 	count = (count + 3) & ~3;
    292 	if (count > sizeof(data))
    293 		count = sizeof(data);
    294 
    295 	lastaddr = addr + count;
    296 	lastcount = count;
    297 
    298 	count /= 4;
    299 	if (swdp_ahb_read32(addr, data, count))
    300 		return -1;
    301 
    302 	for (n = 0; count > 0; n += 4, addr += 16) {
    303 		switch (count) {
    304 		case 1:
    305 			count = 0;
    306 			xprintf(XDATA, "%08x: %08x\n", addr, data[n]);
    307 			break;
    308 		case 2:
    309 			count = 0;
    310 			xprintf(XDATA, "%08x: %08x %08x\n",
    311 				addr, data[n], data[n+1]);
    312 			break;
    313 		case 3:
    314 			count = 0;
    315 			xprintf(XDATA, "%08x: %08x %08x %08x\n",
    316 				addr, data[n], data[n+1], data[n+2]);
    317 			break;
    318 		default:
    319 			count -= 4;
    320 			xprintf(XDATA, "%08x: %08x %08x %08x %08x\n",
    321 				addr, data[n], data[n+1], data[n+2], data[n+3]);
    322 			break;
    323 		}
    324 	}
    325 	return 0;
    326 }
    327 
    328 
    329 int do_db(int argc, param *argv) {
    330 	u32 addr, count;
    331 	u8 data[1024];
    332 	char line[256];
    333 	unsigned n, m, xfer;
    334 
    335 	if (argc < 2)
    336 		return -1;
    337 
    338 	addr = argv[0].n;
    339 	count = argv[1].n;
    340 
    341 	if (count > 1024)
    342 		count = 1024;
    343 
    344 	memset(data, 0xee, 1024);
    345 	// todo: fix this
    346 	swdp_ahb_write(AHB_CSW, AHB_CSW_MDEBUG | AHB_CSW_PRIV |
    347 		AHB_CSW_DBG_EN | AHB_CSW_8BIT);
    348 	for (n = 0; n < count; n++) {
    349 		u32 tmp;
    350 		if (swdp_ahb_read(addr + n, &tmp)) {
    351 			swdp_reset();
    352 			break;
    353 		}
    354 		data[n] = tmp >> (8 * (n & 3));
    355 	}
    356 	swdp_ahb_write(AHB_CSW, AHB_CSW_MDEBUG | AHB_CSW_PRIV |
    357 		AHB_CSW_DBG_EN | AHB_CSW_32BIT);
    358 
    359 	for (n = 0; count > 0; count -= xfer) {
    360 		xfer = (count > 16) ? 16 : count;
    361 		char *p = line + sprintf(line, "%08x:", addr + n);
    362 		for (m = 0; m < xfer; m++) {
    363 			p += sprintf(p, " %02x", data[n++]);
    364 		}
    365 		xprintf(XDATA, "%s\n", line);
    366 	}
    367 	return 0;
    368 }
    369 
    370 // vector catch flags to apply
    371 u32 vcflags = DEMCR_VC_HARDERR | DEMCR_VC_BUSERR | DEMCR_VC_STATERR | DEMCR_VC_CHKERR;
    372 
    373 int do_reset(int argc, param *argv) {
    374 	swdp_core_halt();
    375 	swdp_ahb_write(DEMCR, DEMCR_TRCENA | vcflags);
    376 	/* core reset and sys reset */
    377 	swdp_ahb_write(0xe000ed0c, 0x05fa0005);
    378 	swdp_ahb_write(DEMCR, DEMCR_TRCENA | vcflags);
    379 	return 0;
    380 }
    381 
    382 int do_reset_hw(int argc, param *argv) {
    383 	swdp_target_reset(1);
    384 	usleep(10000);
    385 	swdp_target_reset(0);
    386 	usleep(10000);
    387 	return 0;
    388 }
    389 
    390 extern int swd_verbose;
    391 
    392 int wait_for_stop() {
    393 	u32 x;
    394 	unsigned m = 0;
    395 	unsigned xr = -1;
    396 	for (unsigned n = 0; n < 100; n++) {
    397 		if (swdp_ahb_read(DHCSR, &x) == 0) {
    398 			if (x & DHCSR_S_HALT) {
    399 				xprintf(XSWD,"CPU HALTED (%u,%u)\n", n,m);
    400 				unsigned y = -1, z = -1;
    401 				swdp_ahb_read(DFSR, &y);
    402 				swdp_ahb_read(DEMCR, &z);
    403 				xprintf(XSWD,"DHCSR %08x (%08x)\nDFSR  %08x\nDEMCR %08x\n", x, xr, y, z);
    404 				return 0;
    405 			}
    406 			if (x & DHCSR_S_RESET_ST) {
    407 				xr = x;
    408 				m++;
    409 				continue;
    410 			}
    411 			//xprintf(XSWD,"??? %08x\n", x);
    412 			swdp_ahb_write(DHCSR, DHCSR_DBGKEY | DHCSR_C_HALT | DHCSR_C_DEBUGEN);
    413 		} else {
    414 			swdp_reset();
    415 		}
    416 	}
    417 	xprintf(XSWD,"CPU DID NOT HALT\n");
    418 	return -1;
    419 }
    420 		
    421 int do_reset_stop(int argc, param *argv) {
    422 	swdp_core_halt();
    423 	wait_for_stop();
    424 
    425 	// enable vector-trap on reset, enable DWT/FPB
    426 	swdp_ahb_write(DEMCR, DEMCR_VC_CORERESET | DEMCR_TRCENA | vcflags);
    427 
    428 	swdp_ahb_write(0xe00ee08, 0x00010002);
    429 	// core reset and sys reset
    430 	//swdp_ahb_write(0xe000ed0c, 0x05fa0005);
    431 	// sys reset
    432 	// TRM says requesting both at once is unpredictable...
    433 	swdp_ahb_write(0xe000ed0c, 0x05fa0004);
    434 
    435 	swd_verbose = 0;
    436 	wait_for_stop();
    437 	swd_verbose = 1;
    438 
    439 	//swdp_core_wait_for_halt();
    440 	//do_stop(0,0);
    441 	//swdp_ahb_write(DEMCR, DEMCR_TRCENA | vcflags);
    442 	return 0;
    443 }
    444 
    445 int do_watch_pc(int argc, param *argv) {
    446 	if (argc < 1)
    447 		return -1;
    448 	return swdp_watchpoint_pc(0, argv[0].n);
    449 }
    450 
    451 int do_watch_rw(int argc, param *argv) {
    452 	if (argc < 1)
    453 		return -1;
    454 	return swdp_watchpoint_rw(0, argv[0].n);
    455 }
    456 
    457 int do_watch_off(int argc, param *argv) {
    458 	return swdp_watchpoint_disable(0);
    459 }
    460 
    461 int do_print(int argc, param *argv) {
    462 	while (argc-- > 0)
    463 		xprintf(XCORE, "%08x\n", argv++[0].n);
    464 	return 0;
    465 }
    466 
    467 int do_echo(int argc, param *argv) {
    468 	while (argc-- > 0) {
    469 		unsigned int argn = argv[0].n;
    470 		const char *arg = argv++[0].s;
    471 
    472 		if (arg[0] == '$') {
    473 			xprintf(XCORE, "%08x\n", argn);
    474 		} else {
    475 			xprintf(XCORE, "%s\n", arg);
    476 		}
    477 	}
    478 	return 0;
    479 }
    480 
    481 int do_bootloader(int argc, param *argv) {
    482 	return swdp_bootloader();
    483 }
    484 
    485 int do_setclock(int argc, param *argv) {
    486 	if (argc < 1)
    487 		return -1;
    488 	return swdp_set_clock(argv[0].n);
    489 }
    490 
    491 int do_swoclock(int argc, param *argv) {
    492 	if (argc < 1)
    493 		return -1;
    494 	return swo_set_clock(argv[0].n);
    495 }
    496 
    497 int do_help(int argc, param *argv) {
    498 	struct debugger_command *cmd;
    499 	for (cmd = debugger_commands; cmd->func != NULL; cmd++) {
    500 		xprintf(XCORE, "%-16s: %s\n", cmd->name, cmd->help);
    501 	}
    502 
    503 	return 0;
    504 }
    505 
    506 void *get_builtin_file(const char *fn, size_t *sz);
    507 const char *get_builtin_filename(unsigned n);
    508 
    509 void *load_file(const char *fn, size_t *_sz) {
    510 	int fd;
    511 	off_t sz;
    512 	void *data = NULL;
    513 	fd = open(fn, O_RDONLY);
    514 	if (fd < 0) goto fail;
    515 	sz = lseek(fd, 0, SEEK_END);
    516 	if (sz < 0) goto fail;
    517 	if (lseek(fd, 0, SEEK_SET)) goto fail;
    518 	if ((data = malloc(sz + 4)) == NULL) goto fail;
    519 	if (read(fd, data, sz) != sz) goto fail;
    520 	*_sz = sz;
    521 	return data;
    522 fail:
    523 	if (data) free(data);
    524 	if (fd >= 0) close(fd);
    525 	return NULL;
    526 }
    527 
    528 int do_upload(int argc, param *argv) {
    529 	u32 addr;
    530 	size_t sz;
    531 	long long t0, t1;
    532 	int fd, r;
    533 	void *data;
    534 	char *x;
    535 
    536 	if (argc != 3) {
    537 		xprintf(XCORE, "error: usage: upload <file> <addr> <length>\n");
    538 		return -1;
    539 	}
    540 
    541 	if ((fd = open(argv[0].s, O_CREAT | O_TRUNC | O_WRONLY, 0644)) < 0) {
    542 		xprintf(XCORE, "error: cannot open '%s'\n", argv[0].s);
    543 		return -1;
    544 	}
    545 	addr = argv[1].n;
    546 	sz = argv[2].n;
    547 	addr = (addr + 3) & ~3;
    548 	sz = (sz + 3) & ~3;
    549 
    550 	if ((data = malloc(sz)) == NULL) {
    551 		xprintf(XCORE, "out of memory\n");
    552 		close(fd);
    553 		return -1;
    554 	}
    555 
    556 	xprintf(XCORE, "reading %d bytes...\n", sz);
    557 	t0 = now();
    558 	if (swdp_ahb_read32(addr, (void*) data, sz / 4)) {
    559 		xprintf(XCORE, "error: failed to read data\n");
    560 		free(data);
    561 		close(fd);
    562 		return -1;
    563 	}
    564 	t1 = now();
    565 	xprintf(XCORE, "%lld uS -> %lld B/s\n", (t1 - t0),
    566 		(((long long)sz) * 1000000LL) / (t1 - t0));
    567 
    568 	x = data;
    569 	while (sz > 0) {
    570 		r = write(fd, x, sz);
    571 		if (r < 0) {
    572 			if (errno == EINTR) continue;
    573 			xprintf(XCORE, "write error\n");
    574 			break;
    575 		}
    576 		x += r;
    577 		sz -= r;
    578 	}
    579 	close(fd);
    580 	free(data);
    581 	return 0;
    582 }
    583 int do_download(int argc, param *argv) {
    584 	u32 addr;
    585 	void *data;
    586 	size_t sz;
    587 	long long t0, t1;
    588 
    589 	if (argc != 2) {
    590 		xprintf(XCORE, "error: usage: download <file> <addr>\n");
    591 		return -1;
    592 	}
    593 
    594 	if ((data = load_file(argv[0].s, &sz)) == NULL) {
    595 		xprintf(XCORE, "error: cannot read '%s'\n", argv[0].s);
    596 		return -1;
    597 	}
    598 	sz = (sz + 3) & ~3;
    599 	addr = argv[1].n;
    600 
    601 	xprintf(XCORE, "sending %d bytes...\n", sz);
    602 	t0 = now();
    603 	if (swdp_ahb_write32(addr, (void*) data, sz / 4)) {
    604 		xprintf(XCORE, "error: failed to write data\n");
    605 		free(data);
    606 		return -1;
    607 	}
    608 	t1 = now();
    609 	xprintf(XCORE, "%lld uS -> %lld B/s\n", (t1 - t0), 
    610 		(((long long)sz) * 1000000LL) / (t1 - t0));
    611 	free(data);
    612 	return 0;
    613 }
    614 
    615 int do_run(int argc, param *argv) {
    616 	u32 addr;
    617 	void *data;
    618 	size_t sz;
    619 	u32 sp, pc;
    620 	if (argc != 2) {
    621 		xprintf(XCORE, "error: usage: run <file> <addr>\n");
    622 		return -1;
    623 	}
    624 	if ((data = load_file(argv[0].s, &sz)) == NULL) {
    625 		xprintf(XCORE, "error: cannot read '%s'\n", argv[0].s);
    626 		return -1;
    627 	}
    628 	swdp_core_halt();
    629 	sz = (sz + 3) & ~3;
    630 	addr = argv[1].n;
    631 	if (swdp_ahb_write32(addr, (void*) data, sz / 4)) {
    632 		xprintf(XCORE, "error: failed to write data\n");
    633 		free(data);
    634 		return -1;
    635 	}
    636 	memcpy(&sp, data, 4);
    637 	memcpy(&pc, ((char*) data) + 4, 4);
    638 	swdp_core_write(13, sp);
    639 	swdp_core_write(15, pc);
    640 	swdp_ahb_write(0xe000ed0c, 0x05fa0002);
    641 	swdp_core_write(16, 0x01000000);
    642 	swdp_core_resume();
    643 	free(data);
    644 	return 0;
    645 }
    646 
    647 
    648 void *load_agent(const char *arch, size_t *_sz) {
    649 	void *data;
    650 	size_t sz;
    651 	char name[256];
    652 	if (arch == NULL) return NULL;
    653 	snprintf(name, 256, "agent-%s.bin", arch);
    654 	if ((data = get_builtin_file(name, &sz))) {
    655 		void *copy = malloc(sz + 4);
    656 		if (copy == NULL) return NULL;
    657 		memcpy(copy, data, sz);
    658 		*_sz = sz;
    659 		return copy;
    660 	}
    661 	snprintf(name, sizeof(name), "out/agent-%s.bin", arch);
    662 	return load_file(name, _sz);
    663 }
    664 
    665 static flash_agent *AGENT = NULL;
    666 static size_t AGENT_sz = 0;
    667 static char *AGENT_arch = NULL;
    668 
    669 int do_setarch(int argc, param *argv) {
    670 	unsigned n;
    671 	char *x;
    672 	const char *name;
    673 	if (argc != 1) {
    674 		if (AGENT_arch) {
    675 			xprintf(XCORE, "current flash agent is '%s'\n", AGENT_arch);
    676 		} else {
    677 			xprintf(XCORE, "no flash agent selected\n");
    678 		}
    679 fail_load:
    680 		xprintf(XCORE, "error: set architecture with: arch <name> (omit the .bin)\n");
    681 		for (n = 0; (name = get_builtin_filename(n)) != NULL; n++) {
    682 			if (strncmp(name, "agent-", 6)) {
    683 				continue;
    684 			}
    685 			xprintf(XCORE, "   %s\n", name + 6);
    686 		}
    687 		goto fail;
    688 	}
    689 	if ((x = strdup(argv[0].s)) == NULL) {
    690 		goto fail;
    691 	}
    692 	free(AGENT_arch);
    693 	free(AGENT);
    694 	AGENT_arch = x;
    695 
    696 	if ((AGENT = load_agent(AGENT_arch, &AGENT_sz)) == NULL) {
    697 		xprintf(XCORE, "error: cannot load flash agent for architecture '%s'\n", AGENT_arch);
    698 		goto fail_load;
    699 	}
    700 
    701 	// sanity check
    702 	if ((AGENT_sz < sizeof(flash_agent)) ||
    703 		(AGENT->magic != AGENT_MAGIC) ||
    704 		(AGENT->version != AGENT_VERSION)) {
    705 		xprintf(XCORE, "error: invalid agent image\n");
    706 		free(AGENT);
    707 		AGENT = NULL;
    708 		goto fail;
    709 	}
    710 
    711 	xprintf(XCORE, "flash agent '%s' loaded.\n", AGENT_arch);
    712 	return 0;
    713 
    714 fail:
    715 	if (AGENT) {
    716 		free(AGENT);
    717 		AGENT = NULL;
    718 	}
    719 	if (AGENT_arch) {
    720 		free(AGENT_arch);
    721 		AGENT_arch = NULL;
    722 	}
    723 	AGENT_sz = 0;
    724 	return -1;
    725 }
    726 
    727 int invoke(u32 agent, u32 func, u32 r0, u32 r1, u32 r2, u32 r3) {
    728 	swdp_core_write(0, r0);
    729 	swdp_core_write(1, r1);
    730 	swdp_core_write(2, r2);
    731 	swdp_core_write(3, r3);
    732 	swdp_core_write(13, agent - 4);
    733 	swdp_core_write(14, agent | 1); // include T bit
    734 	swdp_core_write(15, func | 1); // include T bit
    735 
    736 	// if the target has bogus data at 0, the processor may be in
    737 	// pending-exception state after reset-stop, so we will clear
    738 	// any exceptions and then set the PSR to something reasonable
    739 
    740 	// Write VECTCLRACTIVE to AIRCR
    741 	swdp_ahb_write(0xe000ed0c, 0x05fa0002);
    742 	swdp_core_write(16, 0x01000000);
    743 
    744 	// todo: readback and verify?
    745 
    746 	xprintf(XCORE, "invoke <func@%08x>(0x%x,0x%x,0x%x,0x%x)\n", func, r0, r1, r2, r3);
    747 
    748 	swdp_core_resume();
    749 	if (swdp_core_wait_for_halt() == 0) {
    750 		// todo: timeout after a few seconds?
    751 		u32 pc = 0xffffffff, res = 0xffffffff;
    752 		swdp_core_read(0, &res);
    753 		swdp_core_read(15, &pc);
    754 		if (pc != agent) {
    755 			xprintf(XCORE, "error: pc (%08x) is not at %08x\n", pc, agent);
    756 			return -1;
    757 		}
    758 		if (res) xprintf(XCORE, "failure code %08x\n", res);
    759 		return res;
    760 	}
    761 	xprintf(XCORE, "interrupted\n");
    762 	return -1;
    763 }
    764 
    765 int run_flash_agent(u32 flashaddr, void *data, size_t data_sz) {
    766 	u8 buffer[4096];
    767 	flash_agent *agent;
    768 	size_t agent_sz;
    769 	int r;
    770 
    771 	if (AGENT == NULL) {
    772 		xprintf(XCORE, "error: no flash agent selected\n");
    773 		xprintf(XCORE, "error: set architecture with: arch <name>\n");
    774 		goto fail;
    775 	}
    776 	if (AGENT_sz > sizeof(buffer)) {
    777 		xprintf(XCORE, "error: flash agent too large\n");
    778 		goto fail;
    779 	}
    780 
    781 	memcpy(buffer, AGENT, AGENT_sz);
    782 	agent_sz = AGENT_sz;
    783 	agent = (void*) buffer;
    784 
    785 	// replace magic with bkpt instructions
    786 	agent->magic = 0xbe00be00;
    787 
    788 	if (do_attach(0,0)) {
    789 		xprintf(XCORE, "error: failed to attach\n");
    790 		goto fail;
    791 	}
    792 	do_reset_stop(0,0);
    793 
    794 	if (agent->flags & FLAG_BOOT_ROM_HACK) {
    795 		xprintf(XCORE, "executing boot rom\n");
    796 		if (swdp_watchpoint_rw(0, 0)) {
    797 			goto fail;
    798 		}
    799 		swdp_core_resume();
    800 		swdp_core_wait_for_halt();
    801 		swdp_watchpoint_disable(0);
    802 		// todo: timeout?
    803 		// todo: confirm halted
    804 	}
    805 
    806 	if (swdp_ahb_write32(agent->load_addr, (void*) agent, agent_sz / 4)) {
    807 		xprintf(XCORE, "error: failed to download agent\n");
    808 		goto fail;
    809 	}
    810 	r = invoke(agent->load_addr, agent->setup, agent->load_addr, 0, 0, 0);
    811 	if (r != 0) {
    812 		if (r == ERR_INVALID) {
    813 			xprintf(XCORE, "agent: unsupported part\n");
    814 		}
    815 		goto fail;
    816 	}
    817 	if (swdp_ahb_read32(agent->load_addr + 16, (void*) &agent->data_addr, 4)) {
    818 		goto fail;
    819 	}
    820 	xprintf(XCORE, "agent %d @%08x, buffer %dK @%08x, flash %dK @%08x\n",
    821 		agent_sz, agent->load_addr,
    822 		agent->data_size / 1024, agent->data_addr,
    823 		agent->flash_size / 1024, agent->flash_addr);
    824 
    825 	if ((flashaddr == 0) && (data == NULL) && (data_sz == 0xFFFFFFFF)) {
    826 		// erase all
    827 		flashaddr = agent->flash_addr;
    828 		data_sz = agent->flash_size;
    829 	}
    830 
    831 	if ((flashaddr < agent->flash_addr) ||
    832 		(data_sz > agent->flash_size) ||
    833 		((flashaddr + data_sz) > (agent->flash_addr + agent->flash_size))) {
    834 		xprintf(XCORE, "invalid flash address %08x..%08x\n",
    835 			flashaddr, flashaddr + data_sz);
    836 		goto fail;
    837 	}
    838 
    839 	if (data == NULL) {
    840 		// erase
    841 		if (invoke(agent->load_addr, agent->erase, flashaddr, data_sz, 0, 0)) {
    842 			xprintf(XCORE, "failed to erase %d bytes at %08x\n", data_sz, flashaddr);
    843 			goto fail;
    844 		}
    845 	} else {
    846 		// write
    847 		u8 *ptr = (void*) data;
    848 		u32 xfer;
    849 		xprintf(XCORE, "flashing %d bytes at %08x...\n", data_sz, flashaddr);
    850 		if (invoke(agent->load_addr, agent->erase, flashaddr, data_sz, 0, 0)) {
    851 			xprintf(XCORE, "failed to erase %d bytes at %08x\n", data_sz, flashaddr);
    852 			goto fail;
    853 		}
    854 		while (data_sz > 0) {
    855 			if (data_sz > agent->data_size) {
    856 				xfer = agent->data_size;
    857 			} else {
    858 				xfer = data_sz;
    859 			}
    860 			if (swdp_ahb_write32(agent->data_addr, (void*) ptr, xfer / 4)) {
    861 				xprintf(XCORE, "download to %08x failed\n", agent->data_addr);
    862 				goto fail;
    863 			}
    864 			if (invoke(agent->load_addr, agent->write,
    865 				flashaddr, agent->data_addr, xfer, 0)) {
    866 				xprintf(XCORE, "failed to flash %d bytes to %08x\n", xfer, flashaddr);
    867 				goto fail;
    868 			}
    869 			ptr += xfer;
    870 			data_sz -= xfer;
    871 			flashaddr += xfer;
    872 		}
    873 	}
    874 
    875 	if (data) free(data);
    876 	return 0;
    877 fail:
    878 	if (data) free(data);
    879 	return -1;
    880 }
    881 
    882 int do_flash(int argc, param *argv) {
    883 	void *data = NULL;
    884 	size_t data_sz;
    885 	if (argc != 2) {
    886 		xprintf(XCORE, "error: usage: flash <file> <addr>\n");
    887 		return -1;
    888 	}
    889 	if ((data = load_file(argv[0].s, &data_sz)) == NULL) {
    890 		xprintf(XCORE, "error: cannot load '%s'\n", argv[0].s);
    891 		return -1;
    892 	}
    893 	// word align
    894 	data_sz = (data_sz + 3) & ~3;
    895 	return run_flash_agent(argv[1].n, data, data_sz);
    896 }
    897 
    898 int do_erase(int argc, param *argv) {
    899 	if ((argc == 1) && !strcmp(argv[0].s, "all")) {
    900 		return run_flash_agent(0, NULL, 0xFFFFFFFF);
    901 	}
    902 	if (argc != 2) {
    903 		xprintf(XCORE, "error: usage: erase <addr> <length> | erase all\n");
    904 		return -1;
    905 	}
    906 	return run_flash_agent(argv[0].n, NULL, argv[1].n);
    907 }
    908 
    909 int do_log(int argc, param *argv) {
    910 	unsigned flags = 0;
    911 	while (argc > 0) {
    912 		if (!strcmp(argv[0].s, "gdb")) {
    913 			flags |= LF_GDB;
    914 		} else if (!strcmp(argv[0].s, "swd")) {
    915 			flags |= LF_SWD;
    916 		} else {
    917 			xprintf(XCORE, "error: allowed flags: gdb swd\n");
    918 			return -1;
    919 		}
    920 		argc--;
    921 		argv++;
    922 	}
    923 	log_flags = flags;
    924 	return 0;
    925 }
    926 
    927 int do_finfo(int argc, param *argv) {
    928 	u32 cfsr = 0, hfsr = 0, dfsr = 0, mmfar = 0, bfar = 0;
    929 	swdp_ahb_read(CFSR, &cfsr);
    930 	swdp_ahb_read(HFSR, &hfsr);
    931 	swdp_ahb_read(DFSR, &dfsr);
    932 	swdp_ahb_read(MMFAR, &mmfar);
    933 	swdp_ahb_read(BFAR, &bfar);
    934 
    935 	xprintf(XDATA, "CFSR %08x  MMFAR %08x\n", cfsr, mmfar);
    936 	xprintf(XDATA, "HFSR %08x   BFAR %08x\n", hfsr, bfar);
    937 	xprintf(XDATA, "DFSR %08x\n", dfsr);
    938 
    939 	if (cfsr & CFSR_IACCVIOL)	xprintf(XDATA, ">MM: Inst Access Violation\n");
    940 	if (cfsr & CFSR_DACCVIOL)	xprintf(XDATA, ">MM: Data Access Violation\n");
    941 	if (cfsr & CFSR_MUNSTKERR)	xprintf(XDATA, ">MM: Derived MM Fault on Exception Return\n");
    942 	if (cfsr & CFSR_MSTKERR)	xprintf(XDATA, ">MM: Derived MM Fault on Exception Entry\n");
    943 	if (cfsr & CFSR_MLSPERR)	xprintf(XDATA, ">MM: MM Fault During Lazy FP Save\n");
    944 	if (cfsr & CFSR_MMARVALID)	xprintf(XDATA, ">MM: MMFAR has valid contents\n");
    945 
    946 	if (cfsr & CFSR_IBUSERR)	xprintf(XDATA, ">BF: Bus Fault on Instruction Prefetch\n");
    947 	if (cfsr & CFSR_PRECISERR)	xprintf(XDATA, ">BF: Precise Data Access Error, Addr in BFAR\n");
    948 	if (cfsr & CFSR_IMPRECISERR)	xprintf(XDATA, ">BF: Imprecise Data Access Error\n");
    949 	if (cfsr & CFSR_UNSTKERR)	xprintf(XDATA, ">BF: Derived Bus Fault on Exception Return\n");
    950 	if (cfsr & CFSR_STKERR)		xprintf(XDATA, ">BF: Derived Bus Fault on Exception Entry\n");
    951 	if (cfsr & CFSR_LSPERR)		xprintf(XDATA, ">BF: Bus Fault During Lazy FP Save\n");
    952 	if (cfsr & CFSR_BFARVALID)	xprintf(XDATA, ">BF: BFAR has valid contents\n");
    953 
    954 	if (cfsr & CFSR_UNDEFINSTR)	xprintf(XDATA, ">UF: Undefined Instruction Usage Fault\n");
    955 	if (cfsr & CFSR_INVSTATE)	xprintf(XDATA, ">UF: EPSR.T or ESPR.IT invalid\n");
    956 	if (cfsr & CFSR_INVPC)		xprintf(XDATA, ">UF: Integrity Check Error on EXC_RETURN\n");
    957 	if (cfsr & CFSR_NOCP)		xprintf(XDATA, ">UF: Coprocessor Error\n");
    958 	if (cfsr & CFSR_UNALIGNED)	xprintf(XDATA, ">UF: Unaligned Access Error\n");
    959 	if (cfsr & CFSR_DIVBYZERO)	xprintf(XDATA, ">UF: Divide by Zero\n");
    960 
    961 	if (hfsr & HFSR_VECTTBL)	xprintf(XDATA, ">HF: Vector Table Read Fault\n");
    962 	if (hfsr & HFSR_FORCED)		xprintf(XDATA, ">HF: Exception Escalated to Hard Fault\n");
    963 	if (hfsr & HFSR_DEBUGEVT)	xprintf(XDATA, ">HF: Debug Event\n");
    964 
    965 	// clear sticky fault bits
    966 	swdp_ahb_write(CFSR, CFSR_ALL);
    967 	swdp_ahb_write(HFSR, HFSR_ALL);
    968 	return 0;
    969 }
    970 
    971 extern int swdp_step_no_ints;
    972 
    973 int do_maskints(int argc, param *argv) {
    974 	if (argc != 1) {
    975 		xprintf(XCORE, "usage: maskints [on|off|always]\n");
    976 		return -1;
    977 	}
    978 	if (!strcmp(argv[0].s, "on")) {
    979 		swdp_step_no_ints = 1;
    980 		xprintf(XCORE, "maskints: while stepping\n");
    981 	} else if (!strcmp(argv[0].s, "always")) {
    982 		swdp_step_no_ints = 2;
    983 		xprintf(XCORE, "maskints: always\n");
    984 	} else {
    985 		swdp_step_no_ints = 0;
    986 		xprintf(XCORE, "maskints: never\n");
    987 	}
    988 	return 0;
    989 }
    990 
    991 int do_threads(int argc, param *argv) {
    992 	if (argc == 1) {
    993 		if (strcmp(argv[0].s, "clear")) {
    994 			xprintf(XCORE, "usage: threads [clear]\n");
    995 			return -1;
    996 		}
    997 		swdp_core_halt();
    998 		clear_lk_threads();
    999 		return 0;
   1000 	}
   1001 	lkthread_t *t;
   1002 	swdp_core_halt();
   1003 	t = find_lk_threads(1);
   1004 	dump_lk_threads(t);
   1005 	free_lk_threads(t);
   1006 	return 0;
   1007 }
   1008 
   1009 int remote_msg(u32 cmd) {
   1010 	unsigned timeout = 250;
   1011 	u32 n = 0;
   1012 	if (swdp_ahb_write(DCRDR, cmd)) goto fail;
   1013 	if (swdp_ahb_read(DEMCR, &n)) goto fail;
   1014 	if (swdp_ahb_write(DEMCR, n | DEMCR_MON_PEND)) goto fail;
   1015 	while (timeout > 0) {
   1016 		if (swdp_ahb_read(DCRDR, &n)) goto fail;
   1017 		if (!(n & 0x80000000)) return 0;
   1018 		timeout--;
   1019 	}
   1020 	xprintf(XCORE, "console write timeout\n");
   1021 	return -1;
   1022 fail:
   1023 	xprintf(XCORE, "console write io error\n");
   1024 	return -1;
   1025 }
   1026 
   1027 int do_wconsole(int argc, param *argv) {
   1028 	if (argc != 1) return -1;
   1029 	const char *line = argv[0].s;
   1030 	while (*line) {
   1031 		if (remote_msg(0x80000000 | *line)) return -1;
   1032 		line++;
   1033 	}
   1034 	if (remote_msg(0x80000000 | '\r')) return -1;
   1035 	return 0;
   1036 }
   1037 
   1038 
   1039 struct debugger_command debugger_commands[] = {
   1040 	{ "exit",	"", do_exit,		"" },
   1041 	{ "attach",	"", do_attach,		"attach/reattach to sw-dp" },
   1042 	{ "regs",	"", do_regs,		"show cpu registers" },
   1043 	{ "finfo",	"", do_finfo,		"Fault Information" },
   1044 	{ "stop",	"", do_stop,		"halt cpu" },
   1045 	{ "step",	"", do_step,		"single-step cpu" },
   1046 	{ "go",		"", do_resume,		"resume cpu" },
   1047 	{ "dw",		"", do_dw,		"dump words" },
   1048 	{ "db",		"", do_db,		"dump bytes" },
   1049 	{ "dr",		"", do_dr,		"dump register" },
   1050 	{ "wr",		"", do_wr,		"write register" },
   1051 	{ "download",	"", do_download,	"download file to device" },
   1052 	{ "upload",	"", do_upload,		"upload device memory to file" },
   1053 	{ "run",	"", do_run,		"download file and execute it" },
   1054 	{ "flash",	"", do_flash,		"write file to device flash" },
   1055 	{ "erase",	"", do_erase,		"erase flash" },
   1056 	{ "reset",	"", do_reset,		"reset target" },
   1057 	{ "reset-stop",	"", do_reset_stop,	"reset target and halt cpu" },
   1058 	{ "reset-hw",	"", do_reset_hw,	"strobe /RESET pin" },
   1059 	{ "watch-pc",	"", do_watch_pc,	"set watchpoint at addr" },
   1060 	{ "watch-rw",	"", do_watch_rw,	"set watchpoint at addr" },
   1061 	{ "watch-off",	"", do_watch_off,	"disable watchpoint" },
   1062 	{ "log",	"", do_log,		"enable/disable logging" },
   1063 	{ "maskints",	"", do_maskints,	"enable/disable IRQ mask during step" },
   1064 	{ "print",	"", do_print,		"print numeric arguments" },
   1065 	{ "echo",	"", do_echo,		"echo command line" },
   1066 	{ "bootloader", "", do_bootloader,	"reboot into bootloader" },
   1067 	{ "setclock",	"", do_setclock,	"set SWD clock rate (khz)" },
   1068 	{ "swoclock",	"", do_swoclock,	"set SWO clock rate (khz)" },
   1069 	{ "arch",	"", do_setarch,		"set architecture for flash agent" },
   1070 	{ "threads",	"", do_threads,		"thread dump" },
   1071 	{ "text",	"", do_text,		"dump text" },
   1072 	{ "wconsole",	"", do_wconsole,	"write to remote console" },
   1073 	{ "help",	"", do_help,		"help" },
   1074 	{ 0, 0, 0, 0 },
   1075 };
   1076