jtagdev, pif, mehfet: refactor device_class ops to be unified under jtagdev instead of using separate implementations

This commit is contained in:
Triss 2022-07-24 15:14:27 +02:00
parent 0a8ebf4a66
commit ddfffa06fb
5 changed files with 248 additions and 571 deletions

View File

@ -35,10 +35,14 @@
*/ */
#include <stdlib.h> #include <stdlib.h>
#include "jtaglib.h" #include "jtaglib.h"
#include "output.h"
#include "jtaglib_defs.h" #include "jtaglib_defs.h"
#include "output.h"
#include "ctrlc.h"
#include "device.h"
/* Reset target JTAG interface and perform fuse-HW check */ /* Reset target JTAG interface and perform fuse-HW check */
static void jtag_default_reset_tap(struct jtdev *p) static void jtag_default_reset_tap(struct jtdev *p)
{ {
@ -525,7 +529,7 @@ int jtag_is_fuse_blown (struct jtdev *p)
} }
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
int jtag_refresh_bps(const char *module, device_t dev, struct jtdev *p) int jtag_refresh_bps(device_t dev, struct jtdev *p)
{ {
int i; int i;
int ret; int ret;
@ -536,9 +540,8 @@ int jtag_refresh_bps(const char *module, device_t dev, struct jtdev *p)
for (i = 0; i < dev->max_breakpoints; i++) { for (i = 0; i < dev->max_breakpoints; i++) {
bp = &dev->breakpoints[i]; bp = &dev->breakpoints[i];
printc_dbg("%s: refresh breakpoint %d: type=%d " printc_dbg("jtaglib: refresh breakpoint %d: type=%d "
"addr=%04x flags=%04x\n", module, "addr=%04x flags=%04x\n", i, bp->type, bp->addr, bp->flags);
i, bp->type, bp->addr, bp->flags);
if ( (bp->flags & DEVICE_BP_DIRTY) && if ( (bp->flags & DEVICE_BP_DIRTY) &&
(bp->type == DEVICE_BPTYPE_BREAK) ) { (bp->type == DEVICE_BPTYPE_BREAK) ) {
@ -549,8 +552,7 @@ int jtag_refresh_bps(const char *module, device_t dev, struct jtdev *p)
} }
if ( jtag_set_breakpoint (p, i, addr) == 0) { if ( jtag_set_breakpoint (p, i, addr) == 0) {
printc_err("%s: failed to refresh " printc_err("jtaglib: failed to refresh breakpoint #%d\n", i);
"breakpoint #%d\n", module, i);
ret = -1; ret = -1;
} else { } else {
bp->flags &= ~DEVICE_BP_DIRTY; bp->flags &= ~DEVICE_BP_DIRTY;
@ -561,3 +563,184 @@ int jtag_refresh_bps(const char *module, device_t dev, struct jtdev *p)
return ret; return ret;
} }
/* ========================================================================= */
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("jtaglib: 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;
}
static int read_words(device_t dev_base, const struct chipinfo_memory *m,
address_t addr, address_t len, uint8_t *data) {
struct jtdev *p = (struct jtdev*)dev_base;
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_words(device_t dev_base, const struct chipinfo_memory *m,
address_t addr, address_t len, const uint8_t *data) {
struct jtdev *p = (struct jtdev*)dev_base;
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("jtaglib: write_words at address 0x%x failed\n", addr);
return -1;
}
return len;}
int jtag_dev_readmem(device_t dev_base, address_t addr, uint8_t *mem, address_t len) {
struct jtdev *p = (struct jtdev*)dev_base;
p->failed = 0;
return readmem(dev_base, addr, mem, len, read_words);
}
int jtag_dev_writemem(device_t dev_base, address_t addr, const uint8_t *mem, address_t len) {
struct jtdev *p = (struct jtdev*)dev_base;
p->failed = 0;
return writemem(dev_base, addr, mem, len, write_words, read_words);
}
int jtag_dev_erase(device_t dev_base, device_erase_type_t type, address_t addr) {
struct jtdev *p = (struct jtdev*)dev_base;
p->failed = 0;
switch (type) {
case DEVICE_ERASE_MAIN:
jtag_erase_flash(p, JTAG_ERASE_MAIN, addr);
break;
case DEVICE_ERASE_ALL:
jtag_erase_flash(p, JTAG_ERASE_MASS, addr);
break;
case DEVICE_ERASE_SEGMENT:
jtag_erase_flash(p, JTAG_ERASE_SGMT, addr);
break;
default: return -1;
}
return p->failed ? -1 : 0;
}
int jtag_dev_getregs(device_t dev_base, address_t *regs) {
struct jtdev *p = (struct jtdev*)dev_base;
p->failed = 0;
for (int i = 0; i < DEVICE_NUM_REGS; i++) {
regs[i] = jtag_read_reg(p, i);
}
return p->failed ? -1 : 0;
}
int jtag_dev_setregs(device_t dev_base, const address_t *regs) {
struct jtdev *p = (struct jtdev*)dev_base;
p->failed = 0;
for (int i = 0; i < DEVICE_NUM_REGS; i++) {
jtag_write_reg(p, i, regs[i]);
}
return p->failed ? -1 : 0;
}
int jtag_dev_ctl(device_t dev_base, device_ctl_t type) {
struct jtdev *p = (struct jtdev*)dev_base;
p->failed = 0;
switch (type) {
case DEVICE_CTL_RESET:
/* perform soft reset */
jtag_execute_puc(p);
break;
case DEVICE_CTL_RUN:
/* transfer changed breakpoints to device */
if (jtag_refresh_bps(&p->base, p) < 0)
return -1;
/* start program execution at current PC */
jtag_release_device(p, 0xffff);
break;
case DEVICE_CTL_HALT:
/* take device under JTAG control */
jtag_get_device(p);
break;
case DEVICE_CTL_STEP:
/* execute next instruction at current PC */
jtag_single_step(p);
break;
default:
printc_err("mehfet: unsupported operation %d\n", type);
return -1;
}
return p->failed ? -1 : 0;
}
device_status_t jtag_dev_poll(device_t dev_base) {
struct jtdev *p = (struct jtdev*)dev_base;
if (delay_ms(100) < 0 || ctrlc_check())
return DEVICE_STATUS_INTR;
int r = jtag_cpu_state(p);
if (r == 1) return DEVICE_STATUS_HALTED;
return DEVICE_STATUS_RUNNING;
}
int jtag_dev_getconfigfuses(device_t dev_base) {
struct jtdev *p = (struct jtdev*)dev_base;
return jtag_get_config_fuses(p);
}
int jtag_dev_init(struct jtdev *p) {
unsigned int jtagid = jtag_init(p);
if (p->failed) return -1;
printc("JTAG ID: 0x%02x\n", jtagid);
// TODO: validate JTAG ID in a better way!
if (jtagid != 0x89 && jtagid != 0x91) {
printc_err("mehfet: unexpected JTAG ID: 0x%02x\n", jtagid);
jtag_release_device(p, 0xfffe);
return -1;
}
return 0;
}

View File

@ -40,11 +40,6 @@
#include "jtdev.h" #include "jtdev.h"
#include "util.h" #include "util.h"
/* Flash erasing modes */
#define JTAG_ERASE_MASS 0xA506
#define JTAG_ERASE_MAIN 0xA504
#define JTAG_ERASE_SGMT 0xA502
/* Colleciton of functions that need different implementation for different /* Colleciton of functions that need different implementation for different
* CPU types (that is, 16-bit vs CPUX vs Xv2) */ * CPU types (that is, 16-bit vs CPUX vs Xv2) */
struct jtaglib_funcs { struct jtaglib_funcs {
@ -167,6 +162,16 @@ uint32_t jtag_default_dr_shift_20(struct jtdev *p, uint32_t dr);
void jtag_default_tms_sequence(struct jtdev *p, int bits, unsigned int value); void jtag_default_tms_sequence(struct jtdev *p, int bits, unsigned int value);
void jtag_default_init_dap(struct jtdev *p); void jtag_default_init_dap(struct jtdev *p);
int jtag_refresh_bps(const char *driver, device_t dev, struct jtdev *p); int jtag_refresh_bps(device_t dev, struct jtdev *p);
int jtag_dev_readmem(device_t dev_base, address_t addr, uint8_t *mem, address_t len);
int jtag_dev_writemem(device_t dev_base, address_t addr, const uint8_t *mem, address_t len);
int jtag_dev_getregs(device_t dev_base, address_t *regs);
int jtag_dev_setregs(device_t dev_base, const address_t *regs);
int jtag_dev_ctl(device_t dev_base, device_ctl_t type);
device_status_t jtag_dev_poll(device_t dev_base);
int jtag_dev_erase(device_t dev_base, device_erase_type_t, address_t addr);
int jtag_dev_getconfigfuses(device_t dev_base);
int jtag_dev_init(struct jtdev *p);
#endif #endif

View File

@ -2,6 +2,11 @@
#include "jtaglib.h" #include "jtaglib.h"
#include "eem_defs.h" #include "eem_defs.h"
/* Flash erasing modes */
#define JTAG_ERASE_MASS 0xA506
#define JTAG_ERASE_MAIN 0xA504
#define JTAG_ERASE_SGMT 0xA502
/* JTAG identification value for all existing Flash-based MSP430 devices /* JTAG identification value for all existing Flash-based MSP430 devices
*/ */
#define JTAG_ID_CPU16 0x89 #define JTAG_ID_CPU16 0x89

View File

@ -223,257 +223,6 @@ static const struct jtdev_func jtdev_func_mehfet = {
}; };
/*---------------------------------------------------------------------------*/
// 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)
{
#ifdef DEBUG_MEHFET_DRIVER
printc_dbg("mehfet: read_words: addr=0x%04x, len=0x%x\n", addr, len);
#endif
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) {
#ifdef DEBUG_MEHFET_DRIVER
printc_dbg("mehfet: write_words: addr=0x%04x, len=0x%x data=0x%04x\n",
addr, len, r16le(data));
if (len != 2) {
printc_dbg("mehfet: WARN: write_words: len != 2! but 0x%04x\n", len);
__builtin_trap();
}
#endif
len = 2;
r = write_ram_word(p, addr, r16le(data));
} else {
#ifdef DEBUG_MEHFET_DRIVER
printc_dbg("mehfet: write_flash_block: addr=0x%04x, len=0x%x\n", addr, len);
#endif
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;
#ifdef DEBUG_MEHFET_DRIVER
printc_dbg("mehfet: set regs\n");
#endif
for (int i = 0; i < DEVICE_NUM_REGS; i++) {
#ifdef DEBUG_MEHFET_DRIVER
printc_dbg("mehfet: [%d] = 0x%04x\n", i, regs[i]);
#endif
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;
#ifdef DEBUG_MEHFET_DRIVER
printc_dbg("mehfet: get regs\n");
#endif
for (int i = 0; i < DEVICE_NUM_REGS; i++) {
regs[i] = jtag_read_reg(&dev->jtag, i);
#ifdef DEBUG_MEHFET_DRIVER
printc_dbg("mehfet: [%d] = 0x%04x\n", i, regs[i]);
#endif
}
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 */
#ifdef DEBUG_MEHFET_DRIVER
printc_dbg("mehfet: soft reset (PUC)\n");
#endif
jtag_execute_puc(&dev->jtag);
break;
case DEVICE_CTL_RUN:
#ifdef DEBUG_MEHFET_DRIVER
printc_dbg("mehfet: set breakpoints\n");
#endif
/* transfer changed breakpoints to device */
if (jtag_refresh_bps("mehfet", &dev->jtag.base, &dev->jtag) < 0) return -1;
#ifdef DEBUG_MEHFET_DRIVER
printc_dbg("mehfet: run @ current PC\n");
#endif
/* start program execution at current PC */
jtag_release_device(&dev->jtag, 0xffff);
break;
case DEVICE_CTL_HALT:
#ifdef DEBUG_MEHFET_DRIVER
printc_dbg("mehfet: halt\n");
#endif
/* take device under JTAG control */
jtag_get_device(&dev->jtag);
break;
case DEVICE_CTL_STEP:
#ifdef DEBUG_MEHFET_DRIVER
printc_dbg("mehfet: single-step\n");
#endif
/* execute next instruction at current PC */
jtag_single_step(&dev->jtag);
break;
default:
printc_err("mehfet: unsupported operation %d\n", type);
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;
int r = jtag_cpu_state(&dev->jtag);
#ifdef DEBUG_MEHFET_DRIVER
printc_dbg("mehfet: cpu state: %d\n", r);
#endif
if (r == 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;
}
#ifdef DEBUG_MEHFET_DRIVER
printc_dbg("mehfet: erase flash %d at %04x: %s\n", type, addr, dev->jtag.failed ? "failed" : "succeeded");
#endif
return dev->jtag.failed ? -1 : 0;
}
static int mehfet_getconfigfuses(device_t dev_base)
{
struct mehfet_device* dev = (struct mehfet_device*)dev_base;
int r = jtag_get_config_fuses(&dev->jtag);
#ifdef DEBUG_MEHFET_DRIVER
printc_dbg("mehfet: get_config_fuses: %d\n", r);
#endif
return r;
}
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static int check_dev_ok(struct mehfet_device* dev, const struct device_args* args, static int check_dev_ok(struct mehfet_device* dev, const struct device_args* args,
@ -529,32 +278,6 @@ static int check_dev_ok(struct mehfet_device* dev, const struct device_args* arg
return 0; 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 = 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) { static void mehfet_destroy(device_t dev_base) {
struct mehfet_device* dev = (struct mehfet_device*)dev_base; struct mehfet_device* dev = (struct mehfet_device*)dev_base;
@ -619,7 +342,13 @@ static device_t mehfet_open(const struct device_args* args) {
goto FAIL; goto FAIL;
} }
r = init_device(dev); r = jtag_dev_init(&dev->jtag);
if (r < 0) goto FAIL;
// 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
r = mehfet_cmd_set_clkspeed(dev->trans, true);
if (r < 0) goto FAIL; if (r < 0) goto FAIL;
#ifdef DEBUG_MEHFET_DRIVER #ifdef DEBUG_MEHFET_DRIVER
@ -638,13 +367,13 @@ const struct device_class device_mehfet = {
.help = "MehFET USB JTAG/SBW device", .help = "MehFET USB JTAG/SBW device",
.open = mehfet_open, .open = mehfet_open,
.destroy = mehfet_destroy, .destroy = mehfet_destroy,
.readmem = mehfet_readmem, .readmem = jtag_dev_readmem,
.writemem = mehfet_writemem, .writemem = jtag_dev_writemem,
.getregs = mehfet_getregs, .getregs = jtag_dev_getregs,
.setregs = mehfet_setregs, .setregs = jtag_dev_setregs,
.ctl = mehfet_ctl, .ctl = jtag_dev_ctl,
.poll = mehfet_poll, .poll = jtag_dev_poll,
.erase = mehfet_erase, .erase = jtag_dev_erase,
.getconfigfuses = mehfet_getconfigfuses .getconfigfuses = jtag_dev_getconfigfuses
}; };

View File

@ -38,252 +38,7 @@ struct pif_device {
struct jtdev jtag; struct jtdev jtag;
}; };
/*============================================================================*/
/* pif MSP430 JTAG operations */
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
/* Read a word-aligned block from any kind of memory
* returns the number of bytes read or -1 on failure
*/
static int read_words(device_t dev, const struct chipinfo_memory *m,
address_t addr, address_t len, uint8_t *data)
{
struct pif_device *pif = (struct pif_device *)dev;
struct jtdev *p = &pif->jtag;
unsigned int index;
unsigned int word;
for ( index = 0; index < len; index += 2 ) {
word = jtag_read_mem( p, 16, addr+index );
data[index] = word & 0x00ff;
data[index+1] = (word >> 8) & 0x00ff;
}
return p->failed ? -1 : len;
}
/*----------------------------------------------------------------------------*/
/* Write a word to RAM */
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;
}
/*----------------------------------------------------------------------------*/
/* Write a word-aligned flash block. */
/* The starting address must be within the flash memory range. */
static int write_flash_block( struct jtdev *p, address_t addr,
address_t len,
const uint8_t *data)
{
unsigned int i;
uint16_t *word;
word = malloc( len / 2 * sizeof(*word) );
if (!word) {
pr_error("pif: failed to allocate memory");
return -1;
}
for(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, const struct chipinfo_memory *m,
address_t addr, address_t len, const uint8_t *data)
{
struct pif_device *pif = (struct pif_device *)dev;
struct jtdev *p = &pif->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("pif: write_words at address 0x%x failed\n", addr);
return -1;
}
return len;
}
/*----------------------------------------------------------------------------*/
static int init_device(struct jtdev *p)
{
unsigned int jtag_id;
printc_dbg("Starting JTAG\n");
jtag_id = jtag_init(p);
printc("JTAG ID: 0x%02x\n", jtag_id);
if (jtag_id != 0x89 && jtag_id != 0x91) {
printc_err("pif: unexpected JTAG ID: 0x%02x\n", jtag_id);
jtag_release_device(p, 0xfffe);
return -1;
}
return 0;
}
/*===== MSPDebug Device interface ============================================*/
/*----------------------------------------------------------------------------*/
static int pif_readmem( device_t dev_base,
address_t addr,
uint8_t* mem,
address_t len )
{
struct pif_device *dev = (struct pif_device *)dev_base;
dev->jtag.failed = 0;
return readmem(dev_base, addr, mem, len, read_words);
}
/*----------------------------------------------------------------------------*/
static int pif_writemem( device_t dev_base,
address_t addr,
const uint8_t* mem,
address_t len )
{
struct pif_device *dev = (struct pif_device *)dev_base;
dev->jtag.failed = 0;
return writemem(dev_base, addr, mem, len, write_words, read_words);
}
/*----------------------------------------------------------------------------*/
static int pif_getregs(device_t dev_base, address_t *regs)
{
struct pif_device *dev = (struct pif_device *)dev_base;
int i;
dev->jtag.failed = 0;
for (i = 0; i < DEVICE_NUM_REGS; i++)
regs[i] = jtag_read_reg(&dev->jtag, i);
return dev->jtag.failed ? -1 : 0;
}
/*----------------------------------------------------------------------------*/
static int pif_setregs( device_t dev_base, const address_t* regs )
{
struct pif_device *dev = (struct pif_device *)dev_base;
int i;
dev->jtag.failed = 0;
for (i = 0; i < DEVICE_NUM_REGS; i++) {
jtag_write_reg( &dev->jtag, i, regs[i] );
}
return dev->jtag.failed ? -1 : 0;
}
/*----------------------------------------------------------------------------*/
static int pif_ctl(device_t dev_base, device_ctl_t type)
{
struct pif_device *dev = (struct pif_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("pif", &dev->jtag.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("pif: unsupported operation\n");
return -1;
}
return dev->jtag.failed ? -1 : 0;
}
/*----------------------------------------------------------------------------*/
static device_status_t pif_poll(device_t dev_base)
{
struct pif_device *dev = (struct pif_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 pif_erase( device_t dev_base,
device_erase_type_t type,
address_t addr )
{
struct pif_device *dev = (struct pif_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 pif_getconfigfuses(device_t dev_base)
{
struct pif_device *dev = (struct pif_device *)dev_base;
return jtag_get_config_fuses(&dev->jtag);
}
/*----------------------------------------------------------------------------*/
static device_t pif_open(const struct device_args *args) static device_t pif_open(const struct device_args *args)
{ {
@ -317,7 +72,7 @@ static device_t pif_open(const struct device_args *args)
return NULL; return NULL;
} }
if (init_device(&dev->jtag) < 0) { if (jtag_dev_init(&dev->jtag) < 0) {
printc_err("pif: initialization failed\n"); printc_err("pif: initialization failed\n");
free(dev); free(dev);
return NULL; return NULL;
@ -360,7 +115,7 @@ static device_t gpio_open(const struct device_args *args)
return NULL; return NULL;
} }
if (init_device(&dev->jtag) < 0) { if (jtag_dev_init(&dev->jtag) < 0) {
printc_err("gpio: initialization failed\n"); printc_err("gpio: initialization failed\n");
free(dev); free(dev);
return NULL; return NULL;
@ -404,7 +159,7 @@ static device_t bp_open(const struct device_args *args)
return NULL; return NULL;
} }
if (init_device(&dev->jtag) < 0) { if (jtag_dev_init(&dev->jtag) < 0) {
printc_err("bp: initialization failed\n"); printc_err("bp: initialization failed\n");
free(dev); free(dev);
return NULL; return NULL;
@ -431,14 +186,14 @@ const struct device_class device_pif = {
.help = "Parallel Port JTAG", .help = "Parallel Port JTAG",
.open = pif_open, .open = pif_open,
.destroy = pif_destroy, .destroy = pif_destroy,
.readmem = pif_readmem, .readmem = jtag_dev_readmem,
.writemem = pif_writemem, .writemem = jtag_dev_writemem,
.getregs = pif_getregs, .getregs = jtag_dev_getregs,
.setregs = pif_setregs, .setregs = jtag_dev_setregs,
.ctl = pif_ctl, .ctl = jtag_dev_ctl,
.poll = pif_poll, .poll = jtag_dev_poll,
.erase = pif_erase, .erase = jtag_dev_erase,
.getconfigfuses = pif_getconfigfuses .getconfigfuses = jtag_dev_getconfigfuses
}; };
const struct device_class device_gpio = { const struct device_class device_gpio = {
@ -446,14 +201,14 @@ const struct device_class device_gpio = {
.help = "/sys/class/gpio direct connect", .help = "/sys/class/gpio direct connect",
.open = gpio_open, .open = gpio_open,
.destroy = pif_destroy, .destroy = pif_destroy,
.readmem = pif_readmem, .readmem = jtag_dev_readmem,
.writemem = pif_writemem, .writemem = jtag_dev_writemem,
.getregs = pif_getregs, .getregs = jtag_dev_getregs,
.setregs = pif_setregs, .setregs = jtag_dev_setregs,
.ctl = pif_ctl, .ctl = jtag_dev_ctl,
.poll = pif_poll, .poll = jtag_dev_poll,
.erase = pif_erase, .erase = jtag_dev_erase,
.getconfigfuses = pif_getconfigfuses .getconfigfuses = jtag_dev_getconfigfuses
}; };
const struct device_class device_bp = { const struct device_class device_bp = {
@ -461,12 +216,12 @@ const struct device_class device_bp = {
.help = "Bus Pirate JTAG, MISO-TDO, MOSI-TDI, CS-TMS, AUX-RESET, CLK-TCK", .help = "Bus Pirate JTAG, MISO-TDO, MOSI-TDI, CS-TMS, AUX-RESET, CLK-TCK",
.open = bp_open, .open = bp_open,
.destroy = pif_destroy, .destroy = pif_destroy,
.readmem = pif_readmem, .readmem = jtag_dev_readmem,
.writemem = pif_writemem, .writemem = jtag_dev_writemem,
.getregs = pif_getregs, .getregs = jtag_dev_getregs,
.setregs = pif_setregs, .setregs = jtag_dev_setregs,
.ctl = pif_ctl, .ctl = jtag_dev_ctl,
.poll = pif_poll, .poll = jtag_dev_poll,
.erase = pif_erase, .erase = jtag_dev_erase,
.getconfigfuses = pif_getconfigfuses .getconfigfuses = jtag_dev_getconfigfuses
}; };