Remove unfinished ARM7TDMI driver.
This commit is contained in:
parent
64c79e1d03
commit
d9af3cca6c
|
@ -20,7 +20,6 @@ SRC = \
|
|||
adiv5.c \
|
||||
adiv5_jtagdp.c \
|
||||
adiv5_swdp.c \
|
||||
arm7tdmi.c \
|
||||
command.c \
|
||||
cortexm.c \
|
||||
crc32.c \
|
||||
|
|
291
src/arm7tdmi.c
291
src/arm7tdmi.c
|
@ -1,291 +0,0 @@
|
|||
/*
|
||||
* This file is part of the Black Magic Debug project.
|
||||
*
|
||||
* Copyright (C) 2011 Black Sphere Technologies Ltd.
|
||||
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* This file implements the ARM7TDMI target support using the JTAG
|
||||
* interface as described in ARM7TDMI Technical Reference Manual,
|
||||
* ARM Document DDI 0210C
|
||||
*/
|
||||
|
||||
#include "general.h"
|
||||
#include "target.h"
|
||||
#include "jtag_scan.h"
|
||||
#include "jtagtap.h"
|
||||
|
||||
/* TODO:
|
||||
* Skeleton target.
|
||||
* EmbeddedICE registers, halt/resume target.
|
||||
* Check target mode on halt, switch to ARM if needed.
|
||||
* Read registers on halt, restore on resume. Give GDB cached copy.
|
||||
* System speed access, read/write memory.
|
||||
* Misaligned/byte memory access.
|
||||
* Breakpoint support.
|
||||
* Watchpoint support.
|
||||
* Funnies: abort on breakpointed instruction, etc.
|
||||
* Flash programming for STR73x and LPC2xxx.
|
||||
*/
|
||||
static const char arm7_driver_str[] = "ARM7TDMI";
|
||||
|
||||
/* ARM7 JTAG IR values */
|
||||
#define ARM7_IR_EXTEST 0x0
|
||||
#define ARM7_IR_SCAN_N 0x2
|
||||
#define ARM7_IR_SAMPLE_PRELOAD 0x3
|
||||
#define ARM7_IR_RESTART 0x4
|
||||
#define ARM7_IR_CLAMP 0x5
|
||||
#define ARM7_IR_HIGHZ 0x7
|
||||
#define ARM7_IR_CLAMPZ 0x9
|
||||
#define ARM7_IR_INTEST 0xC
|
||||
#define ARM7_IR_IDCODE 0xE
|
||||
#define ARM7_IR_BYPASS 0xF
|
||||
|
||||
/* ARM7 SCAN_N scan chain values */
|
||||
#define ARM7_SCANN_BOUNDARY 0
|
||||
#define ARM7_SCANN_DBUS 1
|
||||
#define ARM7_SCANN_EICE 2
|
||||
|
||||
/* EmbeddedICE-RT Register addresses */
|
||||
#define ARM7_EICE_DEBUG_CTRL 0x00
|
||||
#define ARM7_EICE_DEBUG_STAT 0x01
|
||||
#define ARM7_EICE_ABORT_STAT 0x02
|
||||
#define ARM7_EICE_COMMS_CTRL 0x04
|
||||
#define ARM7_EICE_COMMS_DATA 0x05
|
||||
#define ARM7_EICE_WATCH_ADDR(x) (0x08 + (8 * (x))
|
||||
#define ARM7_EICE_WATCH_ADDR_MASK(x) (0x09 + (8 * (x))
|
||||
#define ARM7_EICE_WATCH_DATA(x) (0x0A + (8 * (x))
|
||||
#define ARM7_EICE_WATCH_DATA_MASK(x) (0x0B + (8 * (x))
|
||||
#define ARM7_EICE_WATCH_CTRL(x) (0x0C + (8 * (x))
|
||||
#define ARM7_EICE_WATCH_CTRL_MASK(x) (0x0D + (8 * (x))
|
||||
|
||||
/* Read/write bit in EmbeddedICE-RT scan chain */
|
||||
#define ARM7_EICE_READ (0uLL << 37)
|
||||
#define ARM7_EICE_WRITE (1uLL << 37)
|
||||
|
||||
/* Debug Control Register bits */
|
||||
#define ARM7_EICE_DEBUG_CTRL_EICE_DISABLE (1 << 5)
|
||||
#define ARM7_EICE_DEBUG_CTRL_MONITOR (1 << 4)
|
||||
/* Bit 3 - Reserved */
|
||||
#define ARM7_EICE_DEBUG_CTRL_INTDIS (1 << 2)
|
||||
#define ARM7_EICE_DEBUG_CTRL_DBGRQ (1 << 1)
|
||||
#define ARM7_EICE_DEBUG_CTRL_DBGACK (1 << 0)
|
||||
|
||||
/* Debug Status Register bits */
|
||||
#define ARM7_EICE_DEBUG_STAT_TBIT (1 << 4)
|
||||
#define ARM7_EICE_DEBUG_STAT_NMREQ (1 << 3)
|
||||
#define ARM7_EICE_DEBUG_STAT_INTDIS (1 << 2)
|
||||
#define ARM7_EICE_DEBUG_STAT_DBGRQ (1 << 1)
|
||||
#define ARM7_EICE_DEBUG_STAT_DBGACK (1 << 0)
|
||||
|
||||
#define ARM7_OP_NOP 0xE1A00000
|
||||
|
||||
struct target_arm7_s {
|
||||
target t;
|
||||
jtag_dev_t *jtag;
|
||||
uint32_t reg_cache[16];
|
||||
};
|
||||
|
||||
/* FIXME: Remove: */
|
||||
static void do_nothing(void)
|
||||
{
|
||||
}
|
||||
|
||||
static bool arm7_attach(struct target_s *target);
|
||||
static int arm7_regs_read(struct target_s *target, void *data);
|
||||
static int arm7_regs_write(struct target_s *target, const void *data);
|
||||
static void arm7_halt_request(struct target_s *target);
|
||||
static int arm7_halt_wait(struct target_s *target);
|
||||
static void arm7_halt_resume(struct target_s *target, bool step);
|
||||
|
||||
void arm7tdmi_jtag_handler(jtag_dev_t *dev)
|
||||
{
|
||||
struct target_arm7_s *tj = (void*)target_new(sizeof(*tj));
|
||||
target *t = (target *)tj;
|
||||
|
||||
t->driver = arm7_driver_str;
|
||||
tj->jtag = dev;
|
||||
|
||||
/* Setup mandatory virtual methods */
|
||||
t->attach = arm7_attach;
|
||||
t->detach = (void *)do_nothing;
|
||||
t->check_error = (void *)do_nothing;
|
||||
t->mem_read = (void *)do_nothing;
|
||||
t->mem_write = (void *)do_nothing;
|
||||
t->regs_size = 16 * sizeof(uint32_t);
|
||||
t->regs_read = (void *)arm7_regs_read;
|
||||
t->regs_write = (void *)arm7_regs_write;
|
||||
t->pc_write = (void *)do_nothing;
|
||||
t->reset = (void *)do_nothing;
|
||||
t->halt_request = arm7_halt_request;
|
||||
t->halt_wait = arm7_halt_wait;
|
||||
t->halt_resume = arm7_halt_resume;
|
||||
|
||||
/* TODO: Breakpoint and watchpoint functions. */
|
||||
/* TODO: Fault unwinder. */
|
||||
/* TODO: Memory map / Flash programming. */
|
||||
}
|
||||
|
||||
static void arm7_select_scanchain(struct target_arm7_s *target, uint8_t chain)
|
||||
{
|
||||
jtag_dev_write_ir(target->jtag, ARM7_IR_SCAN_N);
|
||||
jtag_dev_shift_dr(target->jtag, NULL, &chain, 4);
|
||||
jtag_dev_write_ir(target->jtag, ARM7_IR_INTEST);
|
||||
}
|
||||
|
||||
static void arm7_eice_write(struct target_arm7_s *target,
|
||||
uint8_t addr, uint32_t value)
|
||||
{
|
||||
uint64_t val = ((uint64_t)addr << 32) | value | ARM7_EICE_WRITE;
|
||||
|
||||
arm7_select_scanchain(target, ARM7_SCANN_EICE);
|
||||
jtag_dev_shift_dr(target->jtag, NULL, (uint8_t *)&val, 38);
|
||||
DEBUG("eice_write(%d, 0x%08X)\n", addr, value);
|
||||
}
|
||||
|
||||
static uint32_t arm7_eice_read(struct target_arm7_s *target, uint8_t addr)
|
||||
{
|
||||
uint64_t val = ((uint64_t)addr << 32) | ARM7_EICE_READ;
|
||||
|
||||
arm7_select_scanchain(target, ARM7_SCANN_EICE);
|
||||
jtag_dev_shift_dr(target->jtag, NULL, (uint8_t *)&val, 38);
|
||||
jtag_dev_shift_dr(target->jtag, (uint8_t *)&val, (uint8_t *)&val, 38);
|
||||
DEBUG("eice_read(%d, 0x%08X)\n", addr, (uint32_t)val);
|
||||
|
||||
return (uint32_t)val;
|
||||
}
|
||||
|
||||
/* Execute a single instruction at debug speed.
|
||||
* Performs datalen data bus accesses after the op to capture data.
|
||||
*/
|
||||
static void arm7_op_debug(struct target_arm7_s *t, uint32_t op, uint32_t *data,
|
||||
int datalen)
|
||||
{
|
||||
uint64_t tmp;
|
||||
/* FIXME: This routine is broken.
|
||||
* This process isn't very well documented. Maybe NOPs need to
|
||||
* be shifted into pipeline before data is read out.
|
||||
*/
|
||||
DEBUG("op_debug(0x%08X)\n", op);
|
||||
arm7_select_scanchain(t, ARM7_SCANN_DBUS);
|
||||
tmp = op;
|
||||
jtag_dev_shift_dr(t->jtag, NULL, (const uint8_t*)&tmp, 33);
|
||||
while(datalen--) {
|
||||
tmp = *data;
|
||||
jtag_dev_shift_dr(t->jtag, (uint8_t*)&tmp, (uint8_t*)&tmp, 33);
|
||||
*data = (uint32_t)tmp;
|
||||
DEBUG("\t0x%08X\n", *data);
|
||||
data++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Execute a single instruction at system speed. */
|
||||
static void arm7_op_system(struct target_arm7_s *t, uint32_t op)
|
||||
{
|
||||
uint64_t tmp;
|
||||
arm7_select_scanchain(t, ARM7_SCANN_DBUS);
|
||||
tmp = op | (1uLL << 32);
|
||||
jtag_dev_shift_dr(t->jtag, NULL, (const uint8_t*)&tmp, 33);
|
||||
}
|
||||
|
||||
static void arm7_halt_request(struct target_s *target)
|
||||
{
|
||||
struct target_arm7_s *t = (struct target_arm7_s *)target;
|
||||
|
||||
arm7_eice_write(t, ARM7_EICE_DEBUG_CTRL, ARM7_EICE_DEBUG_CTRL_DBGRQ);
|
||||
}
|
||||
|
||||
static int arm7_halt_wait(struct target_s *target)
|
||||
{
|
||||
struct target_arm7_s *t = (struct target_arm7_s *)target;
|
||||
int stat = arm7_eice_read(t, ARM7_EICE_DEBUG_STAT);
|
||||
|
||||
if(!(stat & ARM7_EICE_DEBUG_STAT_DBGACK))
|
||||
return 0;
|
||||
|
||||
/* We are halted, so switch to ARM mode if needed. */
|
||||
if(stat & ARM7_EICE_DEBUG_STAT_TBIT) {
|
||||
/* This sequence switches to ARM mode:
|
||||
* 6000 STR R0, [R0] ; Save R0 before use
|
||||
* 4678 MOV R0, PC ; Copy PC into R0
|
||||
* 6000 STR R0, [R0] ; Now save the PC in R0
|
||||
* 4778 BX PC ; Jump into ARM state
|
||||
* 46c0 MOV R8, R8 ; NOP
|
||||
* 46c0 MOV R8, R8 ; NOP
|
||||
*/
|
||||
/* FIXME: Switch to ARM mode. */
|
||||
}
|
||||
|
||||
/* Fetch core register values */
|
||||
/* E880FFFF STM R0, {R0-R15} */
|
||||
arm7_op_debug(t, 0xE880FFFF, t->reg_cache, 16);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void arm7_halt_resume(struct target_s *target, bool step)
|
||||
{
|
||||
struct target_arm7_s *t = (struct target_arm7_s *)target;
|
||||
|
||||
if(step) {
|
||||
/* FIXME: Set breakpoint on any instruction to single step. */
|
||||
}
|
||||
|
||||
/* Restore core registers. */
|
||||
/* E890FFFF LDM R0, {R0-R15} */
|
||||
arm7_op_debug(t, 0xE890FFFF, t->reg_cache, 16);
|
||||
|
||||
/* Release DBGRQ */
|
||||
arm7_eice_write(t, ARM7_EICE_DEBUG_CTRL, 0);
|
||||
/* This sequence restores PC if no other instructions issued in
|
||||
* debug mode...
|
||||
* 0 E1A00000; MOV R0, R0
|
||||
* 1 E1A00000; MOV R0, R0
|
||||
* 0 EAFFFFFA; B -6
|
||||
* FIXME: Add adjustment for other opcodes.
|
||||
*/
|
||||
arm7_op_debug(t, ARM7_OP_NOP, NULL, 0);
|
||||
arm7_op_system(t, ARM7_OP_NOP);
|
||||
arm7_op_debug(t, 0xEAFFFFF8, NULL, 0);
|
||||
|
||||
jtag_dev_write_ir(t->jtag, ARM7_IR_RESTART);
|
||||
}
|
||||
|
||||
static bool arm7_attach(struct target_s *target)
|
||||
{
|
||||
int tries = 0;
|
||||
target_halt_request(target);
|
||||
while(!target_halt_wait(target) && --tries)
|
||||
platform_delay(2);
|
||||
if(!tries)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int arm7_regs_read(struct target_s *target, void *data)
|
||||
{
|
||||
struct target_arm7_s *t = (struct target_arm7_s *)target;
|
||||
memcpy(data, t->reg_cache, target->regs_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int arm7_regs_write(struct target_s *target, const void *data)
|
||||
{
|
||||
struct target_arm7_s *t = (struct target_arm7_s *)target;
|
||||
memcpy(t->reg_cache, data, target->regs_size);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -43,9 +43,6 @@ static struct jtag_dev_descr_s {
|
|||
{.idcode = 0x0BA00477, .idmask = 0x0FFF0FFF,
|
||||
.descr = "ARM Limited: ADIv5 JTAG-DP port.",
|
||||
.handler = adiv5_jtag_dp_handler},
|
||||
{.idcode = 0x3F0F0F0F, .idmask = 0xFFFFFFFF,
|
||||
.descr = "ST Microelectronics: STR730",
|
||||
.handler = arm7tdmi_jtag_handler},
|
||||
{.idcode = 0x06410041, .idmask = 0x0FFFFFFF,
|
||||
.descr = "ST Microelectronics: STM32, Medium density."},
|
||||
{.idcode = 0x06412041, .idmask = 0x0FFFFFFF,
|
||||
|
|
Loading…
Reference in New Issue