woah it works
This commit is contained in:
parent
6573bbb6da
commit
d64791bac6
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#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
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#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
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#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
|
||||
};
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#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
|
||||
};
|
||||
|
|
461
drivers/mehfet.c
461
drivers/mehfet.c
|
@ -1,4 +1,5 @@
|
|||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue