commit a40174ffcba9b1331b3e8857c4b4b3fc781e0aac
parent 95db60c95beaaf3ffd3600804df5941e3be83b2d
Author: Brian Swetland <swetland@frotz.net>
Date: Tue, 7 Mar 2023 14:10:43 -0800
more core debugger features
- show commands in log
- ignore blank commandlines
- treat ESC as an interrupt key
- provide dc_core_step() and dc_core_wait_halt()
- add step, rd, and wr commands
- display registers on successfult halt or step
Diffstat:
6 files changed, 125 insertions(+), 8 deletions(-)
diff --git a/src/commands.c b/src/commands.c
@@ -22,7 +22,7 @@ static uint32_t reglist[20] = {
};
static uint32_t lastregs[20];
-int do_regs(DC* dc, CC* cc) {
+static int read_show_regs(DC* dc) {
if (dc_core_reg_rd_list(dc, reglist, lastregs, 20)) {
return DBG_ERR;
}
@@ -44,6 +44,10 @@ int do_regs(DC* dc, CC* cc) {
return 0;
}
+int do_regs(DC* dc, CC* cc) {
+ return read_show_regs(dc);
+}
+
static uint32_t lastaddr = 0x20000000;
static uint32_t lastcount = 0x40;
@@ -90,15 +94,59 @@ int do_dw(DC* dc, CC* cc) {
return 0;
}
+int do_rd(DC* dc, CC* cc) {
+ uint32_t addr, val;
+ if (cmd_arg_u32(cc, 1, &addr)) return DBG_ERR;
+ int r = dc_mem_rd32(dc, addr, &val);
+ if (r < 0) {
+ INFO("%08x: ????????\n", addr);
+ } else {
+ INFO("%08x: %08x\n", addr, val);
+ }
+ return r;
+}
+
+int do_wr(DC* dc, CC* cc) {
+ uint32_t addr, val;
+ if (cmd_arg_u32(cc, 1, &addr)) return DBG_ERR;
+ if (cmd_arg_u32(cc, 2, &val)) return DBG_ERR;
+ int r;
+ if ((r = dc_mem_wr32(dc, addr, val)) == 0) {
+ INFO("%08x< %08x\n", addr, val);
+ }
+ return r;
+}
int do_stop(DC* dc, CC* cc) {
- return dc_core_halt(dc);
+ int r;
+ if ((r = dc_core_halt(dc)) < 0) {
+ return r;
+ }
+ if ((r = dc_core_wait_halt(dc)) < 0) {
+ return r;
+ }
+ return read_show_regs(dc);
}
int do_resume(DC* dc, CC* cc) {
return dc_core_resume(dc);
}
+int do_step(DC* dc, CC* cc) {
+ int r;
+ if ((r = dc_core_step(dc)) < 0) {
+ return r;
+ }
+ if ((r = dc_core_wait_halt(dc)) < 0) {
+ return r;
+ }
+ return read_show_regs(dc);
+}
+
+int do_reset(DC* dc, CC* cc) {
+ return -1; //return dc_core_reset(dc);
+}
+
int do_exit(DC* dc, CC* cc) {
debugger_exit();
return 0;
@@ -114,12 +162,17 @@ struct {
{ "attach", do_attach, "connect to target" },
{ "stop", do_stop, "halt core" },
{ "halt", do_stop, NULL },
- { "resume", do_resume, "resume core" },
{ "go", do_resume, NULL },
- { "dw", do_dw, "dw <addr> [ <count> ] - dump words" },
- //{ "db", do_db, "db <addr> [ <count> ] - dump bytes" },
+ { "resume", do_resume, "resume core" },
+ { "step", do_step, "single-step core" },
+ { "reset", do_reset, "reset core" },
+ { "dw", do_dw, "dump words dw <addr> [ <count> ]" },
+ //{ "db", do_db, "dump bytes db <addr> [ <count> ]" },
+ { "rd", do_rd, "read word rd <addr>" },
+ { "dr", do_rd, NULL },
+ { "wr", do_wr, "write word wr <addr> <val>" },
{ "regs", do_regs, "dump registers" },
- { "help", do_help, "list debugger commands" },
+ { "help", do_help, "list commands" },
{ "exit", do_exit, "exit debugger" },
{ "quit", do_exit, NULL },
};
diff --git a/src/transport-arm-debug.c b/src/transport-arm-debug.c
@@ -206,7 +206,44 @@ int dc_core_resume(DC* dc){
}
int dc_core_step(DC* dc) {
- return DC_ERR_FAILED;
+ uint32_t val;
+ int r;
+ if ((r = dc_mem_rd32(dc, DHCSR, &val)) < 0) {
+ return r;
+ }
+ val &= (DHCSR_C_DEBUGEN | DHCSR_C_HALT | DHCSR_C_MASKINTS);
+ val |= DHCSR_DBGKEY;
+
+ if (!(val & DHCSR_C_HALT)) {
+ val |= DHCSR_C_HALT | DHCSR_C_DEBUGEN;
+ if ((r = dc_mem_wr32(dc, DHCSR, val)) < 0) {
+ return r;
+ }
+ } else {
+ val = (val & (~DHCSR_C_HALT)) | DHCSR_C_STEP;
+ if ((r = dc_mem_wr32(dc, DHCSR, val)) < 0) {
+ return r;
+ }
+ }
+ return 0;
+}
+
+int dc_core_wait_halt(DC* dc) {
+ uint32_t last = dc_get_attn_value(dc);
+ uint32_t val;
+ int r;
+ for (;;) {
+ if ((r = dc_mem_rd32(dc, DHCSR, &val)) < 0) {
+ return r;
+ }
+ if (val & DHCSR_S_HALT) {
+ return 0;
+ }
+ if (last != dc_get_attn_value(dc)) {
+ return DC_ERR_INTERRUPTED;
+ }
+ }
+ return 0;
}
static void dc_q_core_reg_rd(DC* dc, unsigned id, uint32_t* val) {
diff --git a/src/transport-dap.c b/src/transport-dap.c
@@ -12,6 +12,14 @@
#include "transport.h"
#include "transport-private.h"
+void dc_interrupt(DC *dc) {
+ dc->attn++;
+}
+
+uint32_t dc_get_attn_value(DC *dc) {
+ return dc->attn;
+}
+
static void usb_failure(DC* dc, int status) {
ERROR("usb_failure status %d usb %p\n", status, dc->usb);
if (dc->usb != NULL) {
diff --git a/src/transport-private.h b/src/transport-private.h
@@ -13,6 +13,8 @@ struct debug_context {
usb_handle* usb;
unsigned status;
+ volatile uint32_t attn;
+
// dap protocol info
uint32_t max_packet_count;
uint32_t max_packet_size;
@@ -68,4 +70,5 @@ static void dump(const char* str, const void* ptr, unsigned len) {
#define dump(...) do {} while (0)
#endif
+uint32_t dc_get_attn_value(DC* dc);
diff --git a/src/transport.h b/src/transport.h
@@ -12,6 +12,8 @@ void dc_require_serialno(const char* sn);
typedef struct debug_context dctx_t;
int dc_periodic(dctx_t* dc);
+void dc_interrupt(dctx_t* dc);
+
#define DC_OK 0
#define DC_ERR_FAILED -1 // generic internal failure
#define DC_ERR_BAD_PARAMS -2 // Invalid parameters
@@ -27,6 +29,8 @@ int dc_periodic(dctx_t* dc);
#define DC_ERR_UNSUPPORTED -12 // unsupported operation
#define DC_ERR_REMOTE -13 // failure from debug probe
#define DC_ERR_DETACHED -14 // transport not connected to target
+#define DC_ERR_BAD_STATE -15
+#define DC_ERR_INTERRUPTED -16
int dc_set_clock(dctx_t* dc, uint32_t hz);
@@ -85,6 +89,7 @@ int dc_mem_wr_words(dctx_t* dc, uint32_t addr, uint32_t num, const uint32_t* ptr
int dc_core_halt(dctx_t* dc);
int dc_core_resume(dctx_t* dc);
int dc_core_step(dctx_t* dc);
+int dc_core_wait_halt(dctx_t* dc);
int dc_core_reg_rd(dctx_t* dc, unsigned id, uint32_t* val);
int dc_core_reg_wr(dctx_t* dc, unsigned id, uint32_t val);
diff --git a/src/xdebug.c b/src/xdebug.c
@@ -116,6 +116,8 @@ int parse(TOKEN* tok) {
void debug_command(char *line) {
CC cc;
+ INFO("> %s\n", line);
+
while (*line && (*line <= ' ')) line++;
if (*line == '/') {
cc.count = 2;
@@ -205,9 +207,18 @@ static void *work_thread(void* arg) {
}
void handle_line(char *line, unsigned len) {
+ if (!strcmp(line, "@ESC@")) {
+ dc_interrupt(dc);
+ return;
+ }
+ if (len == 0) {
+ return;
+ }
if (busy) {
INFO("busy\n");
- } else if (len < (sizeof(linebuf)-1)) {
+ return;
+ }
+ if (len < (sizeof(linebuf)-1)) {
memcpy(linebuf, line, len + 1);
busy = 1;
uint64_t n = 1;