diff --git a/drivers/jtaglib.c b/drivers/jtaglib.c index 493ba79..c74adb9 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_sequence()? */ 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,10 @@ 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); + + /* Go through DR path without shifting data in/out */ + jtag_tms_sequence(p, 6, 0x19); /* TMS=1 0 0 1 1 0 ; 6 clocks */ + jtag_tclk_clr(p); } @@ -414,25 +444,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)) { @@ -1151,7 +1163,44 @@ unsigned int jtag_cpu_state( struct jtdev *p ) /*----------------------------------------------------------------------------*/ int jtag_get_config_fuses( struct jtdev *p ) { - jtag_ir_shift(p, IR_CONFIG_FUSES); + jtag_ir_shift(p, IR_CONFIG_FUSES); - return jtag_dr_shift_8(p, 0); + 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..0755d92 100644 --- a/drivers/jtdev.h +++ b/drivers/jtdev.h @@ -64,6 +64,12 @@ struct jtdev_func{ void (*jtdev_led_green)(struct jtdev *p, int out); void (*jtdev_led_red)(struct jtdev *p, int out); +/* 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 d22bef1..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__) @@ -186,7 +186,8 @@ static void jtbp_close(struct jtdev *p) out_buff = 0x0f; // Don't care if this fails, user can just power cycle the bus pirate - if(write(p->port, &out_buff, 1)); + if(write(p->port, &out_buff, 1)) + ; close(p->port); } @@ -351,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/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 */