commit 17f651981597f1f537338d2f7451e9466b345ced
parent d4e864786316d20aba890b7784c9a408d1ade6f4
Author: Brian Swetland <swetland@frotz.net>
Date: Mon, 3 Aug 2015 18:47:58 -0700
debugger: support rswd protocol version 1.0
- query device protocol version, id, etc
- handle variable rx buffers up to 8kb
- for older firmware devices, assume reasonable default values
(so they keep working)
Diffstat:
2 files changed, 90 insertions(+), 16 deletions(-)
diff --git a/include/protocol/rswdp.h b/include/protocol/rswdp.h
@@ -23,14 +23,14 @@
/* Basic framing:
* - host and device exchange "transactions" consisting of
* some number of "messages".
- * - each "message" has a 32bit header and may have 0 or more
- * 32bit words of payload
+ * - each "message" has a 32bit header and may have 0 or more
+ * 32bit words of payload
* - a transaction may not exceed 4K (1024 words)
* - a transaction is sent in a series of USB BULK packets
- * - the final packet must be a short packet unless the
+ * - the final packet must be a short packet unless the
* transaction is exactly 4K in length
* - packets must be a multiple of 4 bytes
- * - the first message in a transaction must be
+ * - the first message in a transaction must be
* CMD_TXN_START or CMD_TXN_ASYNC
*/
@@ -50,7 +50,7 @@
#define CMD_SWD_READ 0x02 /* op=addr arg=count payload: data x count */
#define CMD_SWD_DISCARD 0x03 /* op=addr arg=count payload: none (discards) */
#define CMD_ATTACH 0x04 /* do swdp reset/connect handshake */
-#define CMD_RESET 0x05 /* arg=1 -> assert RESETn, otherwise deassert */
+#define CMD_RESET 0x05 /* arg=1 -> assert RESETn, otherwise deassert */
#define CMD_DOWNLOAD 0x06 /* arg=wordcount, payload: addr x 1, data x n */
#define CMD_EXECUTE 0x07 /* payload: addr x 1 */
#define CMD_TRACE 0x08 /* op=tracebits n=0 */
@@ -64,6 +64,15 @@
/* valid: target to host async */
#define CMD_DEBUG_PRINT 0x20 /* arg*4 bytes of ascii debug output */
+/* valid: bidirectional query/config messages */
+#define CMD_VERSION 0x30 /* arg=bcdversion (0x0100 etc) */
+#define CMD_BUILD_STR 0x31 /* arg=wordcount, payload = asciiz */
+#define CMD_BOARD_STR 0x32 /* arg=wordcount, payload = asciiz */
+#define CMD_RX_MAXDATA 0x33 /* arg=bytes, declares senders rx buffer size */
+#define CMD_CLOCK_KHZ 0x34 /* arg=khz, reports active clock rate */
+
+#define RSWD_VERSION 0x0100
+
/* CMD_SWD_OP operations - combine for direct AP/DP io */
#define OP_RD 0x00
#define OP_WR 0x01
@@ -84,7 +93,7 @@
/* AHB AP registers */
#define AHB_CSW 0x00
-#define AHB_TAR 0x04
+#define AHB_TAR 0x04
#define AHB_DRW 0x0C
#define AHB_BD0 0x10
#define AHB_BD1 0x14
diff --git a/tools/rswdp.c b/tools/rswdp.c
@@ -1,7 +1,7 @@
/* rswdp.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
@@ -62,14 +62,16 @@ static int swd_txn_status = 0;
// this by zeroing the usb handle and setting swd_online to 0
// at which point the swd_thread may attempt to reconnect.
+#define MAXWORDS (8192/4)
+static unsigned swd_maxwords = 512;
+static unsigned swd_version = 0x0001;
+
static int swd_error = 0;
int swdp_error(void) {
return swd_error;
}
-#define MAXWORDS 512
-
struct txn {
/* words to transmit */
u32 tx[MAXWORDS];
@@ -114,6 +116,53 @@ static void process_async(u32 *data, unsigned count) {
}
}
+static void process_query(u32 *data, unsigned count) {
+ unsigned n;
+ const char *board = "unknown";
+ const char *build = "unknown";
+ unsigned version = 0x0005;
+ unsigned maxdata = 2048;
+
+ while (count-- > 0) {
+ unsigned msg = *data++;
+ switch (RSWD_MSG_CMD(msg)) {
+ case CMD_NULL:
+ break;
+ case CMD_BUILD_STR:
+ n = RSWD_MSG_ARG(msg);
+ if (n > count) goto done;
+ build = (void*) data;
+ data += n;
+ break;
+ case CMD_BOARD_STR:
+ n = RSWD_MSG_ARG(msg);
+ if (n > count) goto done;
+ board = (void*) data;
+ data += n;
+ break;
+ case CMD_VERSION:
+ version = RSWD_MSG_ARG(msg);
+ break;
+ case CMD_RX_MAXDATA:
+ maxdata = RSWD_MSG_ARG(msg);
+ break;
+ default:
+ goto done;
+ }
+ }
+done:
+ if (maxdata > (MAXWORDS * 4)) {
+ maxdata = MAXWORDS * 4;
+ }
+ xprintf(XSWD, "usb: board id: %s\n", board);
+ xprintf(XSWD, "usb: build id: %s\n", build);
+ xprintf(XSWD, "usb: protocol: %d.%d\n", version >> 8, version & 0xff);
+ xprintf(XSWD, "usb: max data: %d byte rx buffer\n", maxdata);
+
+ swd_version = version;
+ swd_maxwords = maxdata / 4;
+}
+
static int process_reply(struct txn *t, u32 *data, int count) {
unsigned msg, op, n, rxp, rxc;
@@ -147,6 +196,9 @@ static int process_reply(struct txn *t, u32 *data, int count) {
} else {
return 0;
}
+ case CMD_CLOCK_KHZ:
+ xprintf(XSWD,"mdebug: SWD clock: %d KHz\n", n);
+ continue;
default:
xprintf(XSWD,"unknown command 0x%02x\n", RSWD_MSG_CMD(msg));
return -1;
@@ -156,7 +208,7 @@ static int process_reply(struct txn *t, u32 *data, int count) {
}
static int q_exec(struct txn *t) {
- unsigned data[1028];
+ unsigned data[MAXWORDS];
unsigned seq;
int r;
u32 id;
@@ -170,7 +222,7 @@ static int q_exec(struct txn *t) {
/* If we are a multiple of 64, and not exactly 4K,
* add padding to ensure the target can detect the end of txn
*/
- if (((t->txc % 16) == 0) && (t->txc != MAXWORDS))
+ if (((t->txc % 16) == 0) && (t->txc != swd_maxwords))
t->tx[t->txc++] = RSWD_MSG(CMD_NULL, 0, 0);
pthread_mutex_lock(&swd_lock);
@@ -215,7 +267,8 @@ static int q_exec(struct txn *t) {
}
static void *swd_reader(void *arg) {
- unsigned data[1024];
+ uint32_t data[MAXWORDS];
+ unsigned query_id;
int r;
int once = 1;
restart:
@@ -230,11 +283,19 @@ restart:
}
once = 0;
xprintf(XSWD, "usb: debugger connected\n");
+
pthread_mutex_lock(&swd_lock);
- swd_online = 1;
+
+ // send a version query to find out about the firmware
+ // old m3debug fw will just report failure
+ query_id = sequence++;
+ query_id = RSWD_TXN_START(query_id);
+ data[0] = query_id;
+ data[1] = RSWD_MSG(CMD_VERSION, 0, RSWD_VERSION);
+ usb_write(usb, data, 8);
for (;;) {
pthread_mutex_unlock(&swd_lock);
- r = usb_read_forever(usb, data, 4096);
+ r = usb_read_forever(usb, data, MAXWORDS * 4);
pthread_mutex_lock(&swd_lock);
if (r < 0) {
xprintf(XSWD, "usb: debugger disconnected\n");
@@ -247,7 +308,11 @@ restart:
xprintf(XSWD, "usb: discard packet (%d)\n", r);
continue;
}
- if (swd_txn_status == TXN_STATUS_WAIT) {
+ if (query_id && (data[0] == query_id)) {
+ query_id = 0;
+ process_query(data + 1, (r / 4) - 1);
+ swd_online = 1;
+ } else if (swd_txn_status == TXN_STATUS_WAIT) {
if (data[0] == swd_txn_id) {
swd_txn_status = r;
memcpy(swd_txn_data, data, r);
@@ -393,7 +458,7 @@ int swdp_ahb_write32(u32 addr, u32 *in, int count) {
return 0;
}
#else
-#define MAXDATAWORDS (MAXWORDS - 16)
+#define MAXDATAWORDS (swd_maxwords - 16)
/* 10 txns overhead per 128 read txns - 126KB/s on 72MHz STM32F
* 8 txns overhead per 128 write txns - 99KB/s on 72MHz STM32F
*/