jtaglib xv2: memory accesses start to work now

This commit is contained in:
Triss 2022-07-25 01:20:26 +02:00
parent 98c434555f
commit 649d82b695
2 changed files with 135 additions and 40 deletions

View File

@ -331,15 +331,6 @@ unsigned int jtag_get_device(struct jtdev *p)
return r; return r;
} }
/* Reads one byte/word from a given address */
uint16_t jtag_read_mem(struct jtdev *p, unsigned int format, address_t address)
{
// 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_read_mem(p, format, address);
}
/* Execute a Power-Up Clear (PUC) using JTAG CNTRL SIG register */ /* Execute a Power-Up Clear (PUC) using JTAG CNTRL SIG register */
unsigned int jtag_execute_puc(struct jtdev *p) unsigned int jtag_execute_puc(struct jtdev *p)
{ {
@ -349,10 +340,19 @@ unsigned int jtag_execute_puc(struct jtdev *p)
return get_jlf(p)->jlf_execute_puc(p); return get_jlf(p)->jlf_execute_puc(p);
} }
/* Reads one byte/word from a given address */
uint16_t jtag_read_mem(struct jtdev *p, unsigned int format, address_t address)
{
return get_jlf(p)->jlf_read_mem(p, format, address);
}
/* Reads an array of words from target memory */ /* Reads an array of words from target memory */
void jtag_read_mem_quick(struct jtdev *p, address_t start_address, void jtag_read_mem_quick(struct jtdev *p, address_t start_address,
unsigned int word_count, uint16_t *data) unsigned int word_count, uint16_t *data)
{ {
// NOTE: this is one of the special functions that have to be called early
// on before chip ID stuff is done
get_jlf(p)->jlf_read_mem_quick(p, start_address, word_count, data); get_jlf(p)->jlf_read_mem_quick(p, start_address, word_count, data);
} }
@ -589,7 +589,7 @@ static int read_words(device_t dev_base, const struct chipinfo_memory *m,
if (len > 2 && !(len & 1)) { if (len > 2 && !(len & 1)) {
uint16_t* word = malloc((len>>1) * sizeof(*word)); uint16_t* word = malloc((len>>1) * sizeof(*word));
if (!word) { if (!word) {
pr_error("jtaglib: failed to allocate memory"); pr_error("jtaglib: read_words: failed to allocate memory");
return -1; return -1;
} }
@ -619,8 +619,32 @@ static int write_words(device_t dev_base, const struct chipinfo_memory *m,
if (m->type != CHIPINFO_MEMTYPE_FLASH) { if (m->type != CHIPINFO_MEMTYPE_FLASH) {
printc_dbg("jtaglib: write_words: ram: len=%d addr=%06x\n", len, addr); printc_dbg("jtaglib: write_words: ram: len=%d addr=%06x\n", len, addr);
uint16_t value = data[0] | ((uint16_t)data[1] << 8); if ((len > 2) && !(len & 1)) {
uint16_t* word = malloc((len>>1) * sizeof(*word));
if (!word) {
pr_error("jtaglib: write_words: failed to allocate memory");
return -1;
}
for (unsigned int i = 0; i < len/2; i++) {
word[i] = data[2*i] | ((uint16_t)data[2*i+1] << 8);
}
jtag_write_mem_quick(p, addr, (len >> 1), word);
free(word);
} else {
for (address_t i = 0; i < len; i += 2) {
uint16_t value;
if ((len & 1) && i == len - 1) {
value = data[i];
jtag_write_mem(p, 8, addr, value);
} else {
value = data[i] | ((uint16_t)data[i+1] << 8);
jtag_write_mem(p, 16, addr, value); jtag_write_mem(p, 16, addr, value);
}
if (p->failed) break;
}
}
r = p->failed ? -1 : 0; r = p->failed ? -1 : 0;
} else { } else {
r = write_flash_block(p, addr, len, data); r = write_flash_block(p, addr, len, data);

View File

@ -8,12 +8,10 @@
#define SAFE_FRAM_PC 0x0004 #define SAFE_FRAM_PC 0x0004
// FIXME: // FIXME:
// * read mem (broken)
// * read mem quick (consecutive ones break)
// * write mem (no effect)
// * read reg (nonsense values) // * read reg (nonsense values)
// -> also loses FES
// * write reg? // * write reg?
// * implement flash write, erase, verify stuff
// * other stuff?
// * single step: check if it works // * single step: check if it works
// * breakpoints are a big TODO // * breakpoints are a big TODO
@ -151,26 +149,32 @@ static unsigned int jlfxv2_get_device(struct jtdev *p)
return jtag_id; return jtag_id;
} }
static void jlfxv2_read_mem_quick(struct jtdev *p, address_t address,
unsigned int length, uint16_t *data);
/* Reads one byte/word from a given address /* Reads one byte/word from a given address
* format : 8-byte, 16-word * format : 8-byte, 16-word
* address: address of memory * address: address of memory
* return : content 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) static uint16_t jlfxv2_read_mem(struct jtdev *p, unsigned int format, address_t address)
{ // SLAU320AJ name: ReadMem { // SLAU320AJ name: ReadMem
uint16_t r=0; 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)) if (!jlfxv2_check_full_emu_state(p))
return 0; return 0;
// the code below (an attempt at implementing the real read_mem) doesn't
// work, so let's use read_mem_quick as a backup
jlfxv2_read_mem_quick(p, address ^ (address & 1), 1, &r);
if (format == 8) {
if (address & 1) return (r >> 8) & 0xff;
else return r & 0xff;
} else return r;
/*//jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
//uint16_t dr = jtag_dr_shift_16(p, 0);
jtag_tclk_clr(p); jtag_tclk_clr(p);
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT); jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
jtag_dr_shift_16(p, (format == 16) ? 0x0501 : 0x0511); jtag_dr_shift_16(p, (format == 16) ? 0x0501 : 0x0511);
@ -179,6 +183,7 @@ static uint16_t jlfxv2_read_mem(struct jtdev *p, unsigned int format, address_t
jtag_ir_shift(p, IR_DATA_TO_ADDR); jtag_ir_shift(p, IR_DATA_TO_ADDR);
jtag_tclk_set(p); jtag_tclk_set(p);
jtag_tclk_clr(p); jtag_tclk_clr(p);
jtag_ir_shift(p, IR_DATA_CAPTURE);
r = jtag_dr_shift_16(p, 0); r = jtag_dr_shift_16(p, 0);
@ -186,7 +191,7 @@ static uint16_t jlfxv2_read_mem(struct jtdev *p, unsigned int format, address_t
jtag_tclk_clr(p); jtag_tclk_clr(p);
jtag_tclk_set(p); jtag_tclk_set(p);
return r; return r;*/
} }
/* Reads an array of words from target memory /* Reads an array of words from target memory
@ -197,9 +202,12 @@ static uint16_t jlfxv2_read_mem(struct jtdev *p, unsigned int format, address_t
static void jlfxv2_read_mem_quick(struct jtdev *p, address_t address, static void jlfxv2_read_mem_quick(struct jtdev *p, address_t address,
unsigned int length, uint16_t *data) unsigned int length, uint16_t *data)
{ // SLAU320AJ name: ReadMemQuick { // SLAU320AJ name: ReadMemQuick
address_t pc_bak;
if (!jlfxv2_check_full_emu_state(p)) if (!jlfxv2_check_full_emu_state(p))
return; return;
//pc_bak = jlfxv2_read_reg(p, 0); // FIXME
jlfxv2_set_pc(p, address); jlfxv2_set_pc(p, address);
//jtag_tclk_set(p); //jtag_tclk_set(p);
@ -218,12 +226,18 @@ static void jlfxv2_read_mem_quick(struct jtdev *p, address_t address,
jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE); jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
jtag_dr_shift_16(p, 0); jtag_dr_shift_16(p, 0);
if (p->jtag_id == 0x99) {
jlfxv2_set_pc(p, SAFE_FRAM_PC); jlfxv2_set_pc(p, SAFE_FRAM_PC);
} jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
jtag_dr_shift_16(p, 0x0501);
jtag_tclk_set(p); jtag_tclk_set(p);
jtag_ir_shift(p, IR_ADDR_CAPTURE);
//jlfxv2_write_reg(p, 0, pc_bak); // FIXME
} }
static void jlfxv2_write_mem_quick(struct jtdev *p, address_t address,
unsigned int length, const uint16_t *data);
/* Writes one byte/word at a given address /* Writes one byte/word at a given address
* format : 8-byte, 16-word * format : 8-byte, 16-word
* address: address to be written * address: address to be written
@ -232,10 +246,24 @@ static void jlfxv2_read_mem_quick(struct jtdev *p, address_t address,
static void jlfxv2_write_mem(struct jtdev *p, unsigned int format, static void jlfxv2_write_mem(struct jtdev *p, unsigned int format,
address_t address, uint16_t data) address_t address, uint16_t data)
{ // SLAU320AJ name: WriteMem { // SLAU320AJ name: WriteMem
if (!jlfxv2_check_full_emu_state(p)) printc_dbg("jlfxv2 write mem: %d %06x <- %04x\n", format, address, data);
if (format == 8) {
p->failed = 1;
printc_err("jlfxv2 write mem: byte access not yet implemented!\n");
return;
}
// same story as with read_mem
jlfxv2_write_mem_quick(p, address, 1, &data);
/*if (!jlfxv2_check_full_emu_state(p))
return; return;
printc_dbg("write mem %d: %06x<-%04x\n", format, address, data); jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
uint16_t dr = jtag_dr_shift_16(p, 0);
printc_dbg("write mem %d: %06x<-%04x: dr=%04x\n", format, address, data, dr);
jtag_tclk_clr(p); jtag_tclk_clr(p);
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT); jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
@ -251,7 +279,7 @@ static void jlfxv2_write_mem(struct jtdev *p, unsigned int format,
jtag_tclk_set(p); jtag_tclk_set(p);
jtag_tclk_clr(p); jtag_tclk_clr(p);
jtag_tclk_set(p); jtag_tclk_set(p);*/
} }
/* Writes an array of words into target memory /* Writes an array of words into target memory
@ -262,9 +290,41 @@ static void jlfxv2_write_mem(struct jtdev *p, unsigned int format,
static void jlfxv2_write_mem_quick(struct jtdev *p, address_t address, static void jlfxv2_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 { // SLAU320AJ name: WriteMemQuick
for (unsigned int i = 0; i < length; ++i) { uint16_t pc_bak;
/*for (unsigned int i = 0; i < length; ++i) {
jlfxv2_write_mem(p, 16, address + i*2, data[i]); jlfxv2_write_mem(p, 16, address + i*2, data[i]);
}*/
if (!jlfxv2_check_full_emu_state(p))
return;
//pc_bak = jlfxv2_read_reg(p, 0); // FIXME
jlfxv2_set_pc(p, address);
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
jtag_dr_shift_16(p, 0x0500);
jtag_tclk_set(p);
jtag_ir_shift(p, IR_DATA_QUICK);
for (unsigned int i = 0; i < length; ++i) {
jtag_tclk_set(p);
jtag_dr_shift_16(p, data[i]);
jtag_tclk_clr(p);
} }
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
jtag_dr_shift_16(p, 0x0501);
jtag_tclk_set(p);
jlfxv2_set_pc(p, SAFE_FRAM_PC);
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);
//jlfxv2_write_reg(p, 0, pc_bak);
} }
/* Execute a Power-Up Clear (PUC) using JTAG CNTRL SIG register /* Execute a Power-Up Clear (PUC) using JTAG CNTRL SIG register
@ -392,6 +452,7 @@ static address_t jlfxv2_read_reg(struct jtdev *p, int reg)
{ // libmsp430 BIOS name: ReadCpuReg { // libmsp430 BIOS name: ReadCpuReg
uint16_t reglo, reghi; uint16_t reglo, reghi;
uint16_t jtag_id, jmb_addr; uint16_t jtag_id, jmb_addr;
const bool alt_addr = true;
if (reg == 3) return 0; // CG if (reg == 3) return 0; // CG
@ -399,8 +460,9 @@ static address_t jlfxv2_read_reg(struct jtdev *p, int reg)
if (!jlfxv2_check_full_emu_state(p)) if (!jlfxv2_check_full_emu_state(p))
return 0; return 0;
jtag_id = jtag_ir_shift(p, IR_CNTRL_SIG_CAPTURE);
jtag_tclk_clr(p); jtag_tclk_clr(p);
jtag_id = jtag_ir_shift(p, IR_DATA_16BIT); jtag_ir_shift(p, IR_DATA_16BIT);
jtag_tclk_set(p); jtag_tclk_set(p);
jtag_dr_shift_16(p, reg); jtag_dr_shift_16(p, reg);
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT); jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
@ -409,14 +471,22 @@ static address_t jlfxv2_read_reg(struct jtdev *p, int reg)
jtag_tclk_clr(p); jtag_tclk_clr(p);
jtag_tclk_set(p); jtag_tclk_set(p);
if (alt_addr) {
jtag_dr_shift_16(p, 0x0ff6);
} else {
jmb_addr = (jtag_id == 0x98) ? 0x14c : 0x18c; jmb_addr = (jtag_id == 0x98) ? 0x14c : 0x18c;
jtag_dr_shift_16(p, jmb_addr); jtag_dr_shift_16(p, jmb_addr);
}
jtag_tclk_clr(p); jtag_tclk_clr(p);
jtag_tclk_set(p); jtag_tclk_set(p);
jtag_dr_shift_16(p, 0x3ffd); jtag_dr_shift_16(p, 0x3ffd);
jtag_tclk_clr(p); jtag_tclk_clr(p);
if (alt_addr) {
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
jtag_dr_shift_16(p, 0x0501);
}
jtag_ir_shift(p, IR_DATA_CAPTURE); jtag_ir_shift(p, IR_DATA_CAPTURE);
jtag_tclk_set(p); jtag_tclk_set(p);
reglo = jtag_dr_shift_16(p, 0); reglo = jtag_dr_shift_16(p, 0);
@ -430,14 +500,15 @@ static address_t jlfxv2_read_reg(struct jtdev *p, int reg)
jtag_tclk_clr(p); jtag_tclk_clr(p);
jtag_tclk_set(p); jtag_tclk_set(p);
if (!alt_addr) {
jtag_ir_shift(p, IR_CNTRL_SIG_16BIT); jtag_ir_shift(p, IR_CNTRL_SIG_16BIT);
jtag_dr_shift_16(p, 0x0501); jtag_dr_shift_16(p, 0x0501);
}
jtag_tclk_clr(p); jtag_tclk_clr(p);
jtag_ir_shift(p, IR_DATA_CAPTURE); jtag_ir_shift(p, IR_DATA_CAPTURE);
jtag_tclk_set(p); jtag_tclk_set(p);
printc_dbg("read reg %d: lo=%04x hi=%04x\n", reg, reglo, reghi); printc_dbg("read reg %d: lo=%04x hi=%04x\n", reg, reglo, reghi);
return reglo | ((address_t)reghi << 16); return reglo | ((address_t)reghi << 16);
} }