jtaglib: getting cpuxv2 stuff to work, very slowly...
This commit is contained in:
parent
9809da335e
commit
2170693f2f
|
@ -562,12 +562,6 @@ int jtag_refresh_bps(device_t dev, struct jtdev *p)
|
||||||
|
|
||||||
/* ========================================================================= */
|
/* ========================================================================= */
|
||||||
|
|
||||||
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,
|
static int write_flash_block(struct jtdev *p, address_t addr,
|
||||||
address_t len, const uint8_t *data)
|
address_t len, const uint8_t *data)
|
||||||
{
|
{
|
||||||
|
@ -591,6 +585,25 @@ static int read_words(device_t dev_base, const struct chipinfo_memory *m,
|
||||||
address_t addr, address_t len, uint8_t *data) {
|
address_t addr, address_t len, uint8_t *data) {
|
||||||
struct jtdev *p = (struct jtdev*)dev_base;
|
struct jtdev *p = (struct jtdev*)dev_base;
|
||||||
|
|
||||||
|
printc_dbg("jtaglib: read_words: ram: len=%d addr=%06x\n", len, addr);
|
||||||
|
if (len > 2 && !(len & 1)) {
|
||||||
|
uint16_t* word = malloc((len>>1) * sizeof(*word));
|
||||||
|
if (!word) {
|
||||||
|
pr_error("jtaglib: failed to allocate memory");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
jtag_read_mem_quick(p, addr, len >> 1, word);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < len/2; i++) {
|
||||||
|
data[2*i+0] = word[i] & 0xff;
|
||||||
|
data[2*i+1] = word[i] >> 8;
|
||||||
|
}
|
||||||
|
free(word);
|
||||||
|
|
||||||
|
return p->failed ? -1 : len;
|
||||||
|
}
|
||||||
|
|
||||||
for (unsigned int index = 0; index < len; index += 2) {
|
for (unsigned int index = 0; index < len; index += 2) {
|
||||||
unsigned int word = jtag_read_mem(p, 16, addr+index);
|
unsigned int word = jtag_read_mem(p, 16, addr+index);
|
||||||
data[index ] = word & 0x00ff;
|
data[index ] = word & 0x00ff;
|
||||||
|
@ -605,8 +618,10 @@ static int write_words(device_t dev_base, const struct chipinfo_memory *m,
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (m->type != CHIPINFO_MEMTYPE_FLASH) {
|
if (m->type != CHIPINFO_MEMTYPE_FLASH) {
|
||||||
len = 2;
|
printc_dbg("jtaglib: write_words: ram: len=%d addr=%06x\n", len, addr);
|
||||||
r = write_ram_word(p, addr, r16le(data));
|
uint16_t value = data[0] | ((uint16_t)data[1] << 8);
|
||||||
|
jtag_write_mem(p, 16, addr, value);
|
||||||
|
r = p->failed ? -1 : 0;
|
||||||
} else {
|
} else {
|
||||||
r = write_flash_block(p, addr, len, data);
|
r = write_flash_block(p, addr, len, data);
|
||||||
}
|
}
|
||||||
|
@ -773,11 +788,12 @@ static int idproc_9x(struct jtdev *p, uint32_t dev_id_ptr, struct chipinfo_id *i
|
||||||
memset(iddata, 0, sizeof iddata);
|
memset(iddata, 0, sizeof iddata);
|
||||||
|
|
||||||
// read 8 words starting at dev_id_ptr
|
// read 8 words starting at dev_id_ptr
|
||||||
// don't use read_mem_quick because we want to minimize the number of
|
// need to use read_mem_quick because apparently it's the only one capable
|
||||||
// functions that need special care before the device ID is read
|
// of reading from TLV...
|
||||||
for (int i = 0; i < sizeof(iddata)/sizeof(*iddata); ++i) {
|
jtag_read_mem_quick(p, dev_id_ptr, sizeof(iddata)/sizeof(*iddata), iddata);
|
||||||
iddata[i] = jtag_read_mem(p, 16, dev_id_ptr + i*2);
|
/*for (int i = 0; i < 8; ++i) {
|
||||||
}
|
printc_dbg("TLV[%d] = %04x\n", i, iddata[i]);
|
||||||
|
}*/
|
||||||
|
|
||||||
info_len = iddata[0] & 0xff;
|
info_len = iddata[0] & 0xff;
|
||||||
id->ver_id = iddata[2];
|
id->ver_id = iddata[2];
|
||||||
|
@ -801,9 +817,7 @@ static int idproc_9x(struct jtdev *p, uint32_t dev_id_ptr, struct chipinfo_id *i
|
||||||
tlv_size);
|
tlv_size);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < (tlv_size >> 1); ++i) {
|
jtag_read_mem_quick(p, dev_id_ptr, tlv_size >> 1, (uint16_t*)tlvdata);
|
||||||
w16le(&tlvdata[i*2], jtag_read_mem(p, 16, dev_id_ptr + i*2));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* search TLV for sub-ID */
|
/* search TLV for sub-ID */
|
||||||
for (int i = 8; i + 3 < tlv_size; ) {
|
for (int i = 8; i + 3 < tlv_size; ) {
|
||||||
|
@ -862,12 +876,13 @@ int jtag_dev_init(struct jtdev *p) {
|
||||||
jtag_ir_shift(p, IR_DEVICE_ID);
|
jtag_ir_shift(p, IR_DEVICE_ID);
|
||||||
device_id = jtag_dr_shift_20(p, 0);
|
device_id = jtag_dr_shift_20(p, 0);
|
||||||
|
|
||||||
device_id = ((device_id & 0xffff) << 4) | (device_id >> 16);
|
//device_id = ((device_id & 0xffff) << 4) | (device_id >> 16);
|
||||||
printc_dbg("jtaglib: Xv2: core IP ID=%04x, device ID=%06x\n",
|
printc_dbg("jtaglib: Xv2: core IP ID=%04x, device ID=%06x\n",
|
||||||
core_ip_id, device_id);
|
core_ip_id, device_id);
|
||||||
|
|
||||||
if (device_id != 0) return device_id + 4;
|
if (device_id != 0 && (device_id & 0xff) != 0x80)
|
||||||
else return 0x0ff0; // ???
|
dev_id_addr = device_id + 4;
|
||||||
|
else dev_id_addr = 0x1a00; // ???
|
||||||
} else {
|
} else {
|
||||||
dev_id_addr = 0x0ff0;
|
dev_id_addr = 0x0ff0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,9 +8,11 @@
|
||||||
* 0 - otherwise
|
* 0 - otherwise
|
||||||
*/
|
*/
|
||||||
static int jlf16_set_instruction_fetch(struct jtdev *p)
|
static int jlf16_set_instruction_fetch(struct jtdev *p)
|
||||||
{
|
{ // SLAU320AJ name: SetInstrFetch / SyncJtag?
|
||||||
unsigned int loop_counter;
|
unsigned int loop_counter;
|
||||||
|
|
||||||
|
// SyncJtag: has CTLR_SIG_16BIT=0x2401 here
|
||||||
|
|
||||||
jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||||
/* Wait until CPU is in instruction fetch state
|
/* Wait until CPU is in instruction fetch state
|
||||||
* timeout after limited attempts
|
* timeout after limited attempts
|
||||||
|
@ -31,7 +33,7 @@ static int jlf16_set_instruction_fetch(struct jtdev *p)
|
||||||
|
|
||||||
/* Set the CPU into a controlled stop state */
|
/* Set the CPU into a controlled stop state */
|
||||||
static void jlf16_halt_cpu(struct jtdev *p)
|
static void jlf16_halt_cpu(struct jtdev *p)
|
||||||
{
|
{ // SLAU320AJ name: HaltCPU
|
||||||
/* Set CPU into instruction fetch mode */
|
/* Set CPU into instruction fetch mode */
|
||||||
jlf16_set_instruction_fetch(p);
|
jlf16_set_instruction_fetch(p);
|
||||||
|
|
||||||
|
@ -42,7 +44,7 @@ static void jlf16_halt_cpu(struct jtdev *p)
|
||||||
/* Send JMP $ instruction to keep CPU from changing the state */
|
/* Send JMP $ instruction to keep CPU from changing the state */
|
||||||
jtag_ir_shift(p, IR_DATA_16BIT);
|
jtag_ir_shift(p, IR_DATA_16BIT);
|
||||||
jtag_dr_shift_16(p, 0x3FFF);
|
jtag_dr_shift_16(p, 0x3FFF);
|
||||||
jtag_tclk_set(p);
|
//jtag_tclk_set(p); // TODO: ???
|
||||||
jtag_tclk_clr(p);
|
jtag_tclk_clr(p);
|
||||||
|
|
||||||
/* Set JTAG_HALT bit */
|
/* Set JTAG_HALT bit */
|
||||||
|
@ -53,7 +55,7 @@ static void jlf16_halt_cpu(struct jtdev *p)
|
||||||
|
|
||||||
/* Release the target CPU from the controlled stop state */
|
/* Release the target CPU from the controlled stop state */
|
||||||
static void jlf16_release_cpu(struct jtdev *p)
|
static void jlf16_release_cpu(struct jtdev *p)
|
||||||
{
|
{ // SLAU320AJ name: ReleaseCPU
|
||||||
jtag_tclk_clr(p);
|
jtag_tclk_clr(p);
|
||||||
|
|
||||||
/* clear the HALT_JTAG bit */
|
/* clear the HALT_JTAG bit */
|
||||||
|
@ -76,7 +78,7 @@ static int jlf16_verify_mem(struct jtdev *p,
|
||||||
unsigned int start_address,
|
unsigned int start_address,
|
||||||
unsigned int length,
|
unsigned int length,
|
||||||
const uint16_t *data)
|
const uint16_t *data)
|
||||||
{
|
{ // SLAU320AJ name: VerifyMem/VerifyPSA
|
||||||
unsigned int psa_value;
|
unsigned int psa_value;
|
||||||
unsigned int index;
|
unsigned int index;
|
||||||
|
|
||||||
|
@ -146,7 +148,7 @@ static int jlf16_erase_check(struct jtdev *p, unsigned int start_address,
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int jlf16_get_device(struct jtdev *p)
|
static unsigned int jlf16_get_device(struct jtdev *p)
|
||||||
{
|
{ // SLAU320AJ name: GetDevice
|
||||||
unsigned int jtag_id = 0;
|
unsigned int jtag_id = 0;
|
||||||
unsigned int loop_counter;
|
unsigned int loop_counter;
|
||||||
|
|
||||||
|
@ -165,7 +167,7 @@ static unsigned int jlf16_get_device(struct jtdev *p)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loop_counter == 0) {
|
if (loop_counter == 0) {
|
||||||
printc_err("jtaglib_cpu16: jtag_get_device: timed out\n");
|
printc_err("jlf16_get_device: timed out\n");
|
||||||
p->failed = 1;
|
p->failed = 1;
|
||||||
/* timeout reached */
|
/* timeout reached */
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -180,7 +182,7 @@ static unsigned int jlf16_get_device(struct jtdev *p)
|
||||||
* return : content of memory
|
* return : content of memory
|
||||||
*/
|
*/
|
||||||
static uint16_t jlf16_read_mem(struct jtdev *p, unsigned int format, address_t address)
|
static uint16_t jlf16_read_mem(struct jtdev *p, unsigned int format, address_t address)
|
||||||
{
|
{ // SLAU320AJ name: ReadMem
|
||||||
uint16_t content;
|
uint16_t content;
|
||||||
|
|
||||||
jlf16_halt_cpu(p);
|
jlf16_halt_cpu(p);
|
||||||
|
@ -217,7 +219,7 @@ static uint16_t jlf16_read_mem(struct jtdev *p, unsigned int format, address_t a
|
||||||
*/
|
*/
|
||||||
static void jlf16_read_mem_quick(struct jtdev *p, address_t address,
|
static void jlf16_read_mem_quick(struct jtdev *p, address_t address,
|
||||||
unsigned int length, uint16_t *data)
|
unsigned int length, uint16_t *data)
|
||||||
{
|
{ // SLAU320AJ name: ReadMemQuick
|
||||||
unsigned int index;
|
unsigned int index;
|
||||||
|
|
||||||
/* Initialize reading: */
|
/* Initialize reading: */
|
||||||
|
@ -232,9 +234,10 @@ static void jlf16_read_mem_quick(struct jtdev *p, address_t address,
|
||||||
|
|
||||||
for (index = 0; index < length; index++) {
|
for (index = 0; index < length; index++) {
|
||||||
jtag_tclk_set(p);
|
jtag_tclk_set(p);
|
||||||
jtag_tclk_clr(p);
|
//jtag_tclk_clr(p); // TODO: ???
|
||||||
/* shift out the data from the target */
|
/* shift out the data from the target */
|
||||||
data[index] = jtag_dr_shift_16(p, 0x0000);
|
data[index] = jtag_dr_shift_16(p, 0x0000);
|
||||||
|
jtag_tclk_clr(p); // TODO: ???
|
||||||
}
|
}
|
||||||
|
|
||||||
jtag_tclk_set(p);
|
jtag_tclk_set(p);
|
||||||
|
@ -248,7 +251,7 @@ static void jlf16_read_mem_quick(struct jtdev *p, address_t address,
|
||||||
*/
|
*/
|
||||||
static void jlf16_write_mem(struct jtdev *p, unsigned int format,
|
static void jlf16_write_mem(struct jtdev *p, unsigned int format,
|
||||||
address_t address, uint16_t data)
|
address_t address, uint16_t data)
|
||||||
{
|
{ // SLAU320AJ name: WriteMem
|
||||||
jlf16_halt_cpu(p);
|
jlf16_halt_cpu(p);
|
||||||
jtag_tclk_clr(p);
|
jtag_tclk_clr(p);
|
||||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||||
|
@ -279,7 +282,7 @@ static void jlf16_write_mem(struct jtdev *p, unsigned int format,
|
||||||
*/
|
*/
|
||||||
static void jlf16_write_mem_quick(struct jtdev *p, address_t address,
|
static void jlf16_write_mem_quick(struct jtdev *p, address_t address,
|
||||||
unsigned int length, const uint16_t *data)
|
unsigned int length, const uint16_t *data)
|
||||||
{
|
{ // SLAU320AJ name: WriteMemQuick
|
||||||
unsigned int index;
|
unsigned int index;
|
||||||
|
|
||||||
/* Initialize writing */
|
/* Initialize writing */
|
||||||
|
@ -288,11 +291,11 @@ static void jlf16_write_mem_quick(struct jtdev *p, address_t address,
|
||||||
jtag_tclk_clr(p);
|
jtag_tclk_clr(p);
|
||||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||||
|
|
||||||
|
for (index = 0; index < length; index++) {
|
||||||
/* Set RW to write */
|
/* Set RW to write */
|
||||||
jtag_dr_shift_16(p, 0x2408);
|
jtag_dr_shift_16(p, 0x2408);
|
||||||
jtag_ir_shift(p, IR_DATA_QUICK);
|
jtag_ir_shift(p, IR_DATA_QUICK);
|
||||||
|
|
||||||
for (index = 0; index < length; index++) {
|
|
||||||
/* Write data */
|
/* Write data */
|
||||||
jtag_dr_shift_16(p, data[index]);
|
jtag_dr_shift_16(p, data[index]);
|
||||||
|
|
||||||
|
@ -309,7 +312,7 @@ static void jlf16_write_mem_quick(struct jtdev *p, address_t address,
|
||||||
* return: JTAG ID
|
* return: JTAG ID
|
||||||
*/
|
*/
|
||||||
static unsigned int jlf16_execute_puc(struct jtdev *p)
|
static unsigned int jlf16_execute_puc(struct jtdev *p)
|
||||||
{
|
{ // SLAU320AJ name: ExecutePOR
|
||||||
unsigned int jtag_id;
|
unsigned int jtag_id;
|
||||||
|
|
||||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||||
|
@ -322,13 +325,15 @@ static unsigned int jlf16_execute_puc(struct jtdev *p)
|
||||||
jtag_tclk_clr(p);
|
jtag_tclk_clr(p);
|
||||||
jtag_tclk_set(p);
|
jtag_tclk_set(p);
|
||||||
jtag_tclk_clr(p);
|
jtag_tclk_clr(p);
|
||||||
jtag_tclk_set(p);
|
//jtag_tclk_set(p); // TODO: ???
|
||||||
|
|
||||||
/* Read jtag id */
|
/* Read jtag id */
|
||||||
jtag_id = jtag_ir_shift(p, IR_ADDR_CAPTURE);
|
jtag_id = jtag_ir_shift(p, IR_ADDR_CAPTURE);
|
||||||
|
|
||||||
|
jtag_tclk_set(p); // TODO: ???
|
||||||
|
|
||||||
/* Disable watchdog on target device */
|
/* Disable watchdog on target device */
|
||||||
jtag_write_mem(p, 16, 0x0120, 0x5A80);
|
jtag_write_mem(p, 16, 0x0120, 0x5A80); // FIXME
|
||||||
|
|
||||||
return jtag_id;
|
return jtag_id;
|
||||||
}
|
}
|
||||||
|
@ -341,7 +346,7 @@ static unsigned int jlf16_execute_puc(struct jtdev *p)
|
||||||
* other - load Address into PC
|
* other - load Address into PC
|
||||||
*/
|
*/
|
||||||
static void jlf16_release_device(struct jtdev *p, address_t address)
|
static void jlf16_release_device(struct jtdev *p, address_t address)
|
||||||
{
|
{ // SLAU320AJ name: ReleaseDevice
|
||||||
switch (address) {
|
switch (address) {
|
||||||
case 0xffff: /* Nothing to do */
|
case 0xffff: /* Nothing to do */
|
||||||
break;
|
break;
|
||||||
|
@ -378,7 +383,7 @@ static void jlf16_release_device(struct jtdev *p, address_t address)
|
||||||
*/
|
*/
|
||||||
static void jlf16_write_flash(struct jtdev *p, address_t start_address,
|
static void jlf16_write_flash(struct jtdev *p, address_t start_address,
|
||||||
unsigned int length, const uint16_t *data)
|
unsigned int length, const uint16_t *data)
|
||||||
{
|
{ // SLAU320AJ name: WriteFLASH
|
||||||
unsigned int index;
|
unsigned int index;
|
||||||
unsigned int address;
|
unsigned int address;
|
||||||
|
|
||||||
|
@ -392,7 +397,7 @@ static void jlf16_write_flash(struct jtdev *p, address_t start_address,
|
||||||
|
|
||||||
/* FCTL1 register */
|
/* FCTL1 register */
|
||||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||||
jtag_dr_shift_16(p, 0x0128);
|
jtag_dr_shift_16(p, 0x0128); // FIXME
|
||||||
|
|
||||||
/* Enable FLASH write */
|
/* Enable FLASH write */
|
||||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||||
|
@ -402,7 +407,7 @@ static void jlf16_write_flash(struct jtdev *p, address_t start_address,
|
||||||
|
|
||||||
/* FCTL2 register */
|
/* FCTL2 register */
|
||||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||||
jtag_dr_shift_16(p, 0x012A);
|
jtag_dr_shift_16(p, 0x012A); // FIXME
|
||||||
|
|
||||||
/* Select MCLK as source, DIV=1 */
|
/* Select MCLK as source, DIV=1 */
|
||||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||||
|
@ -412,7 +417,7 @@ static void jlf16_write_flash(struct jtdev *p, address_t start_address,
|
||||||
|
|
||||||
/* FCTL3 register */
|
/* FCTL3 register */
|
||||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||||
jtag_dr_shift_16(p, 0x012C);
|
jtag_dr_shift_16(p, 0x012C); // FIXME
|
||||||
|
|
||||||
/* Clear FCTL3 register */
|
/* Clear FCTL3 register */
|
||||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||||
|
@ -455,7 +460,7 @@ static void jlf16_write_flash(struct jtdev *p, address_t start_address,
|
||||||
|
|
||||||
/* FCTL1 register */
|
/* FCTL1 register */
|
||||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||||
jtag_dr_shift_16(p, 0x0128);
|
jtag_dr_shift_16(p, 0x0128); // FIXME
|
||||||
|
|
||||||
/* Disable FLASH write */
|
/* Disable FLASH write */
|
||||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||||
|
@ -465,7 +470,7 @@ static void jlf16_write_flash(struct jtdev *p, address_t start_address,
|
||||||
|
|
||||||
/* Reset FCTL3 */
|
/* Reset FCTL3 */
|
||||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||||
jtag_dr_shift_16(p, 0x012C);
|
jtag_dr_shift_16(p, 0x012C); // FIXME
|
||||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||||
jtag_dr_shift_16(p, 0xA510);
|
jtag_dr_shift_16(p, 0xA510);
|
||||||
jtag_tclk_set(p);
|
jtag_tclk_set(p);
|
||||||
|
@ -479,7 +484,7 @@ static void jlf16_write_flash(struct jtdev *p, address_t start_address,
|
||||||
*/
|
*/
|
||||||
static void jlf16_erase_flash(struct jtdev *p, unsigned int erase_mode,
|
static void jlf16_erase_flash(struct jtdev *p, unsigned int erase_mode,
|
||||||
address_t erase_address)
|
address_t erase_address)
|
||||||
{
|
{ // SLAU320AJ name: EraseFLASH
|
||||||
unsigned int number_of_strobes = 4820; /* default for segment erase */
|
unsigned int number_of_strobes = 4820; /* default for segment erase */
|
||||||
unsigned int loop_counter;
|
unsigned int loop_counter;
|
||||||
unsigned int max_loop_count = 1; /* erase cycle repeating for mass erase */
|
unsigned int max_loop_count = 1; /* erase cycle repeating for mass erase */
|
||||||
|
@ -500,17 +505,17 @@ static void jlf16_erase_flash(struct jtdev *p, unsigned int erase_mode,
|
||||||
|
|
||||||
/* FCTL1 address */
|
/* FCTL1 address */
|
||||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||||
jtag_dr_shift_16(p, 0x0128);
|
jtag_dr_shift_16(p, 0x0128); // FIXME
|
||||||
|
|
||||||
/* Enable erase mode */
|
/* Enable erase mode */
|
||||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||||
jtag_dr_shift_16(p, erase_mode);
|
jtag_dr_shift_16(p, erase_mode); // FIXME?
|
||||||
jtag_tclk_set(p);
|
jtag_tclk_set(p);
|
||||||
jtag_tclk_clr(p);
|
jtag_tclk_clr(p);
|
||||||
|
|
||||||
/* FCTL2 address */
|
/* FCTL2 address */
|
||||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||||
jtag_dr_shift_16(p, 0x012A);
|
jtag_dr_shift_16(p, 0x012A); // FIXME
|
||||||
|
|
||||||
/* MCLK is source, DIV=1 */
|
/* MCLK is source, DIV=1 */
|
||||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||||
|
@ -520,7 +525,7 @@ static void jlf16_erase_flash(struct jtdev *p, unsigned int erase_mode,
|
||||||
|
|
||||||
/* FCTL3 address */
|
/* FCTL3 address */
|
||||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||||
jtag_dr_shift_16(p, 0x012C);
|
jtag_dr_shift_16(p, 0x012C); // FIXME
|
||||||
|
|
||||||
/* Clear FCTL3 */
|
/* Clear FCTL3 */
|
||||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||||
|
@ -551,7 +556,7 @@ static void jlf16_erase_flash(struct jtdev *p, unsigned int erase_mode,
|
||||||
|
|
||||||
/* FCTL1 address */
|
/* FCTL1 address */
|
||||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||||
jtag_dr_shift_16(p, 0x0128);
|
jtag_dr_shift_16(p, 0x0128); // FIXME
|
||||||
|
|
||||||
/* Disable erase */
|
/* Disable erase */
|
||||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||||
|
@ -561,7 +566,7 @@ static void jlf16_erase_flash(struct jtdev *p, unsigned int erase_mode,
|
||||||
|
|
||||||
/* Reset FCTL3 */
|
/* Reset FCTL3 */
|
||||||
jtag_ir_shift(p, IR_ADDR_16BIT);
|
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||||
jtag_dr_shift_16(p, 0x012C);
|
jtag_dr_shift_16(p, 0x012C); // FIXME
|
||||||
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||||
jtag_dr_shift_16(p, 0xA510);
|
jtag_dr_shift_16(p, 0xA510);
|
||||||
jtag_tclk_set(p);
|
jtag_tclk_set(p);
|
||||||
|
@ -572,7 +577,7 @@ static void jlf16_erase_flash(struct jtdev *p, unsigned int erase_mode,
|
||||||
|
|
||||||
/* Reads a register from the target CPU */
|
/* Reads a register from the target CPU */
|
||||||
static address_t jlf16_read_reg(struct jtdev *p, int reg)
|
static address_t jlf16_read_reg(struct jtdev *p, int reg)
|
||||||
{
|
{ // libmsp430 BIOS name: ReadCpuReg
|
||||||
unsigned int value;
|
unsigned int value;
|
||||||
|
|
||||||
/* Set CPU into instruction fetch mode */
|
/* Set CPU into instruction fetch mode */
|
||||||
|
@ -602,7 +607,9 @@ static address_t jlf16_read_reg(struct jtdev *p, int reg)
|
||||||
*/
|
*/
|
||||||
jtag_dr_shift_16(p, 0x4082 | (((unsigned int)reg << 8) & 0x0f00) );
|
jtag_dr_shift_16(p, 0x4082 | (((unsigned int)reg << 8) & 0x0f00) );
|
||||||
jtag_tclk_clr(p);
|
jtag_tclk_clr(p);
|
||||||
|
jtag_ir_shift(p, IR_DATA_CAPTURE); // TODO: ???
|
||||||
jtag_tclk_set(p);
|
jtag_tclk_set(p);
|
||||||
|
jtag_ir_shift(p, IR_DATA_16BIT); // TODO: ???
|
||||||
jtag_dr_shift_16(p, 0x01fe);
|
jtag_dr_shift_16(p, 0x01fe);
|
||||||
jtag_tclk_clr(p);
|
jtag_tclk_clr(p);
|
||||||
jtag_tclk_set(p);
|
jtag_tclk_set(p);
|
||||||
|
@ -633,7 +640,7 @@ static address_t jlf16_read_reg(struct jtdev *p, int reg)
|
||||||
|
|
||||||
/* Writes a value into a register of the target CPU */
|
/* Writes a value into a register of the target CPU */
|
||||||
static void jlf16_write_reg(struct jtdev *p, int reg, address_t value)
|
static void jlf16_write_reg(struct jtdev *p, int reg, address_t value)
|
||||||
{
|
{ // SLAU320AJ name: SetPC
|
||||||
/* Set CPU into instruction fetch mode */
|
/* Set CPU into instruction fetch mode */
|
||||||
jlf16_set_instruction_fetch(p);
|
jlf16_set_instruction_fetch(p);
|
||||||
|
|
||||||
|
@ -664,6 +671,10 @@ static void jlf16_write_reg(struct jtdev *p, int reg, address_t value)
|
||||||
jtag_tclk_clr(p);
|
jtag_tclk_clr(p);
|
||||||
jtag_tclk_set(p);
|
jtag_tclk_set(p);
|
||||||
|
|
||||||
|
// TODO: ???
|
||||||
|
jtag_ir_shift(p, IR_ADDR_CAPTURE);
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
|
||||||
/* JTAG controls RW & BYTE */
|
/* JTAG controls RW & BYTE */
|
||||||
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||||
jtag_dr_shift_16(p, 0x2401);
|
jtag_dr_shift_16(p, 0x2401);
|
||||||
|
@ -671,7 +682,7 @@ static void jlf16_write_reg(struct jtdev *p, int reg, address_t value)
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
static void jlf16_single_step( struct jtdev *p )
|
static void jlf16_single_step( struct jtdev *p )
|
||||||
{
|
{ // libmsp430 BIOS name: SingleStep
|
||||||
unsigned int loop_counter;
|
unsigned int loop_counter;
|
||||||
|
|
||||||
/* CPU controls RW & BYTE */
|
/* CPU controls RW & BYTE */
|
||||||
|
@ -696,7 +707,7 @@ static void jlf16_single_step( struct jtdev *p )
|
||||||
|
|
||||||
if (loop_counter == 0) {
|
if (loop_counter == 0) {
|
||||||
/* timeout reached */
|
/* timeout reached */
|
||||||
printc_err("pif: single step failed\n");
|
printc_err("jtaglib_cpu16: single step failed\n");
|
||||||
p->failed = 1;
|
p->failed = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -715,7 +726,7 @@ static unsigned int jlf16_set_breakpoint( struct jtdev *p,int bp_num, address_t
|
||||||
|
|
||||||
if (bp_num >= 8) {
|
if (bp_num >= 8) {
|
||||||
/* there are no more than 8 breakpoints in EEM */
|
/* there are no more than 8 breakpoints in EEM */
|
||||||
printc_err("jtag_set_breakpoint: failed setting "
|
printc_err("jlf16_set_breakpoint: failed setting "
|
||||||
"breakpoint %d at %04x\n", bp_num, bp_addr);
|
"breakpoint %d at %04x\n", bp_num, bp_addr);
|
||||||
p->failed = 1;
|
p->failed = 1;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -766,7 +777,7 @@ static unsigned int jlf16_set_breakpoint( struct jtdev *p,int bp_num, address_t
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
static unsigned int jlf16_cpu_state( struct jtdev *p )
|
static unsigned int jlf16_cpu_state( struct jtdev *p )
|
||||||
{
|
{ // libmsp430 BIOS name: WaitForEem(?)
|
||||||
jtag_ir_shift(p, IR_EMEX_READ_CONTROL);
|
jtag_ir_shift(p, IR_EMEX_READ_CONTROL);
|
||||||
|
|
||||||
if ((jtag_dr_shift_16(p, 0x0000) & 0x0080) == 0x0080) {
|
if ((jtag_dr_shift_16(p, 0x0000) & 0x0080) == 0x0080) {
|
||||||
|
@ -778,7 +789,7 @@ static unsigned int jlf16_cpu_state( struct jtdev *p )
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
static int jlf16_get_config_fuses( struct jtdev *p )
|
static int jlf16_get_config_fuses( struct jtdev *p )
|
||||||
{
|
{ // always the same?
|
||||||
jtag_ir_shift(p, IR_CONFIG_FUSES);
|
jtag_ir_shift(p, IR_CONFIG_FUSES);
|
||||||
|
|
||||||
return jtag_dr_shift_8(p, 0);
|
return jtag_dr_shift_8(p, 0);
|
||||||
|
|
|
@ -1,7 +1,631 @@
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "jtaglib.h"
|
#include "jtaglib.h"
|
||||||
#include "jtaglib_defs.h"
|
#include "jtaglib_defs.h"
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
|
|
||||||
const struct jtaglib_funcs jlf_cpuxv2;
|
#define SAFE_FRAM_PC 0x0004
|
||||||
|
|
||||||
|
// FIXME:
|
||||||
|
// * read mem (broken)
|
||||||
|
// * read mem quick (consecutive ones break)
|
||||||
|
// * write mem (no effect)
|
||||||
|
// * read reg (nonsense values)
|
||||||
|
// -> also loses FES
|
||||||
|
// * write reg?
|
||||||
|
// * single step: check if it works
|
||||||
|
// * breakpoints are a big TODO
|
||||||
|
|
||||||
|
static int jlfxv2_check_full_emu_state_ex(struct jtdev *p, const char* fnname)
|
||||||
|
{ // see SLAU320AJ ExecutePOR
|
||||||
|
uint16_t dr;
|
||||||
|
uint8_t jtag_id;
|
||||||
|
|
||||||
|
jtag_id = jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||||
|
if (((dr = jtag_dr_shift_16(p, 0)) & 0x0301) == 0x0301) {
|
||||||
|
return 1; // OK
|
||||||
|
}
|
||||||
|
|
||||||
|
printc_err("jlfxv2: %s: not in full emu state, while expected!"
|
||||||
|
" (dr=%04x jid=%02x)\n", fnname, dr, jtag_id);
|
||||||
|
p->failed = 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#define jlfxv2_check_full_emu_state(p) jlfxv2_check_full_emu_state_ex((p), __func__)
|
||||||
|
|
||||||
|
|
||||||
|
static void jlfxv2_set_pc(struct jtdev *p, address_t addr)
|
||||||
|
{
|
||||||
|
printc_dbg("set pc %06x\n", addr);
|
||||||
|
|
||||||
|
jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||||
|
jtag_dr_shift_16(p, 0);
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
|
||||||
|
jtag_ir_shift(p, IR_DATA_16BIT);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
jtag_dr_shift_16(p, 0x0080 | ((addr >> 8) & 0x0f00));
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
|
||||||
|
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||||
|
jtag_dr_shift_16(p, 0x1400);
|
||||||
|
|
||||||
|
jtag_ir_shift(p, IR_DATA_16BIT);
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
jtag_dr_shift_16(p, addr & 0xffff);
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
|
||||||
|
jtag_dr_shift_16(p, 0x4303);
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_ir_shift(p, IR_ADDR_CAPTURE);
|
||||||
|
jtag_dr_shift_20(p, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compares the computed PSA (Pseudo Signature Analysis) value to the PSA
|
||||||
|
* value shifted out from the target device. It is used for very fast data
|
||||||
|
* block write or erasure verification.
|
||||||
|
* start_address: start of data
|
||||||
|
* length : number of data
|
||||||
|
* data : pointer to data, 0 for erase check
|
||||||
|
* RETURN : 1 - comparison was successful
|
||||||
|
* 0 - otherwise
|
||||||
|
*/
|
||||||
|
static int jlfxv2_verify_mem(struct jtdev *p,
|
||||||
|
unsigned int start_address,
|
||||||
|
unsigned int length,
|
||||||
|
const uint16_t *data)
|
||||||
|
{ // SLAU320AJ name: VerifyMem/VerifyPSA
|
||||||
|
uint16_t crc, psaval;
|
||||||
|
|
||||||
|
jtag_execute_puc(p);
|
||||||
|
|
||||||
|
crc = start_address - 2;
|
||||||
|
jlfxv2_set_pc(p, start_address);
|
||||||
|
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||||
|
jtag_dr_shift_16(p, 0x0501);
|
||||||
|
jtag_ir_shift(p, IR_DATA_16BIT);
|
||||||
|
jtag_dr_shift_16(p, start_address - 2);
|
||||||
|
jtag_ir_shift(p, IR_DATA_PSA);
|
||||||
|
|
||||||
|
for (unsigned int addr = 0; addr < length; ++addr) {
|
||||||
|
if (crc & 0x8000) {
|
||||||
|
crc ^= 0x0805;
|
||||||
|
crc <<= 1;
|
||||||
|
crc |= 1;
|
||||||
|
} else {
|
||||||
|
crc <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data) crc ^= data[addr];
|
||||||
|
else crc ^= 0xffff;
|
||||||
|
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
/* Go through DR path without shifting data in/out */
|
||||||
|
jtag_tms_sequence(p, 6, 0x19); /* TMS=1 0 0 1 1 0 ; 6 clocks */
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
jtag_ir_shift(p, IR_SHIFT_OUT_PSA);
|
||||||
|
psaval = jtag_dr_shift_16(p, 0);
|
||||||
|
|
||||||
|
jtag_execute_puc(p);
|
||||||
|
|
||||||
|
return (psaval == crc) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static int jlfxv2_erase_check(struct jtdev *p, unsigned int start_address,
|
||||||
|
unsigned int length)
|
||||||
|
{
|
||||||
|
return jlfxv2_verify_mem(p, start_address, length, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int jlfxv2_get_device(struct jtdev *p)
|
||||||
|
{ // SLAU320AJ name: GetDevice (and SyncJtag_AssertPor)
|
||||||
|
unsigned int jtag_id = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||||
|
jtag_dr_shift_16(p, 0x1501);
|
||||||
|
|
||||||
|
jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||||
|
for (i = 0; i < 50; ++i) {
|
||||||
|
if ((jtag_dr_shift_16(p, 0) & (1<<9)) == (1<<9))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 50) {
|
||||||
|
printc_err("jlfxv2_get_device: failed\n");
|
||||||
|
p->failed = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
jtag_id = jtag_execute_puc(p);
|
||||||
|
return jtag_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reads one byte/word from a given address
|
||||||
|
* format : 8-byte, 16-word
|
||||||
|
* address: address of memory
|
||||||
|
* return : content of memory
|
||||||
|
*/
|
||||||
|
static void jlfxv2_read_mem_quick(struct jtdev *p, address_t address,
|
||||||
|
unsigned int length, uint16_t *data);
|
||||||
|
static uint16_t jlfxv2_read_mem(struct jtdev *p, unsigned int format, address_t address)
|
||||||
|
{ // SLAU320AJ name: ReadMem
|
||||||
|
uint16_t r=0;
|
||||||
|
printc_dbg("read mem %d %06x\n", format, address);
|
||||||
|
jlfxv2_read_mem_quick(p, address ^ (address & 1), 1, &r);
|
||||||
|
if (format == 8) {
|
||||||
|
if (address & 1) return r >> 8;
|
||||||
|
else return r & 0xff;
|
||||||
|
} else return r;
|
||||||
|
|
||||||
|
if (!jlfxv2_check_full_emu_state(p))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||||
|
jtag_dr_shift_16(p, (format == 16) ? 0x0501 : 0x0511);
|
||||||
|
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||||
|
jtag_dr_shift_20(p, address);
|
||||||
|
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
|
||||||
|
r = jtag_dr_shift_16(p, 0);
|
||||||
|
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reads an array of words from target memory
|
||||||
|
* address: address to read from
|
||||||
|
* length : number of word to read
|
||||||
|
* data : memory to write to
|
||||||
|
*/
|
||||||
|
static void jlfxv2_read_mem_quick(struct jtdev *p, address_t address,
|
||||||
|
unsigned int length, uint16_t *data)
|
||||||
|
{ // SLAU320AJ name: ReadMemQuick
|
||||||
|
if (!jlfxv2_check_full_emu_state(p))
|
||||||
|
return;
|
||||||
|
|
||||||
|
jlfxv2_set_pc(p, address);
|
||||||
|
|
||||||
|
//jtag_tclk_set(p);
|
||||||
|
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||||
|
jtag_dr_shift_16(p, 0x0501);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
jtag_ir_shift(p, IR_ADDR_CAPTURE);
|
||||||
|
jtag_ir_shift(p, IR_DATA_QUICK);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < length; ++i) {
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
data[i] = jtag_dr_shift_16(p, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||||
|
jtag_dr_shift_16(p, 0);
|
||||||
|
|
||||||
|
if (p->jtag_id == 0x99) {
|
||||||
|
jlfxv2_set_pc(p, SAFE_FRAM_PC);
|
||||||
|
}
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Writes one byte/word at a given address
|
||||||
|
* format : 8-byte, 16-word
|
||||||
|
* address: address to be written
|
||||||
|
* data : data to write
|
||||||
|
*/
|
||||||
|
static void jlfxv2_write_mem(struct jtdev *p, unsigned int format,
|
||||||
|
address_t address, uint16_t data)
|
||||||
|
{ // SLAU320AJ name: WriteMem
|
||||||
|
if (!jlfxv2_check_full_emu_state(p))
|
||||||
|
return;
|
||||||
|
|
||||||
|
printc_dbg("write mem %d: %06x<-%04x\n", format, address, data);
|
||||||
|
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||||
|
jtag_dr_shift_16(p, (format == 16) ? 0x0500 : 0x0510);
|
||||||
|
jtag_ir_shift(p, IR_ADDR_16BIT);
|
||||||
|
jtag_dr_shift_20(p, address);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
jtag_ir_shift(p, IR_DATA_TO_ADDR);
|
||||||
|
jtag_dr_shift_16(p, data);
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||||
|
jtag_dr_shift_16(p, 0x0501);
|
||||||
|
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Writes an array of words into target memory
|
||||||
|
* address: address to write to
|
||||||
|
* length : number of word to write
|
||||||
|
* data : data to write
|
||||||
|
*/
|
||||||
|
static void jlfxv2_write_mem_quick(struct jtdev *p, address_t address,
|
||||||
|
unsigned int length, const uint16_t *data)
|
||||||
|
{ // SLAU320AJ name: WriteMemQuick
|
||||||
|
for (unsigned int i = 0; i < length; ++i) {
|
||||||
|
jlfxv2_write_mem(p, 16, address + i*2, data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Execute a Power-Up Clear (PUC) using JTAG CNTRL SIG register
|
||||||
|
* return: JTAG ID
|
||||||
|
*/
|
||||||
|
static unsigned int jlfxv2_execute_puc(struct jtdev *p)
|
||||||
|
{ // SLAU320AJ name: ExecutePOR
|
||||||
|
unsigned int jtag_id;
|
||||||
|
|
||||||
|
jtag_id = jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||||
|
|
||||||
|
// empty CPU pipeline
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
|
||||||
|
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||||
|
|
||||||
|
/* Apply and remove reset */
|
||||||
|
jtag_dr_shift_16(p, 0x0C01);
|
||||||
|
jtag_dr_shift_16(p, 0x0401);
|
||||||
|
|
||||||
|
if (jtag_id == 0x91) { // TODO: is this correct?
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
jtag_tclk_clr(p); // two more cycles to release CPU internal POR delay signals
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
} else { // FRAM
|
||||||
|
jtag_ir_shift(p, IR_DATA_16BIT);
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
jtag_dr_shift_16(p, SAFE_FRAM_PC);
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
|
||||||
|
jtag_ir_shift(p, IR_DATA_CAPTURE);
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||||
|
jtag_dr_shift_16(p, 0x0501);
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
|
||||||
|
jtag_write_mem(p, 16, 0x015c, 0x5a80); // disable WDT
|
||||||
|
// TODO: disable WDT
|
||||||
|
// Disable Watchdog Timer on target device now by setting the HOLD signal
|
||||||
|
// in the WDT_CNTRL register (i.e. by using WriteMem_430Xv2 – note
|
||||||
|
// different WDT addresses for individual FRAM device groups)
|
||||||
|
//
|
||||||
|
// Initialize Test Memory with default values to ensure consistency between
|
||||||
|
// PC value and MAB (MAB is +2 after sync) – Use WriteMem_430Xv2 to write
|
||||||
|
// 0x3FFF to addresses 0x06 and 0x08 (this is only applicable for devices
|
||||||
|
// with JTAG ID 0x91 or 0x99)
|
||||||
|
|
||||||
|
return jtag_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release the target device from JTAG control
|
||||||
|
* address: 0xFFFE - perform Reset,
|
||||||
|
* load Reset Vector into PC
|
||||||
|
* 0xFFFF - start execution at current
|
||||||
|
* PC position
|
||||||
|
* other - load Address into PC
|
||||||
|
*/
|
||||||
|
static void jlfxv2_release_device(struct jtdev *p, address_t address)
|
||||||
|
{ // SLAU320AJ name: ReleaseDevice. from Replicator430 code, not in the PDF
|
||||||
|
switch (address) {
|
||||||
|
case 0xffff: // BOR
|
||||||
|
jtag_ir_shift(p, IR_TEST_REG);
|
||||||
|
jtag_dr_shift_16(p, 0x0200);
|
||||||
|
delay_ms(5);
|
||||||
|
break;
|
||||||
|
case 0xfffe: // reset
|
||||||
|
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||||
|
jtag_dr_shift_16(p, 0x0C01);
|
||||||
|
jtag_dr_shift_16(p, 0x0401);
|
||||||
|
jtag_ir_shift(p, IR_CNTRL_SIG_RELEASE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
jlfxv2_set_pc(p, address);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||||
|
jtag_dr_shift_16(p, 0x0401);
|
||||||
|
jtag_ir_shift(p, IR_ADDR_CAPTURE);
|
||||||
|
jtag_ir_shift(p, IR_CNTRL_SIG_RELEASE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Programs/verifies an array of words into a FLASH by using the
|
||||||
|
* FLASH controller. The JTAG FLASH register isn't needed.
|
||||||
|
* start_address: start in FLASH
|
||||||
|
* length : number of words
|
||||||
|
* data : pointer to data
|
||||||
|
*/
|
||||||
|
static void jlfxv2_write_flash(struct jtdev *p, address_t start_address,
|
||||||
|
unsigned int length, const uint16_t *data)
|
||||||
|
{ // SLAU320AJ name: WriteFLASH
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Performs a mass erase (with and w/o info memory) or a segment erase of a
|
||||||
|
* FLASH module specified by the given mode and address. Large memory devices
|
||||||
|
* get additional mass erase operations to meet the spec.
|
||||||
|
* erase_mode : ERASE_MASS, ERASE_MAIN, ERASE_SGMT
|
||||||
|
* erase_address: address within the selected segment
|
||||||
|
*/
|
||||||
|
static void jlfxv2_erase_flash(struct jtdev *p, unsigned int erase_mode,
|
||||||
|
address_t erase_address)
|
||||||
|
{ // SLAU320AJ name: EraseFLASH
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reads a register from the target CPU */
|
||||||
|
static address_t jlfxv2_read_reg(struct jtdev *p, int reg)
|
||||||
|
{ // libmsp430 BIOS name: ReadCpuReg
|
||||||
|
uint16_t reglo, reghi;
|
||||||
|
uint16_t jtag_id, jmb_addr;
|
||||||
|
|
||||||
|
if (reg == 3) return 0; // CG
|
||||||
|
|
||||||
|
printc_dbg("read reg %d\n", reg);
|
||||||
|
if (!jlfxv2_check_full_emu_state(p))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_id = jtag_ir_shift(p, IR_DATA_16BIT);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
jtag_dr_shift_16(p, reg);
|
||||||
|
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||||
|
jtag_dr_shift_16(p, 0x1401);
|
||||||
|
jtag_ir_shift(p, IR_DATA_16BIT);
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
|
||||||
|
jmb_addr = (jtag_id == 0x98) ? 0x14c : 0x18c;
|
||||||
|
|
||||||
|
jtag_dr_shift_16(p, jmb_addr);
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
jtag_dr_shift_16(p, 0x3ffd);
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
|
||||||
|
jtag_ir_shift(p, IR_DATA_CAPTURE);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
reglo = jtag_dr_shift_16(p, 0);
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
reghi = jtag_dr_shift_16(p, 0);
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
|
||||||
|
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||||
|
jtag_dr_shift_16(p, 0x0501);
|
||||||
|
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_ir_shift(p, IR_DATA_CAPTURE);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
|
||||||
|
|
||||||
|
printc_dbg("read reg %d: lo=%04x hi=%04x\n", reg, reglo, reghi);
|
||||||
|
return reglo | ((address_t)reghi << 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Writes a value into a register of the target CPU */
|
||||||
|
static void jlfxv2_write_reg(struct jtdev *p, int reg, address_t value)
|
||||||
|
{ // SLAU320AJ name: SetPC
|
||||||
|
jlfxv2_check_full_emu_state(p);
|
||||||
|
printc_dbg("write reg %d %06x\n", reg, value);
|
||||||
|
|
||||||
|
jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||||
|
jtag_dr_shift_16(p, 0);
|
||||||
|
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_ir_shift(p, IR_DATA_16BIT);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
jtag_dr_shift_16(p, 0x0080 | ((value >> 8) & 0x0f00));
|
||||||
|
|
||||||
|
//jtag_tclk_clr(p);
|
||||||
|
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||||
|
jtag_dr_shift_16(p, 0x1401/*1400*/);
|
||||||
|
jtag_ir_shift(p, IR_DATA_16BIT);
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
jtag_dr_shift_16(p, value & 0xffff);
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
|
||||||
|
jtag_dr_shift_16(p, 0x3ffd); // rewind PC
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
|
||||||
|
jtag_ir_shift(p, IR_ADDR_CAPTURE);
|
||||||
|
jtag_dr_shift_20(p, 0);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
|
||||||
|
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||||
|
jtag_dr_shift_16(p, /*0x4303*/0x0501); // insert NOP to be prefetched by the CPU
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
|
||||||
|
jtag_ir_shift(p, IR_DATA_CAPTURE);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
//jtag_dr_shift_20(p, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
static void jlfxv2_single_step( struct jtdev *p )
|
||||||
|
{ // libmsp430 BIOS name: SingleStep
|
||||||
|
|
||||||
|
int i, timeout;
|
||||||
|
uint16_t tmp;
|
||||||
|
printc_dbg("jlfxv2: single step\n");
|
||||||
|
|
||||||
|
/*jtag_ir_shift(p, IR_EMEX_READ_CONTROL);
|
||||||
|
timeout = 3000;
|
||||||
|
for (i = 0; i < timeout; ++i)
|
||||||
|
if (jtag_dr_shift_16(p, 0) & EEM_STOPPED)
|
||||||
|
break;
|
||||||
|
if (i == timeout) {
|
||||||
|
printc_err("jlfxv2_single_step: EEM timeout\n");
|
||||||
|
goto err;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
jtag_ir_shift(p, IR_EMEX_WRITE_CONTROL);
|
||||||
|
jtag_dr_shift_16(p, EMU_CLK_EN | EEM_EN);
|
||||||
|
|
||||||
|
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||||
|
jtag_dr_shift_16(p, 0x1501);
|
||||||
|
jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||||
|
timeout = 50;
|
||||||
|
for (i = 0; i < timeout; ++i) {
|
||||||
|
tmp = jtag_dr_shift_16(p, 0);
|
||||||
|
if (tmp != 0xffff && (tmp & 0x200) == 0x0200)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == timeout) {
|
||||||
|
printc_err("jlfxv2_single_step: JTAG sync timeout\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
jtag_ir_shift(p, IR_EMEX_WRITE_CONTROL);
|
||||||
|
jtag_dr_shift_16(p, EMU_CLK_EN | CLEAR_STOP);
|
||||||
|
jtag_dr_shift_16(p, EMU_CLK_EN | CLEAR_STOP | EEM_EN);
|
||||||
|
|
||||||
|
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||||
|
jtag_dr_shift_16(p, 0x1501);
|
||||||
|
|
||||||
|
jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||||
|
timeout = 30000;
|
||||||
|
for (i = 0; i < timeout; ++i) {
|
||||||
|
if ((jtag_dr_shift_16(p, 0) & 8) == 0) break;
|
||||||
|
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
|
||||||
|
jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||||
|
}
|
||||||
|
if (i == timeout) {
|
||||||
|
printc_err("jlfxv2_single_step: single-step timeout\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
|
||||||
|
timeout = 10000;
|
||||||
|
for (i = 0; i < timeout; ++i) {
|
||||||
|
jtag_tclk_clr(p);
|
||||||
|
tmp = jtag_dr_shift_16(p, 0);
|
||||||
|
jtag_tclk_set(p);
|
||||||
|
|
||||||
|
if ((tmp & CNTRL_SIG_CPUSUSP) == CNTRL_SIG_CPUSUSP) break;
|
||||||
|
}
|
||||||
|
if (i == timeout) {
|
||||||
|
printc_err("jlfxv2_single_step: pipeline empty timeout\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
|
||||||
|
jtag_dr_shift_16(p, 0x0501);
|
||||||
|
|
||||||
|
return;
|
||||||
|
err:
|
||||||
|
p->failed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
static unsigned int jlfxv2_set_breakpoint( struct jtdev *p,int bp_num, address_t bp_addr )
|
||||||
|
{
|
||||||
|
/* The breakpoint logic is explained in 'SLAU414c EEM.pdf' */
|
||||||
|
/* A good overview is given with Figure 1-1 */
|
||||||
|
/* MBx is TBx in EEM_defs.h */
|
||||||
|
/* CPU Stop is BREAKREACT in EEM_defs.h */
|
||||||
|
/* State Storage is STOR_REACT in EEM_defs.h */
|
||||||
|
/* Cycle Counter is EVENT_REACT in EEM_defs.h */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
static unsigned int jlfxv2_cpu_state( struct jtdev *p )
|
||||||
|
{ // libmsp430 BIOS name: WaitForEem(?)
|
||||||
|
// TODO: does this need an update?
|
||||||
|
jtag_ir_shift(p, IR_EMEX_READ_CONTROL);
|
||||||
|
|
||||||
|
if ((jtag_dr_shift_16(p, 0x0000) & EEM_STOPPED) == EEM_STOPPED) {
|
||||||
|
printc_dbg("jlfxv2_cpu_state: halted\n");
|
||||||
|
return 1; /* halted */
|
||||||
|
} else {
|
||||||
|
printc_dbg("jlfxv2_cpu_state: running\n");
|
||||||
|
return 0; /* running */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
static int jlfxv2_get_config_fuses( struct jtdev *p )
|
||||||
|
{ // always the same?
|
||||||
|
// TODO: does this need an update?
|
||||||
|
jtag_ir_shift(p, IR_CONFIG_FUSES);
|
||||||
|
|
||||||
|
return jtag_dr_shift_8(p, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
const struct jtaglib_funcs jlf_cpuxv2 = {
|
||||||
|
.jlf_get_device = jlfxv2_get_device,
|
||||||
|
|
||||||
|
.jlf_read_mem = jlfxv2_read_mem,
|
||||||
|
.jlf_read_mem_quick = jlfxv2_read_mem_quick,
|
||||||
|
.jlf_write_mem = jlfxv2_write_mem,
|
||||||
|
.jlf_write_mem_quick = jlfxv2_write_mem_quick,
|
||||||
|
|
||||||
|
.jlf_execute_puc = jlfxv2_execute_puc,
|
||||||
|
.jlf_release_device = jlfxv2_release_device,
|
||||||
|
|
||||||
|
.jlf_verify_mem = jlfxv2_verify_mem,
|
||||||
|
.jlf_erase_check = jlfxv2_erase_check,
|
||||||
|
|
||||||
|
.jlf_write_flash = jlfxv2_write_flash,
|
||||||
|
.jlf_erase_flash = jlfxv2_erase_flash,
|
||||||
|
|
||||||
|
.jlf_read_reg = jlfxv2_read_reg,
|
||||||
|
.jlf_write_reg = jlfxv2_write_reg,
|
||||||
|
.jlf_single_step = jlfxv2_single_step,
|
||||||
|
.jlf_set_breakpoint = jlfxv2_set_breakpoint,
|
||||||
|
.jlf_cpu_state = jlfxv2_cpu_state,
|
||||||
|
.jlf_get_config_fuses = jlfxv2_get_config_fuses,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
/* Instructions for the JTAG Fuse */
|
/* Instructions for the JTAG Fuse */
|
||||||
#define IR_PREPARE_BLOW 0x44 /* 0x22 */
|
#define IR_PREPARE_BLOW 0x44 /* 0x22 */
|
||||||
#define IR_EX_BLOW 0x24 /* 0x24 */
|
#define IR_EX_BLOW 0x24 /* 0x24 */
|
||||||
|
/* Instructions for the JTAG mailbox */
|
||||||
|
#define IR_TEST_REG 0x54 /* 0x2A */
|
||||||
/* Instructions for the Configuration Fuse */
|
/* Instructions for the Configuration Fuse */
|
||||||
#define IR_CONFIG_FUSES 0x94
|
#define IR_CONFIG_FUSES 0x94
|
||||||
/* Bypass instruction */
|
/* Bypass instruction */
|
||||||
|
@ -39,6 +41,14 @@
|
||||||
#define IR_EMEX_WRITE_CONTROL 0x30 /* 0x0C */
|
#define IR_EMEX_WRITE_CONTROL 0x30 /* 0x0C */
|
||||||
#define IR_EMEX_READ_CONTROL 0xD0 /* 0x0B */
|
#define IR_EMEX_READ_CONTROL 0xD0 /* 0x0B */
|
||||||
|
|
||||||
|
/* EEM stuff */
|
||||||
|
#define EEM_STOPPED 0x0080
|
||||||
|
#define EEM_EN 0x0001
|
||||||
|
#define CLEAR_STOP 0x0002
|
||||||
|
#define EMU_CLK_EN 0x0004
|
||||||
|
|
||||||
|
#define CNTRL_SIG_CPUSUSP (1<<8)
|
||||||
|
|
||||||
#define jtag_tms_set(p) p->f->jtdev_tms(p, 1)
|
#define jtag_tms_set(p) p->f->jtdev_tms(p, 1)
|
||||||
#define jtag_tms_clr(p) p->f->jtdev_tms(p, 0)
|
#define jtag_tms_clr(p) p->f->jtdev_tms(p, 0)
|
||||||
#define jtag_tck_set(p) p->f->jtdev_tck(p, 1)
|
#define jtag_tck_set(p) p->f->jtdev_tck(p, 1)
|
||||||
|
|
Loading…
Reference in New Issue