Only write to existing dram. Clear dbus error.
Old code would write 64 bytes of DRAM if the dbus was busy in cache_write(). New code clears the dbus error condition when the bus is busy. (This part is untested.) Change-Id: Ia396fe819fa1828bb75726d85513b113cc9e13f0
This commit is contained in:
parent
54c65a9a4b
commit
c67850b63d
|
@ -46,9 +46,10 @@
|
||||||
|
|
||||||
/*** JTAG registers. ***/
|
/*** JTAG registers. ***/
|
||||||
|
|
||||||
#define DTMINFO 0x10
|
#define DTMCONTROL 0x10
|
||||||
#define DTMINFO_ADDRBITS (0xf<<4)
|
#define DTMCONTROL_DBUS_RESET (1<<16)
|
||||||
#define DTMINFO_VERSION (0xf)
|
#define DTMCONTROL_ADDRBITS (0xf<<4)
|
||||||
|
#define DTMCONTROL_VERSION (0xf)
|
||||||
|
|
||||||
#define DBUS 0x11
|
#define DBUS 0x11
|
||||||
#define DBUS_OP_START 0
|
#define DBUS_OP_START 0
|
||||||
|
@ -197,10 +198,10 @@ static int poll_target(struct target *target, bool announce);
|
||||||
|
|
||||||
/*** Utility functions. ***/
|
/*** Utility functions. ***/
|
||||||
|
|
||||||
static uint8_t ir_dtminfo[1] = {DTMINFO};
|
static uint8_t ir_dtmcontrol[1] = {DTMCONTROL};
|
||||||
static struct scan_field select_dtminfo = {
|
static struct scan_field select_dtmcontrol = {
|
||||||
.in_value = NULL,
|
.in_value = NULL,
|
||||||
.out_value = ir_dtminfo
|
.out_value = ir_dtmcontrol
|
||||||
};
|
};
|
||||||
static uint8_t ir_dbus[1] = {DBUS};
|
static uint8_t ir_dbus[1] = {DBUS};
|
||||||
static struct scan_field select_dbus = {
|
static struct scan_field select_dbus = {
|
||||||
|
@ -284,11 +285,43 @@ static uint16_t dram_address(unsigned int index)
|
||||||
return 0x40 + index - 0x10;
|
return 0x40 + index - 0x10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t dtmcontrol_scan(struct target *target, uint32_t out)
|
||||||
|
{
|
||||||
|
struct scan_field field;
|
||||||
|
uint8_t in_value[4];
|
||||||
|
uint8_t out_value[4];
|
||||||
|
|
||||||
|
buf_set_u32(out_value, 0, 32, out);
|
||||||
|
|
||||||
|
jtag_add_ir_scan(target->tap, &select_dtmcontrol, TAP_IDLE);
|
||||||
|
|
||||||
|
field.num_bits = 32;
|
||||||
|
field.out_value = out_value;
|
||||||
|
field.in_value = in_value;
|
||||||
|
jtag_add_dr_scan(target->tap, 1, &field, TAP_IDLE);
|
||||||
|
|
||||||
|
int retval = jtag_execute_queue();
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
|
LOG_ERROR("failed jtag scan: %d", retval);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Always return to dbus. */
|
||||||
|
jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
|
||||||
|
|
||||||
|
uint32_t in = buf_get_u32(field.in_value, 0, 32);
|
||||||
|
LOG_DEBUG("DTMCONTROL: 0x%x -> 0x%x", out, in);
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
static void increase_dbus_busy_delay(struct target *target)
|
static void increase_dbus_busy_delay(struct target *target)
|
||||||
{
|
{
|
||||||
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
||||||
info->dbus_busy_delay++;
|
info->dbus_busy_delay++;
|
||||||
LOG_INFO("Increment dbus_busy_delay to %d", info->dbus_busy_delay);
|
LOG_INFO("Increment dbus_busy_delay to %d", info->dbus_busy_delay);
|
||||||
|
|
||||||
|
dtmcontrol_scan(target, DTMCONTROL_DBUS_RESET);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void increase_interrupt_high_delay(struct target *target)
|
static void increase_interrupt_high_delay(struct target *target)
|
||||||
|
@ -314,7 +347,7 @@ static void add_dbus_scan(const struct target *target, struct scan_field *field,
|
||||||
|
|
||||||
jtag_add_dr_scan(target->tap, 1, field, TAP_IDLE);
|
jtag_add_dr_scan(target->tap, 1, field, TAP_IDLE);
|
||||||
|
|
||||||
// TODO: 1 should come from the dtminfo register
|
// TODO: 1 should come from the dtmcontrol register
|
||||||
int idle_count = 1 + info->dbus_busy_delay;
|
int idle_count = 1 + info->dbus_busy_delay;
|
||||||
if (data & DMCONTROL_INTERRUPT) {
|
if (data & DMCONTROL_INTERRUPT) {
|
||||||
idle_count += info->interrupt_high_delay;
|
idle_count += info->interrupt_high_delay;
|
||||||
|
@ -480,7 +513,7 @@ static int scans_execute(scans_t *scans)
|
||||||
{
|
{
|
||||||
int retval = jtag_execute_queue();
|
int retval = jtag_execute_queue();
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("dtminfo_read failed jtag scan");
|
LOG_ERROR("failed jtag scan: %d", retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -563,30 +596,6 @@ static uint64_t scans_get_u64(scans_t *scans, unsigned int index,
|
||||||
|
|
||||||
/*** end of scans class ***/
|
/*** end of scans class ***/
|
||||||
|
|
||||||
static uint32_t dtminfo_read(struct target *target)
|
|
||||||
{
|
|
||||||
struct scan_field field;
|
|
||||||
uint8_t in[4];
|
|
||||||
|
|
||||||
jtag_add_ir_scan(target->tap, &select_dtminfo, TAP_IDLE);
|
|
||||||
|
|
||||||
field.num_bits = 32;
|
|
||||||
field.out_value = NULL;
|
|
||||||
field.in_value = in;
|
|
||||||
jtag_add_dr_scan(target->tap, 1, &field, TAP_IDLE);
|
|
||||||
|
|
||||||
int retval = jtag_execute_queue();
|
|
||||||
if (retval != ERROR_OK) {
|
|
||||||
LOG_ERROR("dtminfo_read failed jtag scan");
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Always return to dbus. */
|
|
||||||
jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
|
|
||||||
|
|
||||||
return buf_get_u32(field.in_value, 0, 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t dram_read32(struct target *target, unsigned int index)
|
static uint32_t dram_read32(struct target *target, unsigned int index)
|
||||||
{
|
{
|
||||||
uint16_t address = dram_address(index);
|
uint16_t address = dram_address(index);
|
||||||
|
@ -825,7 +834,8 @@ static int cache_write(struct target *target, unsigned int address, bool run)
|
||||||
increase_dbus_busy_delay(target);
|
increase_dbus_busy_delay(target);
|
||||||
|
|
||||||
// Try again, using the slow careful code.
|
// Try again, using the slow careful code.
|
||||||
for (unsigned int i = 0; i < DRAM_CACHE_SIZE; i++) {
|
// Write all RAM, just to be extra cautious.
|
||||||
|
for (unsigned int i = 0; i < info->dramsize; i++) {
|
||||||
if (i == last && run) {
|
if (i == last && run) {
|
||||||
dram_write32(target, last, info->dram_cache[last].data, true);
|
dram_write32(target, last, info->dram_cache[last].data, true);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1245,7 +1255,7 @@ static int riscv_init_target(struct command_context *cmd_ctx,
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
||||||
|
|
||||||
select_dtminfo.num_bits = target->tap->ir_length;
|
select_dtmcontrol.num_bits = target->tap->ir_length;
|
||||||
select_dbus.num_bits = target->tap->ir_length;
|
select_dbus.num_bits = target->tap->ir_length;
|
||||||
select_debug.num_bits = target->tap->ir_length;
|
select_debug.num_bits = target->tap->ir_length;
|
||||||
|
|
||||||
|
@ -1617,26 +1627,26 @@ static int riscv_examine(struct target *target)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't need to select dbus, since the first thing we do is read dtminfo.
|
// Don't need to select dbus, since the first thing we do is read dtmcontrol.
|
||||||
|
|
||||||
uint32_t dtminfo = dtminfo_read(target);
|
uint32_t dtmcontrol = dtmcontrol_scan(target, 0);
|
||||||
LOG_DEBUG("dtminfo=0x%x", dtminfo);
|
LOG_DEBUG("dtmcontrol=0x%x", dtmcontrol);
|
||||||
LOG_DEBUG(" addrbits=%d", get_field(dtminfo, DTMINFO_ADDRBITS));
|
LOG_DEBUG(" addrbits=%d", get_field(dtmcontrol, DTMCONTROL_ADDRBITS));
|
||||||
LOG_DEBUG(" version=%d", get_field(dtminfo, DTMINFO_VERSION));
|
LOG_DEBUG(" version=%d", get_field(dtmcontrol, DTMCONTROL_VERSION));
|
||||||
// TODO: Add support for the idle field, once it's implemented in the FPGA
|
// TODO: Add support for the idle field, once it's implemented in the FPGA
|
||||||
// image.
|
// image.
|
||||||
if (dtminfo == 0) {
|
if (dtmcontrol == 0) {
|
||||||
LOG_ERROR("dtminfo is 0. Check JTAG connectivity/board power.");
|
LOG_ERROR("dtmcontrol is 0. Check JTAG connectivity/board power.");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
if (get_field(dtminfo, DTMINFO_VERSION) != 0) {
|
if (get_field(dtmcontrol, DTMCONTROL_VERSION) != 0) {
|
||||||
LOG_ERROR("Unsupported DTM version %d. (dtminfo=0x%x)",
|
LOG_ERROR("Unsupported DTM version %d. (dtmcontrol=0x%x)",
|
||||||
get_field(dtminfo, DTMINFO_VERSION), dtminfo);
|
get_field(dtmcontrol, DTMCONTROL_VERSION), dtmcontrol);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
||||||
info->addrbits = get_field(dtminfo, DTMINFO_ADDRBITS);
|
info->addrbits = get_field(dtmcontrol, DTMCONTROL_ADDRBITS);
|
||||||
|
|
||||||
uint32_t dminfo = dbus_read(target, DMINFO);
|
uint32_t dminfo = dbus_read(target, DMINFO);
|
||||||
LOG_DEBUG("dminfo: 0x%08x", dminfo);
|
LOG_DEBUG("dminfo: 0x%08x", dminfo);
|
||||||
|
|
Loading…
Reference in New Issue