forked from cores/microwatt
New C based JTAG debug tool
This works with both the sim socket and urjtag, and supports the new core functions, loading a file in memory etc... The code still needs a lot of cleanup and a help! Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>jtag-port
parent
98f0994698
commit
fe275effeb
@ -1,103 +0,0 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
import urjtag;
|
||||
|
||||
def do_command(urc, op, addr, data):
|
||||
urc.set_dr_in(op,1,0)
|
||||
urc.set_dr_in(data,65,2)
|
||||
urc.set_dr_in(addr,73,66)
|
||||
# print("Sending:", urc.get_dr_in_string())
|
||||
urc.shift_dr()
|
||||
urc.set_dr_in(0x0,73,0)
|
||||
for x in range(5):
|
||||
urc.shift_dr()
|
||||
# print("Received:", urc.get_dr_out_string())
|
||||
rsp_code = urc.get_dr_out(1,0)
|
||||
if rsp_code == 0:
|
||||
return urc.get_dr_out(65,2)
|
||||
if rsp_code != 3:
|
||||
print("Weird response ! rsp=%x" % rsp_code);
|
||||
print("Timeout sending command !")
|
||||
|
||||
def do_read(urc, addr):
|
||||
return do_command(urc, 1, addr, 0)
|
||||
|
||||
def do_write(urc, addr, val):
|
||||
do_command(urc, 2, addr, val)
|
||||
|
||||
def main():
|
||||
# Init jtag
|
||||
#urjtag.loglevel( urjtag.URJ_LOG_LEVEL_ALL )
|
||||
|
||||
urc = urjtag.chain()
|
||||
urc.cable("DigilentHS1")
|
||||
print('Cable frequency:', urc.get_frequency())
|
||||
#urc.tap_detect()
|
||||
#length = urc.len()
|
||||
#for i in range(0,urc.len()):
|
||||
# idcode = urc.partid(0)
|
||||
# print('[%d] 0x%08x' % (i, idcode))
|
||||
urc.addpart(6);
|
||||
print("Part ID: ", urc.partid(0))
|
||||
#urc.part(0)
|
||||
#urc.reset();
|
||||
urc.add_register("USER2_REG", 74);
|
||||
urc.add_instruction("USER2", "000011", "USER2_REG");
|
||||
urc.add_register("IDCODE_REG", 32);
|
||||
urc.add_instruction("IDCODE", "001001", "IDCODE_REG");
|
||||
# Send test command
|
||||
urc.set_instruction("IDCODE")
|
||||
urc.shift_ir()
|
||||
urc.shift_dr()
|
||||
print("Got:", hex(urc.get_dr_out()))
|
||||
|
||||
urc.set_instruction("USER2")
|
||||
urc.shift_ir()
|
||||
|
||||
print("Reading memory at 0:")
|
||||
do_write(urc, 0, 0)
|
||||
do_write(urc, 2, 0x7ff)
|
||||
print("00: %016x" % do_read(urc, 1))
|
||||
print("08: %016x" % do_read(urc, 1))
|
||||
print("10: %016x" % do_read(urc, 1))
|
||||
print("18: %016x" % do_read(urc, 1))
|
||||
do_write(urc, 0, 0x10)
|
||||
do_write(urc, 1, 0xabcdef0123456789)
|
||||
do_write(urc, 0, 0)
|
||||
do_write(urc, 2, 0x7ff)
|
||||
print("00: %016x" % do_read(urc, 1))
|
||||
print("08: %016x" % do_read(urc, 1))
|
||||
print("10: %016x" % do_read(urc, 1))
|
||||
print("18: %016x" % do_read(urc, 1))
|
||||
|
||||
# urc.set_dr_in(0,73,0);
|
||||
# print("Test DR_IN 1:", urc.get_dr_in_string())
|
||||
# urc.set_dr_in(0xa,3,0);
|
||||
# print("Test DR_IN 2:", urc.get_dr_in_string())
|
||||
# urc.set_dr_in(0x5,7,4);
|
||||
# print("Test DR_IN 3:", urc.get_dr_in_string())
|
||||
# urc.set_dr_in(1,73,73);
|
||||
# print("Test DR_IN 4:", urc.get_dr_in_string())
|
||||
|
||||
# print("Reading ADDR reg: %x" % do_read(urc, 0))
|
||||
# print("Writing all 1's to it:")
|
||||
# do_write(urc, 0, 0xffffffffffffffff)
|
||||
# print("Reading ADDR reg: %x" % do_read(urc, 0))
|
||||
# print("Writing 0xabcdef0123456789 to it:")
|
||||
# do_write(urc, 0, 0xabcdef0123456789)
|
||||
# print("Reading ADDR reg: %x" % do_read(urc, 0))
|
||||
|
||||
|
||||
|
||||
# urc.set_dr_in(0x1,41,0)
|
||||
# print("Sending:", urc.get_dr_in_string())
|
||||
# urc.shift_dr()
|
||||
# urc.set_dr_in(0x0,41,0)
|
||||
# urc.shift_dr()
|
||||
# print("Got1:", urc.get_dr_out_string())
|
||||
# urc.shift_dr()
|
||||
# print("Got2:", hex(urc.get_dr_out()))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -0,0 +1,7 @@
|
||||
CFLAGS = -O2 -g -Wall -std=c99
|
||||
|
||||
all: mw_debug
|
||||
|
||||
mw_debug: mw_debug.c
|
||||
$(CC) -o $@ $^ -lurjtag
|
||||
|
@ -0,0 +1,583 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <getopt.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <urjtag/urjtag.h>
|
||||
|
||||
#define DBG_WB_ADDR 0x00
|
||||
#define DBG_WB_DATA 0x01
|
||||
#define DBG_WB_CTRL 0x02
|
||||
|
||||
#define DBG_CORE_CTRL 0x10
|
||||
#define DBG_CORE_CTRL_STOP (1 << 0)
|
||||
#define DBG_CORE_CTRL_RESET (1 << 1)
|
||||
#define DBG_CORE_CTRL_ICRESET (1 << 2)
|
||||
#define DBG_CORE_CTRL_STEP (1 << 3)
|
||||
#define DBG_CORE_CTRL_START (1 << 4)
|
||||
|
||||
#define DBG_CORE_STAT 0x11
|
||||
#define DBG_CORE_STAT_STOPPING (1 << 0)
|
||||
#define DBG_CORE_STAT_STOPPED (1 << 1)
|
||||
#define DBG_CORE_STAT_TERM (1 << 2)
|
||||
|
||||
#define DBG_CORE_NIA 0x12
|
||||
|
||||
static bool debug;
|
||||
|
||||
struct backend {
|
||||
int (*init)(const char *target);
|
||||
int (*reset)(void);
|
||||
int (*command)(uint8_t op, uint8_t addr, uint64_t *data);
|
||||
};
|
||||
static struct backend *b;
|
||||
|
||||
static void check(int r, const char *failstr)
|
||||
{
|
||||
if (r >= 0)
|
||||
return;
|
||||
fprintf(stderr, "Error %s\n", failstr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* -------------- SIM backend -------------- */
|
||||
|
||||
static int sim_fd = -1;
|
||||
|
||||
static int sim_init(const char *target)
|
||||
{
|
||||
struct sockaddr_in saddr;
|
||||
struct hostent *hp;
|
||||
const char *p, *host;
|
||||
int port, rc;
|
||||
|
||||
if (!target)
|
||||
target = "localhost:13245";
|
||||
p = strchr(target, ':');
|
||||
host = strndup(target, p - target);
|
||||
if (p && *p)
|
||||
p++;
|
||||
else
|
||||
p = "13245";
|
||||
port = strtoul(p, NULL, 10);
|
||||
if (debug)
|
||||
printf("Opening sim backend host '%s' port %d\n", host, port);
|
||||
|
||||
sim_fd = socket(PF_INET, SOCK_STREAM, 0);
|
||||
if (sim_fd < 0) {
|
||||
fprintf(stderr, "Error opening socket: %s\n",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
hp = gethostbyname(host);
|
||||
if (!hp) {
|
||||
fprintf(stderr,"Unknown host '%s'\n", host);
|
||||
return -1;
|
||||
}
|
||||
memcpy(&saddr.sin_addr, hp->h_addr, hp->h_length);
|
||||
saddr.sin_port = htons(port);
|
||||
saddr.sin_family = PF_INET;
|
||||
rc = connect(sim_fd, (struct sockaddr *)&saddr, sizeof(saddr));
|
||||
if (rc < 0) {
|
||||
close(sim_fd);
|
||||
fprintf(stderr,"Connection to '%s' failed: %s\n",
|
||||
host, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sim_reset(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void add_bits(uint8_t **p, int *b, uint64_t d, int c)
|
||||
{
|
||||
uint8_t md = 1 << *b;
|
||||
uint64_t ms = 1;
|
||||
|
||||
while (c--) {
|
||||
if (d & ms)
|
||||
(**p) |= md;
|
||||
ms <<= 1;
|
||||
if (*b == 7) {
|
||||
*b = 0;
|
||||
(*p)++;
|
||||
md = 1;
|
||||
} else {
|
||||
(*b)++;
|
||||
md <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t read_bits(uint8_t **p, int *b, int c)
|
||||
{
|
||||
uint8_t ms = 1 << *b;
|
||||
uint64_t md = 1;
|
||||
uint64_t d = 0;
|
||||
|
||||
while (c--) {
|
||||
if ((**p) & ms)
|
||||
d |= md;
|
||||
md <<= 1;
|
||||
if (*b == 7) {
|
||||
*b = 0;
|
||||
(*p)++;
|
||||
ms = 1;
|
||||
} else {
|
||||
(*b)++;
|
||||
ms <<= 1;
|
||||
}
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
static int sim_command(uint8_t op, uint8_t addr, uint64_t *data)
|
||||
{
|
||||
uint8_t buf[16], *p;
|
||||
uint64_t d = data ? *data : 0;
|
||||
int r, s, b = 0;
|
||||
|
||||
memset(buf, 0, 16);
|
||||
p = buf+1;
|
||||
add_bits(&p, &b, op, 2);
|
||||
add_bits(&p, &b, d, 64);
|
||||
add_bits(&p, &b, addr, 8);
|
||||
if (b)
|
||||
p++;
|
||||
buf[0] = 74;
|
||||
if (0)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<(p-buf); i++)
|
||||
printf("%02x ", buf[i]);
|
||||
printf("\n");
|
||||
}
|
||||
write(sim_fd, buf, p - buf);
|
||||
r = read(sim_fd, buf, 127);
|
||||
if (0 && r > 0) {
|
||||
int i;
|
||||
|
||||
for (i=0; i<r; i++)
|
||||
printf("%02x ", buf[i]);
|
||||
printf("\n");
|
||||
}
|
||||
p = buf+1;
|
||||
b = 0;
|
||||
r = read_bits(&p, &b, 2);
|
||||
if (data)
|
||||
*data = read_bits(&p, &b, 64);
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct backend sim_backend = {
|
||||
.init = sim_init,
|
||||
.reset = sim_reset,
|
||||
.command = sim_command,
|
||||
};
|
||||
|
||||
/* -------------- JTAG backend -------------- */
|
||||
|
||||
static urj_chain_t *jc;
|
||||
|
||||
static int jtag_init(const char *target)
|
||||
{
|
||||
const char *sep;
|
||||
const char *cable;
|
||||
char *params[] = { NULL, };
|
||||
urj_part_t *p;
|
||||
uint32_t id;
|
||||
int rc, part;
|
||||
|
||||
if (!target)
|
||||
target = "DigilentHS1";
|
||||
sep = strchr(target, ':');
|
||||
cable = strndup(target, sep - target);
|
||||
if (sep && *sep) {
|
||||
fprintf(stderr, "jtag cable params not supported yet\n");
|
||||
return -1;
|
||||
}
|
||||
if (debug)
|
||||
printf("Opening jtag backend cable '%s'\n", cable);
|
||||
|
||||
jc = urj_tap_chain_alloc();
|
||||
if (!jc) {
|
||||
fprintf(stderr, "Failed to alloc JTAG\n");
|
||||
return -1;
|
||||
}
|
||||
jc->main_part = 0;
|
||||
|
||||
rc = urj_tap_chain_connect(jc, cable, params);
|
||||
if (rc != URJ_STATUS_OK) {
|
||||
fprintf(stderr, "JTAG cable detect failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* XXX Hard wire part 0, that might need to change (use params and detect !) */
|
||||
rc = urj_tap_manual_add(jc, 6);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "JTAG failed to add part !\n");
|
||||
return -1;
|
||||
}
|
||||
if (jc->parts == NULL || jc->parts->len == 0) {
|
||||
fprintf(stderr, "JTAG Something's wrong after adding part !\n");
|
||||
return -1;
|
||||
}
|
||||
urj_part_parts_set_instruction(jc->parts, "BYPASS");
|
||||
|
||||
jc->active_part = part = 0;
|
||||
|
||||
p = urj_tap_chain_active_part(jc);
|
||||
if (!p) {
|
||||
fprintf(stderr, "Failed to get active JTAG part\n");
|
||||
return -1;
|
||||
}
|
||||
rc = urj_part_data_register_define(p, "IDCODE_REG", 32);
|
||||
if (rc != URJ_STATUS_OK) {
|
||||
fprintf(stderr, "JTAG failed to add IDCODE_REG register !\n");
|
||||
return -1;
|
||||
}
|
||||
if (urj_part_instruction_define(p, "IDCODE", "001001", "IDCODE_REG") == NULL) {
|
||||
fprintf(stderr, "JTAG failed to add IDCODE instruction !\n");
|
||||
return -1;
|
||||
}
|
||||
rc = urj_part_data_register_define(p, "USER2_REG", 74);
|
||||
if (rc != URJ_STATUS_OK) {
|
||||
fprintf(stderr, "JTAG failed to add USER2_REG register !\n");
|
||||
return -1;
|
||||
}
|
||||
if (urj_part_instruction_define(p, "USER2", "000011", "USER2_REG") == NULL) {
|
||||
fprintf(stderr, "JTAG failed to add USER2 instruction !\n");
|
||||
return -1;
|
||||
}
|
||||
urj_part_set_instruction(p, "IDCODE");
|
||||
urj_tap_chain_shift_instructions(jc);
|
||||
urj_tap_chain_shift_data_registers(jc, 1);
|
||||
id = urj_tap_register_get_value(p->active_instruction->data_register->out);
|
||||
printf("Found device ID: 0x%08x\n", id);
|
||||
urj_part_set_instruction(p, "USER2");
|
||||
urj_tap_chain_shift_instructions(jc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jtag_reset(void)
|
||||
{
|
||||
}
|
||||
|
||||
static int jtag_command(uint8_t op, uint8_t addr, uint64_t *data)
|
||||
{
|
||||
urj_part_t *p = urj_tap_chain_active_part(jc);
|
||||
urj_part_instruction_t *insn;
|
||||
urj_data_register_t *dr;
|
||||
uint64_t d = data ? *data : 0;
|
||||
int rc;
|
||||
|
||||
if (!p)
|
||||
return -1;
|
||||
insn = p->active_instruction;
|
||||
if (!insn)
|
||||
return -1;
|
||||
dr = insn->data_register;
|
||||
if (!dr)
|
||||
return -1;
|
||||
rc = urj_tap_register_set_value_bit_range(dr->in, op, 1, 0);
|
||||
if (rc != URJ_STATUS_OK)
|
||||
return -1;
|
||||
rc = urj_tap_register_set_value_bit_range(dr->in, d, 65, 2);
|
||||
if (rc != URJ_STATUS_OK)
|
||||
return -1;
|
||||
rc = urj_tap_register_set_value_bit_range(dr->in, addr, 73, 66);
|
||||
if (rc != URJ_STATUS_OK)
|
||||
return -1;
|
||||
rc = urj_tap_chain_shift_data_registers(jc, 1);
|
||||
if (rc != URJ_STATUS_OK)
|
||||
return -1;
|
||||
rc = urj_tap_register_get_value_bit_range(dr->out, 1, 0);
|
||||
if (data)
|
||||
*data = urj_tap_register_get_value_bit_range(dr->out, 65, 2);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static struct backend jtag_backend = {
|
||||
.init = jtag_init,
|
||||
.reset = jtag_reset,
|
||||
.command = jtag_command,
|
||||
};
|
||||
|
||||
static int dmi_read(uint8_t addr, uint64_t *data)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = b->command(1, addr, data);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
for (;;) {
|
||||
rc = b->command(0, 0, data);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
if (rc == 0)
|
||||
return 0;
|
||||
if (rc != 3)
|
||||
fprintf(stderr, "Unknown status code %d !\n", rc);
|
||||
}
|
||||
}
|
||||
|
||||
static int dmi_write(uint8_t addr, uint64_t data)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = b->command(2, addr, &data);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
for (;;) {
|
||||
rc = b->command(0, 0, NULL);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
if (rc == 0)
|
||||
return 0;
|
||||
if (rc != 3)
|
||||
fprintf(stderr, "Unknown status code %d !\n", rc);
|
||||
}
|
||||
}
|
||||
|
||||
static void core_status(void)
|
||||
{
|
||||
uint64_t stat, nia;
|
||||
const char *statstr, *statstr2;
|
||||
|
||||
check(dmi_read(DBG_CORE_STAT, &stat), "reading core status");
|
||||
check(dmi_read(DBG_CORE_NIA, &nia), "reading core NIA");
|
||||
|
||||
if (debug)
|
||||
printf("Core status = 0x%llx\n", (unsigned long long)stat);
|
||||
statstr = "running";
|
||||
statstr2 = "";
|
||||
if (stat & DBG_CORE_STAT_STOPPED) {
|
||||
statstr = "stopped";
|
||||
if (!(stat & DBG_CORE_STAT_STOPPING))
|
||||
statstr2 = " (restarting?)";
|
||||
else if (stat & DBG_CORE_STAT_TERM)
|
||||
statstr2 = " (terminated)";
|
||||
} else if (stat & DBG_CORE_STAT_STOPPING)
|
||||
statstr = "stopping";
|
||||
else if (stat & DBG_CORE_STAT_TERM)
|
||||
statstr = "odd state (TERM but no STOP)";
|
||||
printf("Core: %s%s\n", statstr, statstr2);
|
||||
printf(" NIA: %016llx\n", (unsigned long long)nia);
|
||||
}
|
||||
|
||||
static void core_stop(void)
|
||||
{
|
||||
check(dmi_write(DBG_CORE_CTRL, DBG_CORE_CTRL_STOP), "stopping core");
|
||||
}
|
||||
|
||||
static void core_start(void)
|
||||
{
|
||||
check(dmi_write(DBG_CORE_CTRL, DBG_CORE_CTRL_START), "starting core");
|
||||
}
|
||||
|
||||
static void core_reset(void)
|
||||
{
|
||||
check(dmi_write(DBG_CORE_CTRL, DBG_CORE_CTRL_START), "resetting core");
|
||||
}
|
||||
|
||||
static void core_step(void)
|
||||
{
|
||||
uint64_t stat;
|
||||
|
||||
check(dmi_read(DBG_CORE_STAT, &stat), "reading core status");
|
||||
|
||||
if (!(stat & DBG_CORE_STAT_STOPPED)) {
|
||||
printf("Core not stopped !\n");
|
||||
return;
|
||||
}
|
||||
check(dmi_write(DBG_CORE_CTRL, DBG_CORE_CTRL_STEP), "stepping core");
|
||||
}
|
||||
|
||||
static void icache_reset(void)
|
||||
{
|
||||
check(dmi_write(DBG_CORE_CTRL, DBG_CORE_CTRL_ICRESET), "resetting icache");
|
||||
}
|
||||
|
||||
static void mem_read(uint64_t addr, uint64_t count)
|
||||
{
|
||||
uint64_t data;
|
||||
int i, rc;
|
||||
|
||||
rc = dmi_write(2, 0x7ff);
|
||||
if (rc < 0)
|
||||
return;
|
||||
rc = dmi_write(0, addr);
|
||||
if (rc < 0)
|
||||
return;
|
||||
for (i = 0; i < count; i++) {
|
||||
rc = dmi_read(1, &data);
|
||||
if (rc < 0)
|
||||
return;
|
||||
printf("%016llx: %016llx\n",
|
||||
(unsigned long long)addr,
|
||||
(unsigned long long)data);
|
||||
addr += 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void load(const char *filename, uint64_t addr)
|
||||
{
|
||||
uint64_t data;
|
||||
int fd, rc, count;
|
||||
|
||||
fd = open(filename, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "Failed to open '%s': %s\n", filename, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
// XX dumb, do better
|
||||
rc = dmi_write(2, 0x7ff);
|
||||
if (rc < 0)
|
||||
return;
|
||||
rc = dmi_write(0, addr);
|
||||
if (rc < 0)
|
||||
return;
|
||||
count = 0;
|
||||
for (;;) {
|
||||
data = 0;
|
||||
rc = read(fd, &data, 8);
|
||||
if (rc <= 0)
|
||||
break;
|
||||
// if (rc < 8) XXX fixup endian ?
|
||||
dmi_write(1, data);
|
||||
count += 8;
|
||||
if (!(count % 1024))
|
||||
printf("%x...\n", count);
|
||||
}
|
||||
printf("%x done.\n", count);
|
||||
}
|
||||
|
||||
static void usage(const char *cmd)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s <command> <args>\n", cmd);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
const char *progname = argv[0];
|
||||
const char *target = NULL;
|
||||
int rc, i = 1;
|
||||
|
||||
b = NULL;
|
||||
|
||||
while(1) {
|
||||
int c, oindex;
|
||||
static struct option lopts[] = {
|
||||
{ "help", no_argument, 0, 'h' },
|
||||
{ "backend", required_argument, 0, 'b' },
|
||||
{ "target", required_argument, 0, 't' },
|
||||
{ "debug", no_argument, 0, 'd' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
c = getopt_long(argc, argv, "dhb:t:", lopts, &oindex);
|
||||
if (c < 0)
|
||||
break;
|
||||
switch(c) {
|
||||
case 'h':
|
||||
usage(progname);
|
||||
break;
|
||||
case 'b':
|
||||
if (strcmp(optarg, "sim") == 0)
|
||||
b = &sim_backend;
|
||||
else if (strcmp(optarg, "jtag") == 0)
|
||||
b = &jtag_backend;
|
||||
else {
|
||||
fprintf(stderr, "Unknown backend %s\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
target = optarg;
|
||||
break;
|
||||
case 'd':
|
||||
debug = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (b == NULL) {
|
||||
fprintf(stderr, "No backend selected\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
rc = b->init(target);
|
||||
if (rc < 0)
|
||||
exit(1);
|
||||
for (i = optind; i < argc; i++) {
|
||||
if (strcmp(argv[i], "dmiread") == 0) {
|
||||
uint8_t addr;
|
||||
uint64_t data;
|
||||
|
||||
if ((i+1) >= argc)
|
||||
usage(argv[0]);
|
||||
addr = strtoul(argv[++i], NULL, 16);
|
||||
dmi_read(addr, &data);
|
||||
printf("%02x: %016llx\n", addr, (unsigned long long)data);
|
||||
} else if (strcmp(argv[i], "dmiwrite") == 0) {
|
||||
uint8_t addr;
|
||||
uint64_t data;
|
||||
|
||||
if ((i+2) >= argc)
|
||||
usage(argv[0]);
|
||||
addr = strtoul(argv[++i], NULL, 16);
|
||||
data = strtoul(argv[++i], NULL, 16);
|
||||
dmi_write(addr, data);
|
||||
} else if (strcmp(argv[i], "creset") == 0) {
|
||||
core_reset();
|
||||
} else if (strcmp(argv[i], "stop") == 0) {
|
||||
core_stop();
|
||||
} else if (strcmp(argv[i], "start") == 0) {
|
||||
core_start();
|
||||
} else if (strcmp(argv[i], "step") == 0) {
|
||||
core_step();
|
||||
} else if (strcmp(argv[i], "quit") == 0) {
|
||||
dmi_write(0xff, 0);
|
||||
} else if (strcmp(argv[i], "status") == 0) {
|
||||
/* do nothing, always done below */
|
||||
} else if (strcmp(argv[i], "mr") == 0) {
|
||||
uint64_t addr, count = 1;
|
||||
|
||||
if ((i+1) >= argc)
|
||||
usage(argv[0]);
|
||||
addr = strtoul(argv[++i], NULL, 16);
|
||||
if (((i+1) < argc) && isdigit(argv[i+1][0]))
|
||||
count = strtoul(argv[++i], NULL, 16);
|
||||
mem_read(addr, count);
|
||||
} else if (strcmp(argv[i], "load") == 0) {
|
||||
const char *filename;
|
||||
uint64_t addr = 0;
|
||||
|
||||
if ((i+1) >= argc)
|
||||
usage(argv[0]);
|
||||
filename = argv[++i];
|
||||
if (((i+1) < argc) && isdigit(argv[i+1][0]))
|
||||
addr = strtoul(argv[++i], NULL, 16);
|
||||
load(filename, addr);
|
||||
} else {
|
||||
fprintf(stderr, "Unknown command %s\n", argv[i]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
core_status();
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue