Merge pull request #28 from sifive/readmem_autoexec

Readmem autoexec
nohartstatus
Megan Wachs 2017-04-04 22:27:52 -07:00 committed by GitHub
commit 7203102c25
1 changed files with 27 additions and 11 deletions

View File

@ -1859,11 +1859,34 @@ static int read_memory(struct target *target, uint32_t address,
return ERROR_FAIL; return ERROR_FAIL;
} }
// Set up autoexec s.t. each read of the the result that was in S1
// will start another run of reading the address pointed to by S0,
// copying it to S1, and storing S1 into Data 0.
if (count > 1) {
dmi_write(target, DMI_ABSTRACTAUTO, 0x1 << DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET);
}
uint32_t abstractcs; uint32_t abstractcs;
for (uint32_t i = 0; i < count; i++) { for (uint32_t i = 0; i < count; i++) {
// On last iteration, turn off autoexec before reading the value
// so that we don't inadvertently read too far into memory.
if ((count > 1) && ((i + 1) == count)) {
dmi_write(target, DMI_ABSTRACTAUTO, 0);
}
uint32_t value = dmi_read(target, DMI_DATA0); uint32_t value = dmi_read(target, DMI_DATA0);
if (i == 0) // If autoexec was set, the above dmi_read started an abstract command.
dmi_write(target, DMI_ABSTRACTAUTO, 0x1 << DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET); // If we just immediately loop and do another read here,
// we'll probably get a busy error. Wait for idle first,
// or otherwise take ac_command_busy into account (this defeats the purpose
// of autoexec, this whole code needs optimization).
if ((count > 1) && ((i + 1) < count)) {
if (wait_for_idle(target, &abstractcs) != ERROR_OK) {
dmi_write(target, DMI_ABSTRACTAUTO, 0);
return ERROR_FAIL;
}
}
switch (size) { switch (size) {
case 1: case 1:
buffer[i] = value; buffer[i] = value;
@ -1881,15 +1904,8 @@ static int read_memory(struct target *target, uint32_t address,
default: default:
return ERROR_FAIL; return ERROR_FAIL;
} }
// The above dmi_read started an abstract command. If we just
// immediately read here, we'll probably get a busy error. Wait for idle first,
// or otherwise take ac_command_busy into account (this defeats the purpose
// of autoexec, this whole code needs optimization).
if (wait_for_idle(target, &abstractcs) != ERROR_OK) {
return ERROR_FAIL;
} }
}
dmi_write(target, DMI_ABSTRACTAUTO, 0);
abstractcs = dmi_read(target, DMI_ABSTRACTCS); abstractcs = dmi_read(target, DMI_ABSTRACTCS);
unsigned cmderr = get_field(abstractcs, DMI_ABSTRACTCS_CMDERR); unsigned cmderr = get_field(abstractcs, DMI_ABSTRACTCS_CMDERR);
if (cmderr == CMDERR_BUSY) { if (cmderr == CMDERR_BUSY) {