m3dev

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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:
Minclude/protocol/rswdp.h | 21+++++++++++++++------
Mtools/rswdp.c | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
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 */