From 8a1afe6c91531109a36ffd54c11260fb42cac8fc Mon Sep 17 00:00:00 2001 From: Alex Orange Date: Wed, 14 Jun 2017 13:28:07 -0600 Subject: [PATCH 1/2] Add a function to the device struct to handle config fuses. Also provide a getconfigfuses implementation for the pif based drivers (pif and gpio). --- drivers/bsl.c | 3 +- drivers/device.c | 5 +- drivers/device.h | 3 + drivers/fet.c | 15 ++- drivers/fet3.c | 3 +- drivers/flash_bsl.c | 3 +- drivers/gdbc.c | 3 +- drivers/goodfet.c | 3 +- drivers/jtaglib.c | 220 ++++++++++++++++++++++++++------------------ drivers/jtaglib.h | 1 + drivers/loadbsl.c | 3 +- drivers/pif.c | 14 ++- drivers/rom_bsl.c | 3 +- drivers/sim.c | 3 +- drivers/tilib.c | 3 +- 15 files changed, 176 insertions(+), 109 deletions(-) diff --git a/drivers/bsl.c b/drivers/bsl.c index ac4d6ba..c2fa678 100644 --- a/drivers/bsl.c +++ b/drivers/bsl.c @@ -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 }; diff --git a/drivers/device.c b/drivers/device.c index 2ad4431..32a592e 100644 --- a/drivers/device.c +++ b/drivers/device.c @@ -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); diff --git a/drivers/device.h b/drivers/device.h index e9ad66d..455b7ce 100644 --- a/drivers/device.h +++ b/drivers/device.h @@ -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 { diff --git a/drivers/fet.c b/drivers/fet.c index ae05e72..12ef2ca 100644 --- a/drivers/fet.c +++ b/drivers/fet.c @@ -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 }; diff --git a/drivers/fet3.c b/drivers/fet3.c index a864036..6bd6de7 100644 --- a/drivers/fet3.c +++ b/drivers/fet3.c @@ -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 }; diff --git a/drivers/flash_bsl.c b/drivers/flash_bsl.c index 4c435fe..c074056 100644 --- a/drivers/flash_bsl.c +++ b/drivers/flash_bsl.c @@ -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 }; diff --git a/drivers/gdbc.c b/drivers/gdbc.c index e297ac4..68ab44d 100644 --- a/drivers/gdbc.c +++ b/drivers/gdbc.c @@ -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 }; diff --git a/drivers/goodfet.c b/drivers/goodfet.c index 7d5773c..acaba3f 100644 --- a/drivers/goodfet.c +++ b/drivers/goodfet.c @@ -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 }; diff --git a/drivers/jtaglib.c b/drivers/jtaglib.c index 17975ce..0807998 100644 --- a/drivers/jtaglib.c +++ b/drivers/jtaglib.c @@ -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<> 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); +} diff --git a/drivers/jtaglib.h b/drivers/jtaglib.h index 009c736..0f99f78 100644 --- a/drivers/jtaglib.h +++ b/drivers/jtaglib.h @@ -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 diff --git a/drivers/loadbsl.c b/drivers/loadbsl.c index 1c57b9c..633b26b 100644 --- a/drivers/loadbsl.c +++ b/drivers/loadbsl.c @@ -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 }; diff --git a/drivers/pif.c b/drivers/pif.c index 39b0566..919e0b6 100644 --- a/drivers/pif.c +++ b/drivers/pif.c @@ -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); +} + /*----------------------------------------------------------------------------*/ @@ -423,7 +431,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 +446,6 @@ const struct device_class device_gpio = { .setregs = pif_setregs, .ctl = pif_ctl, .poll = pif_poll, - .erase = pif_erase + .erase = pif_erase, + .getconfigfuses = pif_getconfigfuses }; diff --git a/drivers/rom_bsl.c b/drivers/rom_bsl.c index b465337..9cc989f 100644 --- a/drivers/rom_bsl.c +++ b/drivers/rom_bsl.c @@ -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 }; diff --git a/drivers/sim.c b/drivers/sim.c index ed45629..b317695 100644 --- a/drivers/sim.c +++ b/drivers/sim.c @@ -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 }; diff --git a/drivers/tilib.c b/drivers/tilib.c index 6d96004..587c128 100644 --- a/drivers/tilib.c +++ b/drivers/tilib.c @@ -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 }; From 682d7ecc9ce77f6b4c258606b34ed90084fbd6e4 Mon Sep 17 00:00:00 2001 From: Alex Orange Date: Wed, 14 Jun 2017 13:53:03 -0600 Subject: [PATCH 2/2] Add a bus pirate driver. This is extremely slow at programming things, but is very useful for unbricking an MSP-FET430UIF if you have a bus pirate and no other programmers around. --- Makefile | 1 + drivers/jtdev.h | 4 + drivers/jtdev_bus_pirate.c | 356 +++++++++++++++++++++++++++++++++++++ drivers/pif.c | 59 ++++++ drivers/pif.h | 1 + ui/main.c | 3 +- 6 files changed, 423 insertions(+), 1 deletion(-) create mode 100644 drivers/jtdev_bus_pirate.c diff --git a/Makefile b/Makefile index b2a06ec..415cbe6 100644 --- a/Makefile +++ b/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 \ diff --git a/drivers/jtdev.h b/drivers/jtdev.h index 37d2987..88bd52b 100644 --- a/drivers/jtdev.h +++ b/drivers/jtdev.h @@ -19,6 +19,9 @@ #ifndef JTDEV_H_ #define JTDEV_H_ + +#include + 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 diff --git a/drivers/jtdev_bus_pirate.c b/drivers/jtdev_bus_pirate.c new file mode 100644 index 0000000..1c94f9c --- /dev/null +++ b/drivers/jtdev_bus_pirate.c @@ -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 +#include "jtdev.h" +#include "output.h" + +#if defined(__linux__) +/*===== includes =============================================================*/ + +#include +#include +#include +#include +#include + +#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 + +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 +}; + diff --git a/drivers/pif.c b/drivers/pif.c index 919e0b6..0b07753 100644 --- a/drivers/pif.c +++ b/drivers/pif.c @@ -407,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) { @@ -449,3 +493,18 @@ const struct device_class device_gpio = { .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 +}; diff --git a/drivers/pif.h b/drivers/pif.h index e5def7d..e10b75a 100644 --- a/drivers/pif.h +++ b/drivers/pif.h @@ -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 diff --git a/ui/main.c b/ui/main.c index a0e5085..f9be59a 100644 --- a/ui/main.c +++ b/ui/main.c @@ -90,7 +90,8 @@ static const struct device_class *const driver_table[] = { &device_gpio, &device_loadbsl, &device_ezfet, - &device_rom_bsl + &device_rom_bsl, + &device_bp }; static const char *version_text =