jtaglib: proper device identification
This commit is contained in:
parent
ddfffa06fb
commit
9809da335e
|
@ -34,7 +34,9 @@
|
|||
* jtag_write_reg corrected
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jtaglib.h"
|
||||
#include "jtaglib_defs.h"
|
||||
|
@ -303,16 +305,16 @@ static const struct jtaglib_funcs* get_jlf(struct jtdev *p)
|
|||
printc_err("jtaglib: ERROR: no JTAG ID set!\n");
|
||||
__builtin_trap();
|
||||
return NULL;
|
||||
} else if (p->jtag_id == JTAG_ID_CPU16) {
|
||||
return &jlf_cpu16;
|
||||
} else if (JTAG_ID_IS_XV2(p->jtag_id)) {
|
||||
return &jlf_cpuxv2;
|
||||
} else {
|
||||
// Here, it's hard to predict whether the target is CPUX or Xv2
|
||||
// Here, it's hard to predict whether the target is CPUX or regular
|
||||
// from the JTAG ID alone. However, this is only needed relatively
|
||||
// little as the actual MCU ID should be read from info memory
|
||||
// after connecting, so let's just assume Xv2 here, and add some
|
||||
// after connecting, so let's just assume old here, and add some
|
||||
// extra care to the few functions that will be called before the
|
||||
// ID readout happens to make it all work
|
||||
return &jlf_cpuxv2;
|
||||
return &jlf_cpu16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -329,14 +331,6 @@ unsigned int jtag_get_device(struct jtdev *p)
|
|||
return r;
|
||||
}
|
||||
|
||||
unsigned int jtag_chip_id(struct jtdev *p)
|
||||
{
|
||||
// NOTE: this is one of the special functions that have to be called early
|
||||
// on before chip ID stuff is done
|
||||
|
||||
return get_jlf(p)->jlf_chip_id(p);
|
||||
}
|
||||
|
||||
/* Reads one byte/word from a given address */
|
||||
uint16_t jtag_read_mem(struct jtdev *p, unsigned int format, address_t address)
|
||||
{
|
||||
|
@ -452,6 +446,9 @@ unsigned int jtag_cpu_state(struct jtdev *p)
|
|||
}
|
||||
int jtag_get_config_fuses(struct jtdev *p)
|
||||
{
|
||||
// NOTE: this is one of the special functions that have to be called early
|
||||
// on before chip ID stuff is done
|
||||
|
||||
return get_jlf(p)->jlf_get_config_fuses(p);
|
||||
}
|
||||
|
||||
|
@ -729,16 +726,174 @@ int jtag_dev_getconfigfuses(device_t 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;
|
||||
static uint8_t jtag_ids_known[] = {
|
||||
0x89, 0x8D, 0x91, 0x95, 0x98, 0x99
|
||||
};
|
||||
|
||||
static int idproc_89(struct jtdev *p, uint32_t id_data_addr, struct chipinfo_id *id)
|
||||
{
|
||||
uint16_t iddata[8];
|
||||
|
||||
printc_dbg("Identify (89)...\n");
|
||||
printc_dbg("Read device ID bytes at 0x%05x...\n", id_data_addr);
|
||||
memset(iddata, 0, sizeof iddata);
|
||||
|
||||
// read 8 words starting at id_data_addr
|
||||
// don't use read_mem_quick because we want to minimize the number of
|
||||
// functions that need special care before the device ID is read
|
||||
for (int i = 0; i < sizeof(iddata)/sizeof(*iddata); ++i) {
|
||||
iddata[i] = jtag_read_mem(p, 16, id_data_addr + i*2);
|
||||
}
|
||||
|
||||
id->ver_id = iddata[0];
|
||||
id->ver_sub_id = 0;
|
||||
id->revision = iddata[1];
|
||||
id->fab = iddata[1] >> 8;
|
||||
id->self = iddata[2];
|
||||
id->config = (iddata[6]>>8) & 0x7f;
|
||||
if (get_jlf(p)->jlf_get_config_fuses) {
|
||||
id->fuses = jtag_get_config_fuses(p);
|
||||
} else {
|
||||
id->fuses = 0x55;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int idproc_9x(struct jtdev *p, uint32_t dev_id_ptr, struct chipinfo_id *id)
|
||||
{
|
||||
uint16_t iddata[8];
|
||||
uint8_t info_len;
|
||||
int tlv_size;
|
||||
|
||||
printc_dbg("Identify (9x)...\n");
|
||||
printc_dbg("Read device ID bytes at 0x%05x...\n", dev_id_ptr);
|
||||
memset(iddata, 0, sizeof iddata);
|
||||
|
||||
// read 8 words starting at dev_id_ptr
|
||||
// don't use read_mem_quick because we want to minimize the number of
|
||||
// functions that need special care before the device ID is read
|
||||
for (int i = 0; i < sizeof(iddata)/sizeof(*iddata); ++i) {
|
||||
iddata[i] = jtag_read_mem(p, 16, dev_id_ptr + i*2);
|
||||
}
|
||||
|
||||
info_len = iddata[0] & 0xff;
|
||||
id->ver_id = iddata[2];
|
||||
id->revision = iddata[3]&0xff;
|
||||
id->config = iddata[3]>>8;
|
||||
id->fab = 0x55;
|
||||
id->self = 0x5555;
|
||||
id->fuses = 0x55;
|
||||
|
||||
if (info_len < 1 || info_len > 11) {
|
||||
printc_dbg("jtaglib: idproc_9x: invalid info length %d\n", info_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
printc_dbg("Read TLV...\n");
|
||||
|
||||
tlv_size = ((1 << info_len) - 2) << 2;
|
||||
uint8_t *tlvdata = (uint8_t*)malloc(tlv_size);
|
||||
if (!tlvdata) {
|
||||
printc_err("jtaglib: idproc_9x: can't allocate %d bytes of memory for TLV\n",
|
||||
tlv_size);
|
||||
return -1;
|
||||
}
|
||||
for (int i = 0; i < (tlv_size >> 1); ++i) {
|
||||
w16le(&tlvdata[i*2], jtag_read_mem(p, 16, dev_id_ptr + i*2));
|
||||
}
|
||||
|
||||
/* search TLV for sub-ID */
|
||||
for (int i = 8; i + 3 < tlv_size; ) {
|
||||
uint8_t tag = tlvdata[i]; ++i;
|
||||
uint8_t len = tlvdata[i]; ++i;
|
||||
|
||||
if (tag == 0xff) break;
|
||||
|
||||
if (tag == 0x14 && len >= 2) {
|
||||
id->ver_sub_id = r16le(&tlvdata[i]);
|
||||
break;
|
||||
}
|
||||
|
||||
i += len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int jtag_dev_init(struct jtdev *p) {
|
||||
unsigned int jtagid;
|
||||
uint32_t dev_id_addr;
|
||||
struct chipinfo_id id;
|
||||
const struct chipinfo *chip;
|
||||
|
||||
jtagid = jtag_init(p);
|
||||
if (p->failed) return -1;
|
||||
|
||||
memset(&id, 0, sizeof id);
|
||||
|
||||
printc("JTAG ID: 0x%02x\n", jtagid);
|
||||
|
||||
bool found = false;
|
||||
for (int i = 0; i < sizeof(jtag_ids_known)/sizeof(*jtag_ids_known); ++i) {
|
||||
if (jtagid == jtag_ids_known[i]) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
printc_err("jtaglib: unknown JTAG ID: 0x%02x\n", jtagid);
|
||||
jtag_release_device(p, 0xfffe);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (JTAG_ID_IS_XV2(jtagid)) {
|
||||
uint16_t core_ip_id;
|
||||
unsigned int device_id;
|
||||
|
||||
jtag_ir_shift(p, IR_COREIP_ID);
|
||||
core_ip_id = jtag_dr_shift_16(p, 0);
|
||||
|
||||
if (jtagid == 0x95) delay_ms(1500);
|
||||
|
||||
jtag_ir_shift(p, IR_DEVICE_ID);
|
||||
device_id = jtag_dr_shift_20(p, 0);
|
||||
|
||||
device_id = ((device_id & 0xffff) << 4) | (device_id >> 16);
|
||||
printc_dbg("jtaglib: Xv2: core IP ID=%04x, device ID=%06x\n",
|
||||
core_ip_id, device_id);
|
||||
|
||||
if (device_id != 0) return device_id + 4;
|
||||
else return 0x0ff0; // ???
|
||||
} else {
|
||||
dev_id_addr = 0x0ff0;
|
||||
}
|
||||
|
||||
if (!JTAG_ID_IS_XV2(jtagid)) {
|
||||
if (idproc_89(p, dev_id_addr, &id) < 0)
|
||||
return -1;
|
||||
} else {
|
||||
if (idproc_9x(p, dev_id_addr, &id) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
printc_dbg(" ver_id: %04x\n", id.ver_id);
|
||||
printc_dbg(" ver_sub_id: %04x\n", id.ver_sub_id);
|
||||
printc_dbg(" revision: %02x\n", id.revision);
|
||||
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(" activation_key: %08x\n", id.activation_key);
|
||||
|
||||
chip = chipinfo_find_by_id(&id);
|
||||
if (!chip) {
|
||||
printc_err("jtaglib: unknown chip ID\n");
|
||||
} else {
|
||||
p->base.chip = chip;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
* CPU types (that is, 16-bit vs CPUX vs Xv2) */
|
||||
struct jtaglib_funcs {
|
||||
unsigned int (*jlf_get_device)(struct jtdev *p);
|
||||
unsigned int (*jlf_chip_id)(struct jtdev *p);
|
||||
|
||||
uint16_t (*jlf_read_mem)(struct jtdev *p, unsigned int format, address_t address);
|
||||
void (*jlf_read_mem_quick)(struct jtdev *p, address_t start_address,
|
||||
|
|
|
@ -174,22 +174,6 @@ static unsigned int jlf16_get_device(struct jtdev *p)
|
|||
return jtag_id;
|
||||
}
|
||||
|
||||
/* Read the target chip id.
|
||||
* return: chip id
|
||||
*/
|
||||
static unsigned int jlf16_chip_id(struct jtdev *p)
|
||||
{
|
||||
unsigned short chip_id;
|
||||
|
||||
/* Read id from address 0x0ff0 */
|
||||
chip_id = jtag_read_mem(p, 16, 0x0FF0);
|
||||
|
||||
/* High / low byte are stored in reverse order */
|
||||
chip_id = (chip_id << 8) + (chip_id >> 8);
|
||||
|
||||
return chip_id;
|
||||
}
|
||||
|
||||
/* Reads one byte/word from a given address
|
||||
* format : 8-byte, 16-word
|
||||
* address: address of memory
|
||||
|
@ -804,7 +788,6 @@ static int jlf16_get_config_fuses( struct jtdev *p )
|
|||
|
||||
const struct jtaglib_funcs jlf_cpu16 = {
|
||||
.jlf_get_device = jlf16_get_device,
|
||||
.jlf_chip_id = jlf16_chip_id,
|
||||
|
||||
.jlf_read_mem = jlf16_read_mem,
|
||||
.jlf_read_mem_quick = jlf16_read_mem_quick,
|
||||
|
|
|
@ -7,15 +7,14 @@
|
|||
#define JTAG_ERASE_MAIN 0xA504
|
||||
#define JTAG_ERASE_SGMT 0xA502
|
||||
|
||||
/* JTAG identification value for all existing Flash-based MSP430 devices
|
||||
*/
|
||||
#define JTAG_ID_CPU16 0x89
|
||||
#define JTAG_ID_IS_XV2(x) ((x)==0x91||(x)==0x95||(x)==0x98||(x)==0x99)
|
||||
|
||||
/* Instructions for the JTAG control signal register in reverse bit order
|
||||
*/
|
||||
#define IR_CNTRL_SIG_16BIT 0xC8 /* 0x13 */
|
||||
#define IR_CNTRL_SIG_CAPTURE 0x28 /* 0x14 */
|
||||
#define IR_CNTRL_SIG_RELEASE 0xA8 /* 0x15 */
|
||||
#define IR_COREIP_ID 0xE8 /* 0x17 */
|
||||
/* Instructions for the JTAG data register */
|
||||
#define IR_DATA_16BIT 0x82 /* 0x41 */
|
||||
#define IR_DATA_CAPTURE 0x42 /* 0x42 */
|
||||
|
@ -24,6 +23,7 @@
|
|||
#define IR_ADDR_16BIT 0xC1 /* 0x83 */
|
||||
#define IR_ADDR_CAPTURE 0x21 /* 0x84 */
|
||||
#define IR_DATA_TO_ADDR 0xA1 /* 0x85 */
|
||||
#define IR_DEVICE_ID 0xE1 /* 0x87 */
|
||||
/* Instructions for the JTAG PSA mode */
|
||||
#define IR_DATA_PSA 0x22 /* 0x44 */
|
||||
#define IR_SHIFT_OUT_PSA 0x62 /* 0x46 */
|
||||
|
@ -31,7 +31,7 @@
|
|||
#define IR_PREPARE_BLOW 0x44 /* 0x22 */
|
||||
#define IR_EX_BLOW 0x24 /* 0x24 */
|
||||
/* Instructions for the Configuration Fuse */
|
||||
#define IR_CONFIG_FUSES 0x94
|
||||
#define IR_CONFIG_FUSES 0x94
|
||||
/* Bypass instruction */
|
||||
#define IR_BYPASS 0xFF /* 0xFF */
|
||||
/* Instructions for the EEM */
|
||||
|
@ -60,6 +60,7 @@
|
|||
#define jtag_ir_shift(p, ir) p->f->jtdev_ir_shift(p, ir)
|
||||
#define jtag_dr_shift_8(p, dr) p->f->jtdev_dr_shift_8(p, dr)
|
||||
#define jtag_dr_shift_16(p, dr) p->f->jtdev_dr_shift_16(p, dr)
|
||||
#define jtag_dr_shift_20(p, dr) p->f->jtdev_dr_shift_20(p, dr)
|
||||
#define jtag_tms_sequence(p, bits, tms) p->f->jtdev_tms_sequence(p, bits, tms)
|
||||
#define jtag_init_dap(p) p->f->jtdev_init_dap(p)
|
||||
|
||||
|
|
|
@ -1121,8 +1121,11 @@ static int idproc_9x(struct v3hil *fet, uint32_t dev_id_ptr,
|
|||
if (tag == 0xff)
|
||||
break;
|
||||
|
||||
if ((tag == 0x14) && (len >= 2))
|
||||
if ((tag == 0x14) && (len >= 2)) {
|
||||
// FIXME: this looks like it's reading from the wrong address?
|
||||
id->ver_sub_id = r16le(fet->hal.payload);
|
||||
// FIXME: break here?
|
||||
}
|
||||
|
||||
i += len;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue