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