jtagonizer

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

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:
MMakefile | 12++++++------
Av7debug-registers.h | 116+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mv7debug.c | 61++-----------------------------------------------------------
Mv7debug.h | 129+++++++++++++++++--------------------------------------------------------------
Azynq.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; +} +