commit d4e864786316d20aba890b7784c9a408d1ade6f4
parent fe8c772672f36a87bc12085c9c2cc898feb2e188
Author: Brian Swetland <swetland@frotz.net>
Date:   Mon,  3 Aug 2015 17:12:43 -0700
debugger: simplify "ui" output path
- all printing uses xprintf() now
- linenoise pause/resume handled only in xprintf
- xprintf takes a content type tag to allow fancier display
Diffstat:
7 files changed, 204 insertions(+), 193 deletions(-)
diff --git a/tools/debugger-commands.c b/tools/debugger-commands.c
@@ -1,4 +1,4 @@
-/* debugger-commands.c
+/* debugger-commands.);
  *
  * Copyright 2011 Brian Swetland <swetland@frotz.net>
  * 
@@ -69,7 +69,7 @@ int disassemble(u32 addr) {
 		r = disassemble_thumb2(addr, mem.h[0], mem.h[1], text, 128);
 	}
 	if (r > 0)
-		xprintf("%s\n", text);
+		xprintf(XDATA, "%s\n", text);
 	return r;
 #else
 	return -1;
@@ -91,16 +91,16 @@ int do_regs(int argc, param *argv) {
 	if (swdp_core_read_all(lastregs))
 		return -1;
 
-	xprintf("r0 %08x r4 %08x r8 %08x ip %08x psr %08x\n",
+	xprintf(XDATA, "r0 %08x r4 %08x r8 %08x ip %08x psr %08x\n",
 		lastregs[0], lastregs[4], lastregs[8],
 		lastregs[12], lastregs[16]);
-	xprintf("r1 %08x r5 %08x r9 %08x sp %08x msp %08x\n",
+	xprintf(XDATA, "r1 %08x r5 %08x r9 %08x sp %08x msp %08x\n",
 		lastregs[1], lastregs[5], lastregs[9],
 		lastregs[13], lastregs[17]);
-	xprintf("r2 %08x r6 %08x 10 %08x lr %08x psp %08x\n",
+	xprintf(XDATA, "r2 %08x r6 %08x 10 %08x lr %08x psp %08x\n",
 		lastregs[2], lastregs[6], lastregs[10],
 		lastregs[14], lastregs[18]);
-	xprintf("r3 %08x r7 %08x 11 %08x pc %08x\n",
+	xprintf(XDATA, "r3 %08x r7 %08x 11 %08x pc %08x\n",
 		lastregs[3], lastregs[7], lastregs[11],
 		lastregs[15]);
 	disassemble(lastregs[15]);
@@ -125,13 +125,11 @@ int do_step(int argc, param *argv) {
 			swdp_core_step();
 			swdp_core_wait_for_halt();
 			if (swdp_core_read(15, &pc)) {
-				xprintf("error\n");
+				xprintf(XCORE, "step: error\n");
 				return -1;
 			}
-			xprintf(".");
 			fflush(stdout);
 		} while (pc != argv[0].n);
-		xprintf("\n");
 	} else {
 		swdp_core_step();
 		swdp_core_wait_for_halt();
@@ -189,12 +187,12 @@ int do_dr(int argc, param *argv) {
 	for (n = 0; n < (sizeof(core_regmap) / sizeof(core_regmap[0])); n++) {
 		if (!strcasecmp(argv[0].s, core_regmap[n].name)) {
 			swdp_core_read(core_regmap[n].n, &x);
-			xprintf("%s: %08x\n", argv[0].s, x);
+			xprintf(XDATA, "%s: %08x\n", argv[0].s, x);
 			return 0;
 		}
 	}
 	swdp_ahb_read(argv[0].n, &x);
-	xprintf("%08x: %08x\n", argv[0].n, x);
+	xprintf(XDATA, "%08x: %08x\n", argv[0].n, x);
 	return 0;
 }
 
@@ -205,12 +203,12 @@ int do_wr(int argc, param *argv) {
 	for (n = 0; n < (sizeof(core_regmap) / sizeof(core_regmap[0])); n++) {
 		if (!strcasecmp(argv[0].s, core_regmap[n].name)) {
 			swdp_core_write(core_regmap[n].n, argv[1].n);
-			xprintf("%s<<%08x\n", argv[0].s, argv[1].n);
+			xprintf(XDATA, "%s<<%08x\n", argv[0].s, argv[1].n);
 			return 0;
 		}
 	}
 	swdp_ahb_write(argv[0].n, argv[1].n);
-	xprintf("%08x<<%08x\n", argv[0].n, argv[1].n);
+	xprintf(XDATA, "%08x<<%08x\n", argv[0].n, argv[1].n);
 	return 0;
 }
 
@@ -222,7 +220,7 @@ int do_text(int argc, param *argv) {
 		return -1;
 	addr = argv[0].n;
 	memset(data, 0, sizeof(data));
-	
+
 	if (swdp_ahb_read32(addr, (void*) data, sizeof(data)/4))
 		return -1;
 
@@ -234,7 +232,7 @@ int do_text(int argc, param *argv) {
 			continue;
 		*x = '.';
 	}
-	fprintf(stderr,"%s\n", (char*) data);
+	xprintf(XDATA, "%08x: %s\n", addr, (char*) data);
 	return 0;
 }
 
@@ -264,12 +262,30 @@ int do_dw(int argc, param *argv) {
 	count /= 4;
 	if (swdp_ahb_read32(addr, data, count))
 		return -1;
-	for (n = 0; n < count; n++) {
-		if ((n & 3) == 0)
-			xprintf("\n%08x:", addr + (n << 2));
-		xprintf(" %08x", data[n]);
+
+	for (n = 0; count > 0; n += 4, addr += 16) {
+		switch (count) {
+		case 1:
+			count = 0;
+			xprintf(XDATA, "%08x: %08x\n", addr, data[n]);
+			break;
+		case 2:
+			count = 0;
+			xprintf(XDATA, "%08x: %08x %08x\n",
+				addr, data[n], data[n+1]);
+			break;
+		case 3:
+			count = 0;
+			xprintf(XDATA, "%08x: %08x %08x %08x\n",
+				addr, data[n], data[n+1], data[n+2]);
+			break;
+		default:
+			count -= 4;
+			xprintf(XDATA, "%08x: %08x %08x %08x %08x\n",
+				addr, data[n], data[n+1], data[n+2], data[n+3]);
+			break;
+		}
 	}
-	xprintf("\n");
 	return 0;
 }
 
@@ -277,7 +293,8 @@ int do_dw(int argc, param *argv) {
 int do_db(int argc, param *argv) {
 	u32 addr, count;
 	u8 data[1024];
-	unsigned n;
+	char line[256];
+	unsigned n, m, xfer;
 
 	if (argc < 2)
 		return -1;
@@ -289,7 +306,7 @@ int do_db(int argc, param *argv) {
 		count = 1024;
 
 	memset(data, 0xee, 1024);
-
+	// todo: fix this
 	swdp_ahb_write(AHB_CSW, AHB_CSW_MDEBUG | AHB_CSW_PRIV |
 		AHB_CSW_DBG_EN | AHB_CSW_8BIT);
 	for (n = 0; n < count; n++) {
@@ -300,16 +317,17 @@ int do_db(int argc, param *argv) {
 		}
 		data[n] = tmp >> (8 * (n & 3));
 	}
-
 	swdp_ahb_write(AHB_CSW, AHB_CSW_MDEBUG | AHB_CSW_PRIV |
 		AHB_CSW_DBG_EN | AHB_CSW_32BIT);
 
-	for (n = 0; n < count; n++) {
-		if ((n & 15) == 0)
-			xprintf("\n%08x:", addr + n);
-		xprintf(" %02x", data[n]);
+	for (n = 0; count > 0; count -= xfer) {
+		xfer = (count > 16) ? 16 : count;
+		char *p = line + sprintf(line, "%08x:", addr + n);
+		for (m = 0; m < xfer; m++) {
+			p += sprintf(p, " %02x", data[n++]);
+		}
+		xprintf(XDATA, "%s\n", line);
 	}
-	xprintf("\n");
 	return 0;
 }
 
@@ -317,7 +335,7 @@ int do_db(int argc, param *argv) {
 u32 vcflags = DEMCR_VC_HARDERR | DEMCR_VC_BUSERR | DEMCR_VC_STATERR | DEMCR_VC_CHKERR;
 
 int do_reset(int argc, param *argv) {
-	swdp_core_halt();	
+	swdp_core_halt();
 	swdp_ahb_write(DEMCR, DEMCR_TRCENA | vcflags);
 	/* core reset and sys reset */
 	swdp_ahb_write(0xe000ed0c, 0x05fa0005);
