Merge pull request #37 from CrazyCasta/config_fuses
Add a function to the device struct to handle config fuses.
This commit is contained in:
commit
21c0e7863c
1
Makefile
1
Makefile
|
@ -176,6 +176,7 @@ OBJ=\
|
|||
drivers/devicelist.o \
|
||||
drivers/fet_olimex_db.o \
|
||||
drivers/jtdev.o \
|
||||
drivers/jtdev_bus_pirate.o \
|
||||
drivers/jtdev_gpio.o \
|
||||
drivers/jtaglib.o \
|
||||
drivers/pif.o \
|
||||
|
|
|
@ -411,5 +411,6 @@ const struct device_class device_bsl = {
|
|||
.getregs = bsl_getregs,
|
||||
.setregs = bsl_setregs,
|
||||
.ctl = bsl_ctl,
|
||||
.poll = bsl_poll
|
||||
.poll = bsl_poll,
|
||||
.getconfigfuses = NULL
|
||||
};
|
||||
|
|
|
@ -212,6 +212,9 @@ int device_probe_id(device_t dev, const char *force_id)
|
|||
id.fab = data[3];
|
||||
id.self = r16le(data + 8);
|
||||
id.config = data[13] & 0x7f;
|
||||
if(dev->type->getconfigfuses != NULL) {
|
||||
id.fuses = dev->type->getconfigfuses(dev);
|
||||
}
|
||||
}
|
||||
|
||||
printc_dbg("Chip ID data:\n");
|
||||
|
@ -221,7 +224,7 @@ int device_probe_id(device_t dev, const char *force_id)
|
|||
printc_dbg(" fab: %02x\n", id.fab);
|
||||
printc_dbg(" self: %04x\n", id.self);
|
||||
printc_dbg(" config: %02x\n", id.config);
|
||||
//printc_dbg(" fuses: %02x\n", id.fuses);
|
||||
printc_dbg(" fuses: %02x\n", id.fuses);
|
||||
//printc_dbg(" activation_key: %08x\n", id.activation_key);
|
||||
|
||||
dev->chip = chipinfo_find_by_id(&id);
|
||||
|
|
|
@ -117,6 +117,9 @@ struct device_class {
|
|||
|
||||
/* Wait a little while for the CPU to change state */
|
||||
device_status_t (*poll)(device_t dev);
|
||||
|
||||
/* Get the configuration fuse values */
|
||||
int (*getconfigfuses)(device_t dev);
|
||||
};
|
||||
|
||||
struct device {
|
||||
|
|
|
@ -63,7 +63,8 @@ const struct device_class device_rf2500 = {
|
|||
.getregs = fet_getregs,
|
||||
.setregs = fet_setregs,
|
||||
.ctl = fet_ctl,
|
||||
.poll = fet_poll
|
||||
.poll = fet_poll,
|
||||
.getconfigfuses = NULL
|
||||
};
|
||||
|
||||
static device_t fet_open_olimex_iso_mk2(const struct device_args *args)
|
||||
|
@ -125,7 +126,8 @@ const struct device_class device_olimex_iso_mk2 = {
|
|||
.getregs = fet_getregs,
|
||||
.setregs = fet_setregs,
|
||||
.ctl = fet_ctl,
|
||||
.poll = fet_poll
|
||||
.poll = fet_poll,
|
||||
.getconfigfuses = NULL
|
||||
};
|
||||
|
||||
static device_t fet_open_olimex(const struct device_args *args)
|
||||
|
@ -160,7 +162,8 @@ const struct device_class device_olimex = {
|
|||
.getregs = fet_getregs,
|
||||
.setregs = fet_setregs,
|
||||
.ctl = fet_ctl,
|
||||
.poll = fet_poll
|
||||
.poll = fet_poll,
|
||||
.getconfigfuses = NULL
|
||||
};
|
||||
|
||||
static device_t fet_open_olimex_v1(const struct device_args *args)
|
||||
|
@ -230,7 +233,8 @@ const struct device_class device_olimex_iso = {
|
|||
.getregs = fet_getregs,
|
||||
.setregs = fet_setregs,
|
||||
.ctl = fet_ctl,
|
||||
.poll = fet_poll
|
||||
.poll = fet_poll,
|
||||
.getconfigfuses = NULL
|
||||
};
|
||||
|
||||
static device_t fet_open_uif(const struct device_args *args)
|
||||
|
@ -260,5 +264,6 @@ const struct device_class device_uif = {
|
|||
.getregs = fet_getregs,
|
||||
.setregs = fet_setregs,
|
||||
.ctl = fet_ctl,
|
||||
.poll = fet_poll
|
||||
.poll = fet_poll,
|
||||
.getconfigfuses = NULL
|
||||
};
|
||||
|
|
|
@ -309,5 +309,6 @@ const struct device_class device_ezfet = {
|
|||
.setregs = fet3_setregs,
|
||||
.ctl = fet3_ctl,
|
||||
.poll = fet3_poll,
|
||||
.erase = fet3_erase
|
||||
.erase = fet3_erase,
|
||||
.getconfigfuses = NULL
|
||||
};
|
||||
|
|
|
@ -665,5 +665,6 @@ const struct device_class device_flash_bsl = {
|
|||
.setregs = flash_bsl_setregs,
|
||||
.ctl = flash_bsl_ctl,
|
||||
.poll = flash_bsl_poll,
|
||||
.erase = flash_bsl_erase
|
||||
.erase = flash_bsl_erase,
|
||||
.getconfigfuses = NULL
|
||||
};
|
||||
|
|
|
@ -472,5 +472,6 @@ const struct device_class device_gdbc = {
|
|||
.getregs = gdbc_getregs,
|
||||
.setregs = gdbc_setregs,
|
||||
.ctl = gdbc_ctl,
|
||||
.poll = gdbc_poll
|
||||
.poll = gdbc_poll,
|
||||
.getconfigfuses = NULL
|
||||
};
|
||||
|
|
|
@ -580,5 +580,6 @@ const struct device_class device_goodfet = {
|
|||
.setregs = goodfet_setregs,
|
||||
.ctl = goodfet_ctl,
|
||||
.poll = goodfet_poll,
|
||||
.erase = goodfet_erase
|
||||
.erase = goodfet_erase,
|
||||
.getconfigfuses = NULL
|
||||
};
|
||||
|
|
|
@ -60,6 +60,8 @@
|
|||
/* Instructions for the JTAG Fuse */
|
||||
#define IR_PREPARE_BLOW 0x44 /* 0x22 */
|
||||
#define IR_EX_BLOW 0x24 /* 0x24 */
|
||||
/* Instructions for the Configuration Fuse */
|
||||
#define IR_CONFIG_FUSES 0x94
|
||||
/* Bypass instruction */
|
||||
#define IR_BYPASS 0xFF /* 0xFF */
|
||||
/* Instructions for the EEM */
|
||||
|
@ -203,11 +205,37 @@ static unsigned int jtag_ir_shift(struct jtdev *p, unsigned int instruction)
|
|||
/* JTAG state = Run-Test/Idle */
|
||||
}
|
||||
|
||||
/* Shifts a given 8-bit byte into the JTAG data register through TDI.
|
||||
* data : 8 bit data
|
||||
* return: scanned TDO value
|
||||
*/
|
||||
static unsigned int jtag_dr_shift_8(struct jtdev *p, unsigned int data)
|
||||
{
|
||||
/* JTAG state = Run-Test/Idle */
|
||||
jtag_tms_set(p);
|
||||
jtag_tck_clr(p);
|
||||
jtag_tck_set(p);
|
||||
|
||||
/* JTAG state = Select DR-Scan */
|
||||
jtag_tms_clr(p);
|
||||
jtag_tck_clr(p);
|
||||
jtag_tck_set(p);
|
||||
|
||||
/* JTAG state = Capture-DR */
|
||||
jtag_tck_clr(p);
|
||||
jtag_tck_set(p);
|
||||
|
||||
/* JTAG state = Shift-DR, Shift in TDI (16-bit) */
|
||||
return jtag_shift(p, 8, data);
|
||||
|
||||
/* JTAG state = Run-Test/Idle */
|
||||
}
|
||||
|
||||
/* Shifts a given 16-bit word into the JTAG data register through TDI.
|
||||
* data : 16 bit data
|
||||
* return: scanned TDO value
|
||||
*/
|
||||
static unsigned int jtag_dr_shift(struct jtdev *p, unsigned int data)
|
||||
static unsigned int jtag_dr_shift_16(struct jtdev *p, unsigned int data)
|
||||
{
|
||||
/* JTAG state = Run-Test/Idle */
|
||||
jtag_tms_set(p);
|
||||
|
@ -242,10 +270,10 @@ static int jtag_set_instruction_fetch(struct jtdev *p)
|
|||
* timeout after limited attempts
|
||||
*/
|
||||
for (loop_counter = 50; loop_counter > 0; loop_counter--) {
|
||||
if ((jtag_dr_shift(p, 0x0000) & 0x0080) == 0x0080)
|
||||
if ((jtag_dr_shift_16(p, 0x0000) & 0x0080) == 0x0080)
|
||||
return 1;
|
||||
|
||||
jtag_tclk_clr(p); /* The TCLK pulse befor jtag_dr_shift leads to */
|
||||
jtag_tclk_clr(p); /* The TCLK pulse befor jtag_dr_shift_16 leads to */
|
||||
jtag_tclk_set(p); /* problems at MEM_QUICK_READ, it's from SLAU265 */
|
||||
}
|
||||
|
||||
|
@ -263,17 +291,17 @@ static void jtag_halt_cpu(struct jtdev *p)
|
|||
|
||||
/* Set device into JTAG mode + read */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift(p, 0x2401);
|
||||
jtag_dr_shift_16(p, 0x2401);
|
||||
|
||||
/* Send JMP $ instruction to keep CPU from changing the state */
|
||||
jtag_ir_shift(p, IR_DATA_16BIT);
|
||||
jtag_dr_shift(p, 0x3FFF);
|
||||
jtag_dr_shift_16(p, 0x3FFF);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
/* Set JTAG_HALT bit */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift(p, 0x2409);
|
||||
jtag_dr_shift_16(p, 0x2409);
|
||||
jtag_tclk_set(p);
|
||||
}
|
||||
|
||||
|
@ -284,7 +312,7 @@ static void jtag_release_cpu(struct jtdev *p)
|
|||
|
||||
/* clear the HALT_JTAG bit */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift(p, 0x2401);
|
||||
jtag_dr_shift_16(p, 0x2401);
|
||||
jtag_ir_shift(p, IR_ADDR_CAPTURE);
|
||||
jtag_tclk_set(p);
|
||||
}
|
||||
|
@ -313,13 +341,13 @@ static int jtag_verify_psa(struct jtdev *p,
|
|||
|
||||
jtag_execute_puc(p);
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift(p, 0x2401);
|
||||
jtag_dr_shift_16(p, 0x2401);
|
||||
jtag_set_instruction_fetch(p);
|
||||
jtag_ir_shift(p, IR_DATA_16BIT);
|
||||
jtag_dr_shift(p, 0x4030);
|
||||
jtag_dr_shift_16(p, 0x4030);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_dr_shift(p, start_address-2);
|
||||
jtag_dr_shift_16(p, start_address-2);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
|
@ -327,7 +355,7 @@ static int jtag_verify_psa(struct jtdev *p,
|
|||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_ir_shift(p, IR_ADDR_CAPTURE);
|
||||
jtag_dr_shift(p, 0x0000);
|
||||
jtag_dr_shift_16(p, 0x0000);
|
||||
jtag_ir_shift(p, IR_DATA_PSA);
|
||||
|
||||
for (index = 0; index < length; index++) {
|
||||
|
@ -369,7 +397,7 @@ static int jtag_verify_psa(struct jtdev *p,
|
|||
|
||||
/* Read out the PSA value */
|
||||
jtag_ir_shift(p, IR_SHIFT_OUT_PSA);
|
||||
psa_value = jtag_dr_shift(p, 0x0000);
|
||||
psa_value = jtag_dr_shift_16(p, 0x0000);
|
||||
jtag_tclk_set(p);
|
||||
|
||||
return (psa_value == psa_crc) ? 1 : 0;
|
||||
|
@ -436,14 +464,14 @@ unsigned int jtag_get_device(struct jtdev *p)
|
|||
|
||||
/* Set device into JTAG mode + read */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift(p, 0x2401);
|
||||
jtag_dr_shift_16(p, 0x2401);
|
||||
|
||||
/* Wait until CPU is synchronized,
|
||||
* timeout after a limited number of attempts
|
||||
*/
|
||||
jtag_id = jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||
for ( loop_counter = 50; loop_counter > 0; loop_counter--) {
|
||||
if ( (jtag_dr_shift(p, 0x0000) & 0x0200) == 0x0200 ) {
|
||||
if ( (jtag_dr_shift_16(p, 0x0000) & 0x0200) == 0x0200 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -491,20 +519,20 @@ uint16_t jtag_read_mem(struct jtdev *p,
|
|||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
if (format == 16) {
|
||||
/* set word read */
|
||||
jtag_dr_shift(p, 0x2409);
|
||||
jtag_dr_shift_16(p, 0x2409);
|
||||
} else {
|
||||
/* set byte read */
|
||||
jtag_dr_shift(p, 0x2419);
|
||||
jtag_dr_shift_16(p, 0x2419);
|
||||
}
|
||||
/* set address */
|
||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||
jtag_dr_shift(p, address);
|
||||
jtag_dr_shift_16(p, address);
|
||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
/* shift out 16 bits */
|
||||
content = jtag_dr_shift(p, 0x0000);
|
||||
content = jtag_dr_shift_16(p, 0x0000);
|
||||
jtag_tclk_set(p); /* is also the first instruction in jtag_release_cpu() */
|
||||
jtag_release_cpu(p);
|
||||
if (format == 8)
|
||||
|
@ -532,14 +560,14 @@ void jtag_read_mem_quick(struct jtdev *p,
|
|||
|
||||
/* set RW to read */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift(p, 0x2409);
|
||||
jtag_dr_shift_16(p, 0x2409);
|
||||
jtag_ir_shift(p, IR_DATA_QUICK);
|
||||
|
||||
for (index = 0; index < length; index++) {
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
/* shift out the data from the target */
|
||||
data[index] = jtag_dr_shift(p, 0x0000);
|
||||
data[index] = jtag_dr_shift_16(p, 0x0000);
|
||||
}
|
||||
|
||||
jtag_tclk_set(p);
|
||||
|
@ -562,19 +590,19 @@ void jtag_write_mem(struct jtdev *p,
|
|||
|
||||
if (format == 16)
|
||||
/* Set word write */
|
||||
jtag_dr_shift(p, 0x2408);
|
||||
jtag_dr_shift_16(p, 0x2408);
|
||||
else
|
||||
/* Set byte write */
|
||||
jtag_dr_shift(p, 0x2418);
|
||||
jtag_dr_shift_16(p, 0x2418);
|
||||
|
||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||
|
||||
/* Set addr */
|
||||
jtag_dr_shift(p, address);
|
||||
jtag_dr_shift_16(p, address);
|
||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||
|
||||
/* Shift in 16 bits */
|
||||
jtag_dr_shift(p, data);
|
||||
jtag_dr_shift_16(p, data);
|
||||
jtag_tclk_set(p);
|
||||
jtag_release_cpu(p);
|
||||
}
|
||||
|
@ -598,12 +626,12 @@ void jtag_write_mem_quick(struct jtdev *p,
|
|||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
|
||||
/* Set RW to write */
|
||||
jtag_dr_shift(p, 0x2408);
|
||||
jtag_dr_shift_16(p, 0x2408);
|
||||
jtag_ir_shift(p, IR_DATA_QUICK);
|
||||
|
||||
for (index = 0; index < length; index++) {
|
||||
/* Write data */
|
||||
jtag_dr_shift(p, data[index]);
|
||||
jtag_dr_shift_16(p, data[index]);
|
||||
|
||||
/* Increment PC by 2 */
|
||||
jtag_tclk_set(p);
|
||||
|
@ -625,7 +653,7 @@ int jtag_is_fuse_blown (struct jtdev *p)
|
|||
/* First trial could be wrong */
|
||||
for (loop_counter = 3; loop_counter > 0; loop_counter--) {
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||
if (jtag_dr_shift(p, 0xAAAA) == 0x5555)
|
||||
if (jtag_dr_shift_16(p, 0xAAAA) == 0x5555)
|
||||
/* Fuse is blown */
|
||||
return 1;
|
||||
}
|
||||
|
@ -644,8 +672,8 @@ unsigned int jtag_execute_puc(struct jtdev *p)
|
|||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
|
||||
/* Apply and remove reset */
|
||||
jtag_dr_shift(p, 0x2C01);
|
||||
jtag_dr_shift(p, 0x2401);
|
||||
jtag_dr_shift_16(p, 0x2C01);
|
||||
jtag_dr_shift_16(p, 0x2401);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
|
@ -681,8 +709,8 @@ void jtag_release_device(struct jtdev *p, address_t address)
|
|||
jtag_set_breakpoint(p,-1,0);
|
||||
/* issue reset */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift(p, 0x2C01);
|
||||
jtag_dr_shift(p, 0x2401);
|
||||
jtag_dr_shift_16(p, 0x2C01);
|
||||
jtag_dr_shift_16(p, 0x2401);
|
||||
break;
|
||||
default: /* Set target CPU's PC */
|
||||
jtag_write_reg(p, 0, address);
|
||||
|
@ -692,11 +720,11 @@ void jtag_release_device(struct jtdev *p, address_t address)
|
|||
jtag_set_instruction_fetch(p);
|
||||
|
||||
jtag_ir_shift(p, IR_EMEX_DATA_EXCHANGE);
|
||||
jtag_dr_shift(p, BREAKREACT + READ);
|
||||
jtag_dr_shift(p, 0x0000);
|
||||
jtag_dr_shift_16(p, BREAKREACT + READ);
|
||||
jtag_dr_shift_16(p, 0x0000);
|
||||
|
||||
jtag_ir_shift(p, IR_EMEX_WRITE_CONTROL);
|
||||
jtag_dr_shift(p, 0x000f);
|
||||
jtag_dr_shift_16(p, 0x000f);
|
||||
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_RELEASE);
|
||||
}
|
||||
|
@ -746,56 +774,56 @@ void jtag_write_flash(struct jtdev *p,
|
|||
|
||||
/* Set RW to write */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift(p, 0x2408);
|
||||
jtag_dr_shift_16(p, 0x2408);
|
||||
|
||||
/* FCTL1 register */
|
||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||
jtag_dr_shift(p, 0x0128);
|
||||
jtag_dr_shift_16(p, 0x0128);
|
||||
|
||||
/* Enable FLASH write */
|
||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||
jtag_dr_shift(p, 0xA540);
|
||||
jtag_dr_shift_16(p, 0xA540);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
/* FCTL2 register */
|
||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||
jtag_dr_shift(p, 0x012A);
|
||||
jtag_dr_shift_16(p, 0x012A);
|
||||
|
||||
/* Select MCLK as source, DIV=1 */
|
||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||
jtag_dr_shift(p, 0xA540);
|
||||
jtag_dr_shift_16(p, 0xA540);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
/* FCTL3 register */
|
||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||
jtag_dr_shift(p, 0x012C);
|
||||
jtag_dr_shift_16(p, 0x012C);
|
||||
|
||||
/* Clear FCTL3 register */
|
||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||
jtag_dr_shift(p, 0xA500);
|
||||
jtag_dr_shift_16(p, 0xA500);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
for (index = 0; index < length; index++) {
|
||||
/* Set RW to write */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift(p, 0x2408);
|
||||
jtag_dr_shift_16(p, 0x2408);
|
||||
|
||||
/* Set address */
|
||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||
jtag_dr_shift(p, address);
|
||||
jtag_dr_shift_16(p, address);
|
||||
|
||||
/* Set data */
|
||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||
jtag_dr_shift(p, data[index]);
|
||||
jtag_dr_shift_16(p, data[index]);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
/* Set RW to read */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift(p, 0x2409);
|
||||
jtag_dr_shift_16(p, 0x2409);
|
||||
|
||||
/* provide TCLKs
|
||||
* min. 33 for F149 and F449
|
||||
|
@ -809,15 +837,15 @@ void jtag_write_flash(struct jtdev *p,
|
|||
|
||||
/* Set RW to write */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift(p, 0x2408);
|
||||
jtag_dr_shift_16(p, 0x2408);
|
||||
|
||||
/* FCTL1 register */
|
||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||
jtag_dr_shift(p, 0x0128);
|
||||
jtag_dr_shift_16(p, 0x0128);
|
||||
|
||||
/* Disable FLASH write */
|
||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||
jtag_dr_shift(p, 0xA500);
|
||||
jtag_dr_shift_16(p, 0xA500);
|
||||
jtag_tclk_set(p);
|
||||
jtag_release_cpu(p);
|
||||
|
||||
|
@ -853,66 +881,66 @@ void jtag_erase_flash(struct jtdev *p,
|
|||
|
||||
/* Set RW to write */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift(p, 0x2408);
|
||||
jtag_dr_shift_16(p, 0x2408);
|
||||
|
||||
/* FCTL1 address */
|
||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||
jtag_dr_shift(p, 0x0128);
|
||||
jtag_dr_shift_16(p, 0x0128);
|
||||
|
||||
/* Enable erase mode */
|
||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||
jtag_dr_shift(p, erase_mode);
|
||||
jtag_dr_shift_16(p, erase_mode);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
/* FCTL2 address */
|
||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||
jtag_dr_shift(p, 0x012A);
|
||||
jtag_dr_shift_16(p, 0x012A);
|
||||
|
||||
/* MCLK is source, DIV=1 */
|
||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||
jtag_dr_shift(p, 0xA540);
|
||||
jtag_dr_shift_16(p, 0xA540);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
/* FCTL3 address */
|
||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||
jtag_dr_shift(p, 0x012C);
|
||||
jtag_dr_shift_16(p, 0x012C);
|
||||
|
||||
/* Clear FCTL3 */
|
||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||
jtag_dr_shift(p, 0xA500);
|
||||
jtag_dr_shift_16(p, 0xA500);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
/* Set erase address */
|
||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||
jtag_dr_shift(p, erase_address);
|
||||
jtag_dr_shift_16(p, erase_address);
|
||||
|
||||
/* Dummy write to start erase */
|
||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||
jtag_dr_shift(p, 0x55AA);
|
||||
jtag_dr_shift_16(p, 0x55AA);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
/* Set RW to read */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift(p, 0x2409);
|
||||
jtag_dr_shift_16(p, 0x2409);
|
||||
|
||||
/* provide TCLKs */
|
||||
p->f->jtdev_tclk_strobe(p, number_of_strobes);
|
||||
|
||||
/* Set RW to write */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift(p, 0x2408);
|
||||
jtag_dr_shift_16(p, 0x2408);
|
||||
|
||||
/* FCTL1 address */
|
||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||
jtag_dr_shift(p, 0x0128);
|
||||
jtag_dr_shift_16(p, 0x0128);
|
||||
|
||||
/* Disable erase */
|
||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||
jtag_dr_shift(p, 0xA500);
|
||||
jtag_dr_shift_16(p, 0xA500);
|
||||
jtag_tclk_set(p);
|
||||
jtag_release_cpu(p);
|
||||
}
|
||||
|
@ -927,7 +955,7 @@ address_t jtag_read_reg(struct jtdev *p, int reg)
|
|||
|
||||
/* CPU controls RW & BYTE */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift(p, 0x3401);
|
||||
jtag_dr_shift_16(p, 0x3401);
|
||||
|
||||
/* Set CPU into instruction fetch mode */
|
||||
jtag_set_instruction_fetch(p);
|
||||
|
@ -937,7 +965,7 @@ address_t jtag_read_reg(struct jtdev *p, int reg)
|
|||
/* "jmp $-4" instruction */
|
||||
/* PC - 4 -> PC */
|
||||
/* needs 2 clock cycles */
|
||||
jtag_dr_shift(p, 0x3ffd);
|
||||
jtag_dr_shift_16(p, 0x3ffd);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
|
@ -950,10 +978,10 @@ address_t jtag_read_reg(struct jtdev *p, int reg)
|
|||
* it's a ROM address, write has no effect, but
|
||||
* the registers value is placed on the databus
|
||||
*/
|
||||
jtag_dr_shift(p, 0x4082 | (((unsigned int)reg << 8) & 0x0f00) );
|
||||
jtag_dr_shift_16(p, 0x4082 | (((unsigned int)reg << 8) & 0x0f00) );
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_dr_shift(p, 0x01fe);
|
||||
jtag_dr_shift_16(p, 0x01fe);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
|
@ -963,11 +991,11 @@ address_t jtag_read_reg(struct jtdev *p, int reg)
|
|||
|
||||
/* Read databus which contains the registers value */
|
||||
jtag_ir_shift(p, IR_DATA_CAPTURE);
|
||||
value = jtag_dr_shift(p, 0x0000);
|
||||
value = jtag_dr_shift_16(p, 0x0000);
|
||||
|
||||
/* JTAG controls RW & BYTE */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift(p, 0x2401);
|
||||
jtag_dr_shift_16(p, 0x2401);
|
||||
|
||||
jtag_tclk_set(p);
|
||||
|
||||
|
@ -980,7 +1008,7 @@ void jtag_write_reg(struct jtdev *p, int reg, address_t value)
|
|||
{
|
||||
/* CPU controls RW & BYTE */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift(p, 0x3401);
|
||||
jtag_dr_shift_16(p, 0x3401);
|
||||
|
||||
/* Set CPU into instruction fetch mode */
|
||||
jtag_set_instruction_fetch(p);
|
||||
|
@ -990,7 +1018,7 @@ void jtag_write_reg(struct jtdev *p, int reg, address_t value)
|
|||
/* "jmp $-4" instruction */
|
||||
/* PC - 4 -> PC */
|
||||
/* needs 4 clock cycles */
|
||||
jtag_dr_shift(p, 0x3ffd);
|
||||
jtag_dr_shift_16(p, 0x3ffd);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
|
@ -1001,16 +1029,16 @@ void jtag_write_reg(struct jtdev *p, int reg, address_t value)
|
|||
* PC is advanced 4 bytes by this instruction
|
||||
* needs 2 clock cycles
|
||||
*/
|
||||
jtag_dr_shift(p, 0x4030 | (reg & 0x000f) );
|
||||
jtag_dr_shift_16(p, 0x4030 | (reg & 0x000f) );
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
jtag_dr_shift(p, value);
|
||||
jtag_dr_shift_16(p, value);
|
||||
jtag_tclk_set(p);
|
||||
jtag_tclk_clr(p);
|
||||
|
||||
/* JTAG controls RW & BYTE */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift(p, 0x2401);
|
||||
jtag_dr_shift_16(p, 0x2401);
|
||||
|
||||
jtag_tclk_set(p);
|
||||
}
|
||||
|
@ -1022,7 +1050,7 @@ void jtag_single_step( struct jtdev *p )
|
|||
|
||||
/* CPU controls RW & BYTE */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift(p, 0x3401);
|
||||
jtag_dr_shift_16(p, 0x3401);
|
||||
|
||||
/* clock CPU until next instruction fetch cycle */
|
||||
/* failure after 10 clock cycles */
|
||||
|
@ -1031,14 +1059,14 @@ void jtag_single_step( struct jtdev *p )
|
|||
for (loop_counter = 10; loop_counter > 0; loop_counter--) {
|
||||
jtag_tclk_clr(p);
|
||||
jtag_tclk_set(p);
|
||||
if ((jtag_dr_shift(p, 0x0000) & 0x0080) == 0x0080) {
|
||||
if ((jtag_dr_shift_16(p, 0x0000) & 0x0080) == 0x0080) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* JTAG controls RW & BYTE */
|
||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||
jtag_dr_shift(p, 0x2401);
|
||||
jtag_dr_shift_16(p, 0x2401);
|
||||
|
||||
if (loop_counter == 0) {
|
||||
/* timeout reached */
|
||||
|
@ -1071,42 +1099,42 @@ unsigned int jtag_set_breakpoint( struct jtdev *p,int bp_num, address_t bp_addr
|
|||
/* disable all breakpoints by deleting the BREAKREACT
|
||||
* register */
|
||||
jtag_ir_shift(p, IR_EMEX_DATA_EXCHANGE);
|
||||
jtag_dr_shift(p, BREAKREACT + WRITE);
|
||||
jtag_dr_shift(p, 0x0000);
|
||||
jtag_dr_shift_16(p, BREAKREACT + WRITE);
|
||||
jtag_dr_shift_16(p, 0x0000);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* set breakpoint */
|
||||
jtag_ir_shift(p, IR_EMEX_DATA_EXCHANGE);
|
||||
jtag_dr_shift(p, GENCTRL + WRITE);
|
||||
jtag_dr_shift(p, EEM_EN + CLEAR_STOP + EMU_CLK_EN + EMU_FEAT_EN);
|
||||
jtag_dr_shift_16(p, GENCTRL + WRITE);
|
||||
jtag_dr_shift_16(p, EEM_EN + CLEAR_STOP + EMU_CLK_EN + EMU_FEAT_EN);
|
||||
|
||||
jtag_ir_shift(p, IR_EMEX_DATA_EXCHANGE); //repeating may not needed
|
||||
jtag_dr_shift(p, 8*bp_num + MBTRIGxVAL + WRITE);
|
||||
jtag_dr_shift(p, bp_addr);
|
||||
jtag_dr_shift_16(p, 8*bp_num + MBTRIGxVAL + WRITE);
|
||||
jtag_dr_shift_16(p, bp_addr);
|
||||
|
||||
jtag_ir_shift(p, IR_EMEX_DATA_EXCHANGE); //repeating may not needed
|
||||
jtag_dr_shift(p, 8*bp_num + MBTRIGxCTL + WRITE);
|
||||
jtag_dr_shift(p, MAB + TRIG_0 + CMP_EQUAL);
|
||||
jtag_dr_shift_16(p, 8*bp_num + MBTRIGxCTL + WRITE);
|
||||
jtag_dr_shift_16(p, MAB + TRIG_0 + CMP_EQUAL);
|
||||
|
||||
jtag_ir_shift(p, IR_EMEX_DATA_EXCHANGE); //repeating may not needed
|
||||
jtag_dr_shift(p, 8*bp_num + MBTRIGxMSK + WRITE);
|
||||
jtag_dr_shift(p, NO_MASK);
|
||||
jtag_dr_shift_16(p, 8*bp_num + MBTRIGxMSK + WRITE);
|
||||
jtag_dr_shift_16(p, NO_MASK);
|
||||
|
||||
jtag_ir_shift(p, IR_EMEX_DATA_EXCHANGE); //repeating may not needed
|
||||
jtag_dr_shift(p, 8*bp_num + MBTRIGxCMB + WRITE);
|
||||
jtag_dr_shift(p, 1<<bp_num);
|
||||
jtag_dr_shift_16(p, 8*bp_num + MBTRIGxCMB + WRITE);
|
||||
jtag_dr_shift_16(p, 1<<bp_num);
|
||||
|
||||
/* read the actual setting of the BREAKREACT register */
|
||||
/* while reading a 1 is automatically shifted into LSB */
|
||||
/* this will be undone and the bit for the new breakpoint set */
|
||||
/* then the updated value is stored back */
|
||||
jtag_ir_shift(p, IR_EMEX_DATA_EXCHANGE); //repeating may not needed
|
||||
breakreact = jtag_dr_shift(p, BREAKREACT + READ);
|
||||
breakreact += jtag_dr_shift(p, 0x000);
|
||||
breakreact = jtag_dr_shift_16(p, BREAKREACT + READ);
|
||||
breakreact += jtag_dr_shift_16(p, 0x000);
|
||||
breakreact = (breakreact >> 1) | (1 << bp_num);
|
||||
jtag_dr_shift(p, BREAKREACT + WRITE);
|
||||
jtag_dr_shift(p, breakreact);
|
||||
jtag_dr_shift_16(p, BREAKREACT + WRITE);
|
||||
jtag_dr_shift_16(p, breakreact);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1115,9 +1143,17 @@ unsigned int jtag_cpu_state( struct jtdev *p )
|
|||
{
|
||||
jtag_ir_shift(p, IR_EMEX_READ_CONTROL);
|
||||
|
||||
if ((jtag_dr_shift(p, 0x0000) & 0x0080) == 0x0080) {
|
||||
if ((jtag_dr_shift_16(p, 0x0000) & 0x0080) == 0x0080) {
|
||||
return 1; /* halted */
|
||||
} else {
|
||||
return 0; /* running */
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int jtag_get_config_fuses( struct jtdev *p )
|
||||
{
|
||||
jtag_ir_shift(p, IR_CONFIG_FUSES);
|
||||
|
||||
return jtag_dr_shift_8(p, 0);
|
||||
}
|
||||
|
|
|
@ -115,5 +115,6 @@ void jtag_single_step(struct jtdev *p);
|
|||
unsigned int jtag_set_breakpoint(struct jtdev *p,
|
||||
int bp_num, address_t bp_addr);
|
||||
unsigned int jtag_cpu_state(struct jtdev *p);
|
||||
int jtag_get_config_fuses(struct jtdev *p);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
|
||||
#ifndef JTDEV_H_
|
||||
#define JTDEV_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct jtdev_func;
|
||||
struct jtdev {
|
||||
int port;
|
||||
|
@ -65,5 +68,6 @@ struct jtdev_func{
|
|||
|
||||
extern const struct jtdev_func jtdev_func_pif;
|
||||
extern const struct jtdev_func jtdev_func_gpio;
|
||||
extern const struct jtdev_func jtdev_func_bp;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,356 @@
|
|||
/* MSPDebug - debugging tool for MSP430 MCUs
|
||||
* Copyright (C) 2009-2012 Daniel Beer
|
||||
* Copyright (C) 2012 Peter Bägel
|
||||
*
|
||||
* ppdev/ppi abstraction inspired by uisp src/DARPA.C
|
||||
* originally written by Sergey Larin;
|
||||
* corrected by Denis Chertykov, Uros Platise and Marek Michalkiewicz.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "jtdev.h"
|
||||
#include "output.h"
|
||||
|
||||
#if defined(__linux__)
|
||||
/*===== includes =============================================================*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
/*===== private symbols ======================================================*/
|
||||
|
||||
/*--- bus pirate pins ---*/
|
||||
#define BP_CS ((unsigned char)0x01)
|
||||
#define BP_MISO ((unsigned char)0x02)
|
||||
#define BP_CLK ((unsigned char)0x04)
|
||||
#define BP_MOSI ((unsigned char)0x08)
|
||||
#define BP_AUX ((unsigned char)0x10)
|
||||
#define BP_PULLUP ((unsigned char)0x20)
|
||||
#define BP_POWER ((unsigned char)0x40)
|
||||
|
||||
/*--- bus pirate binary commands ---*/
|
||||
#define CMD_ENTER_BB ((unsigned char)0x00)
|
||||
#define CMD_LEAVE_BB ((unsigned char)0x0f)
|
||||
#define CMD_CONFIG_PIN_DIR(x) ((unsigned char)0x40 | (x & 0x1f))
|
||||
#define CMD_WRITE_PINS(x) ((unsigned char)0x80 | (x & 0x7f))
|
||||
|
||||
/*--- JTAG signal mapping ---*/
|
||||
#define TDO BP_MISO
|
||||
#define TDI BP_MOSI
|
||||
#define TMS BP_CS
|
||||
#define POWER BP_POWER
|
||||
#define RESET BP_AUX
|
||||
#define TCK BP_CLK
|
||||
|
||||
/*===== public functions =====================================================*/
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
static void do_bus_pirate_data(struct jtdev *p)
|
||||
{
|
||||
char res;
|
||||
char out_buff, in_buff;
|
||||
int buffered;
|
||||
|
||||
out_buff = CMD_WRITE_PINS(p->data_register);
|
||||
|
||||
ioctl(p->port, TIOCINQ, &buffered);
|
||||
if(buffered != 0) {
|
||||
pr_error("jtdev: extraneous bytes available on serial port, flushing it");
|
||||
tcflush(p->port, TCIFLUSH);
|
||||
}
|
||||
|
||||
if(write(p->port, &out_buff, 1) < 1) {
|
||||
pr_error("jtdev: failed writing to serial port");
|
||||
p->failed = 1;
|
||||
}
|
||||
|
||||
res = read(p->port, &in_buff, 1);
|
||||
p->data_register &= ~TDO;
|
||||
p->data_register |= in_buff & TDO;
|
||||
|
||||
// TODO: Handle failure, try again if we don't receive
|
||||
if (res < 1) {
|
||||
pr_error("jtdev: no response with in data");
|
||||
p->failed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int jtbp_open(struct jtdev *p, const char *device)
|
||||
{
|
||||
int i;
|
||||
char in_buff, out_buff;
|
||||
struct termios tio;
|
||||
const char* response = "BBIO1";
|
||||
|
||||
p->port = open(device, O_RDWR | O_NOCTTY);
|
||||
if (p->port < 0) {
|
||||
printc_err("jtdev: can't open %s: %s\n",
|
||||
device, last_error());
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&tio, 0, sizeof(tio));
|
||||
|
||||
tio.c_cflag = B115200 | CS8 | CLOCAL | CREAD;
|
||||
tio.c_iflag = IGNPAR;
|
||||
tio.c_oflag = 0;
|
||||
tio.c_lflag = 0;
|
||||
|
||||
tio.c_cc[VTIME] = 1;
|
||||
tio.c_cc[VMIN] = 0;
|
||||
|
||||
tcflush(p->port, TCIFLUSH);
|
||||
tcsetattr(p->port, TCSANOW, &tio);
|
||||
|
||||
// If it's in the middle of spewing something, let it finish
|
||||
while(read(p->port, &in_buff, 1) != 0);
|
||||
|
||||
out_buff = 0;
|
||||
|
||||
for(i=0; i<20; ++i) {
|
||||
if(write(p->port, &out_buff, 1) < 1) {
|
||||
pr_error("jtdev: failed writing to serial port");
|
||||
p->failed = 1;
|
||||
}
|
||||
|
||||
if(read(p->port, &in_buff, 1) > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == 20) {
|
||||
printc_err("jtdev: bus pirate failed to enter bit bang mode\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(in_buff != *response) {
|
||||
printc_err("jtdev: bus pirate: got bad response %c\n", in_buff);
|
||||
return -1;
|
||||
}
|
||||
|
||||
++response;
|
||||
|
||||
for(i=0; i<4; ++i, ++response) {
|
||||
if(read(p->port, &in_buff, 1) <= 0) {
|
||||
printc_err("jtdev: bus pirate: got no response\n");
|
||||
}
|
||||
|
||||
if(in_buff != *response) {
|
||||
printc_err("jtdev: bus pirate: got bad response %c\n", in_buff);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
out_buff = CMD_CONFIG_PIN_DIR(TDO);
|
||||
if(write(p->port, &out_buff, 1) < 1) {
|
||||
pr_error("jtdev: failed writing to serial port");
|
||||
p->failed = 1;
|
||||
}
|
||||
|
||||
if(read(p->port, &in_buff, 1) <= 0) {
|
||||
printc_err("jtdev: bus pirate: got no response\n");
|
||||
}
|
||||
|
||||
p->data_register = 0;
|
||||
p->control_register = 0;
|
||||
p->failed = 0;
|
||||
|
||||
do_bus_pirate_data(p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void jtbp_close(struct jtdev *p)
|
||||
{
|
||||
char out_buff;
|
||||
|
||||
out_buff = 0x0f;
|
||||
// Don't care if this fails, user can just power cycle the bus pirate
|
||||
if(write(p->port, &out_buff, 1));
|
||||
|
||||
close(p->port);
|
||||
}
|
||||
|
||||
static void jtbp_power_on(struct jtdev *p)
|
||||
{
|
||||
/* power supply on */
|
||||
p->data_register |= POWER;
|
||||
do_bus_pirate_data(p);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
static void jtbp_power_off(struct jtdev *p)
|
||||
{
|
||||
/* power supply off */
|
||||
p->data_register &= ~(POWER | RESET);
|
||||
do_bus_pirate_data(p);
|
||||
}
|
||||
|
||||
static void jtbp_connect(struct jtdev *p)
|
||||
{
|
||||
// unsure what this function does, I presume my setup w/ bus pirate is
|
||||
// "always enabled"
|
||||
}
|
||||
|
||||
static void jtbp_release(struct jtdev *p)
|
||||
{
|
||||
// unsure what this function does, I presume my setup w/ bus pirate is
|
||||
// "always enabled"
|
||||
}
|
||||
|
||||
static void jtbp_tck(struct jtdev *p, int out)
|
||||
{
|
||||
if (out)
|
||||
p->data_register |= TCK;
|
||||
else
|
||||
p->data_register &= ~TCK;
|
||||
|
||||
do_bus_pirate_data(p);
|
||||
}
|
||||
|
||||
static void jtbp_tms(struct jtdev *p, int out)
|
||||
{
|
||||
if (out)
|
||||
p->data_register |= TMS;
|
||||
else
|
||||
p->data_register &= ~TMS;
|
||||
|
||||
do_bus_pirate_data(p);
|
||||
}
|
||||
|
||||
static void jtbp_tdi(struct jtdev *p, int out)
|
||||
{
|
||||
if (out)
|
||||
p->data_register |= TDI;
|
||||
else
|
||||
p->data_register &= ~TDI;
|
||||
|
||||
do_bus_pirate_data(p);
|
||||
}
|
||||
|
||||
static void jtbp_rst(struct jtdev *p, int out)
|
||||
{
|
||||
if (out)
|
||||
p->data_register |= RESET;
|
||||
else
|
||||
p->data_register &= ~RESET;
|
||||
|
||||
do_bus_pirate_data(p);
|
||||
}
|
||||
|
||||
static void jtbp_tst(struct jtdev *p, int out)
|
||||
{
|
||||
// Test not supported on bus pirate
|
||||
}
|
||||
|
||||
static int jtbp_tdo_get(struct jtdev *p)
|
||||
{
|
||||
do_bus_pirate_data(p);
|
||||
|
||||
return (p->data_register & TDO) ? 1 : 0;
|
||||
}
|
||||
|
||||
static void jtbp_tclk(struct jtdev *p, int out)
|
||||
{
|
||||
jtbp_tdi(p, out);
|
||||
}
|
||||
|
||||
static int jtbp_tclk_get(struct jtdev *p)
|
||||
{
|
||||
do_bus_pirate_data(p);
|
||||
|
||||
return (p->data_register & TDI) ? 1 : 0;
|
||||
}
|
||||
|
||||
static void jtbp_tclk_strobe(struct jtdev *p, unsigned int count)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
jtbp_tclk(p, 1);
|
||||
jtbp_tclk(p, 0);
|
||||
|
||||
if (p->failed)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void jtbp_led_green(struct jtdev *p, int out)
|
||||
{
|
||||
// TCLK not supported by bus pirate
|
||||
}
|
||||
|
||||
static void jtbp_led_red(struct jtdev *p, int out)
|
||||
{
|
||||
// TCLK not supported by bus pirate
|
||||
}
|
||||
#else /* __linux__ */
|
||||
static int jtbp_open(struct jtdev *p, const char *device)
|
||||
{
|
||||
printc_err("jtdev: driver is not supported on this platform\n");
|
||||
p->failed = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void jtbp_close(struct jtdev *p) { }
|
||||
|
||||
static void jtbp_power_on(struct jtdev *p) { }
|
||||
static void jtbp_power_off(struct jtdev *p) { }
|
||||
static void jtbp_connect(struct jtdev *p) { }
|
||||
static void jtbp_release(struct jtdev *p) { }
|
||||
|
||||
static void jtbp_tck(struct jtdev *p, int out) { }
|
||||
static void jtbp_tms(struct jtdev *p, int out) { }
|
||||
static void jtbp_tdi(struct jtdev *p, int out) { }
|
||||
static void jtbp_rst(struct jtdev *p, int out) { }
|
||||
static void jtbp_tst(struct jtdev *p, int out) { }
|
||||
static int jtbp_tdo_get(struct jtdev *p) { return 0; }
|
||||
|
||||
static void jtbp_tclk(struct jtdev *p, int out) { }
|
||||
static int jtbp_tclk_get(struct jtdev *p) { return 0; }
|
||||
static void jtbp_tclk_strobe(struct jtdev *p, unsigned int count) { }
|
||||
|
||||
static void jtbp_led_green(struct jtdev *p, int out) { }
|
||||
static void jtbp_led_red(struct jtdev *p, int out) { }
|
||||
#endif
|
||||
|
||||
const struct jtdev_func jtdev_func_bp = {
|
||||
.jtdev_open = jtbp_open,
|
||||
.jtdev_close = jtbp_close,
|
||||
.jtdev_power_on = jtbp_power_on,
|
||||
.jtdev_power_off = jtbp_power_off,
|
||||
.jtdev_connect = jtbp_connect,
|
||||
.jtdev_release = jtbp_release,
|
||||
.jtdev_tck = jtbp_tck,
|
||||
.jtdev_tms = jtbp_tms,
|
||||
.jtdev_tdi = jtbp_tdi,
|
||||
.jtdev_rst = jtbp_rst,
|
||||
.jtdev_tst = jtbp_tst,
|
||||
.jtdev_tdo_get = jtbp_tdo_get,
|
||||
.jtdev_tclk = jtbp_tclk,
|
||||
.jtdev_tclk_get = jtbp_tclk_get,
|
||||
.jtdev_tclk_strobe = jtbp_tclk_strobe,
|
||||
.jtdev_led_green = jtbp_led_green,
|
||||
.jtdev_led_red = jtbp_led_red
|
||||
};
|
||||
|
|
@ -472,5 +472,6 @@ const struct device_class device_loadbsl = {
|
|||
.getregs = loadbsl_getregs,
|
||||
.setregs = loadbsl_setregs,
|
||||
.ctl = loadbsl_ctl,
|
||||
.poll = loadbsl_poll
|
||||
.poll = loadbsl_poll,
|
||||
.getconfigfuses = NULL
|
||||
};
|
||||
|
|
|
@ -312,6 +312,14 @@ static int pif_erase( device_t dev_base,
|
|||
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);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
|
@ -399,6 +407,50 @@ static device_t gpio_open(const struct device_args *args)
|
|||
return &dev->base;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
static device_t bp_open(const struct device_args *args)
|
||||
{
|
||||
struct pif_device *dev;
|
||||
|
||||
if (!(args->flags & DEVICE_FLAG_TTY)) {
|
||||
printc_err("bp: this driver does not support raw USB access\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(args->flags & DEVICE_FLAG_JTAG)) {
|
||||
printc_err("bp: this driver does not support Spy-Bi-Wire\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dev = malloc(sizeof(*dev));
|
||||
if (!dev) {
|
||||
printc_err("bp: malloc: %s\n", last_error());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(dev, 0, sizeof(*dev));
|
||||
dev->base.type = &device_pif;
|
||||
dev->base.max_breakpoints = 2; //supported by all devices
|
||||
dev->base.need_probe = 1;
|
||||
(&dev->jtag)->f = &jtdev_func_bp;
|
||||
|
||||
if ((&dev->jtag)->f->jtdev_open(&dev->jtag, args->path) < 0) {
|
||||
printc_err("bp: can't open port\n");
|
||||
free(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (init_device(&dev->jtag) < 0) {
|
||||
printc_err("bp: initialization failed\n");
|
||||
free(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &dev->base;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static void pif_destroy(device_t dev_base)
|
||||
{
|
||||
|
@ -423,7 +475,8 @@ const struct device_class device_pif = {
|
|||
.setregs = pif_setregs,
|
||||
.ctl = pif_ctl,
|
||||
.poll = pif_poll,
|
||||
.erase = pif_erase
|
||||
.erase = pif_erase,
|
||||
.getconfigfuses = pif_getconfigfuses
|
||||
};
|
||||
|
||||
const struct device_class device_gpio = {
|
||||
|
@ -437,5 +490,21 @@ const struct device_class device_gpio = {
|
|||
.setregs = pif_setregs,
|
||||
.ctl = pif_ctl,
|
||||
.poll = pif_poll,
|
||||
.erase = pif_erase
|
||||
.erase = pif_erase,
|
||||
.getconfigfuses = pif_getconfigfuses
|
||||
};
|
||||
|
||||
const struct device_class device_bp = {
|
||||
.name = "bus-pirate",
|
||||
.help = "Bus Pirate JTAG, MISO-TDO, MOSI-TDI, CS-TMS, AUX-RESET, CLK-TCK",
|
||||
.open = bp_open,
|
||||
.destroy = pif_destroy,
|
||||
.readmem = pif_readmem,
|
||||
.writemem = pif_writemem,
|
||||
.getregs = pif_getregs,
|
||||
.setregs = pif_setregs,
|
||||
.ctl = pif_ctl,
|
||||
.poll = pif_poll,
|
||||
.erase = pif_erase,
|
||||
.getconfigfuses = pif_getconfigfuses
|
||||
};
|
||||
|
|
|
@ -32,5 +32,6 @@
|
|||
extern const struct device_class device_pif;
|
||||
/* share wiht gpio implementation */
|
||||
extern const struct device_class device_gpio;
|
||||
extern const struct device_class device_bp;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -512,5 +512,6 @@ const struct device_class device_rom_bsl = {
|
|||
.getregs = rom_bsl_getregs,
|
||||
.setregs = rom_bsl_setregs,
|
||||
.ctl = rom_bsl_ctl,
|
||||
.poll = rom_bsl_poll
|
||||
.poll = rom_bsl_poll,
|
||||
.getconfigfuses = NULL
|
||||
};
|
||||
|
|
|
@ -817,5 +817,6 @@ const struct device_class device_sim = {
|
|||
.getregs = sim_getregs,
|
||||
.setregs = sim_setregs,
|
||||
.ctl = sim_ctl,
|
||||
.poll = sim_poll
|
||||
.poll = sim_poll,
|
||||
.getconfigfuses = NULL
|
||||
};
|
||||
|
|
|
@ -642,5 +642,6 @@ const struct device_class device_tilib = {
|
|||
.getregs = tilib_getregs,
|
||||
.setregs = tilib_setregs,
|
||||
.ctl = tilib_ctl,
|
||||
.poll = tilib_poll
|
||||
.poll = tilib_poll,
|
||||
.getconfigfuses = NULL
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue