From d64791bac6c04a90927b53561e7a09bd73800534 Mon Sep 17 00:00:00 2001 From: sys64738 Date: Thu, 7 Oct 2021 01:12:04 +0200 Subject: [PATCH] woah it works --- drivers/jtaglib.c | 154 +++++++++---- drivers/jtaglib.h | 11 + drivers/jtdev.c | 10 +- drivers/jtdev.h | 15 ++ drivers/jtdev_bus_pirate.c | 10 +- drivers/jtdev_gpio.c | 10 +- drivers/mehfet.c | 461 ++++++++++++++++++++++++++++++++----- drivers/mehfet_proto.c | 14 +- drivers/mehfet_proto.h | 4 - drivers/pif.c | 39 +--- 10 files changed, 577 insertions(+), 151 deletions(-) diff --git a/drivers/jtaglib.c b/drivers/jtaglib.c index 493ba79..7215d1c 100644 --- a/drivers/jtaglib.c +++ b/drivers/jtaglib.c @@ -89,11 +89,18 @@ #define jtag_led_red_on(p) p->f->jtdev_led_red(p, 1) #define jtag_led_red_off(p) p->f->jtdev_led_red(p, 0) +#define jtag_ir_shift(p, ir) p->f->jtdev_ir_shift(p, ir) +#define jtag_dr_shift_8(p, dr) p->f->jtdev_dr_shift_8(p, dr) +#define jtag_dr_shift_16(p, dr) p->f->jtdev_dr_shift_16(p, dr) +#define jtag_tms_sequence(p, bits, tms) p->f->jtdev_tms_sequence(p, bits, tms) +#define jtag_init_dap(p) p->f->jtdev_init_dap(p) + /* Reset target JTAG interface and perform fuse-HW check */ -static void jtag_reset_tap(struct jtdev *p) +static void jtag_default_reset_tap(struct jtdev *p) { int loop_counter; + // TODO: replace with TMS seq? jtag_tms_set(p); jtag_tck_set(p); @@ -121,7 +128,7 @@ static void jtag_reset_tap(struct jtdev *p) /* This function sets the target JTAG state machine * back into the Run-Test/Idle state after a shift access */ -static void jtag_tclk_prep (struct jtdev *p) +static void jtag_default_tclk_prep (struct jtdev *p) { /* JTAG state = Exit-DR */ jtag_tck_clr(p); @@ -141,7 +148,7 @@ static void jtag_tclk_prep (struct jtdev *p) * data_out: data to be shifted out * return : scanned TDO value */ -static unsigned int jtag_shift( struct jtdev *p, +static unsigned int jtag_default_shift( struct jtdev *p, unsigned char num_bits, unsigned int data_out ) { @@ -171,7 +178,7 @@ static unsigned int jtag_shift( struct jtdev *p, p->f->jtdev_tclk(p, tclk_save); /* Set JTAG state back to Run-Test/Idle */ - jtag_tclk_prep(p); + jtag_default_tclk_prep(p); return data_in; } @@ -181,7 +188,7 @@ static unsigned int jtag_shift( struct jtdev *p, * instruction: 8 bit instruction * return : scanned TDO value */ -static unsigned int jtag_ir_shift(struct jtdev *p, unsigned int instruction) +uint8_t jtag_default_ir_shift(struct jtdev *p, uint8_t instruction) { /* JTAG state = Run-Test/Idle */ jtag_tms_set(p); @@ -202,7 +209,7 @@ static unsigned int jtag_ir_shift(struct jtdev *p, unsigned int instruction) jtag_tck_set(p); /* JTAG state = Shift-IR, Shift in TDI (8-bit) */ - return jtag_shift(p, 8, instruction); + return jtag_default_shift(p, 8, instruction); /* JTAG state = Run-Test/Idle */ } @@ -211,7 +218,7 @@ static unsigned int jtag_ir_shift(struct jtdev *p, unsigned int instruction) * data : 8 bit data * return: scanned TDO value */ -static unsigned int jtag_dr_shift_8(struct jtdev *p, unsigned int data) +uint8_t jtag_default_dr_shift_8(struct jtdev *p, uint8_t data) { /* JTAG state = Run-Test/Idle */ jtag_tms_set(p); @@ -228,7 +235,7 @@ static unsigned int jtag_dr_shift_8(struct jtdev *p, unsigned int data) jtag_tck_set(p); /* JTAG state = Shift-DR, Shift in TDI (16-bit) */ - return jtag_shift(p, 8, data); + return jtag_default_shift(p, 8, data); /* JTAG state = Run-Test/Idle */ } @@ -237,7 +244,7 @@ static unsigned int jtag_dr_shift_8(struct jtdev *p, unsigned int data) * data : 16 bit data * return: scanned TDO value */ -static unsigned int jtag_dr_shift_16(struct jtdev *p, unsigned int data) +uint16_t jtag_default_dr_shift_16(struct jtdev *p, uint16_t data) { /* JTAG state = Run-Test/Idle */ jtag_tms_set(p); @@ -254,11 +261,46 @@ static unsigned int jtag_dr_shift_16(struct jtdev *p, unsigned int data) jtag_tck_set(p); /* JTAG state = Shift-DR, Shift in TDI (16-bit) */ - return jtag_shift(p, 16, data); + return jtag_default_shift(p, 16, data); /* JTAG state = Run-Test/Idle */ } +void jtag_default_tms_sequence(struct jtdev *p, int bits, unsigned int value) +{ + for (int i = 0; i < bits; ++i) { + jtag_tck_clr(p); + if (value & (1u << i)) + jtag_tms_set(p); + else + jtag_tms_clr(p); + jtag_tck_set(p); + } +} + +void jtag_default_init_dap(struct jtdev *p) +{ + jtag_rst_clr(p); + p->f->jtdev_power_on(p); + jtag_tdi_set(p); + jtag_tms_set(p); + jtag_tck_set(p); + jtag_tclk_set(p); + + jtag_rst_set(p); + jtag_tst_clr(p); + + jtag_tst_set(p); + jtag_rst_clr(p); + jtag_tst_clr(p); + + jtag_tst_set(p); + + p->f->jtdev_connect(p); + jtag_rst_set(p); + jtag_default_reset_tap(p); +} + /* Set target CPU JTAG state machine into the instruction fetch state * return: 1 - instruction fetch was set * 0 - otherwise @@ -378,22 +420,25 @@ static int jtag_verify_psa(struct jtdev *p, /* Clock through the PSA */ jtag_tclk_set(p); - jtag_tck_clr(p); - jtag_tms_set(p); - jtag_tck_set(p); /* Select DR scan */ - jtag_tck_clr(p); - jtag_tms_clr(p); - jtag_tck_set(p); /* Capture DR */ - jtag_tck_clr(p); - jtag_tck_set(p); /* Shift DR */ - jtag_tck_clr(p); - jtag_tms_set(p); - jtag_tck_set(p); /* Exit DR */ - jtag_tck_clr(p); - jtag_tck_set(p); - jtag_tms_clr(p); - jtag_tck_clr(p); - jtag_tck_set(p); + + jtag_tms_sequence(p, 6, 0x19); // TMS=1 0 0 1 1 0 ; 6 clocks +// jtag_tck_clr(p); +// jtag_tms_set(p); +// jtag_tck_set(p); /* Select DR scan */ +// jtag_tck_clr(p); +// jtag_tms_clr(p); +// jtag_tck_set(p); /* Capture DR */ +// jtag_tck_clr(p); +// jtag_tck_set(p); /* Shift DR */ +// jtag_tck_clr(p); +// jtag_tms_set(p); +// jtag_tck_set(p); /* Exit DR */ +// jtag_tck_clr(p); +// jtag_tck_set(p); +// jtag_tms_clr(p); +// jtag_tck_clr(p); +// jtag_tck_set(p); + jtag_tclk_clr(p); } @@ -414,25 +459,7 @@ unsigned int jtag_init(struct jtdev *p) { unsigned int jtag_id; - jtag_rst_clr(p); - p->f->jtdev_power_on(p); - jtag_tdi_set(p); - jtag_tms_set(p); - jtag_tck_set(p); - jtag_tclk_set(p); - - jtag_rst_set(p); - jtag_tst_clr(p); - - jtag_tst_set(p); - jtag_rst_clr(p); - jtag_tst_clr(p); - - jtag_tst_set(p); - - p->f->jtdev_connect(p); - jtag_rst_set(p); - jtag_reset_tap(p); + jtag_init_dap(p); /* Check fuse */ if (jtag_is_fuse_blown(p)) { @@ -1155,3 +1182,40 @@ int jtag_get_config_fuses( struct jtdev *p ) return jtag_dr_shift_8(p, 0); } + +/*----------------------------------------------------------------------------*/ +int jtag_refresh_bps(const char *module, device_t dev, struct jtdev *p) +{ + int i; + int ret; + struct device_breakpoint *bp; + address_t addr; + ret = 0; + + for (i = 0; i < dev->max_breakpoints; i++) { + bp = &dev->breakpoints[i]; + + printc_dbg("%s: refresh breakpoint %d: type=%d " + "addr=%04x flags=%04x\n", module, + i, bp->type, bp->addr, bp->flags); + + if ( (bp->flags & DEVICE_BP_DIRTY) && + (bp->type == DEVICE_BPTYPE_BREAK) ) { + addr = bp->addr; + + if ( !(bp->flags & DEVICE_BP_ENABLED) ) { + addr = 0; + } + + if ( jtag_set_breakpoint (p, i, addr) == 0) { + printc_err("%s: failed to refresh " + "breakpoint #%d\n", module, i); + ret = -1; + } else { + bp->flags &= ~DEVICE_BP_DIRTY; + } + } + } + + return ret; +} diff --git a/drivers/jtaglib.h b/drivers/jtaglib.h index 0f99f78..63a248a 100644 --- a/drivers/jtaglib.h +++ b/drivers/jtaglib.h @@ -36,6 +36,7 @@ #include +#include "device.h" #include "jtdev.h" #include "util.h" @@ -117,4 +118,14 @@ unsigned int jtag_set_breakpoint(struct jtdev *p, unsigned int jtag_cpu_state(struct jtdev *p); int jtag_get_config_fuses(struct jtdev *p); +/* Default low-level JTAG routines for jtdev implementations that don't have + * their own implementations of these routines */ +uint8_t jtag_default_ir_shift(struct jtdev *p, uint8_t ir); +uint8_t jtag_default_dr_shift_8(struct jtdev *p, uint8_t dr); +uint16_t jtag_default_dr_shift_16(struct jtdev *p, uint16_t dr); +void jtag_default_tms_sequence(struct jtdev *p, int bits, unsigned int value); +void jtag_default_init_dap(struct jtdev *p); + +int jtag_refresh_bps(const char *driver, device_t dev, struct jtdev *p); + #endif diff --git a/drivers/jtdev.c b/drivers/jtdev.c index 5dea27d..dce1cea 100644 --- a/drivers/jtdev.c +++ b/drivers/jtdev.c @@ -22,7 +22,7 @@ */ #include -#include "jtdev.h" +#include "jtaglib.h" #include "output.h" #if defined(__linux__) || \ @@ -354,6 +354,12 @@ const struct jtdev_func jtdev_func_pif = { .jtdev_tclk_get = jtpif_tclk_get, .jtdev_tclk_strobe = jtpif_tclk_strobe, .jtdev_led_green = jtpif_led_green, - .jtdev_led_red = jtpif_led_red + .jtdev_led_red = jtpif_led_red, + + .jtdev_ir_shift = jtag_default_ir_shift, + .jtdev_dr_shift_8 = jtag_default_dr_shift_8, + .jtdev_dr_shift_16 = jtag_default_dr_shift_16, + .jtdev_tms_sequence= jtag_default_tms_sequence, + .jtdev_init_dap = jtag_default_init_dap }; diff --git a/drivers/jtdev.h b/drivers/jtdev.h index 88bd52b..22ab31d 100644 --- a/drivers/jtdev.h +++ b/drivers/jtdev.h @@ -64,6 +64,21 @@ struct jtdev_func{ void (*jtdev_led_green)(struct jtdev *p, int out); void (*jtdev_led_red)(struct jtdev *p, int out); + // * reset tap (+fuse check) + // * irshift + // * drshift8 + // * drshift16 + // * tclk clr/set + // * PSA needs special treatment! (or just replace with TMS sequence?) + // * jtag_init: idk but it needs something. maybe just special-case it + // TODO: need something to signal when we can switch clock speed for TCLK bursts + +/* Optional functions implementing higher-level stuff */ + uint8_t (*jtdev_ir_shift)(struct jtdev *p, uint8_t ir); + uint8_t (*jtdev_dr_shift_8)(struct jtdev *p, uint8_t dr); + uint16_t (*jtdev_dr_shift_16)(struct jtdev *p, uint16_t dr); + void (*jtdev_tms_sequence)(struct jtdev *p, int bits, unsigned int value); + void (*jtdev_init_dap)(struct jtdev *p); }; extern const struct jtdev_func jtdev_func_pif; diff --git a/drivers/jtdev_bus_pirate.c b/drivers/jtdev_bus_pirate.c index 641ec53..e88130c 100644 --- a/drivers/jtdev_bus_pirate.c +++ b/drivers/jtdev_bus_pirate.c @@ -22,7 +22,7 @@ */ #include -#include "jtdev.h" +#include "jtaglib.h" #include "output.h" #if defined(__linux__) @@ -352,6 +352,12 @@ const struct jtdev_func jtdev_func_bp = { .jtdev_tclk_get = jtbp_tclk_get, .jtdev_tclk_strobe = jtbp_tclk_strobe, .jtdev_led_green = jtbp_led_green, - .jtdev_led_red = jtbp_led_red + .jtdev_led_red = jtbp_led_red, + + .jtdev_ir_shift = jtag_default_ir_shift, + .jtdev_dr_shift_8 = jtag_default_dr_shift_8, + .jtdev_dr_shift_16 = jtag_default_dr_shift_16, + .jtdev_tms_sequence= jtag_default_tms_sequence, + .jtdev_init_dap = jtag_default_init_dap }; diff --git a/drivers/jtdev_gpio.c b/drivers/jtdev_gpio.c index b36cffa..7db6514 100644 --- a/drivers/jtdev_gpio.c +++ b/drivers/jtdev_gpio.c @@ -21,7 +21,7 @@ */ #include -#include "jtdev.h" +#include "jtaglib.h" #include "output.h" #if defined(__linux__) || \ @@ -263,5 +263,11 @@ const struct jtdev_func jtdev_func_gpio = { .jtdev_tclk_get = jtgpio_tclk_get, .jtdev_tclk_strobe = jtgpio_tclk_strobe, .jtdev_led_green = jtgpio_led_green, - .jtdev_led_red = jtgpio_led_red + .jtdev_led_red = jtgpio_led_red, + + .jtdev_ir_shift = jtag_default_ir_shift, + .jtdev_dr_shift_8 = jtag_default_dr_shift_8, + .jtdev_dr_shift_16 = jtag_default_dr_shift_16, + .jtdev_tms_sequence= jtag_default_tms_sequence, + .jtdev_init_dap = jtag_default_init_dap }; diff --git a/drivers/mehfet.c b/drivers/mehfet.c index e81a3f2..20d38cc 100644 --- a/drivers/mehfet.c +++ b/drivers/mehfet.c @@ -1,4 +1,5 @@ +#include #include #include #include @@ -6,6 +7,7 @@ #include "util.h" #include "output.h" #include "ctrlc.h" +#include "jtaglib.h" #include "mehfet_proto.h" #include "mehfet_xport.h" @@ -14,11 +16,379 @@ struct mehfet_device { struct device base; + struct jtdev jtag; transport_t trans; enum mehfet_conn connstat; }; +/*extern void __builtin_trap(void);*/ +#define NO_LL_JTAG_BP 0 +#define no_ll_jtag() \ + do { \ + printc_err("mehfet: %s: low-lewel JTAG function not implemented!\n", __func__); \ + p->failed = 1; \ + if (NO_LL_JTAG_BP) /*__builtin_trap()*/; \ + } while (0) \ + + +#define JTMF_GET_DEV(p) ((struct mehfet_device*)((size_t)(p) - \ + offsetof(struct mehfet_device, jtag))) \ + + +static int jtmf_open(struct jtdev* p, const char* device) +{ + printc_err("mehfet: %s should not get called.\n", __func__); + p->failed = 1; + return -1; +} +static void jtmf_close(struct jtdev* p) +{ + printc_err("mehfet: %s should not get called.\n", __func__); + p->failed = 1; +} +static void jtmf_power_on(struct jtdev* p) +{ + printc_err("mehfet: %s should not get called.\n", __func__); + p->failed = 1; +} +static void jtmf_power_off(struct jtdev* p) +{ + printc_err("mehfet: %s should not get called.\n", __func__); + p->failed = 1; +} +static void jtmf_connect(struct jtdev* p) +{ + printc_err("mehfet: %s should not get called.\n", __func__); + p->failed = 1; +} +static void jtmf_release(struct jtdev* p) +{ + printc_err("mehfet: %s should not get called.\n", __func__); + p->failed = 1; +} + +static void jtmf_tck(struct jtdev* p, int _) { (void)_; no_ll_jtag(); } +static void jtmf_tms(struct jtdev* p, int _) { (void)_; no_ll_jtag(); } +static void jtmf_tdi(struct jtdev* p, int _) { (void)_; no_ll_jtag(); } +static void jtmf_rst(struct jtdev* p, int _) { (void)_; no_ll_jtag(); } +static void jtmf_tst(struct jtdev* p, int _) { (void)_; no_ll_jtag(); } +static int jtmf_tdo_get(struct jtdev* p) { no_ll_jtag(); return 0; } + +static void jtmf_tclk(struct jtdev* p, int out) +{ + struct mehfet_device* d = JTMF_GET_DEV(p); + + int r = mehfet_cmd_tclk_edge(d->trans, out); + if (r < 0) p->failed = 1; +} +static int jtmf_tclk_get(struct jtdev* p) +{ + struct mehfet_device* d = JTMF_GET_DEV(p); + int ret = 1; + + enum mehfet_lines lines = 0; + int r = mehfet_cmd_get_old_lines(d->trans, &lines); + if (r < 0) { + p->failed = 1; + } else { + ret = (lines & mehfet_line_tclk) ? 1 : 0; + } + + return ret; +} +static void jtmf_tclk_strobe(struct jtdev* p, unsigned int count) +{ + struct mehfet_device* d = JTMF_GET_DEV(p); + + int r = mehfet_cmd_tclk_burst(d->trans, count); + if (r < 0) p->failed = 1; +} + +/* MehFET has no leds */ +static void jtmf_led_green(struct jtdev* p, int out) { (void)p; (void)out; } +static void jtmf_led_red (struct jtdev* p, int out) { (void)p; (void)out; } + +static uint8_t jtmf_ir_shift(struct jtdev *p, uint8_t ir) +{ + struct mehfet_device* d = JTMF_GET_DEV(p); + + uint8_t ret = 0; + int r = mehfet_cmd_irshift(d->trans, ir, &ret); + if (r < 0) p->failed = 1; + + return ret; +} +static uint8_t jtmf_dr_shift_8(struct jtdev *p, uint8_t dr) +{ + struct mehfet_device* d = JTMF_GET_DEV(p); + + uint8_t ret = 0; + int r = mehfet_cmd_drshift(d->trans, 8, &dr, &ret); + if (r < 0) p->failed = 1; + + return ret; +} +static uint16_t jtmf_dr_shift_16(struct jtdev *p, uint16_t dr) +{ + struct mehfet_device* d = JTMF_GET_DEV(p); + + uint8_t inbuf[2] = { dr & 0xff, (dr >> 8) & 0xff }; + uint8_t outbuf[2]; + int r = mehfet_cmd_drshift(d->trans, 16, inbuf, outbuf); + if (r < 0) p->failed = 1; + + return outbuf[0] | ((uint16_t)outbuf[1] << 8); +} +static void jtmf_tms_sequence(struct jtdev *p, int bits, unsigned int value) +{ + struct mehfet_device* d = JTMF_GET_DEV(p); + + enum mehfet_lines lines = 0; + int r = mehfet_cmd_get_old_lines(d->trans, &lines); + if (r < 0) { + p->failed = 1; + return; + } + + uint8_t dbuf[4] = { value & 0xff, (value >> 8) & 0xff, + (value >> 16) & 0xff, (value >> 24) & 0xff }; + r = mehfet_cmd_tms_seq(d->trans, lines & mehfet_line_tdi, bits, dbuf); + if (r < 0) p->failed = 1; +} +static void jtmf_init_dap(struct jtdev *p) +{ + struct mehfet_device* dev = JTMF_GET_DEV(p); + + enum mehfet_resettap_status stat = 0; + int r = mehfet_cmd_reset_tap(dev->trans, mehfet_rsttap_do_reset + | mehfet_rsttap_fuse_do, &stat); + + if (r < 0) p->failed = 1; +} + + +static const struct jtdev_func jtdev_func_mehfet = { + .jtdev_open = jtmf_open, + .jtdev_close = jtmf_close, + .jtdev_power_on = jtmf_power_on, + .jtdev_power_off = jtmf_power_off, + .jtdev_connect = jtmf_connect, + .jtdev_release = jtmf_release, + .jtdev_tck = jtmf_tck, + .jtdev_tms = jtmf_tms, + .jtdev_tdi = jtmf_tdi, + .jtdev_rst = jtmf_rst, + .jtdev_tst = jtmf_tst, + .jtdev_tdo_get = jtmf_tdo_get, + .jtdev_tclk = jtmf_tclk, + .jtdev_tclk_get = jtmf_tclk_get, + .jtdev_tclk_strobe = jtmf_tclk_strobe, + .jtdev_led_green = jtmf_led_green, + .jtdev_led_red = jtmf_led_red, + + .jtdev_ir_shift = jtmf_ir_shift, + .jtdev_dr_shift_8 = jtmf_dr_shift_8, + .jtdev_dr_shift_16 = jtmf_dr_shift_16, + .jtdev_tms_sequence= jtmf_tms_sequence, + .jtdev_init_dap = jtmf_init_dap +}; + + +/*---------------------------------------------------------------------------*/ + +// TODO: these five are kinda copied from pif.c, should be deduplicated + +static int read_words(device_t dev_base, const struct chipinfo_memory *m, + address_t addr, address_t len, uint8_t *data) +{ + struct mehfet_device* dev = (struct mehfet_device*)dev_base; + struct jtdev *p = &dev->jtag; + + for (unsigned int index = 0; index < len; index += 2) { + unsigned int word = jtag_read_mem(p, 16, addr+index); + data[index ] = word & 0x00ff; + data[index+1] = (word >> 8) & 0x00ff; + } + + return p->failed ? -1 : len; +} + +static int write_ram_word(struct jtdev *p, address_t addr, uint16_t value) +{ + jtag_write_mem(p, 16, addr, value); + + return p->failed ? -1 : 0; +} + +static int write_flash_block(struct jtdev *p, address_t addr, + address_t len, const uint8_t *data) +{ + uint16_t* word = malloc( len / 2 * sizeof(*word) ); + if (!word) { + pr_error("mehfet: failed to allocate memory"); + return -1; + } + + for (unsigned int i = 0; i < len/2; i++) { + word[i]=data[2*i] + (((uint16_t)data[2*i+1]) << 8); + } + jtag_write_flash(p, addr, len/2, word); + + free(word); + + return p->failed ? -1 : 0; +} + +/* Write a word-aligned block to any kind of memory. + * returns the number of bytes written or -1 on failure + */ +static int write_words(device_t dev_base, const struct chipinfo_memory *m, + address_t addr, address_t len, const uint8_t *data) +{ + struct mehfet_device* dev = (struct mehfet_device*)dev_base; + struct jtdev *p = &dev->jtag; + int r; + + if (m->type != CHIPINFO_MEMTYPE_FLASH) { + len = 2; + r = write_ram_word(p, addr, r16le(data)); + } else { + r = write_flash_block(p, addr, len, data); + } + + if (r < 0) { + printc_err("mehfet: write_words at address 0x%x failed\n", addr); + return -1; + } + + return len; +} + +/*---------------------------------------------------------------------------*/ + +static int mehfet_readmem(device_t dev_base, address_t addr, + uint8_t *mem, address_t len) +{ + struct mehfet_device* dev = (struct mehfet_device*)dev_base; + dev->jtag.failed = 0; + return readmem(dev_base, addr, mem, len, read_words); +} + +static int mehfet_writemem(device_t dev_base, address_t addr, + const uint8_t *mem, address_t len) +{ + struct mehfet_device* dev = (struct mehfet_device*)dev_base; + dev->jtag.failed = 0; + return writemem(dev_base, addr, mem, len, write_words, read_words); +} + +static int mehfet_setregs(device_t dev_base, const address_t *regs) +{ + struct mehfet_device* dev = (struct mehfet_device*)dev_base; + + dev->jtag.failed = 0; + + for (int i = 0; i < DEVICE_NUM_REGS; i++) { + jtag_write_reg(&dev->jtag, i, regs[i]); + } + return dev->jtag.failed ? -1 : 0; +} + +static int mehfet_getregs(device_t dev_base, address_t *regs) +{ + struct mehfet_device* dev = (struct mehfet_device*)dev_base; + + dev->jtag.failed = 0; + + for (int i = 0; i < DEVICE_NUM_REGS; i++) + regs[i] = jtag_read_reg(&dev->jtag, i); + + return dev->jtag.failed ? -1 : 0; +} + +static int mehfet_ctl(device_t dev_base, device_ctl_t type) +{ + struct mehfet_device* dev = (struct mehfet_device*)dev_base; + + dev->jtag.failed = 0; + + switch (type) { + case DEVICE_CTL_RESET: + /* perform soft reset */ + jtag_execute_puc(&dev->jtag); + break; + + case DEVICE_CTL_RUN: + /* transfer changed breakpoints to device */ + if (jtag_refresh_bps("mehfet", &dev->base, &dev->jtag) < 0) return -1; + + /* start program execution at current PC */ + jtag_release_device(&dev->jtag, 0xffff); + break; + + case DEVICE_CTL_HALT: + /* take device under JTAG control */ + jtag_get_device(&dev->jtag); + break; + + case DEVICE_CTL_STEP: + /* execute next instruction at current PC */ + jtag_single_step(&dev->jtag); + break; + + default: + printc_err("mehfet: unsupported operation\n"); + return -1; + } + + return dev->jtag.failed ? -1 : 0; +} + +static device_status_t mehfet_poll(device_t dev_base) +{ + struct mehfet_device* dev = (struct mehfet_device*)dev_base; + + if (delay_ms(100) < 0 || ctrlc_check()) + return DEVICE_STATUS_INTR; + + if (jtag_cpu_state(&dev->jtag) == 1) return DEVICE_STATUS_HALTED; + + return DEVICE_STATUS_RUNNING; +} + +static int mehfet_erase(device_t dev_base, device_erase_type_t type, + address_t addr) +{ + struct mehfet_device* dev = (struct mehfet_device*)dev_base; + + dev->jtag.failed = 0; + + switch (type) { + case DEVICE_ERASE_MAIN: + jtag_erase_flash(&dev->jtag, JTAG_ERASE_MAIN, addr); + break; + case DEVICE_ERASE_ALL: + jtag_erase_flash(&dev->jtag, JTAG_ERASE_MASS, addr); + break; + case DEVICE_ERASE_SEGMENT: + jtag_erase_flash(&dev->jtag, JTAG_ERASE_SGMT, addr); + break; + default: return -1; + } + + return dev->jtag.failed ? -1 : 0; +} + +static int mehfet_getconfigfuses(device_t dev_base) +{ + struct mehfet_device* dev = (struct mehfet_device*)dev_base; + + return jtag_get_config_fuses(&dev->jtag); +} + +/*---------------------------------------------------------------------------*/ + static int check_dev_ok(struct mehfet_device* dev, const struct device_args* args, enum mehfet_conn* useconn) { transport_t t = dev->trans; @@ -72,19 +442,46 @@ static int check_dev_ok(struct mehfet_device* dev, const struct device_args* arg return 0; } +static int init_device(struct mehfet_device* dev) { + printc_dbg("Starting JTAG\n"); + + unsigned int jtagid = jtag_init(&dev->jtag); + if (dev->jtag.failed) return -1; + + printc("JTAG ID: 0x%02x\n", jtagid); + if (jtagid != 0x89 && jtagid != 0x91) { + printc_err("mehfet: unexpected JTAG ID: 0x%02x\n", jtagid); + jtag_release_device(&dev->jtag, 0xfffe); + return -1; + } + + // JTAG fuse check has been performed, so we can now switch to a + // higher-speed physical transport suitable for ~350 kHz TCLK strobes used + // in (and required for) flash programming + int r = 0;//mehfet_cmd_set_clkspeed(dev->trans, true); + if (r < 0) { + jtag_release_device(&dev->jtag, 0xfffe); + return -1; + } + + return 0; +} + static void mehfet_destroy(device_t dev_base) { struct mehfet_device* dev = (struct mehfet_device*)dev_base; + if (!dev) return; + + jtag_release_device(&dev->jtag, 0xfffe); // 0xfffe=reset address : POR + + mehfet_cmd_disconnect(dev->trans); + if (dev->trans) { dev->trans->ops->destroy(dev->trans); dev->trans = NULL; } - // TODO: - // * release device (POR?) - // * Disconnect - free(dev); } @@ -106,6 +503,7 @@ static device_t mehfet_open(const struct device_args* args) { dev->base.type = &device_mehfet; dev->base.max_breakpoints = 2; // TODO dev->base.need_probe = 1; // TODO + dev->jtag.f = &jtdev_func_mehfet; // the MehFET currently doesn't have a designated PID, so we can't really // default to one. @@ -130,10 +528,8 @@ static device_t mehfet_open(const struct device_args* args) { goto FAIL; } - // TODO: - // * GetDevice stuff - // - // => TODO: slau320 routines! + r = init_device(dev); + if (r < 0) goto FAIL; return (device_t)dev; @@ -142,55 +538,6 @@ FAIL: return NULL; } -static int mehfet_readmem(device_t dev_base, address_t addr, - uint8_t *mem, address_t len) -{ - return -1; -} - -static int mehfet_writemem(device_t dev_base, address_t addr, - const uint8_t *mem, address_t len) -{ - return -1; -} - -static int mehfet_setregs(device_t dev_base, const address_t *regs) -{ - (void)dev_base; - (void)regs; - - return -1; -} - -static int mehfet_getregs(device_t dev_base, address_t *regs) -{ - (void)dev_base; - (void)regs; - - return -1; -} - -static int mehfet_ctl(device_t dev_base, device_ctl_t type) -{ - return -1; -} - -static device_status_t mehfet_poll(device_t dev_base) -{ - return DEVICE_STATUS_RUNNING; -} - -static int mehfet_erase(device_t dev_base, device_erase_type_t type, - address_t addr) -{ - return -1; -} - -static int mehfet_getconfigfuses(device_t dev_base) -{ - return -1; -} - const struct device_class device_mehfet = { .name = "mehfet", .help = "MehFET USB JTAG/SBW device", diff --git a/drivers/mehfet_proto.c b/drivers/mehfet_proto.c index 320fd56..8691819 100644 --- a/drivers/mehfet_proto.c +++ b/drivers/mehfet_proto.c @@ -377,9 +377,21 @@ int mehfet_cmd_reset_tap(transport_t t, enum mehfet_resettap_flags flags, return 0; } + +static uint8_t bitswap_nyb(uint8_t in) { + return ((in >> 3) & 1) | ((in >> 1) & 2) | ((in << 1) & 4) | ((in << 3) & 8); +} +static uint8_t bitswap(uint8_t in) { + return (bitswap_nyb(in&0xf) << 4) | bitswap_nyb(in>>4); +} + int mehfet_cmd_irshift(transport_t t, uint8_t newir, uint8_t* oldir) { if (!oldir) return -1; + // NOTE: jtaglib.c uses bitswapped IR values, while MehFET uses values from + // the SLAU320 PDF, so we need to perform a bitswap here + newir = bitswap(newir); + uint8_t buf[64]; int r; @@ -434,7 +446,7 @@ int mehfet_cmd_drshift(transport_t t, uint32_t nbits, const uint8_t* newdr, uint memcpy(olddr, buf, nbytes); #ifdef DEBUG_MEHFET_DRIVER - printc_dbg("mehfet: IRshift(nbits=%u):\n", nbits); + printc_dbg("mehfet: DRshift(nbits=%u):\n", nbits); debug_hexdump("\tin ", newdr, nbytes); debug_hexdump("\tout", olddr, nbytes); #endif diff --git a/drivers/mehfet_proto.h b/drivers/mehfet_proto.h index 4341885..b886ae6 100644 --- a/drivers/mehfet_proto.h +++ b/drivers/mehfet_proto.h @@ -22,7 +22,6 @@ enum mehfet_cmd { mehfet_reset_tap = 0x0c, mehfet_irshift = 0x0d, mehfet_drshift = 0x0e, - mehfet_loop = 0x0f, }; enum mehfet_caps { @@ -88,8 +87,5 @@ int mehfet_cmd_reset_tap(transport_t t, enum mehfet_resettap_flags flags, enum m int mehfet_cmd_irshift(transport_t t, uint8_t newir, uint8_t* oldir); int mehfet_cmd_drshift(transport_t t, uint32_t nbits, const uint8_t* newdr, uint8_t* olddr); -// TODO: Loop - - #endif diff --git a/drivers/pif.c b/drivers/pif.c index 0b07753..70bca8b 100644 --- a/drivers/pif.c +++ b/drivers/pif.c @@ -144,43 +144,6 @@ static int init_device(struct jtdev *p) /*===== MSPDebug Device interface ============================================*/ -/*----------------------------------------------------------------------------*/ -static int refresh_bps(struct pif_device *dev) -{ - int i; - int ret; - struct device_breakpoint *bp; - address_t addr; - ret = 0; - - for (i = 0; i < dev->base.max_breakpoints; i++) { - bp = &dev->base.breakpoints[i]; - - printc_dbg("refresh breakpoint %d: type=%d " - "addr=%04x flags=%04x\n", - i, bp->type, bp->addr, bp->flags); - - if ( (bp->flags & DEVICE_BP_DIRTY) && - (bp->type == DEVICE_BPTYPE_BREAK) ) { - addr = bp->addr; - - if ( !(bp->flags & DEVICE_BP_ENABLED) ) { - addr = 0; - } - - if ( jtag_set_breakpoint (&dev->jtag, i, addr) == 0) { - printc_err("pif: failed to refresh " - "breakpoint #%d\n", i); - ret = -1; - } else { - bp->flags &= ~DEVICE_BP_DIRTY; - } - } - } - - return ret; -} - /*----------------------------------------------------------------------------*/ static int pif_readmem( device_t dev_base, address_t addr, @@ -246,7 +209,7 @@ static int pif_ctl(device_t dev_base, device_ctl_t type) case DEVICE_CTL_RUN: /* transfer changed breakpoints to device */ - if (refresh_bps(dev) < 0) { + if (jtag_refresh_bps("pif", &dev->base, &dev->jtag) < 0) { return -1; } /* start program execution at current PC */