@@ -363,8 +381,7 @@ int do_watch_off(int argc, param *argv) {
 
 int do_print(int argc, param *argv) {
 	while (argc-- > 0)
-		xprintf("%08x ", argv++[0].n);
-	xprintf("\n");
+		xprintf(XCORE, "%08x\n", argv++[0].n);
 	return 0;
 }
 
@@ -374,12 +391,11 @@ int do_echo(int argc, param *argv) {
 		const char *arg = argv++[0].s;
 
 		if (arg[0] == '$') {
-			xprintf("%08x ", argn);
+			xprintf(XCORE, "%08x\n", argn);
 		} else {
-			xprintf("%s ", arg, argn);
+			xprintf(XCORE, "%s\n", arg);
 		}
 	}
-	xprintf("\n");
 	return 0;
 }
 
@@ -396,7 +412,7 @@ int do_setclock(int argc, param *argv) {
 int do_help(int argc, param *argv) {
 	struct debugger_command *cmd;
 	for (cmd = debugger_commands; cmd->func != NULL; cmd++) {
-		xprintf("%-16s: %s\n", cmd->name, cmd->help);
+		xprintf(XCORE, "%-16s: %s\n", cmd->name, cmd->help);
 	}
 
 	return 0;
@@ -430,26 +446,26 @@ int do_download(int argc, param *argv) {
 	long long t0, t1;
 
 	if (argc != 2) {
-		xprintf("error: usage: download <file> <addr>\n");
+		xprintf(XCORE, "error: usage: download <file> <addr>\n");
 		return -1;
 	}
 
 	if ((data = load_file(argv[0].s, &sz)) == NULL) {
-		xprintf("error: cannot read '%s'\n", argv[0].s);
+		xprintf(XCORE, "error: cannot read '%s'\n", argv[0].s);
 		return -1;
 	}
 	sz = (sz + 3) & ~3;
 	addr = argv[1].n;
 
-	xprintf("sending %d bytes...\n", sz);
+	xprintf(XCORE, "sending %d bytes...\n", sz);
 	t0 = now();
 	if (swdp_ahb_write32(addr, (void*) data, sz / 4)) {
-		xprintf("error: failed to write data\n");
+		xprintf(XCORE, "error: failed to write data\n");
 		free(data);
 		return -1;
 	}
 	t1 = now();
-	xprintf("%lld uS -> %lld B/s\n", (t1 - t0), 
+	xprintf(XCORE, "%lld uS -> %lld B/s\n", (t1 - t0), 
 		(((long long)sz) * 1000000LL) / (t1 - t0));
 	free(data);
 	return 0;
@@ -461,18 +477,18 @@ int do_run(int argc, param *argv) {
 	size_t sz;
 	u32 sp, pc;
 	if (argc != 2) {
-		xprintf("error: usage: run <file> <addr>\n");
+		xprintf(XCORE, "error: usage: run <file> <addr>\n");
 		return -1;
 	}
 	if ((data = load_file(argv[0].s, &sz)) == NULL) {
-		xprintf("error: cannot read '%s'\n", argv[0].s);
+		xprintf(XCORE, "error: cannot read '%s'\n", argv[0].s);
 		return -1;
 	}
 	swdp_core_halt();
 	sz = (sz + 3) & ~3;
 	addr = argv[1].n;
 	if (swdp_ahb_write32(addr, (void*) data, sz / 4)) {
-		xprintf("error: failed to write data\n");
+		xprintf(XCORE, "error: failed to write data\n");
 		free(data);
 		return -1;
 	}
@@ -536,7 +552,7 @@ int invoke(u32 agent, u32 func, u32 r0, u32 r1, u32 r2, u32 r3) {
 
 	// todo: readback and verify?
 
-	xprintf("invoke <func@%08x>(0x%x,0x%x,0x%x,0x%x)\n", func, r0, r1, r2, r3);
+	xprintf(XCORE, "invoke <func@%08x>(0x%x,0x%x,0x%x,0x%x)\n", func, r0, r1, r2, r3);
 
 	swdp_core_resume();
 	if (swdp_core_wait_for_halt() == 0) {
@@ -545,13 +561,13 @@ int invoke(u32 agent, u32 func, u32 r0, u32 r1, u32 r2, u32 r3) {
 		swdp_core_read(0, &res);
 		swdp_core_read(15, &pc);
 		if (pc != agent) {
-			xprintf("error: pc (%08x) is not at %08x\n", pc, agent);
+			xprintf(XCORE, "error: pc (%08x) is not at %08x\n", pc, agent);
 			return -1;
 		}
-		if (res) xprintf("failure code %08x\n", res);
+		if (res) xprintf(XCORE, "failure code %08x\n", res);
 		return res;
 	}
-	xprintf("interrupted\n");
+	xprintf(XCORE, "interrupted\n");
 	return -1;
 }
 
@@ -560,29 +576,29 @@ int run_flash_agent(u32 flashaddr, void *data, size_t data_sz) {
 	size_t agent_sz;
 
 	if ((agent = load_agent(agent_arch, &agent_sz)) == NULL) {
-		xprintf("error: cannot load flash agent for architecture '%s'\n",
+		xprintf(XCORE, "error: cannot load flash agent for architecture '%s'\n",
 			agent_arch ? agent_arch : "unknown");
-		xprintf("error: set architecture with: arch <name>\n");
+		xprintf(XCORE, "error: set architecture with: arch <name>\n");
 		goto fail;
 	}
 	// sanity check
 	if ((agent_sz < sizeof(flash_agent)) ||
 		(agent->magic != AGENT_MAGIC) ||
 		(agent->version != AGENT_VERSION)) {
-		xprintf("error: invalid agent image\n");
+		xprintf(XCORE, "error: invalid agent image\n");
 		goto fail;
 	}
 	// replace magic with bkpt instructions
 	agent->magic = 0xbe00be00;
 
 	if (do_attach(0,0)) {
-		xprintf("error: failed to attach\n");
+		xprintf(XCORE, "error: failed to attach\n");
 		goto fail;
 	}
 	do_reset_stop(0,0);
 
 	if (agent->flags & FLAG_BOOT_ROM_HACK) {
-		xprintf("executing boot rom\n");
+		xprintf(XCORE, "executing boot rom\n");
 		if (swdp_watchpoint_rw(0, 0)) {
 			goto fail;
 		}
@@ -594,7 +610,7 @@ int run_flash_agent(u32 flashaddr, void *data, size_t data_sz) {
 	}
 
 	if (swdp_ahb_write32(agent->load_addr, (void*) agent, agent_sz / 4)) {
-		xprintf("error: failed to download agent\n");
+		xprintf(XCORE, "error: failed to download agent\n");
 		goto fail;
 	}
 	if (invoke(agent->load_addr, agent->setup, 0, 0, 0, 0)) {
@@ -603,7 +619,7 @@ int run_flash_agent(u32 flashaddr, void *data, size_t data_sz) {
 	if (swdp_ahb_read32(agent->load_addr + 16, (void*) &agent->data_addr, 4)) {
 		goto fail;
 	}
-	xprintf("agent %d @%08x, buffer %dK @%08x, flash %dK @%08x\n",
+	xprintf(XCORE, "agent %d @%08x, buffer %dK @%08x, flash %dK @%08x\n",
 		agent_sz, agent->load_addr,
 		agent->data_size / 1024, agent->data_addr,
 		agent->flash_size / 1024, agent->flash_addr);
@@ -617,23 +633,23 @@ int run_flash_agent(u32 flashaddr, void *data, size_t data_sz) {
 	if ((flashaddr < agent->flash_addr) ||
 		(data_sz > agent->flash_size) ||
 		((flashaddr + data_sz) > (agent->flash_addr + agent->flash_size))) {
-		xprintf("invalid flash address %08x\n", flashaddr);
+		xprintf(XCORE, "invalid flash address %08x\n", flashaddr);
 		goto fail;
 	}
 
 	if (data == NULL) {
 		// erase
 		if (invoke(agent->load_addr, agent->erase, flashaddr, data_sz, 0, 0)) {
-			xprintf("failed to erase %d bytes at %08x\n", data_sz, flashaddr);
+			xprintf(XCORE, "failed to erase %d bytes at %08x\n", data_sz, flashaddr);
 			goto fail;
 		}
 	} else {
 		// write
 		u8 *ptr = (void*) data;
 		u32 xfer;
-		xprintf("flashing %d bytes at %08x...\n", data_sz, flashaddr);
+		xprintf(XCORE, "flashing %d bytes at %08x...\n", data_sz, flashaddr);
 		if (invoke(agent->load_addr, agent->erase, flashaddr, data_sz, 0, 0)) {
-			xprintf("failed to erase %d bytes at %08x\n", data_sz, flashaddr);
+			xprintf(XCORE, "failed to erase %d bytes at %08x\n", data_sz, flashaddr);
 			goto fail;
 		}
 		while (data_sz > 0) {
@@ -643,12 +659,12 @@ int run_flash_agent(u32 flashaddr, void *data, size_t data_sz) {
 				xfer = data_sz;
 			}
 			if (swdp_ahb_write32(agent->data_addr, (void*) ptr, xfer / 4)) {
-				xprintf("download to %08x failed\n", agent->data_addr);
+				xprintf(XCORE, "download to %08x failed\n", agent->data_addr);
 				goto fail;
 			}
 			if (invoke(agent->load_addr, agent->write,
 				flashaddr, agent->data_addr, xfer, 0)) {
-				xprintf("failed to flash %d bytes to %08x\n", xfer, flashaddr);
+				xprintf(XCORE, "failed to flash %d bytes to %08x\n", xfer, flashaddr);
 				goto fail;
 			}
 			ptr += xfer;
@@ -670,11 +686,11 @@ int do_flash(int argc, param *argv) {
 	void *data = NULL;
 	size_t data_sz;
 	if (argc != 2) {
-		xprintf("error: usage: flash <file> <addr>\n");
+		xprintf(XCORE, "error: usage: flash <file> <addr>\n");
 		return -1;
 	}
 	if ((data = load_file(argv[0].s, &data_sz)) == NULL) {
-		xprintf("error: cannot load '%s'\n", argv[0].s);
+		xprintf(XCORE, "error: cannot load '%s'\n", argv[0].s);
 		return -1;
 	}
 	// word align
@@ -687,7 +703,7 @@ int do_erase(int argc, param *argv) {
 		return run_flash_agent(0, NULL, 0xFFFFFFFF);
 	}
 	if (argc != 2) {
-		xprintf("error: usage: erase <addr> <length> | erase all\n");
+		xprintf(XCORE, "error: usage: erase <addr> <length> | erase all\n");
 		return -1;
 	}
 	return run_flash_agent(argv[0].n, NULL, argv[1].n);
@@ -701,7 +717,7 @@ int do_log(int argc, param *argv) {
 		} else if (!strcmp(argv[0].s, "swd")) {
 			flags |= LF_SWD;
 		} else {
-			xprintf("error: allowed flags: gdb swd\n");
+			xprintf(XCORE, "error: allowed flags: gdb swd\n");
 			return -1;
 		}
 		argc--;
@@ -719,35 +735,35 @@ int do_finfo(int argc, param *argv) {
 	swdp_ahb_read(MMFAR, &mmfar);
 	swdp_ahb_read(BFAR, &bfar);
 
-	xprintf("CFSR %08x  MMFAR %08x\n", cfsr, mmfar);
-	xprintf("HFSR %08x   BFAR %08x\n", hfsr, bfar);
-	xprintf("DFSR %08x\n", dfsr);
-
-	if (cfsr & CFSR_IACCVIOL)	xprintf(">MM: Inst Access Violation\n");
-	if (cfsr & CFSR_DACCVIOL)	xprintf(">MM: Data Access Violation\n");
-	if (cfsr & CFSR_MUNSTKERR)	xprintf(">MM: Derived MM Fault on Exception Return\n");
-	if (cfsr & CFSR_MSTKERR)	xprintf(">MM: Derived MM Fault on Exception Entry\n");
-	if (cfsr & CFSR_MLSPERR)	xprintf(">MM: MM Fault During Lazy FP Save\n");
-	if (cfsr & CFSR_MMARVALID)	xprintf(">MM: MMFAR has valid contents\n");
-
-	if (cfsr & CFSR_IBUSERR)	xprintf(">BF: Bus Fault on Instruction Prefetch\n");
-	if (cfsr & CFSR_PRECISERR)	xprintf(">BF: Precise Data Access Error, Addr in BFAR\n");
-	if (cfsr & CFSR_IMPRECISERR)	xprintf(">BF: Imprecise Data Access Error\n");
-	if (cfsr & CFSR_UNSTKERR)	xprintf(">BF: Derived Bus Fault on Exception Return\n");
-	if (cfsr & CFSR_STKERR)		xprintf(">BF: Derived Bus Fault on Exception Entry\n");
-	if (cfsr & CFSR_LSPERR)		xprintf(">BF: Bus Fault During Lazy FP Save\n");
-	if (cfsr & CFSR_BFARVALID)	xprintf(">BF: BFAR has valid contents\n");
-
-	if (cfsr & CFSR_UNDEFINSTR)	xprintf(">UF: Undefined Instruction Usage Fault\n");
-	if (cfsr & CFSR_INVSTATE)	xprintf(">UF: EPSR.T or ESPR.IT invalid\n");
-	if (cfsr & CFSR_INVPC)		xprintf(">UF: Integrity Check Error on EXC_RETURN\n");
-	if (cfsr & CFSR_NOCP)		xprintf(">UF: Coprocessor Error\n");
-	if (cfsr & CFSR_UNALIGNED)	xprintf(">UF: Unaligned Access Error\n");
-	if (cfsr & CFSR_DIVBYZERO)	xprintf(">UF: Divide by Zero\n");
-
-	if (hfsr & HFSR_VECTTBL)	xprintf(">HF: Vector Table Read Fault\n");
-	if (hfsr & HFSR_FORCED)		xprintf(">HF: Exception Escalated to Hard Fault\n");
-	if (hfsr & HFSR_DEBUGEVT)	xprintf(">HF: Debug Event\n");
+	xprintf(XDATA, "CFSR %08x  MMFAR %08x\n", cfsr, mmfar);
+	xprintf(XDATA, "HFSR %08x   BFAR %08x\n", hfsr, bfar);
+	xprintf(XDATA, "DFSR %08x\n", dfsr);
+
+	if (cfsr & CFSR_IACCVIOL)	xprintf(XDATA, ">MM: Inst Access Violation\n");
+	if (cfsr & CFSR_DACCVIOL)	xprintf(XDATA, ">MM: Data Access Violation\n");
+	if (cfsr & CFSR_MUNSTKERR)	xprintf(XDATA, ">MM: Derived MM Fault on Exception Return\n");
+	if (cfsr & CFSR_MSTKERR)	xprintf(XDATA, ">MM: Derived MM Fault on Exception Entry\n");
+	if (cfsr & CFSR_MLSPERR)	xprintf(XDATA, ">MM: MM Fault During Lazy FP Save\n");
+	if (cfsr & CFSR_MMARVALID)	xprintf(XDATA, ">MM: MMFAR has valid contents\n");
+
+	if (cfsr & CFSR_IBUSERR)	xprintf(XDATA, ">BF: Bus Fault on Instruction Prefetch\n");
+	if (cfsr & CFSR_PRECISERR)	xprintf(XDATA, ">BF: Precise Data Access Error, Addr in BFAR\n");
+	if (cfsr & CFSR_IMPRECISERR)	xprintf(XDATA, ">BF: Imprecise Data Access Error\n");
+	if (cfsr & CFSR_UNSTKERR)	xprintf(XDATA, ">BF: Derived Bus Fault on Exception Return\n");
+	if (cfsr & CFSR_STKERR)		xprintf(XDATA, ">BF: Derived Bus Fault on Exception Entry\n");
+	if (cfsr & CFSR_LSPERR)		xprintf(XDATA, ">BF: Bus Fault During Lazy FP Save\n");
+	if (cfsr & CFSR_BFARVALID)	xprintf(XDATA, ">BF: BFAR has valid contents\n");
+
+	if (cfsr & CFSR_UNDEFINSTR)	xprintf(XDATA, ">UF: Undefined Instruction Usage Fault\n");
+	if (cfsr & CFSR_INVSTATE)	xprintf(XDATA, ">UF: EPSR.T or ESPR.IT invalid\n");
+	if (cfsr & CFSR_INVPC)		xprintf(XDATA, ">UF: Integrity Check Error on EXC_RETURN\n");
+	if (cfsr & CFSR_NOCP)		xprintf(XDATA, ">UF: Coprocessor Error\n");
+	if (cfsr & CFSR_UNALIGNED)	xprintf(XDATA, ">UF: Unaligned Access Error\n");
+	if (cfsr & CFSR_DIVBYZERO)	xprintf(XDATA, ">UF: Divide by Zero\n");
+
+	if (hfsr & HFSR_VECTTBL)	xprintf(XDATA, ">HF: Vector Table Read Fault\n");
+	if (hfsr & HFSR_FORCED)		xprintf(XDATA, ">HF: Exception Escalated to Hard Fault\n");
+	if (hfsr & HFSR_DEBUGEVT)	xprintf(XDATA, ">HF: Debug Event\n");
 
 	// clear sticky fault bits
 	swdp_ahb_write(CFSR, CFSR_ALL);
@@ -759,18 +775,18 @@ extern int swdp_step_no_ints;
 
 int do_maskints(int argc, param *argv) {
 	if (argc != 1) {
-		xprintf("usage: maskints [on|off|always]\n");
+		xprintf(XCORE, "usage: maskints [on|off|always]\n");
 		return -1;
 	}
 	if (!strcmp(argv[0].s, "on")) {
 		swdp_step_no_ints = 1;
-		xprintf("maskints: while stepping\n");
+		xprintf(XCORE, "maskints: while stepping\n");
 	} else if (!strcmp(argv[0].s, "always")) {
 		swdp_step_no_ints = 2;
-		xprintf("maskints: always\n");
+		xprintf(XCORE, "maskints: always\n");
 	} else {
 		swdp_step_no_ints = 0;
-		xprintf("maskints: never\n");
+		xprintf(XCORE, "maskints: never\n");
 	}
 	return 0;
 }
@@ -778,7 +794,7 @@ int do_maskints(int argc, param *argv) {
 int do_threads(int argc, param *argv) {
 	if (argc == 1) {
 		if (strcmp(argv[0].s, "clear")) {
-			xprintf("usage: threads [clear]\n");
+			xprintf(XCORE, "usage: threads [clear]\n");
 			return -1;
 		}
 		swdp_core_halt();
diff --git a/tools/debugger-core.c b/tools/debugger-core.c
@@ -1,7 +1,7 @@
 /* debugger-core.c
  *
  * Copyright 2011 Brian Swetland <swetland@frotz.net>
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
@@ -30,7 +30,6 @@
 #include <protocol/rswdp.h>
 #include "debugger.h"
 #include "rswdp.h"
-#include "linenoise.h"
 
 #define DHCSR_C_DEBUGEN		(1 << 0)
 #define DHCSR_C_HALT		(1 << 1)
@@ -53,9 +52,7 @@
 #define DFSR_MASK		0x1F
 
 static void m_event(const char *evt) {
-	linenoisePause();
-	fprintf(stdout, "DEBUG EVENT: %s\n", evt);
-	linenoiseResume();
+	xprintf(XCORE, "DEBUG EVENT: %s\n", evt);
 }
 
 static void monitor(void) {
@@ -81,9 +78,7 @@ void debugger_lock() {
 	if (swdp_clear_error()) {
 #if 0
 		// way too noisy if the link goes down
-		linenoisePause();
 		xprintf("SWD ERROR persists. Attempting link reset.\n");
-		linenoiseResume();
 #endif
 		swdp_reset();
 	}
@@ -91,9 +86,7 @@ void debugger_lock() {
 
 void debugger_unlock() {
 	if (swdp_error()) {
-		linenoisePause();
-		xprintf("SWD ERROR\n");
-		linenoiseResume();
+		xprintf(XCORE, "SWD ERROR\n");
 	}
 	pthread_mutex_unlock(&_dbg_lock);
 }
@@ -114,7 +107,7 @@ static pthread_t _listen_master;
 void *gdb_listener(void *arg) {
 	int fd;
 	if ((fd = socket_listen_tcp(5555)) < 0) {
-		fprintf(stderr, "gdb_listener() cannot bind to 5555\n");
+		xprintf(XGDB, "gdb_listener() cannot bind to 5555\n");
 		return NULL;
 	}
 	for (;;) {
@@ -185,7 +178,7 @@ static int do_script(int argc, param *argv) {
 		fp = stdin;
 	} else {
 		if (!(fp = fopen(argv[0].s, "r"))) {
-			xprintf("error: cannot open '%s'\n", argv[0].s);
+			xprintf(XCORE, "error: cannot open '%s'\n", argv[0].s);
 			return -1;
 		}
 	}
@@ -200,7 +193,7 @@ static int do_script(int argc, param *argv) {
 			char *name, *x;
 			name = line + 9;
 			if (newfunc) {
-				xprintf("error: nested functions not allowed\n");
+				xprintf(XCORE, "error: nested functions not allowed\n");
 				break;
 			}
 			while (isspace(*name))
@@ -210,12 +203,12 @@ static int do_script(int argc, param *argv) {
 				x++;
 			*x = 0;
 			if (*name == 0) {
-				xprintf("error: functions must have names\n");
+				xprintf(XCORE, "error: functions must have names\n");
 				break;
 			}
 			newfunc = malloc(sizeof(*newfunc) + strlen(name) + 1);
 			if (newfunc == 0) {
-				xprintf("error: out of memory\n");
+				xprintf(XCORE, "error: out of memory\n");
 				break;
 			}
 			strcpy(newfunc->name, name);
@@ -234,7 +227,7 @@ static int do_script(int argc, param *argv) {
 			}
 			fl = malloc(sizeof(*fl) + strlen(line) + 1);
 			if (fl == 0) {
-				xprintf("out of memory");
+				xprintf(XCORE, "out of memory");
 				newfunc = 0;
 				if (fp != stdin)
 					fclose(fp);
@@ -249,7 +242,7 @@ static int do_script(int argc, param *argv) {
 			}
 			lastline = fl;
 		} else {
-			xprintf("script> %s", line);
+			xprintf(XCORE, "script> %s", line);
 			if (debugger_command(line))
 				return -1;
 		}
@@ -265,18 +258,18 @@ static int do_script(int argc, param *argv) {
 static int do_set(int argc, param *argv) {
 	const char *name;
 	if ((argc != 2) && (argc != 4)) {
-		xprintf("error: set requires two or four arguments\n");
+		xprintf(XCORE, "error: set requires two or four arguments\n");
 		return -1;
 	}
 	name = argv[0].s;
 	if (*name == '$')
 		name++;
 	if (*name == 0) {
-		xprintf("error: empty name?!\n");
+		xprintf(XCORE, "error: empty name?!\n");
 		return -1;
 	}
 	if (!isalpha(*name)) {
-		xprintf("error: variable name must begin with a letter\n");
+		xprintf(XCORE, "error: variable name must begin with a letter\n");
 		return -1;
 	}
 
@@ -303,7 +296,7 @@ static int do_set(int argc, param *argv) {
 				n = a / b;
 			}
 		} else {
-			xprintf("error: set <var> <a> <op> <b> requires op: + - * / << >>\n");
+			xprintf(XCORE, "error: set <var> <a> <op> <b> requires op: + - * / << >>\n");
 			return -1;
 		}
 		variable_set(name, n);
@@ -352,14 +345,14 @@ static int parse_number(const char *in, unsigned *out) {
 					return 0;
 				}
 			}
-			xprintf("no local variable %s\n", text);
+			xprintf(XCORE, "no local variable %s\n", text);
 			*out = 0;
 			return 0;
 		}
 		if (variable_get(text + 1, &value) == 0) {
 			*out = value;
 		} else {
-			xprintf("undefined variable '%s'\n", text + 1);
+			xprintf(XCORE, "undefined variable '%s'\n", text + 1);
 			*out = 0;
 		}
 		return 0;
@@ -397,7 +390,7 @@ static int exec_function(struct funcinfo *f, int argc, param *argv) {
 		strcpy(text, line->text);
 		r = debugger_command(text);
 		if (r) {
-			xprintf("error: %s: line %d\n", f->name, n);
+			xprintf(XCORE, "error: %s: line %d\n", f->name, n);
 			goto done;
 		}
 	}
@@ -422,9 +415,7 @@ static int _debugger_exec(const char *cmd, unsigned argc, param *argv) {
 		if (!strcasecmp(cmd, c->name)) {
 			int n;
 			debugger_lock();
-			linenoisePause();
 			n = c->func(argc, argv);
-			linenoiseResume();
 			debugger_unlock();
 			return n;
 		}
@@ -485,14 +476,14 @@ int debugger_command(char *line) {
 
 	for (c = 0; c < n; c++) {
 		if (parse_number(arg[c].s, &(arg[c].n))) {
-			xprintf("error: bad number: %s\n", arg[c].s);
+			xprintf(XCORE, "error: bad number: %s\n", arg[c].s);
 			return -1;
 		}
 	}
 
 	r = _debugger_exec(arg[0].s, n - 1, arg + 1);
 	if (r == ERROR_UNKNOWN) {
-		xprintf("unknown command: %s\n", arg[0].s);
+		xprintf(XCORE, "unknown command: %s\n", arg[0].s);
 	}
 	return r;
 }
diff --git a/tools/debugger.c b/tools/debugger.c
@@ -38,13 +38,15 @@ static const char *scriptfile = NULL;
 
 void gdb_console_puts(const char *msg);
 
-void xprintf(const char *fmt, ...) {
+void xprintf(xpchan ch, const char *fmt, ...) {
 	char line[256];
 	va_list ap;
 	va_start(ap, fmt);
 	vsnprintf(line, 256, fmt, ap);
 	va_end(ap);
+	linenoisePause();
 	if (write(1, line, strlen(line)) < 0) ;
+	linenoiseResume();
 	gdb_console_puts(line);
 }
 
diff --git a/tools/debugger.h b/tools/debugger.h
@@ -1,7 +1,7 @@
 /* debugger.h
  *
  * Copyright 2011 Brian Swetland <swetland@frotz.net>
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
@@ -18,8 +18,16 @@
 #ifndef _DEBUGGER_H_
 #define _DEBUGGER_H_
 
+typedef enum {
+	XDEFAULT,
+	XSWD,		// SWD transport & engine
+	XCORE,		// debugger core
+	XDATA,		// debugger command response
+	XGDB,		// messages from GDB bridge
+} xpchan;
+
 #define printf __use_xprintf_in_debugger__
-extern void xprintf(const char *fmt, ...);
+extern void xprintf(xpchan ch, const char *fmt, ...);
 
 #define ERROR		-1
 #define ERROR_UNKNOWN 	-2
diff --git a/tools/gdb-bridge.c b/tools/gdb-bridge.c
@@ -1,7 +1,7 @@
 /* gdb-bridge.c
  *
  * Copyright 2011 Brian Swetland <swetland@frotz.net>
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
@@ -28,7 +28,6 @@
 #include "rswdp.h"
 #include <protocol/rswdp.h>
 #include "debugger.h"
-#include "linenoise.h"
 #include "lkdebug.h"
 
 // useful gdb stuff
@@ -54,7 +53,7 @@ struct gdbcnxn {
 	unsigned txsum;
 	unsigned rxsum;
 	unsigned flags;
-	unsigned char *txptr;	
+	unsigned char *txptr;
 	unsigned char *rxptr;
 	unsigned char rxbuf[MAXPKT];
 	unsigned char txbuf[MAXPKT];
@@ -64,15 +63,6 @@ struct gdbcnxn {
 	lkthread_t *cselected;
 };
 
-void zprintf(const char *fmt, ...) {
-	linenoisePause();
-	va_list ap;
-	va_start(ap, fmt);
-	vfprintf(stderr, fmt, ap);
-	va_end(ap);
-	linenoiseResume();
-}
-
 void gdb_init(struct gdbcnxn *gc, int fd) {
 	gc->fd = fd;
 	gc->state = S_IDLE;
@@ -121,7 +111,7 @@ void gdb_epilogue(struct gdbcnxn *gc) {
 	gdb_puts(gc, tmp);
 
 	if (tx_full(gc)) {
-		zprintf("GDB: TX Packet Too Large\n");
+		xprintf(XGDB, "gdb: TX Packet Too Large\n");
 		return;
 	}
 
@@ -131,7 +121,7 @@ void gdb_epilogue(struct gdbcnxn *gc) {
 		r = write(gc->fd, ptr, len);
 		if (r <= 0) {
 			if (errno == EINTR) continue;
-			zprintf("GDB: TX Write Error\n");
+			xprintf(XGDB, "gdb: TX Write Error\n");
 			return;
 		}
 		ptr += r;
@@ -153,7 +143,7 @@ void handle_command(struct gdbcnxn *gc, unsigned char *cmd);
 
 void gdb_recv_cmd(struct gdbcnxn *gc) {
 	if (log_flags & LF_GDB) {
-		zprintf("PKT: %s\n", gc->rxbuf);
+		xprintf(XGDB, "gdb: pkt: %s\n", gc->rxbuf);
 	}
 	debugger_lock();
 	handle_command(gc, gc->rxbuf);
@@ -184,7 +174,7 @@ int gdb_recv(struct gdbcnxn *gc, unsigned char *ptr, int len) {
 				gc->state = S_CHK1;
 			} else {
 				if (rx_full(gc)) {
-					zprintf("PKT: Too Large, Discarding.");
+					xprintf(XGDB, "gdb: pkt: Too Large, Discarding.");
 					gc->rxptr = gc->rxbuf;
 					gc->state = S_IDLE;
 				} else {
@@ -315,7 +305,7 @@ static void handle_query(struct gdbcnxn *gc, char *cmd, char *args) {
 			p+=2;
 		}
 		*cmd = 0;
-		zprintf("GDB: %s\n", args);
+		xprintf(XGDB, "gdb: %s\n", args);
 		gc->flags |= F_CONSOLE;
 		debugger_unlock();
 		debugger_command(args);
@@ -340,7 +330,7 @@ static void handle_query(struct gdbcnxn *gc, char *cmd, char *args) {
 	} else if(!strcmp(cmd, "Attached")) {
 		/* no process management. ignore */
 	} else {
-		zprintf("GDB: unsupported: q%s:%s\n", cmd, args);
+		xprintf(XGDB, "gdb: unsupported: q%s:%s\n", cmd, args);
 	}
 }
 
@@ -349,7 +339,7 @@ static void handle_set(struct gdbcnxn *gc, char *cmd, char *args) {
 		gc->flags &= ~F_ACK;
 		gdb_puts(gc, "OK");
 	} else {
-		zprintf("GDB: unsupported: Q%s:%s\n", cmd, args);
+		xprintf(XGDB, "gdb: unsupported: Q%s:%s\n", cmd, args);
 	}
 }
 
@@ -406,13 +396,13 @@ void write_memory(u32 addr, unsigned char *data, int len) {
 #define FP_REMAP	0xE0002004
 #define FP_COMP(n)	(0xE0002008 + ((n) * 4))
 
-#define MAXFP 16 
+#define MAXFP 16
 static u32 maxfp = 0;
 static u32 fp_addr[MAXFP] = { 0, };
 static u32 fp_state[MAXFP] = { 0, };
 
 #define MAXBP 16
-static u32 maxbp; 
+static u32 maxbp;
 static u32 bp_addr[MAXBP] = { 0, };
 static u32 bp_state[MAXBP] = { 0, };
 
@@ -420,12 +410,12 @@ int handle_flashpatch(int add, u32 addr, u32 kind) {
 	u32 x;
 	int n;
 	if (swdp_ahb_read(ROMTAB_FPB, &x)) {
-		zprintf("GDB: cannot read romtable\n");
+		xprintf(XGDB, "gdb: cannot read romtable\n");
 		return -1;
 	}
 	if (x & 1) {
 		if (swdp_ahb_read(FP_CTRL, &x)) {
-			zprintf("GDB: cannot read flashpatch ctrl\n");
+			xprintf(XGDB, "gdb: cannot read flashpatch ctrl\n");
 			return -1;
 		}
 		n = ((x & 0xF0) >> 4) | ((x & 0x7000) >> 4);
@@ -433,10 +423,10 @@ int handle_flashpatch(int add, u32 addr, u32 kind) {
 		n = 0;
 	}
 	if (n != maxfp) {
-		zprintf("GDB: %d flashpatch breakpoint registers\n", n);
+		xprintf(XGDB, "gdb: %d flashpatch breakpoint registers\n", n);
 		if (n > 16) n = 16;
 		if (maxfp != 0) {
-			zprintf("GDB: previously %d registers...\n", maxfp);
+			xprintf(XGDB, "gdb: previously %d registers...\n", maxfp);
 		}
 		maxfp = n;
 	}
@@ -447,7 +437,7 @@ int handle_flashpatch(int add, u32 addr, u32 kind) {
 			} else {
 				fp_state[n] = 0;
 				swdp_ahb_write(FP_COMP(n), 0);
-				zprintf("GDB: - FP BP @ %08x\n", addr);
+				xprintf(XGDB, "gdb: - FP BP @ %08x\n", addr);
 				return 0;
 			}
 		}
@@ -474,7 +464,7 @@ add1:
 	fp_state[n] = 1;
 	fp_addr[n] = addr;
 add0:
-	zprintf("GDB: + FP BP @ %08x\n", addr);
+	xprintf(XGDB, "gdb: + FP BP @ %08x\n", addr);
 	return 0;
 }
 
@@ -486,12 +476,12 @@ int handle_breakpoint(int add, u32 addr, u32 kind) {
 		return 0;
 	}
 	if (swdp_ahb_read(ROMTAB_DWT, &x)) {
-		zprintf("GDB: cannot read romtable\n");
+		xprintf(XGDB, "gdb: cannot read romtable\n");
 		return -1;
 	}
 	if (x & 1) {
 		if (swdp_ahb_read(DWT_CTRL, &x)) {
-			zprintf("GDB: cannot read dwt ctrl\n");
+			xprintf(XGDB, "gdb: cannot read dwt ctrl\n");
 			return -1;
 		}
 		n = x >> 28;
@@ -499,9 +489,9 @@ int handle_breakpoint(int add, u32 addr, u32 kind) {
 		n = 0;
 	}
 	if (n != maxbp) {
-		zprintf("GDB: %d dwt breakpoint registers\n", n);
+		xprintf(XGDB, "gdb: %d dwt breakpoint registers\n", n);
 		if (maxbp != 0) {
-			zprintf("GDB: previously %d registers...\n", maxbp);
+			xprintf(XGDB, "gdb: previously %d registers...\n", maxbp);
 		}
 		maxbp = n;
 	}
@@ -518,12 +508,12 @@ int handle_breakpoint(int add, u32 addr, u32 kind) {
 				bp_addr[n] = addr;
 				bp_state[n] = 1;
 				swdp_watchpoint_pc(n, addr);
-				zprintf("GDB: + HW BP @ %08x\n", addr);
+				xprintf(XGDB, "gdb: + HW BP @ %08x\n", addr);
 				return 0;
 			}
 		}
 		if (n == maxbp) {
-			zprintf("GDB: Out of hardware breakpoints.\n");
+			xprintf(XGDB, "gdb: Out of hardware breakpoints.\n");
 			return 1;
 		}
 		return 0;
@@ -535,17 +525,17 @@ int handle_breakpoint(int add, u32 addr, u32 kind) {
 				break;
 			}
 		}
-		zprintf("GDB: - HW BP @ %08x\n", addr);
+		xprintf(XGDB, "gdb: - HW BP @ %08x\n", addr);
 		return 0;
 	}
 }
 
 void gdb_update_threads(struct gdbcnxn *gc) {
-	zprintf("GDB: sync threadlist\n");
+	xprintf(XGDB, "gdb: sync threadlist\n");
 	free_lk_threads(gc->threadlist);
 	if (gc->flags & F_LK_THREADS) {
 		if ((gc->threadlist = find_lk_threads(0)) == NULL) {
-			zprintf("GDB: problem syncing threadlist\n");
+			xprintf(XGDB, "gdb: problem syncing threadlist\n");
 		}
 		gc->cselected = gc->threadlist;
 		gc->gselected = gc->threadlist;
@@ -609,7 +599,7 @@ void handle_command(struct gdbcnxn *gc, unsigned char *cmd) {
 		} else if (cmd[1] == 'c') {
 			gc->cselected = t;
 		} else {
-			zprintf("GDB: selecting '%c' thread?!\n", cmd[1]);
+			xprintf(XGDB, "gdb: selecting '%c' thread?!\n", cmd[1]);
 		}
 		gdb_puts(gc, "OK");
 		break;
@@ -669,7 +659,7 @@ void handle_command(struct gdbcnxn *gc, unsigned char *cmd) {
 	// write registers 0...
 	case 'G': {
 		if (gc->gselected && !gc->gselected->active) {
-			zprintf("GDB: attempting to write to inactive registers\n");
+			xprintf(XGDB, "gdb: attempting to write to inactive registers\n");
 			break;
 		}
 		int len = hextobin(gc->rxbuf, (char*) cmd + 1, MAXPKT);
@@ -703,7 +693,7 @@ void handle_command(struct gdbcnxn *gc, unsigned char *cmd) {
 		int len;
 		char *data = strchr((char*) cmd + 1, '=');
 		if (gc->gselected && !gc->gselected->active) {
-			zprintf("GDB: attempting to write to inactive registers\n");
+			xprintf(XGDB, "gdb: attempting to write to inactive registers\n");
 			break;
 		}
 		if (data) {
@@ -741,7 +731,6 @@ void handle_command(struct gdbcnxn *gc, unsigned char *cmd) {
 			handle_set(gc, (char*) (cmd + 1), args);
 		}
 		break;
-		
 	}
 	case 'z':
 	case 'Z': {
@@ -760,7 +749,7 @@ void handle_command(struct gdbcnxn *gc, unsigned char *cmd) {
 		break;
 	}
 	default:
-		zprintf("GDB: unknown command: %c\n", cmd[0]);
+		xprintf(XGDB, "gdb: unknown command: %c\n", cmd[0]);
 	}
 	gdb_epilogue(gc);
 }
@@ -799,7 +788,7 @@ void gdb_server(int fd) {
 	if (pipefds[0] == -1) {
 		if (pipe(pipefds)) ;
 	}
-	zprintf("[ gdb connected ]\n");
+	xprintf(XGDB,"[ gdb connected ]\n");
 	debugger_unlock();
 
 	gc.flags |= F_LK_THREADS;
@@ -862,6 +851,6 @@ void gdb_server(int fd) {
 
 	debugger_lock();
 	active_gc = NULL;
-	zprintf("[ gdb connected ]\n");
+	xprintf(XGDB, "[ gdb connected ]\n");
 	debugger_unlock();
 }
diff --git a/tools/lkdebug.c b/tools/lkdebug.c
@@ -57,15 +57,15 @@ static char *lkstate[] = {
 };
 
 void dump_lk_thread(lkthread_t *t) {
-	xprintf("thread: @%08x sp=%08x wq=%08x st=%d name='%s'\n",
+	xprintf(XDATA, "thread: @%08x sp=%08x wq=%08x st=%d name='%s'\n",
 		t->threadptr, t->saved_sp, t->waitq, t->state, t->name);
-	xprintf("  r0 %08x r4 %08x r8 %08x ip %08x\n",
+	xprintf(XDATA, "  r0 %08x r4 %08x r8 %08x ip %08x\n",
 		t->regs[0], t->regs[4], t->regs[8], t->regs[12]);
-	xprintf("  r1 %08x r5 %08x r9 %08x sp %08x\n",
+	xprintf(XDATA, "  r1 %08x r5 %08x r9 %08x sp %08x\n",
 		t->regs[1], t->regs[5], t->regs[9], t->regs[13]);
-	xprintf("  r2 %08x r6 %08x 10 %08x lr %08x\n",
+	xprintf(XDATA, "  r2 %08x r6 %08x 10 %08x lr %08x\n",
 		t->regs[2], t->regs[6], t->regs[10], t->regs[14]);
-	xprintf("  r3 %08x r7 %08x 11 %08x pc %08x\n",
+	xprintf(XDATA, "  r3 %08x r7 %08x 11 %08x pc %08x\n",
 		t->regs[3], t->regs[7], t->regs[11], t->regs[15]);
 }
 
@@ -148,21 +148,21 @@ static int load_debuginfo(lkdebuginfo_t *di, int verbose) {
 	if (swdp_ahb_read(0xE000ED08, &vtbl)) vtbl = 0;
 	if (swdp_ahb_read((DI_OFF_MAGIC + vtbl), &x)) return -1;
 	if (x != DI_MAGIC) {
-		if (verbose) xprintf("debuginfo: bad magic\n");
+		if (verbose) xprintf(XCORE, "debuginfo: bad magic\n");
 		return -1;
 	}
 	if (swdp_ahb_read((DI_OFF_PTR + vtbl), &x)) return -1;
 	if (x & 3) return -1;
-	if (verbose) xprintf("debuginfo @ %08x\n", x);
+	if (verbose) xprintf(XCORE, "debuginfo @ %08x\n", x);
 	if (swdp_ahb_read32(x, (void*) di, sizeof(lkdebuginfo_t) / 4)) return -1;
 	if (verbose) {
-		xprintf("di %08x %08x %08x %d %d %d %d %d %d\n",
+		xprintf(XDATA, "di %08x %08x %08x %d %d %d %d %d %d\n",
 			di->version, di->thread_list_ptr, di->current_thread_ptr,
 			di->off_list_node, di->off_state, di->off_saved_sp,
 			di->off_was_preempted, di->off_name, di->off_waitq);
 	}
 	if (di->version != 0x0100) {
-		if (verbose) xprintf("debuginfo: unsupported version\n");
+		if (verbose) xprintf(XCORE, "debuginfo: unsupported version\n");
 		return -1;
 	}
 	return 0;
diff --git a/tools/rswdp.c b/tools/rswdp.c
@@ -29,6 +29,8 @@
 #include "rswdp.h"
 #include "arm-v7m.h"
 
+#include <debugger.h>
+
 static volatile int ATTN;
 
 void swdp_interrupt(void) {
@@ -101,7 +103,7 @@ static void process_async(u32 *data, unsigned count) {
 				return;
 			tmp = data[n];
 			data[n] = 0;
-			printf("%s",(char*) data);
+			xprintf(XSWD, "%s",(char*) data);
 			data[n] = tmp;
 			data += n;
 			count -= n;
@@ -129,7 +131,7 @@ static int process_reply(struct txn *t, u32 *data, int count) {
 			continue;
 		case CMD_SWD_DATA:
 			if (n > rxc) {
-				fprintf(stderr,"reply overrun (%d > %d)\n", n, rxc);
+				xprintf(XSWD, "reply overrun (%d > %d)\n", n, rxc);
 				return -1;
 			}
 			while (n-- > 0) {
@@ -146,7 +148,7 @@ static int process_reply(struct txn *t, u32 *data, int count) {
 				return 0;
 			}
 		default:
-			fprintf(stderr,"unknown command 0x%02x\n", RSWD_MSG_CMD(msg));
+			xprintf(XSWD,"unknown command 0x%02x\n", RSWD_MSG_CMD(msg));
 			return -1;
 		}
 	}
@@ -221,12 +223,13 @@ restart:
 		if ((usb = usb_open(0x18d1, 0xdb03, 0))) break;
 		if ((usb = usb_open(0x18d1, 0xdb04, 0))) break;
 		if (once) {
-			fprintf(stderr, "\r\nusb: waiting for debugger device\r\n");
+			xprintf(XSWD, "usb: waiting for debugger device\n");
 			once = 0;
 		}
 		usleep(250000);
 	}
-	fprintf(stderr, "\r\nusb: debugger connected\r\n");
+	once = 0;
+	xprintf(XSWD, "usb: debugger connected\n");
 	pthread_mutex_lock(&swd_lock);
 	swd_online = 1;
 	for (;;) {
@@ -234,14 +237,14 @@ restart:
 		r = usb_read_forever(usb, data, 4096);
 		pthread_mutex_lock(&swd_lock);
 		if (r < 0) {
-			fprintf(stderr,"\r\nusb: debugger disconnected\r\n");
+			xprintf(XSWD, "usb: debugger disconnected\n");
 			swd_online = -1;
 			swd_txn_status = TXN_STATUS_FAIL;
 			pthread_cond_broadcast(&swd_event);
 			break;
 		}
 		if ((r < 4) || (r & 3)) {
-			fprintf(stderr,"\r\nusb: rx: discard packet (%d)\r\n", r);
+			xprintf(XSWD, "usb: discard packet (%d)\n", r);
 			continue;
 		}
 		if (swd_txn_status == TXN_STATUS_WAIT) {
@@ -254,7 +257,7 @@ restart:
 				process_async(data + 1, (r / 4) - 1);
 				pthread_mutex_lock(&swd_lock);
 			} else {
-				fprintf(stderr, "\r\nusb: rx: unexpected txn %08x (%d)\r\n",
+				xprintf(XSWD, "usb: rx: unexpected txn %08x (%d)\n",
 					data[0], r);
 			}
 		}
@@ -655,9 +658,11 @@ int swdp_reset(void) {
 	t.tx[t.txc++] = RSWD_MSG(CMD_ATTACH, 0, 0);
 	t.tx[t.txc++] = SWD_RD(DP_IDCODE, 1);
 	t.rx[t.rxc++] = &idcode;
-	q_exec(&t);
-
-	fprintf(stderr,"IDCODE: %08x\n", idcode);
+	if (q_exec(&t)) {
+		xprintf(XSWD, "attach: IDCODE: ????????\n");
+	} else {
+		xprintf(XSWD, "attach: IDCODE: %08x\n", idcode);
+	}
 
 	swd_error = 0;
 	q_init(&t);
@@ -678,7 +683,7 @@ int swdp_reset(void) {
 	if (q_exec(&t))
 		return -1;
 
-	fprintf(stderr,"DPCTRL: %08x\n", n);
+	xprintf(XSWD, "attach: DPCTRL: %08x\n", n);
 	return 0;
 }