commit a68ce9fc2fcc10bd6aeb54afcfd9c814e5a40492
parent 26d914ab21da0c28445869bacc928dcd948bd90a
Author: Brian Swetland <swetland@frotz.net>
Date: Sun, 28 Sep 2014 23:11:33 -0700
v7debug: start poking at the debug interface
Diffstat:
M | Makefile | | | 9 | +++++++-- |
A | v7debug.c | | | 146 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | v7debug.h | | | 6 | ++++-- |
3 files changed, 157 insertions(+), 4 deletions(-)
diff --git a/Makefile b/Makefile
@@ -4,7 +4,7 @@ CFLAGS := -Wall -O0 -g
LIBS := -lusb-1.0 -lrt
-all: jtag dap-test
+all: jtag dap-test debug
JTAG_OBJS := jtag-mpsse-driver.o jtag-core.o jtag.o
$(JTAG_OBJS): jtag.h jtag-driver.h
@@ -16,5 +16,10 @@ $(DAP_OBJS): jtag.h jtag-driver.h dap.h dap-registers.h
dap-test: $(DAP_OBJS)
$(CC) -o dap-test $(DAP_OBJS) $(LIBS)
+DEBUG_OBJS := v7debug.o dap.o jtag-core.o jtag-mpsse-driver.o
+$(DEBUG_OBJS): jtag.h jtag-driver.h dap.h dap-registers.h v7debug.h
+debug: $(DEBUG_OBJS)
+ $(CC) -o debug $(DEBUG_OBJS) $(LIBS)
+
clean:
- rm -f *.o jtag dap-test
+ rm -f *.o jtag dap-test debug
diff --git a/v7debug.c b/v7debug.c
@@ -0,0 +1,146 @@
+// Copyright 2014 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
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "jtag.h"
+#include "dap.h"
+#include "v7debug.h"
+
+typedef struct V7DEBUG V7DEBUG;
+
+struct V7DEBUG {
+ DAP *dap;
+ u32 apnum;
+ u32 base;
+};
+
+static inline int dwr(V7DEBUG *debug, u32 off, u32 val) {
+ return dap_mem_wr32(debug->dap, debug->apnum, debug->base + off, val);
+}
+
+static inline int drd(V7DEBUG *debug, u32 off, u32 *val) {
+ return dap_mem_rd32(debug->dap, debug->apnum, debug->base + off, val);
+}
+
+V7DEBUG *debug_init(DAP *dap, u32 apnum, u32 base) {
+ V7DEBUG *debug = malloc(sizeof(V7DEBUG));
+ if (debug == NULL) {
+ return NULL;
+ }
+ memset(debug, 0, sizeof(V7DEBUG));
+ debug->dap = dap;
+ debug->apnum = apnum;
+ debug->base = base;
+ return debug;
+}
+
+
+#define P(n) do { u32 x; if (!drd(debug, n, &x)) printf("%s: %08x\n", #n, x); } while(0)
+
+int dccrd(V7DEBUG *debug, u32 *val) {
+ u32 x;
+ int n;
+ for (n = 0; n < 10; n++) {
+ if (drd(debug, DBGDSCR, &x)) return -1;
+ if (x & DSCR_TXFULL) {
+ return drd(debug, DBGDTRTX, val);
+ }
+ }
+ fprintf(stderr, "v7debug: dcc read timed out\n");
+ return -1;
+}
+
+int dexec(V7DEBUG *debug, u32 instr) {
+ u32 x;
+ int n;
+ dwr(debug, DBGITR, instr);
+ for (n = 0; n < 10; n++) {
+ if (drd(debug, DBGDSCR, &x)) return -1;
+ if (x & DSCR_INSTRCOMPL) return 0;
+ }
+ fprintf(stderr, "v7debug: instruction timed out\n");
+ return -1;
+}
+
+#define ARM_DSB 0xE57FF040
+#define ARM_MOV_DCC_Rx(x) (0xEE000E15 | ((x) << 12)) // Rx -> DCC
+#define ARM_MOV_Rx_DCC(x) (0xEE100E15 | ((x) << 12)) // DCC -> Rx
+#define ARM_MOV_R0_PC 0xE1A0000F
+#define ARM_MOV_CPSR_R0 0xE12FF000 // R0 -> CPSR
+#define ARM_MOV_R0_CPSR 0xE10F0000 // CPSR -> R0
+
+int debug_attach(V7DEBUG *debug) {
+ u32 x;
+ u32 r[16];
+ u32 cpsr;
+ int n;
+
+ if (dap_attach(debug->dap)) return -1;
+ P(DBGDIDR);
+ P(DBGDEVID);
+ P(DBGDEVTYPE);
+ P(DBGLSR);
+ P(DBGDSCCR);
+ P(DBGDSCR);
+
+ dwr(debug, DBGDRCR, DRCR_HALT_REQ);
+ for (n = 0; n < 100; n++) {
+ if (drd(debug, DBGDSCR, &x)) return -1;
+ if (x & DSCR_HALTED) goto halted;
+ }
+ fprintf(stderr, "v7debug: halt timed out\n");
+
+halted:
+ dwr(debug, DBGDSCR, DSCR_ITR_EN);
+
+ dexec(debug, ARM_DSB); // dsb
+ for (n = 0; n < 15; n++) {
+ dexec(debug, ARM_MOV_DCC_Rx(n));
+ dccrd(debug, r + n);
+ }
+ dexec(debug, ARM_MOV_R0_PC);
+ dexec(debug, ARM_MOV_DCC_Rx(0));
+ dccrd(debug, r + 15);
+ dexec(debug, ARM_MOV_R0_CPSR);
+ dexec(debug, ARM_MOV_DCC_Rx(0));
+ dccrd(debug, &cpsr);
+ for (n = 0; n < 16; n++) {
+ fprintf(stderr,"R%d %08x ", n, r[n]);
+ }
+ fprintf(stderr, "CPSR %08x\n", cpsr);
+ return 0;
+}
+
+#define ZYNQ_DEBUG0_APN 1
+#define ZYNQ_DEBUG0_BASE 0x80090000
+#define ZYNQ_DEBUG1_APN 1
+#define ZYNQ_DEBUG1_BASE 0x80092000
+
+int main(int argc, char **argv) {
+ JTAG *jtag;
+ DAP *dap;
+ V7DEBUG *debug;
+
+ if (jtag_mpsse_open(&jtag)) return -1;
+ if ((dap = dap_init(jtag, 0x4ba00477)) == NULL) return -1;
+ if ((debug = debug_init(dap, ZYNQ_DEBUG0_APN, ZYNQ_DEBUG0_BASE)) == NULL) return -1;
+ if (debug_attach(debug)) return -1;
+
+ fprintf(stderr, "whee!\n");
+ return 0;
+}
+
diff --git a/v7debug.h b/v7debug.h
@@ -34,14 +34,16 @@
#define DBGPID0 0xFD0
#define DBGCID0 0xFF0
-#define DSCR_RXFULL (1 << 31) // (cleared on read)
-#define DSCR_TXFULL (1 << 30) // (cleared on read)
+#define DSCR_RXFULL (1 << 30) // (cleared on read)
+#define DSCR_TXFULL (1 << 29) // (cleared on read)
#define DSCR_PIPEADV (1 << 25) // (cleared on DRCR write) set on instr exec
#define DSCR_INSTRCOMPL (1 << 24) // 0 if cpu executing from ITR
#define DSCR_DCC_MASK (3 << 20) // DTR access mode
#define DSCR_DCC_NBLOCK (0 << 20)
#define DSCR_DCC_STALL (1 << 20)
#define DSCR_DCC_FAST (2 << 20)
+#define DSCR_ADADISCARD (1 << 19) // ro: processor ignores asynch aborts
+ // set in debug state, DSCR_ADABORT instead
#define DSCR_M_DBG_EN (1 << 15) // monitor debug enabled
#define DSCR_H_DBG_EN (1 << 14) // halting debug enabled
#define DSCR_ITR_EN (1 << 13) // instruction execution enabled