commit 940b6d1fa9e0f9483d2f05447a699e98d5903282
parent a5b074a2eb88297b3f60c041062f9c7a5df0c501
Author: Brian Swetland <swetland@frotz.net>
Date: Tue, 30 Sep 2014 19:00:46 -0700
zynq: tool to reset/dumpregs/download-and-run for zynq
some essential functionality that can be provided with the current
state of the library
Diffstat:
M | Makefile | | | 12 | ++++++------ |
A | v7debug-registers.h | | | 116 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | v7debug.c | | | 61 | ++----------------------------------------------------------- |
M | v7debug.h | | | 129 | +++++++++++++++++-------------------------------------------------------------- |
A | zynq.c | | | 110 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
5 files changed, 261 insertions(+), 167 deletions(-)
diff --git a/Makefile b/Makefile
@@ -4,7 +4,7 @@ CFLAGS := -Wall -O0 -g
LIBS := -lusb-1.0 -lrt
-all: jtag dap-test debug
+all: jtag dap-test zynq
JTAG_OBJS := jtag-mpsse-driver.o jtag-core.o jtag.o
$(JTAG_OBJS): jtag.h jtag-driver.h
@@ -16,10 +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)
+ZYNQ_OBJS := zynq.o v7debug.o dap.o jtag-core.o jtag-mpsse-driver.o
+$(ZYNQ_OBJS): jtag.h jtag-driver.h dap.h dap-registers.h v7debug.h v7debug-registers.h
+zynq: $(ZYNQ_OBJS)
+ $(CC) -o zynq $(ZYNQ_OBJS) $(LIBS)
clean:
- rm -f *.o jtag dap-test debug
+ rm -f *.o jtag dap-test zynq
diff --git a/v7debug-registers.h b/v7debug-registers.h
@@ -0,0 +1,116 @@
+
+#ifndef _V7DEBUG_REGISTERS_H_
+#define _V7DEBUG_REGISTERS_H_
+
+// ARM Debug Interface
+
+// See: Cortex R5 r1p2 TRM
+// http://infocenter.arm.com/help/topic/com.arm.doc.ddi0460d/DDI0460D_cortex_r5_r1p2_trm.pdf
+
+#define DBGDIDR 0x000 // Debug ID Register
+#define DBGWFAR 0x018 // Watchpoint Fault Address Register
+#define DBGVCR 0x01C // Vector Catch Register
+#define DBGECR 0x024 // ?
+#define DBGDSCCR 0x028 // Debug State Cache Control Register
+#define DBGDSMCR 0x02C // ?
+#define DBGDTRRX 0x080 // Data Transfer Register (host->target)
+#define DBGITR 0x084 // Instruction Transfer Register
+#define DBGDSCR 0x088 // Debug Status and Control Register
+#define DBGDTRTX 0x08C // Data Transfer Register (target->host)
+#define DBGDRCR 0x090 // Debug Run Control Register
+#define DBGPCSR 0x0A0 // ?
+#define DBGCIDSR 0x0A4 // ?
+#define DBGBVR 0x100 // Breakpoint Value Registers
+#define DBGBCR 0x140 // Breakpoint Control Registers
+#define DBGWVR 0x180 // Watchpoint Value Registers
+#define DBGWCR 0x1C0 // Watchpoint Control Registers
+#define DBGOSLAR 0x300 // ?
+#define DBGOSLSR 0x304 // Operating System Lock Status Register
+#define DBGOSSRR 0x308 // ?
+#define DBGPRCR 0x310 // Device Power-Down and Reset Control Register
+#define DBGPRSR 0x314 // Device Power-Down and Reset Status Register
+#define DBGLAR 0xFB0 // Lock Access Register
+#define DBGLSR 0xFB4 // Lock Status Register
+#define DBGAUTHSTATUS 0xDB8 // Authentication Status Register
+#define DBGDEVID 0xFC8 // Device ID
+#define DBGDEVTYPE 0xFCC // Device Type
+#define DBGPID0 0xFD0
+#define DBGCID0 0xFF0
+
+#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
+#define DSCR_UDCC_DIS (1 << 12) // CP14 user debug disable
+#define DSCR_INT_DIS (1 << 11) // interrupts disable
+#define DSCR_DBG_ACK (1 << 10) // force DBGACKm signal HIGH
+#define DSCR_UND (1 << 8) // sticky undefined bit (wtc)
+#define DSCR_ADABORT (1 << 7) // sticky asynch data abort bit (wtc)
+#define DSCR_SDABORT (1 << 6) // sticky synch data abort bit (wtc)
+#define DSCR_M_MASK (15 << 2) // method-of-entry mask
+#define DSCR_M_HALT (0 << 2) // halt from DRCR[0]
+#define DSCR_M_BKPT (1 << 2) // breakpoint
+#define DSCR_M_EDBGRQ (4 << 2)
+#define DSCR_M_BKPT_INS (3 << 2) // breakpoint instruction
+#define DSCR_M_WATCHPT (10 << 2) // synchronous watchpoint
+#define DSCR_RESTARTED (1 << 1) // 1 = not in debug state
+#define DSCR_HALTED (1 << 0) // 1 = in debug state
+
+#define VCR_FIQ (1 << 7)
+#define VCR_IRQ (1 << 6)
+#define VCR_DABORT (1 << 4)
+#define VCR_PABORT (1 << 3)
+#define VCR_SVC (1 << 2)
+#define VCR_UND (1 << 1)
+#define VCR_RESET (1 << 0)
+
+#define DSCCR_WT_EN (1 << 2) // 0 = force write through in debug state
+#define DSCCR_IL_EN (1 << 1) // 0 = L1 icache line-fills disabled in debug
+#define DSCCR_DL_EN (1 << 0) // 0 = L1 dcache line-fills disabled in debug
+
+#define DRCR_CANCEL (1 << 4) // cancel memory request
+ // processor will abandon inflight mem reqs
+#define DRCR_PIPEADV (1 << 3) // clear DSCR_PIPEADV
+#define DRCR_CLR_EXC (1 << 2) // clear sticky exceptions
+#define DRCR_START_REQ (1 << 1) // request processor restart
+#define DRCR_HALT_REQ (1 << 0) // request processor halt
+
+#define PRSR_S_RESET (1 << 3) // sticky reset status
+#define PRSR_RESET (1 << 2) // reset status
+#define PRSR_S_PDOWN (1 << 1) // sticky power-down status
+#define PRSR_PDOWN (1 << 0) // power-down status
+
+#define LAR_KEY 0xC5ACCE55 // write to LAR to enable debug regs
+
+#define LSR_32BIT (1 << 2)
+#define LSR_LOCKED (1 << 1)
+#define LSR_LOCK_IMPL (1 << 0)
+
+#define CID_ROM_TABLE 0xB105100D
+#define CID_CORESIGHT 0xB105900D
+
+// See: A9 TRM
+#define PID0_DEBUG 0x000BBC09
+
+// See: Zynq TRM
+#define PID0_CTI 0x002BB906
+#define PID0_PTM 0x001BB950
+#define PID0_ETB 0x003BB907
+#define PID0_FTM 0x000C9001
+#define PID0_FUNNEL 0x001BB908
+#define PID0_ITM 0x002BB913
+#define PID0_TPIU 0x004BB912
+// 0x000BB4A9
+// 0x000BB9A0
+// 0x021893B2
+
+#endif
diff --git a/v7debug.c b/v7debug.c
@@ -16,13 +16,12 @@
#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-
#include "jtag.h"
#include "dap.h"
#include "v7debug.h"
+#include "v7debug-registers.h"
+
// CPSR bits
#define ARM_N (1 << 31)
#define ARM_Z (1 << 30)
@@ -45,8 +44,6 @@
#define ARM_M_UND 0x1B
#define ARM_M_SYS 0x1F
-typedef struct V7DEBUG V7DEBUG;
-
#define STATE_IDLE 0
#define STATE_HALTED 1
#define STATE_RUNNING 2
@@ -178,10 +175,6 @@ int debug_attach(V7DEBUG *debug) {
return -1;
}
- if (dap_attach(debug->dap)) {
- return -1;
- }
-
drd(debug, DBGDSCR, &x);
if (x & DSCR_HALTED) {
fprintf(stderr, "debug: warning, processor already halted\n");
@@ -273,53 +266,3 @@ int debug_reg_dump(V7DEBUG *debug) {
printf("cpsr: %08x\n", r[16]);
return 0;
}
-
-#define ZYNQ_DEBUG0_APN 1
-#define ZYNQ_DEBUG0_BASE 0x80090000
-#define ZYNQ_DEBUG1_APN 1
-#define ZYNQ_DEBUG1_BASE 0x80092000
-
-void *loadfile(const char *fn, u32 *sz) {
- int fd;
- off_t end;
- void *data = NULL;
- if ((fd = open(fn, O_RDONLY)) < 0) return NULL;
- if ((end = lseek(fd, 0, SEEK_END)) < 0) goto oops;
- if (lseek(fd, 0, SEEK_SET) < 0) goto oops;
- if ((data = malloc(end + 4)) == NULL) goto oops;
- if (read(fd, data, end) != end) goto oops;
- close(fd);
- *sz = end;
- return data;
-
-oops:
- free(data);
- close(fd);
- return NULL;
-}
-
-int main(int argc, char **argv) {
- JTAG *jtag;
- DAP *dap;
- V7DEBUG *debug;
- void *data;
- u32 sz;
-
- 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;
-
- debug_reg_dump(debug);
-
- if (argc == 2) {
- if ((data = loadfile(argv[1], &sz))) {
- dap_mem_write(dap, 0, 0, data, sz);
- debug_reg_wr(debug, 15, 0);
- }
- }
-
- debug_detach(debug);
- return 0;
-}
-
diff --git a/v7debug.h b/v7debug.h
@@ -1,111 +1,36 @@
+// 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.
-// ARM Debug Interface
+#ifndef _V7DEBUG_H_
+#define _V7DEBUG_H_
-// See: Cortex R5 r1p2 TRM
-// http://infocenter.arm.com/help/topic/com.arm.doc.ddi0460d/DDI0460D_cortex_r5_r1p2_trm.pdf
+#include "dap.h"
-#define DBGDIDR 0x000 // Debug ID Register
-#define DBGWFAR 0x018 // Watchpoint Fault Address Register
-#define DBGVCR 0x01C // Vector Catch Register
-#define DBGECR 0x024 // ?
-#define DBGDSCCR 0x028 // Debug State Cache Control Register
-#define DBGDSMCR 0x02C // ?
-#define DBGDTRRX 0x080 // Data Transfer Register (host->target)
-#define DBGITR 0x084 // Instruction Transfer Register
-#define DBGDSCR 0x088 // Debug Status and Control Register
-#define DBGDTRTX 0x08C // Data Transfer Register (target->host)
-#define DBGDRCR 0x090 // Debug Run Control Register
-#define DBGPCSR 0x0A0 // ?
-#define DBGCIDSR 0x0A4 // ?
-#define DBGBVR 0x100 // Breakpoint Value Registers
-#define DBGBCR 0x140 // Breakpoint Control Registers
-#define DBGWVR 0x180 // Watchpoint Value Registers
-#define DBGWCR 0x1C0 // Watchpoint Control Registers
-#define DBGOSLAR 0x300 // ?
-#define DBGOSLSR 0x304 // Operating System Lock Status Register
-#define DBGOSSRR 0x308 // ?
-#define DBGPRCR 0x310 // Device Power-Down and Reset Control Register
-#define DBGPRSR 0x314 // Device Power-Down and Reset Status Register
-#define DBGLAR 0xFB0 // Lock Access Register
-#define DBGLSR 0xFB4 // Lock Status Register
-#define DBGAUTHSTATUS 0xDB8 // Authentication Status Register
-#define DBGDEVID 0xFC8 // Device ID
-#define DBGDEVTYPE 0xFCC // Device Type
-#define DBGPID0 0xFD0
-#define DBGCID0 0xFF0
+typedef struct V7DEBUG V7DEBUG;
-#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
-#define DSCR_UDCC_DIS (1 << 12) // CP14 user debug disable
-#define DSCR_INT_DIS (1 << 11) // interrupts disable
-#define DSCR_DBG_ACK (1 << 10) // force DBGACKm signal HIGH
-#define DSCR_UND (1 << 8) // sticky undefined bit (wtc)
-#define DSCR_ADABORT (1 << 7) // sticky asynch data abort bit (wtc)
-#define DSCR_SDABORT (1 << 6) // sticky synch data abort bit (wtc)
-#define DSCR_M_MASK (15 << 2) // method-of-entry mask
-#define DSCR_M_HALT (0 << 2) // halt from DRCR[0]
-#define DSCR_M_BKPT (1 << 2) // breakpoint
-#define DSCR_M_EDBGRQ (4 << 2)
-#define DSCR_M_BKPT_INS (3 << 2) // breakpoint instruction
-#define DSCR_M_WATCHPT (10 << 2) // synchronous watchpoint
-#define DSCR_RESTARTED (1 << 1) // 1 = not in debug state
-#define DSCR_HALTED (1 << 0) // 1 = in debug state
+V7DEBUG *debug_init(DAP *dap, u32 apnum, u32 base);
-#define VCR_FIQ (1 << 7)
-#define VCR_IRQ (1 << 6)
-#define VCR_DABORT (1 << 4)
-#define VCR_PABORT (1 << 3)
-#define VCR_SVC (1 << 2)
-#define VCR_UND (1 << 1)
-#define VCR_RESET (1 << 0)
+// attach and halt cpu
+int debug_attach(V7DEBUG *debug);
-#define DSCCR_WT_EN (1 << 2) // 0 = force write through in debug state
-#define DSCCR_IL_EN (1 << 1) // 0 = L1 icache line-fills disabled in debug
-#define DSCCR_DL_EN (1 << 0) // 0 = L1 dcache line-fills disabled in debug
+// detach and resume cpu
+int debug_detach(V7DEBUG *debug);
-#define DRCR_CANCEL (1 << 4) // cancel memory request
- // processor will abandon inflight mem reqs
-#define DRCR_PIPEADV (1 << 3) // clear DSCR_PIPEADV
-#define DRCR_CLR_EXC (1 << 2) // clear sticky exceptions
-#define DRCR_START_REQ (1 << 1) // request processor restart
-#define DRCR_HALT_REQ (1 << 0) // request processor halt
+// only valid while attached
+int debug_reg_rd(V7DEBUG *debug, unsigned n, u32 *val);
+int debug_reg_wr(V7DEBUG *debug, unsigned n, u32 val);
-#define PRSR_S_RESET (1 << 3) // sticky reset status
-#define PRSR_RESET (1 << 2) // reset status
-#define PRSR_S_PDOWN (1 << 1) // sticky power-down status
-#define PRSR_PDOWN (1 << 0) // power-down status
+int debug_reg_dump(V7DEBUG *debug);
-#define LAR_KEY 0xC5ACCE55 // write to LAR to enable debug regs
-
-#define LSR_32BIT (1 << 2)
-#define LSR_LOCKED (1 << 1)
-#define LSR_LOCK_IMPL (1 << 0)
-
-#define CID_ROM_TABLE 0xB105100D
-#define CID_CORESIGHT 0xB105900D
-
-// See: A9 TRM
-#define PID0_DEBUG 0x000BBC09
-
-// See: Zynq TRM
-#define PID0_CTI 0x002BB906
-#define PID0_PTM 0x001BB950
-#define PID0_ETB 0x003BB907
-#define PID0_FTM 0x000C9001
-#define PID0_FUNNEL 0x001BB908
-#define PID0_ITM 0x002BB913
-#define PID0_TPIU 0x004BB912
-// 0x000BB4A9
-// 0x000BB9A0
-// 0x021893B2
+#endif
diff --git a/zynq.c b/zynq.c
@@ -0,0 +1,110 @@
+// 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 <unistd.h>
+#include <fcntl.h>
+
+#include "v7debug.h"
+
+#define ZYNQ_DEBUG0_APN 1
+#define ZYNQ_DEBUG0_BASE 0x80090000
+#define ZYNQ_DEBUG1_APN 1
+#define ZYNQ_DEBUG1_BASE 0x80092000
+
+void *loadfile(const char *fn, u32 *sz) {
+ int fd;
+ off_t end;
+ void *data = NULL;
+ if ((fd = open(fn, O_RDONLY)) < 0) return NULL;
+ if ((end = lseek(fd, 0, SEEK_END)) < 0) goto oops;
+ if (lseek(fd, 0, SEEK_SET) < 0) goto oops;
+ if ((data = malloc(end + 4)) == NULL) goto oops;
+ if (read(fd, data, end) != end) goto oops;
+ close(fd);
+ *sz = end;
+ return data;
+
+oops:
+ free(data);
+ close(fd);
+ return NULL;
+}
+
+int usage(void) {
+ fprintf(stderr,
+"zynq run <image> download image to 0, resume cpu0 at 0\n"
+"zynq regs pause both cpus, dump registers, resume\n"
+"\n"
+ );
+ return -1;
+}
+
+int main(int argc, char **argv) {
+ JTAG *jtag;
+ DAP *dap;
+ V7DEBUG *d0;
+ V7DEBUG *d1;
+ void *data;
+ u32 sz;
+
+ if (argc < 2) {
+ return usage();
+ }
+
+ if (jtag_mpsse_open(&jtag)) return -1;
+ if ((dap = dap_init(jtag, 0x4ba00477)) == NULL) return -1;
+ if (dap_attach(dap)) return -1;
+ if ((d0 = debug_init(dap, ZYNQ_DEBUG0_APN, ZYNQ_DEBUG0_BASE)) == NULL) return -1;
+ if ((d1 = debug_init(dap, ZYNQ_DEBUG1_APN, ZYNQ_DEBUG1_BASE)) == NULL) return -1;
+
+ if (!strcmp(argv[1], "run")) {
+ if (argc != 3) {
+ return usage();
+ }
+ if ((data = loadfile(argv[2], &sz)) == NULL) {
+ fprintf(stderr, "error: could not load '%s'\n", argv[2]);
+ return -1;
+ }
+ if (sz > (192*1024)) {
+ fprintf(stderr, "error: image too large\n");
+ return -1;
+ }
+ if (debug_attach(d0)) return -1;
+ dap_mem_write(dap, 0, 0, data, sz);
+ debug_reg_wr(d0, 15, 0);
+ debug_detach(d0);
+ } else if (!strcmp(argv[1], "regs")) {
+ debug_attach(d0);
+ debug_attach(d1);
+ printf("CPU0:\n");
+ debug_reg_dump(d0);
+ printf("\nCPU1:\n");
+ debug_reg_dump(d1);
+ debug_detach(d0);
+ debug_detach(d1);
+ } else if (!strcmp(argv[1], "reset")) {
+ u32 x;
+ dap_mem_wr32(dap, 0, 0xF8000008, 0xDF0D);
+ dap_mem_wr32(dap, 0, 0xF8000200, 1);
+ } else {
+ return usage();
+ }
+
+ return 0;
+}
+