Check for exceptions in reads and writes.

This commit is contained in:
Tim Newsome 2016-07-29 12:36:12 -07:00
parent f5ae4d864c
commit f8b0f4bf29
1 changed files with 47 additions and 18 deletions

View File

@ -1438,19 +1438,20 @@ static int riscv_read_memory(struct target *target, uint32_t address,
uint8_t *out = 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)); struct scan_field *field = calloc(max_batch_size, sizeof(struct scan_field));
uint32_t result_value = 0x777;
uint32_t i = 0; uint32_t i = 0;
while (i < count + 2) { while (i < count + 3) {
unsigned int batch_size = MIN(count + 2 - i, max_batch_size); unsigned int batch_size = MIN(count + 3 - i, max_batch_size);
for (unsigned int j = 0; j < batch_size; j++) { for (unsigned int j = 0; j < batch_size; j++) {
if (i + j == count) { if (i + j == count) {
// Just insert a read so we can scan out the last value. // Just insert a read so we can scan out the last value.
add_dbus_scan(target, &field[j], out + 8*j, in + 8*j, add_dbus_scan(target, &field[j], out + 8*j, in + 8*j,
DBUS_OP_READ, 4, DMCONTROL_HALTNOT | 0); DBUS_OP_READ, 4, DMCONTROL_HALTNOT);
} else if (i + j == count + 1) { } else if (i + j >= count + 1) {
// And check for errors. // And check for errors.
add_dbus_scan(target, &field[j], out + 8*j, in + 8*j, add_dbus_scan(target, &field[j], out + 8*j, in + 8*j,
DBUS_OP_READ, info->dramsize-1, DMCONTROL_HALTNOT | 0); DBUS_OP_READ, info->dramsize-1, DMCONTROL_HALTNOT);
} else { } else {
// Write the next address and set interrupt. // Write the next address and set interrupt.
uint32_t offset = size * (i + j); uint32_t offset = size * (i + j);
@ -1482,8 +1483,10 @@ static int riscv_read_memory(struct target *target, uint32_t address,
dbus_busy++; dbus_busy++;
break; break;
} }
if (i + j > 1) { uint64_t data = buf_get_u64(in + 8*j, DBUS_DATA_START, DBUS_DATA_SIZE);
uint32_t data = buf_get_u32(in + 8*j, DBUS_DATA_START, 32); if (i + j == count + 2) {
result_value = data;
} else if (i + j > 1) {
uint32_t offset = size * (i + j - 2); uint32_t offset = size * (i + j - 2);
switch (size) { switch (size) {
case 1: case 1:
@ -1501,8 +1504,7 @@ static int riscv_read_memory(struct target *target, uint32_t address,
break; break;
} }
} }
LOG_DEBUG("j=%d status=%d data=%09" PRIx64, j, status, LOG_DEBUG("j=%d status=%d data=%09" PRIx64, j, status, data);
buf_get_u64(in + 8*j, DBUS_DATA_START, DBUS_DATA_SIZE));
} }
if (dbus_busy) { if (dbus_busy) {
increase_dbus_busy_delay(target); increase_dbus_busy_delay(target);
@ -1516,6 +1518,17 @@ static int riscv_read_memory(struct target *target, uint32_t address,
} }
} }
if (result_value != 0) {
LOG_ERROR("Core got an exception (0x%x) while reading from 0x%x",
result_value, address + size * (count-1));
if (count > 1) {
LOG_ERROR("(It may have failed between 0x%x and 0x%x as well, but we "
"didn't check then.)",
address, address + size * (count-2) + size - 1);
}
goto error;
}
free(in); free(in);
free(out); free(out);
free(field); free(field);
@ -1526,6 +1539,7 @@ error:
free(in); free(in);
free(out); free(out);
free(field); free(field);
cache_clean(target);
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -1581,15 +1595,14 @@ static int riscv_write_memory(struct target *target, uint32_t address,
uint8_t *out = 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)); struct scan_field *field = calloc(max_batch_size, sizeof(struct scan_field));
uint32_t result_value = 0x777;
uint32_t i = 0; uint32_t i = 0;
while (i < count + 1) { while (i < count + 2) {
unsigned int batch_size = MIN(count + 1 - i, max_batch_size); unsigned int batch_size = MIN(count + 2 - i, max_batch_size);
for (unsigned int j = 0; j < batch_size; j++) { for (unsigned int j = 0; j < batch_size; j++) {
if (i + j == count) { if (i + j >= count) {
// Just insert a read so we can confirm that the last scan // Check for an exception.
// succeeded.
add_dbus_scan(target, &field[j], out + 8*j, in + 8*j, add_dbus_scan(target, &field[j], out + 8*j, in + 8*j,
DBUS_OP_READ, info->dramsize-1, DMCONTROL_HALTNOT | 0); DBUS_OP_READ, info->dramsize-1, DMCONTROL_HALTNOT | 0);
} else { } else {
@ -1628,7 +1641,8 @@ static int riscv_write_memory(struct target *target, uint32_t address,
int dbus_busy = 0; int dbus_busy = 0;
int execute_busy = 0; int execute_busy = 0;
for (unsigned int j = 0; j < batch_size; j++) { 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); dbus_status_t status = buf_get_u32(in + 8*j, DBUS_OP_START,
DBUS_OP_SIZE);
switch (status) { switch (status) {
case DBUS_STATUS_SUCCESS: case DBUS_STATUS_SUCCESS:
break; break;
@ -1642,8 +1656,11 @@ static int riscv_write_memory(struct target *target, uint32_t address,
dbus_busy++; dbus_busy++;
break; break;
} }
LOG_DEBUG("j=%d status=%d data=%09" PRIx64, j, status, uint64_t data = buf_get_u64(in + 8*j, DBUS_DATA_START, DBUS_DATA_SIZE);
buf_get_u64(in + 8*j, DBUS_DATA_START, DBUS_DATA_SIZE)); if (i + j == count + 1) {
result_value = data;
}
LOG_DEBUG("j=%d status=%d data=%09" PRIx64, j, status, data);
} }
if (dbus_busy) { if (dbus_busy) {
increase_dbus_busy_delay(target); increase_dbus_busy_delay(target);
@ -1673,6 +1690,17 @@ static int riscv_write_memory(struct target *target, uint32_t address,
} }
} }
if (result_value != 0) {
LOG_ERROR("Core got an exception (0x%x) while writing to 0x%x",
result_value, address + size * (count-1));
if (count > 1) {
LOG_ERROR("(It may have failed between 0x%x and 0x%x as well, but we "
"didn't check then.)",
address, address + size * (count-2) + size - 1);
}
goto error;
}
free(in); free(in);
free(out); free(out);
free(field); free(field);
@ -1684,6 +1712,7 @@ error:
free(in); free(in);
free(out); free(out);
free(field); free(field);
cache_clean(target);
return ERROR_FAIL; return ERROR_FAIL;
} }