parent
32e7a962c3
commit
a916d204b9
|
@ -684,6 +684,7 @@ static int wait_for_state(struct target *target, enum target_state state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static int wait_and_read(struct target *target, uint32_t *data, uint16_t address)
|
static int wait_and_read(struct target *target, uint32_t *data, uint16_t address)
|
||||||
{
|
{
|
||||||
time_t start = time(NULL);
|
time_t start = time(NULL);
|
||||||
|
@ -704,6 +705,7 @@ static int wait_and_read(struct target *target, uint32_t *data, uint16_t address
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int read_csr(struct target *target, uint32_t *value, uint32_t csr)
|
static int read_csr(struct target *target, uint32_t *value, uint32_t csr)
|
||||||
{
|
{
|
||||||
|
@ -1529,66 +1531,6 @@ static int riscv_read_memory(struct target *target, uint32_t address,
|
||||||
{
|
{
|
||||||
jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
|
jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
|
||||||
|
|
||||||
#if 0
|
|
||||||
// Plain implementation, where we write the address each time.
|
|
||||||
dram_write32(target, 0, lw(S0, ZERO, DEBUG_RAM_START + 16), false);
|
|
||||||
switch (size) {
|
|
||||||
case 1:
|
|
||||||
dram_write32(target, 1, lb(S1, S0, 0), false);
|
|
||||||
dram_write32(target, 2, sw(S1, ZERO, DEBUG_RAM_START + 16), false);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
dram_write32(target, 1, lh(S1, S0, 0), false);
|
|
||||||
dram_write32(target, 2, sw(S1, ZERO, DEBUG_RAM_START + 16), false);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
dram_write32(target, 1, lw(S1, S0, 0), false);
|
|
||||||
dram_write32(target, 2, sw(S1, ZERO, DEBUG_RAM_START + 16), false);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOG_ERROR("Unsupported size: %d", size);
|
|
||||||
return ERROR_FAIL;
|
|
||||||
}
|
|
||||||
dram_write_jump(target, 3, false);
|
|
||||||
|
|
||||||
uint32_t i = 0;
|
|
||||||
while (i <= count) {
|
|
||||||
uint64_t scan_result;
|
|
||||||
// Write the next address, set interrupt, and read the previous value.
|
|
||||||
uint64_t interrupt = 0;
|
|
||||||
if (i < count) {
|
|
||||||
interrupt = DMCONTROL_INTERRUPT;
|
|
||||||
}
|
|
||||||
dbus_status_t status = dbus_scan(target, &scan_result, DBUS_OP_CONDITIONAL_WRITE,
|
|
||||||
4, DMCONTROL_HALTNOT | interrupt | (address + i * size));
|
|
||||||
if (status == DBUS_STATUS_SUCCESS) {
|
|
||||||
if (i > 0) {
|
|
||||||
uint32_t offset = size * (i-1);
|
|
||||||
switch (size) {
|
|
||||||
case 1:
|
|
||||||
buffer[offset] = scan_result & 0xff;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
buffer[offset] = scan_result & 0xff;
|
|
||||||
buffer[offset + 1] = (scan_result >> 8) & 0xff;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
buffer[offset] = scan_result & 0xff;
|
|
||||||
buffer[offset + 1] = (scan_result >> 8) & 0xff;
|
|
||||||
buffer[offset + 2] = (scan_result >> 16) & 0xff;
|
|
||||||
buffer[offset + 3] = (scan_result >> 24) & 0xff;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
} else if (status == DBUS_STATUS_NO_WRITE || status == DBUS_STATUS_BUSY) {
|
|
||||||
// Need to retry the access that failed, which was the previous one.
|
|
||||||
} else if (status == DBUS_STATUS_FAILED) {
|
|
||||||
LOG_ERROR("dbus write failed!");
|
|
||||||
return ERROR_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
cache_set(target, 0, lw(S0, ZERO, DEBUG_RAM_START + 16));
|
cache_set(target, 0, lw(S0, ZERO, DEBUG_RAM_START + 16));
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -1610,6 +1552,103 @@ static int riscv_read_memory(struct target *target, uint32_t address,
|
||||||
cache_set_jump(target, 3);
|
cache_set_jump(target, 3);
|
||||||
cache_write(target, 4, false);
|
cache_write(target, 4, false);
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
||||||
|
const int max_batch_size = 256;
|
||||||
|
uint8_t *in = malloc(max_batch_size * 8);
|
||||||
|
uint8_t *out = malloc(max_batch_size * 8);
|
||||||
|
struct scan_field *field = calloc(max_batch_size, sizeof(struct scan_field));
|
||||||
|
|
||||||
|
uint32_t i = 0;
|
||||||
|
while (i < count + 2) {
|
||||||
|
unsigned int batch_size = MIN(count + 2 - i, max_batch_size);
|
||||||
|
|
||||||
|
for (unsigned int j = 0; j < batch_size; j++) {
|
||||||
|
if (i + j == count) {
|
||||||
|
// Just insert a read so we can scan out the last value.
|
||||||
|
add_dbus_scan(target, &field[j], out + 8*j, in + 8*j,
|
||||||
|
DBUS_OP_READ, 4, DMCONTROL_HALTNOT | 0);
|
||||||
|
} else if (i + j == count + 1) {
|
||||||
|
// And check for errors.
|
||||||
|
add_dbus_scan(target, &field[j], out + 8*j, in + 8*j,
|
||||||
|
DBUS_OP_READ, info->dramsize-1, DMCONTROL_HALTNOT | 0);
|
||||||
|
} else {
|
||||||
|
// Write the next address and set interrupt.
|
||||||
|
uint32_t offset = size * (i + j);
|
||||||
|
add_dbus_scan(target, &field[j], out + 8*j, in + 8*j,
|
||||||
|
DBUS_OP_WRITE, 4,
|
||||||
|
DMCONTROL_HALTNOT | DMCONTROL_INTERRUPT | (address + offset));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int retval = jtag_execute_queue();
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
|
LOG_ERROR("JTAG execute failed: %d", retval);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dbus_busy = 0;
|
||||||
|
for (unsigned int j = 0; j < batch_size; j++) {
|
||||||
|
dbus_status_t status = buf_get_u32(in + 8*j, DBUS_OP_START, DBUS_OP_SIZE);
|
||||||
|
switch (status) {
|
||||||
|
case DBUS_STATUS_SUCCESS:
|
||||||
|
break;
|
||||||
|
case DBUS_STATUS_NO_WRITE:
|
||||||
|
LOG_ERROR("Got no-write status without conditional write.");
|
||||||
|
goto error;
|
||||||
|
case DBUS_STATUS_FAILED:
|
||||||
|
LOG_ERROR("Debug RAM write failed. Hardware error?");
|
||||||
|
goto error;
|
||||||
|
case DBUS_STATUS_BUSY:
|
||||||
|
dbus_busy++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i + j > 1) {
|
||||||
|
uint32_t data = buf_get_u32(in + 8*j, DBUS_DATA_START, 32);
|
||||||
|
uint32_t offset = size * (i + j - 2);
|
||||||
|
switch (size) {
|
||||||
|
case 1:
|
||||||
|
buffer[offset] = data;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
buffer[offset] = data;
|
||||||
|
buffer[offset+1] = data >> 8;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
buffer[offset] = data;
|
||||||
|
buffer[offset+1] = data >> 8;
|
||||||
|
buffer[offset+2] = data >> 16;
|
||||||
|
buffer[offset+3] = data >> 24;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG_DEBUG("j=%d status=%d data=%09" PRIx64, j, status,
|
||||||
|
buf_get_u64(in + 8*j, DBUS_DATA_START, DBUS_DATA_SIZE));
|
||||||
|
}
|
||||||
|
if (dbus_busy) {
|
||||||
|
increase_dbus_busy_delay(target);
|
||||||
|
|
||||||
|
wait_for_debugint_clear(target, false);
|
||||||
|
|
||||||
|
// Retry.
|
||||||
|
LOG_INFO("Retrying memory read starting from 0x%x with more delays", address + size * i);
|
||||||
|
} else {
|
||||||
|
i += batch_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(in);
|
||||||
|
free(out);
|
||||||
|
free(field);
|
||||||
|
cache_clean(target);
|
||||||
|
return ERROR_OK;
|
||||||
|
|
||||||
|
error:
|
||||||
|
free(in);
|
||||||
|
free(out);
|
||||||
|
free(field);
|
||||||
|
return ERROR_FAIL;
|
||||||
|
#else
|
||||||
for (unsigned int i = 0; i < count; i++) {
|
for (unsigned int i = 0; i < count; i++) {
|
||||||
dram_write32(target, 4, address + i * size, true);
|
dram_write32(target, 4, address + i * size, true);
|
||||||
|
|
||||||
|
@ -1636,9 +1675,9 @@ static int riscv_read_memory(struct target *target, uint32_t address,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
|
|
Loading…
Reference in New Issue