commit ff46e3d61e09c2e5f8363b7e9a32263f66d5d335
parent 03aad6688981becb1fcdf492f96df0ee9a70b52b
Author: Brian Swetland <swetland@frotz.net>
Date:   Wed,  5 Aug 2015 14:28:02 -0700
debugger: decode SWO trace packets, handle console output
Diffstat:
| M | tools/swo.c |  |  | 174 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- | 
1 file changed, 167 insertions(+), 7 deletions(-)
diff --git a/tools/swo.c b/tools/swo.c
@@ -24,15 +24,175 @@
 #include <fw/types.h>
 #include <debugger.h>
 
+#define TRACE 0
+
+static char console_data[256];
+static int console_ptr = 0;
+
+static void handle_swv_src(unsigned id, unsigned val, unsigned n) {
+#if TRACE
+	xprintf(XDATA, "SRC %s %02x %08x\n", (id & 0x100) ? "HW" : "SW", id & 0xFF, val);
+#endif
+	if (id == 0) {
+		console_data[console_ptr++] = val;
+		if (val == '\n') {
+			console_data[console_ptr] = 0;
+			xprintf(XDATA, "[remote] %s", console_data);
+			console_ptr = 0;
+		} else if (console_ptr == 254) {
+			console_data[console_ptr] = 0;
+			xprintf(XDATA, "[remote] %s\n", console_data);
+		}
+	}
+}
+
+static void handle_swv_proto(unsigned char *data, unsigned len) {
+#if TRACE
+	switch (len) {
+	case 1:
+		xprintf(XDATA, "PRO %02x\n", data[0]);
+		break;
+	case 2:
+		xprintf(XDATA, "PRO %02x %02x\n", data[0], data[1]);
+		break;
+	case 3:
+		xprintf(XDATA, "PRO %02x %02x %02x\n",
+			data[0], data[1], data[2]);
+		break;
+	case 4:
+		xprintf(XDATA, "PRO %02x %02x %02x %02x\n",
+			data[0], data[1], data[2], data[3]);
+		break;
+	case 5:
+		xprintf(XDATA, "PRO %02x %02x %02x %02x %02x\n",
+			data[0], data[1], data[2], data[3], data[4]);;
+		break;
+	case 6:
+		xprintf(XDATA, "PRO %02x %02x %02x %02x %02x %02x\n",
+			data[0], data[1], data[2], data[3],
+			data[4], data[5]);
+		break;
+	case 7:
+		xprintf(XDATA, "PRO %02x %02x %02x %02x %02x %02x %02x\n",
+			data[0], data[1], data[2], data[3],
+			data[4], data[5], data[6]);
+		break;
+	}
+#endif
+}
+
+typedef enum {
+	SWV_SYNC,
+	SWV_1X1,
+	SWV_1X2,
+	SWV_1X4,
+	SWV_2X2,
+	SWV_2X4,
+	SWV_3X4,
+	SWV_4X4,
+	SWV_PROTO,
+	SWV_IDLE,
+} swv_state_t;
+
+typedef struct {
+	swv_state_t state;
+	unsigned zcount;
+	unsigned ccount;
+	unsigned id;
+	unsigned val;
+	unsigned char data[8];
+} swv_t;
+
+static swv_t swv = {
+	.state = SWV_SYNC,
+	.zcount = 0
+};
+
+static void handle_swv(swv_t *swv, unsigned x) {
+	// any sequence ending in 00 00 00 00 00 80 is a re-sync
+	if (x == 0) {
+		swv->zcount++;
+	} else {
+		if ((swv->zcount >= 5) && (x == 0x80)) {
+			swv->state = SWV_IDLE;
+			swv->zcount = 0;
+#if TRACE
+			xprintf(XDATA, "SYNC\n");
+#endif
+			return;
+		}
+		swv->zcount = 0;
+	}
+
+	switch (swv->state) {
+	case SWV_IDLE:
+		if (x & 7) {
+			// AAAAAHSS source packet
+			swv->id = (x >> 3) | ((x & 4) << 6);
+			swv->val = 0;
+			swv->state = (x & 3);
+		} else if (x != 0) {
+			// CXXXXX00 protocol packet
+			swv->data[0] = x;
+			if (x & 0x80) {
+				swv->ccount = 1;
+				swv->state = SWV_PROTO;
+			} else {
+				handle_swv_proto(swv->data, 1);
+			}
+		} else {
+			// 00 packets are for sync, ignore
+		}
+		break;
+	case SWV_PROTO:
+		swv->data[swv->ccount++] = x;
+		// protocol packets end at 7 total bytes or a byte with bit7 clear
+		if ((swv->ccount == 7) || (!(x & 0x80))) {
+			handle_swv_proto(swv->data, swv->ccount);
+			swv->state = SWV_IDLE;
+		}
+		break;
+	case SWV_1X1:
+		handle_swv_src(swv->id, x, 1);
+		swv->state = SWV_IDLE;
+		break;
+	case SWV_1X2:
+		swv->val = x;
+		swv->state = SWV_2X2;
+		break;
+	case SWV_2X2:
+		handle_swv_src(swv->id, swv->val | (x << 8), 2);
+		swv->state = SWV_IDLE;
+		break;
+	case SWV_1X4:
+		swv->val = x;
+		swv->state = SWV_2X4;
+		break;
+	case SWV_2X4:
+		swv->val |= (x << 8);
+		swv->state = SWV_3X4;
+		break;
+	case SWV_3X4:
+		swv->val |= (x << 16);
+		swv->state = SWV_4X4;
+		break;
+	case SWV_4X4:
+		handle_swv_src(swv->id, swv->val | (x << 24), 4);
+		swv->state = SWV_IDLE;
+		break;
+	case SWV_SYNC:
+		break;
+	default:
+		// impossible
+		xprintf(XDATA, "fatal error, bad state %d\n", swv->state);
+		exit(1);
+	}
+}
+
 void process_swo_data(void *_data, unsigned count) {
 	unsigned char *data = _data;
-	char buf[8192];
-	char *p = buf;
-	while (count-- > 0) {
-		p += sprintf(p, "%02x ", *data++);
+	while(count-- > 0) {
+		handle_swv(&swv, *data++);
 	}
-	*p++ = '\n';
-	*p++ = 0;
-	xprintf(XDATA, buf);
 }