woah it works

This commit is contained in:
Triss 2021-10-07 01:12:04 +02:00
parent 6573bbb6da
commit d64791bac6
10 changed files with 577 additions and 151 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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
};

View File

@ -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;

View File

@ -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
};

View File

@ -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
};

View File

@ -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",

View File

@ -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

View File

@ -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

View File

@ -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 */