Added more ARM7TDMI functions. Still not usable.
This commit is contained in:
parent
c062e60059
commit
c9ea16312b
|
@ -30,6 +30,7 @@
|
||||||
#include "jtagtap.h"
|
#include "jtagtap.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
/* TODO:
|
/* TODO:
|
||||||
* Skeleton target.
|
* Skeleton target.
|
||||||
|
@ -94,6 +95,8 @@ static const char arm7_driver_str[] = "ARM7TDMI";
|
||||||
#define ARM7_EICE_DEBUG_STAT_DBGRQ (1 << 1)
|
#define ARM7_EICE_DEBUG_STAT_DBGRQ (1 << 1)
|
||||||
#define ARM7_EICE_DEBUG_STAT_DBGACK (1 << 0)
|
#define ARM7_EICE_DEBUG_STAT_DBGACK (1 << 0)
|
||||||
|
|
||||||
|
#define ARM7_OP_NOP 0xE1A00000
|
||||||
|
|
||||||
struct target_arm7_s {
|
struct target_arm7_s {
|
||||||
target t;
|
target t;
|
||||||
jtag_dev_t *jtag;
|
jtag_dev_t *jtag;
|
||||||
|
@ -105,6 +108,9 @@ static void do_nothing(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void 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 void arm7_halt_request(struct target_s *target);
|
||||||
static int arm7_halt_wait(struct target_s *target);
|
static int arm7_halt_wait(struct target_s *target);
|
||||||
static void arm7_halt_resume(struct target_s *target, uint8_t step);
|
static void arm7_halt_resume(struct target_s *target, uint8_t step);
|
||||||
|
@ -118,7 +124,7 @@ void arm7tdmi_jtag_handler(jtag_dev_t *dev)
|
||||||
tj->jtag = dev;
|
tj->jtag = dev;
|
||||||
|
|
||||||
/* Setup mandatory virtual methods */
|
/* Setup mandatory virtual methods */
|
||||||
t->attach = (void *)do_nothing;
|
t->attach = arm7_attach;
|
||||||
t->detach = (void *)do_nothing;
|
t->detach = (void *)do_nothing;
|
||||||
t->check_error = (void *)do_nothing;
|
t->check_error = (void *)do_nothing;
|
||||||
t->mem_read_words = (void *)do_nothing;
|
t->mem_read_words = (void *)do_nothing;
|
||||||
|
@ -126,8 +132,8 @@ void arm7tdmi_jtag_handler(jtag_dev_t *dev)
|
||||||
t->mem_read_bytes = (void *)do_nothing;
|
t->mem_read_bytes = (void *)do_nothing;
|
||||||
t->mem_write_bytes = (void *)do_nothing;
|
t->mem_write_bytes = (void *)do_nothing;
|
||||||
t->regs_size = 16 * 4;
|
t->regs_size = 16 * 4;
|
||||||
t->regs_read = (void *)do_nothing;
|
t->regs_read = (void *)arm7_regs_read;
|
||||||
t->regs_write = (void *)do_nothing;
|
t->regs_write = (void *)arm7_regs_write;
|
||||||
t->pc_write = (void *)do_nothing;
|
t->pc_write = (void *)do_nothing;
|
||||||
t->reset = (void *)do_nothing;
|
t->reset = (void *)do_nothing;
|
||||||
t->halt_request = arm7_halt_request;
|
t->halt_request = arm7_halt_request;
|
||||||
|
@ -156,6 +162,7 @@ static void arm7_eice_write(struct target_arm7_s *target,
|
||||||
|
|
||||||
arm7_select_scanchain(target, ARM7_SCANN_EICE);
|
arm7_select_scanchain(target, ARM7_SCANN_EICE);
|
||||||
jtag_dev_shift_dr(target->jtag, NULL, (uint8_t *)&val, 38);
|
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)
|
static uint32_t arm7_eice_read(struct target_arm7_s *target, uint8_t addr)
|
||||||
|
@ -165,10 +172,44 @@ static uint32_t arm7_eice_read(struct target_arm7_s *target, uint8_t addr)
|
||||||
arm7_select_scanchain(target, ARM7_SCANN_EICE);
|
arm7_select_scanchain(target, ARM7_SCANN_EICE);
|
||||||
jtag_dev_shift_dr(target->jtag, NULL, (uint8_t *)&val, 38);
|
jtag_dev_shift_dr(target->jtag, NULL, (uint8_t *)&val, 38);
|
||||||
jtag_dev_shift_dr(target->jtag, (uint8_t *)&val, (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;
|
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)
|
static void arm7_halt_request(struct target_s *target)
|
||||||
{
|
{
|
||||||
struct target_arm7_s *t = (struct target_arm7_s *)target;
|
struct target_arm7_s *t = (struct target_arm7_s *)target;
|
||||||
|
@ -187,18 +228,19 @@ static int arm7_halt_wait(struct target_s *target)
|
||||||
/* We are halted, so switch to ARM mode if needed. */
|
/* We are halted, so switch to ARM mode if needed. */
|
||||||
if(stat & ARM7_EICE_DEBUG_STAT_TBIT) {
|
if(stat & ARM7_EICE_DEBUG_STAT_TBIT) {
|
||||||
/* This sequence switches to ARM mode:
|
/* This sequence switches to ARM mode:
|
||||||
* STR R0, [R0] ; Save R0 before use
|
* 6000 STR R0, [R0] ; Save R0 before use
|
||||||
* MOV R0, PC ; Copy PC into R0
|
* 4678 MOV R0, PC ; Copy PC into R0
|
||||||
* STR R0, [R0] ; Now save the PC in R0
|
* 6000 STR R0, [R0] ; Now save the PC in R0
|
||||||
* BX PC ; Jump into ARM state
|
* 4778 BX PC ; Jump into ARM state
|
||||||
* MOV R8, R8 ; NOP
|
* 46c0 MOV R8, R8 ; NOP
|
||||||
* MOV R8, R8 ; NOP
|
* 46c0 MOV R8, R8 ; NOP
|
||||||
*/
|
*/
|
||||||
/* FIXME: Switch to ARM mode. */
|
/* FIXME: Switch to ARM mode. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Get core register cache. */
|
/* Fetch core register values */
|
||||||
/* STM R0, {R0-R15} */
|
/* E880FFFF STM R0, {R0-R15} */
|
||||||
|
arm7_op_debug(t, 0xE880FFFF, t->reg_cache, 16);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -211,8 +253,9 @@ static void arm7_halt_resume(struct target_s *target, uint8_t step)
|
||||||
/* FIXME: Set breakpoint on any instruction to single step. */
|
/* FIXME: Set breakpoint on any instruction to single step. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Restore core registers. */
|
/* Restore core registers. */
|
||||||
/* LDM R0, {R0-R15} */
|
/* E890FFFF LDM R0, {R0-R15} */
|
||||||
|
arm7_op_debug(t, 0xE890FFFF, t->reg_cache, 16);
|
||||||
|
|
||||||
/* Release DBGRQ */
|
/* Release DBGRQ */
|
||||||
arm7_eice_write(t, ARM7_EICE_DEBUG_CTRL, 0);
|
arm7_eice_write(t, ARM7_EICE_DEBUG_CTRL, 0);
|
||||||
|
@ -221,8 +264,32 @@ static void arm7_halt_resume(struct target_s *target, uint8_t step)
|
||||||
* 0 E1A00000; MOV R0, R0
|
* 0 E1A00000; MOV R0, R0
|
||||||
* 1 E1A00000; MOV R0, R0
|
* 1 E1A00000; MOV R0, R0
|
||||||
* 0 EAFFFFFA; B -6
|
* 0 EAFFFFFA; B -6
|
||||||
* FIXME: Add this sequence and adjustment for other opcodes.
|
* 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);
|
jtag_dev_write_ir(t->jtag, ARM7_IR_RESTART);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void arm7_attach(struct target_s *target)
|
||||||
|
{
|
||||||
|
target_halt_request(target);
|
||||||
|
while(!target_halt_wait(target));
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,7 @@
|
||||||
|
|
||||||
|
|
||||||
#define target_check_hw_wp(target, addr) \
|
#define target_check_hw_wp(target, addr) \
|
||||||
(target)->check_hw_wp((target), (addr))
|
((target)->check_hw_wp?(target)->check_hw_wp((target), (addr)):0)
|
||||||
|
|
||||||
|
|
||||||
/* Flash memory access functions */
|
/* Flash memory access functions */
|
||||||
|
|
Loading…
Reference in New Issue