commit 3491cb2bfc76504d2fe3c6ee2cb30528d4589c92
parent ae7e5259441321338769bacf0895af7fd604c474
Author: Brian Swetland <swetland@frotz.net>
Date: Sun, 21 Jun 2015 02:29:19 -0700
debugger: attempt to auto-recover from swd errors
Diffstat:
3 files changed, 45 insertions(+), 4 deletions(-)
diff --git a/tools/debugger-core.c b/tools/debugger-core.c
@@ -67,6 +67,7 @@ static void m_event(const char *evt) {
static void monitor(void) {
u32 v;
+ if (swdp_clear_error()) return;
if (swdp_ahb_read(DFSR, &v) == 0) {
if (v & DFSR_MASK) {
swdp_ahb_write(DFSR, DFSR_MASK);
@@ -84,6 +85,10 @@ static pthread_t _dbg_thread;
void debugger_lock() {
pthread_mutex_lock(&_dbg_lock);
+ if (swdp_clear_error()) {
+ xprintf("SWD ERROR persists. Attempting link reset.\n");
+ swdp_reset();
+ }
}
void debugger_unlock() {
@@ -105,9 +110,13 @@ void debugger_init() {
#else
-void debugger_lock() { }
-void debugger_unlock() { }
-void debugger_init() { }
+void debugger_lock() {
+ swdp_clear_error();
+}
+void debugger_unlock() {
+}
+void debugger_init() {
+}
#endif
diff --git a/tools/rswdp.c b/tools/rswdp.c
@@ -37,6 +37,8 @@ static u16 sequence = 1;
static usb_handle *usb;
+static int swd_error = 0;
+
#define MAXWORDS 512
struct txn {
@@ -110,7 +112,15 @@ static int process_reply(struct txn *t, u32 *data, int count) {
}
continue;
case CMD_STATUS:
- return op ? -op : 0;
+ if (op) {
+ if (swd_error == 0) {
+ swd_error = -op;
+ fprintf(stderr, "SWD ERROR\n");
+ }
+ return -op;
+ } else {
+ return 0;
+ }
default:
fprintf(stderr,"unknown command 0x%02x\n", RSWD_MSG_CMD(msg));
return -1;
@@ -505,6 +515,7 @@ int swdp_reset(void) {
struct txn t;
u32 n, idcode;
+ swd_error = 0;
q_init(&t);
t.tx[t.txc++] = RSWD_MSG(CMD_ATTACH, 0, 0);
t.tx[t.txc++] = SWD_RD(DP_IDCODE, 1);
@@ -513,6 +524,7 @@ int swdp_reset(void) {
fprintf(stderr,"IDCODE: %08x\n", idcode);
+ swd_error = 0;
q_init(&t);
/* clear any stale errors */
t.tx[t.txc++] = SWD_WR(DP_ABORT, 1);
@@ -535,6 +547,22 @@ int swdp_reset(void) {
return 0;
}
+int swdp_clear_error(void) {
+ if (swd_error == 0) {
+ return 0;
+ } else {
+ struct txn t;
+ swd_error = 0;
+
+ q_init(&t);
+ t.tx[t.txc++] = SWD_WR(DP_ABORT, 1);
+ t.tx[t.txc++] = 0x1E;
+ q_exec(&t);
+
+ return swd_error;
+ }
+}
+
void swdp_enable_tracing(int yes) {
struct txn t;
q_init(&t);
diff --git a/tools/rswdp.h b/tools/rswdp.h
@@ -46,6 +46,10 @@ int swdp_watchpoint_rd(unsigned n, u32 addr);
int swdp_watchpoint_wr(unsigned n, u32 addr);
int swdp_watchpoint_rw(unsigned n, u32 addr);
+/* attempt to clear any error state from previous transactions */
+/* return 0 if successful (or no error state existed) */
+int swdp_clear_error(void);
+
int swdp_reset(void);
int swdp_open(void);