commit
3ddbbd525d
|
@ -433,8 +433,8 @@ static void increase_dmi_busy_delay(struct target *target)
|
|||
* exec: If this is set, assume the scan results in an execution, so more
|
||||
* run-test/idle cycles may be required.
|
||||
*/
|
||||
static dmi_status_t dmi_scan(struct target *target, uint16_t *address_in,
|
||||
uint32_t *data_in, dmi_op_t op, uint16_t address_out, uint32_t data_out,
|
||||
static dmi_status_t dmi_scan(struct target *target, uint32_t *address_in,
|
||||
uint32_t *data_in, dmi_op_t op, uint32_t address_out, uint32_t data_out,
|
||||
bool exec)
|
||||
{
|
||||
riscv013_info_t *info = get_info(target);
|
||||
|
@ -479,12 +479,12 @@ static dmi_status_t dmi_scan(struct target *target, uint16_t *address_in,
|
|||
return buf_get_u32(in, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH);
|
||||
}
|
||||
|
||||
static uint32_t dmi_read(struct target *target, uint16_t address)
|
||||
static int dmi_read(struct target *target, uint32_t *value, uint32_t address)
|
||||
{
|
||||
select_dmi(target);
|
||||
|
||||
dmi_status_t status;
|
||||
uint16_t address_in;
|
||||
uint32_t address_in;
|
||||
|
||||
unsigned i = 0;
|
||||
|
||||
|
@ -500,21 +500,20 @@ static uint32_t dmi_read(struct target *target, uint16_t address)
|
|||
break;
|
||||
} else {
|
||||
LOG_ERROR("failed read from 0x%x, status=%d", address, status);
|
||||
break;
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (status != DMI_STATUS_SUCCESS) {
|
||||
LOG_ERROR("Failed read from 0x%x; status=%d", address, status);
|
||||
return ~0;
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
/* This second loop ensures that we got the read
|
||||
* data back. Note that NOP can result in a 'busy' result as well, but
|
||||
* that would be noticed on the next DMI access we do. */
|
||||
uint32_t value;
|
||||
for (i = 0; i < 256; i++) {
|
||||
status = dmi_scan(target, &address_in, &value, DMI_OP_NOP, address, 0,
|
||||
status = dmi_scan(target, &address_in, value, DMI_OP_NOP, address, 0,
|
||||
false);
|
||||
if (status == DMI_STATUS_BUSY) {
|
||||
increase_dmi_busy_delay(target);
|
||||
|
@ -522,7 +521,7 @@ static uint32_t dmi_read(struct target *target, uint16_t address)
|
|||
break;
|
||||
} else {
|
||||
LOG_ERROR("failed read (NOP) at 0x%x, status=%d", address, status);
|
||||
break;
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -531,15 +530,15 @@ static uint32_t dmi_read(struct target *target, uint16_t address)
|
|||
LOG_ERROR("Failed read (NOP) from 0x%x; status=%d", address, status);
|
||||
} else {
|
||||
LOG_ERROR("Failed read (NOP) from 0x%x; value=0x%x, status=%d",
|
||||
address, value, status);
|
||||
address, *value, status);
|
||||
}
|
||||
return ~0;
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
return value;
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int dmi_write(struct target *target, uint16_t address, uint64_t value)
|
||||
static int dmi_write(struct target *target, uint32_t address, uint32_t value)
|
||||
{
|
||||
select_dmi(target);
|
||||
dmi_status_t status = DMI_STATUS_BUSY;
|
||||
|
@ -581,7 +580,7 @@ static int dmi_write(struct target *target, uint16_t address, uint64_t value)
|
|||
}
|
||||
}
|
||||
if (status != DMI_STATUS_SUCCESS) {
|
||||
LOG_ERROR("failed to write (NOP) 0x%" PRIx64 " to 0x%x; status=%d", value, address, status);
|
||||
LOG_ERROR("failed to write (NOP) 0x%x to 0x%x; status=%d", value, address, status);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
|
@ -591,7 +590,8 @@ static int dmi_write(struct target *target, uint16_t address, uint64_t value)
|
|||
int dmstatus_read(struct target *target, uint32_t *dmstatus,
|
||||
bool authenticated)
|
||||
{
|
||||
*dmstatus = dmi_read(target, DMI_DMSTATUS);
|
||||
if (dmi_read(target, dmstatus, DMI_DMSTATUS) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
if (authenticated && !get_field(*dmstatus, DMI_DMSTATUS_AUTHENTICATED)) {
|
||||
LOG_ERROR("Debugger is not authenticated to target Debug Module. "
|
||||
"(dmstatus=0x%x). Use `riscv authdata_read` and "
|
||||
|
@ -632,7 +632,8 @@ static int wait_for_idle(struct target *target, uint32_t *abstractcs)
|
|||
RISCV013_INFO(info);
|
||||
time_t start = time(NULL);
|
||||
while (1) {
|
||||
*abstractcs = dmi_read(target, DMI_ABSTRACTCS);
|
||||
if (dmi_read(target, abstractcs, DMI_ABSTRACTCS) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
|
||||
if (get_field(*abstractcs, DMI_ABSTRACTCS_BUSY) == 0)
|
||||
return ERROR_OK;
|
||||
|
@ -674,7 +675,9 @@ static int execute_abstract_command(struct target *target, uint32_t command)
|
|||
wait_for_idle(target, &abstractcs);
|
||||
}
|
||||
|
||||
uint32_t cs = dmi_read(target, DMI_ABSTRACTCS);
|
||||
uint32_t cs;
|
||||
if (dmi_read(target, &cs, DMI_ABSTRACTCS) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
info->cmderr = get_field(cs, DMI_ABSTRACTCS_CMDERR);
|
||||
if (info->cmderr != 0) {
|
||||
LOG_DEBUG("command 0x%x failed; abstractcs=0x%x", command, cs);
|
||||
|
@ -691,16 +694,19 @@ static riscv_reg_t read_abstract_arg(struct target *target, unsigned index,
|
|||
unsigned size_bits)
|
||||
{
|
||||
riscv_reg_t value = 0;
|
||||
uint32_t v;
|
||||
unsigned offset = index * size_bits / 32;
|
||||
switch (size_bits) {
|
||||
default:
|
||||
LOG_ERROR("Unsupported size: %d", size_bits);
|
||||
return ~0;
|
||||
case 64:
|
||||
value |= ((uint64_t) dmi_read(target, DMI_DATA0 + offset + 1)) << 32;
|
||||
dmi_read(target, &v, DMI_DATA0 + offset + 1);
|
||||
value |= ((uint64_t) v) << 32;
|
||||
/* falls through */
|
||||
case 32:
|
||||
value |= dmi_read(target, DMI_DATA0 + offset);
|
||||
dmi_read(target, &v, DMI_DATA0 + offset);
|
||||
value |= v;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@ -871,7 +877,9 @@ static int examine_progbuf(struct target *target)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
uint32_t written = dmi_read(target, DMI_PROGBUF0);
|
||||
uint32_t written;
|
||||
if (dmi_read(target, &written, DMI_PROGBUF0) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
if (written == (uint32_t) info->progbuf_address) {
|
||||
LOG_INFO("progbuf is writable at 0x%" PRIx64,
|
||||
info->progbuf_address);
|
||||
|
@ -961,16 +969,23 @@ static int scratch_find(struct target *target,
|
|||
static int scratch_read64(struct target *target, scratch_mem_t *scratch,
|
||||
uint64_t *value)
|
||||
{
|
||||
uint32_t v;
|
||||
switch (scratch->memory_space) {
|
||||
case SPACE_DMI_DATA:
|
||||
*value = dmi_read(target, DMI_DATA0 + scratch->debug_address);
|
||||
*value |= ((uint64_t) dmi_read(target, DMI_DATA1 +
|
||||
scratch->debug_address)) << 32;
|
||||
if (dmi_read(target, &v, DMI_DATA0 + scratch->debug_address) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
*value = v;
|
||||
if (dmi_read(target, &v, DMI_DATA1 + scratch->debug_address) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
*value |= ((uint64_t) v) << 32;
|
||||
break;
|
||||
case SPACE_DMI_PROGBUF:
|
||||
*value = dmi_read(target, DMI_PROGBUF0 + scratch->debug_address);
|
||||
*value |= ((uint64_t) dmi_read(target, DMI_PROGBUF1 +
|
||||
scratch->debug_address)) << 32;
|
||||
if (dmi_read(target, &v, DMI_PROGBUF0 + scratch->debug_address) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
*value = v;
|
||||
if (dmi_read(target, &v, DMI_PROGBUF1 + scratch->debug_address) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
*value |= ((uint64_t) v) << 32;
|
||||
break;
|
||||
case SPACE_DMI_RAM:
|
||||
{
|
||||
|
@ -1269,7 +1284,9 @@ static int examine(struct target *target)
|
|||
|
||||
uint32_t max_hartsel_mask = ((1L<<10)-1) << DMI_DMCONTROL_HARTSEL_OFFSET;
|
||||
dmi_write(target, DMI_DMCONTROL, max_hartsel_mask | DMI_DMCONTROL_DMACTIVE);
|
||||
uint32_t dmcontrol = dmi_read(target, DMI_DMCONTROL);
|
||||
uint32_t dmcontrol;
|
||||
if (dmi_read(target, &dmcontrol, DMI_DMCONTROL) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
|
||||
if (!get_field(dmcontrol, DMI_DMCONTROL_DMACTIVE)) {
|
||||
LOG_ERROR("Debug Module did not become active. dmcontrol=0x%x",
|
||||
|
@ -1285,7 +1302,9 @@ static int examine(struct target *target)
|
|||
}
|
||||
LOG_DEBUG("hartsellen=%d", info->hartsellen);
|
||||
|
||||
uint32_t hartinfo = dmi_read(target, DMI_HARTINFO);
|
||||
uint32_t hartinfo;
|
||||
if (dmi_read(target, &hartinfo, DMI_HARTINFO) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
|
||||
info->datasize = get_field(hartinfo, DMI_HARTINFO_DATASIZE);
|
||||
info->dataaccess = get_field(hartinfo, DMI_HARTINFO_DATAACCESS);
|
||||
|
@ -1302,10 +1321,13 @@ static int examine(struct target *target)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
info->sbcs = dmi_read(target, DMI_SBCS);
|
||||
if (dmi_read(target, &info->sbcs, DMI_SBCS) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
|
||||
/* Check that abstract data registers are accessible. */
|
||||
uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS);
|
||||
uint32_t abstractcs;
|
||||
if (dmi_read(target, &abstractcs, DMI_ABSTRACTCS) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
info->datacount = get_field(abstractcs, DMI_ABSTRACTCS_DATACOUNT);
|
||||
info->progbufsize = get_field(abstractcs, DMI_ABSTRACTCS_PROGBUFSIZE);
|
||||
|
||||
|
@ -1412,8 +1434,7 @@ int riscv013_authdata_read(struct target *target, uint32_t *value)
|
|||
if (wait_for_authbusy(target, NULL) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
|
||||
*value = dmi_read(target, DMI_AUTHDATA);
|
||||
return ERROR_OK;
|
||||
return dmi_read(target, value, DMI_AUTHDATA);
|
||||
}
|
||||
|
||||
int riscv013_authdata_write(struct target *target, uint32_t value)
|
||||
|
@ -1469,6 +1490,8 @@ static int init_target(struct command_context *cmd_ctx,
|
|||
generic_info->dmi_write_u64_bits = &riscv013_dmi_write_u64_bits;
|
||||
generic_info->authdata_read = &riscv013_authdata_read;
|
||||
generic_info->authdata_write = &riscv013_authdata_write;
|
||||
generic_info->dmi_read = &dmi_read;
|
||||
generic_info->dmi_write = &dmi_write;
|
||||
generic_info->version_specific = calloc(1, sizeof(riscv013_info_t));
|
||||
if (!generic_info->version_specific)
|
||||
return ERROR_FAIL;
|
||||
|
@ -1533,7 +1556,9 @@ static int assert_reset(struct target *target)
|
|||
dmi_write(target, DMI_DMCONTROL, control);
|
||||
|
||||
/* Read back to check if hartreset is supported. */
|
||||
uint32_t rb = dmi_read(target, DMI_DMCONTROL);
|
||||
uint32_t rb;
|
||||
if (dmi_read(target, &rb, DMI_DMCONTROL) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
if (!get_field(rb, DMI_DMCONTROL_HARTRESET)) {
|
||||
/* Use ndmreset instead. That will reset the entire device, but
|
||||
* that's probably what OpenOCD wants anyway. */
|
||||
|
@ -1668,21 +1693,25 @@ static int read_memory_bus_word(struct target *target, target_addr_t address,
|
|||
{
|
||||
uint32_t value;
|
||||
if (size > 12) {
|
||||
value = dmi_read(target, DMI_SBDATA3);
|
||||
if (dmi_read(target, &value, DMI_SBDATA3) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
write_to_buf(buffer + 12, value, 4);
|
||||
log_memory_access(address + 12, value, 4, true);
|
||||
}
|
||||
if (size > 8) {
|
||||
value = dmi_read(target, DMI_SBDATA2);
|
||||
if (dmi_read(target, &value, DMI_SBDATA2) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
write_to_buf(buffer + 8, value, 4);
|
||||
log_memory_access(address + 8, value, 4, true);
|
||||
}
|
||||
if (size > 4) {
|
||||
value = dmi_read(target, DMI_SBDATA1);
|
||||
if (dmi_read(target, &value, DMI_SBDATA1) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
write_to_buf(buffer + 4, value, 4);
|
||||
log_memory_access(address + 4, value, 4, true);
|
||||
}
|
||||
value = dmi_read(target, DMI_SBDATA0);
|
||||
if (dmi_read(target, &value, DMI_SBDATA0) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
write_to_buf(buffer, value, MIN(size, 4));
|
||||
log_memory_access(address, value, MIN(size, 4), true);
|
||||
return ERROR_OK;
|
||||
|
@ -1711,13 +1740,16 @@ static target_addr_t sb_read_address(struct target *target)
|
|||
RISCV013_INFO(info);
|
||||
unsigned sbasize = get_field(info->sbcs, DMI_SBCS_SBASIZE);
|
||||
target_addr_t address = 0;
|
||||
uint32_t v;
|
||||
if (sbasize > 32) {
|
||||
#if BUILD_TARGET64
|
||||
address |= dmi_read(target, DMI_SBADDRESS1);
|
||||
dmi_read(target, &v, DMI_SBADDRESS1);
|
||||
address |= v;
|
||||
address <<= 32;
|
||||
#endif
|
||||
}
|
||||
address |= dmi_read(target, DMI_SBADDRESS0);
|
||||
dmi_read(target, &v, DMI_SBADDRESS0);
|
||||
address |= v;
|
||||
return address;
|
||||
}
|
||||
|
||||
|
@ -1746,7 +1778,8 @@ static int read_sbcs_nonbusy(struct target *target, uint32_t *sbcs)
|
|||
{
|
||||
time_t start = time(NULL);
|
||||
while (1) {
|
||||
*sbcs = dmi_read(target, DMI_SBCS);
|
||||
if (dmi_read(target, sbcs, DMI_SBCS) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
if (!get_field(*sbcs, DMI_SBCS_SBBUSY))
|
||||
return ERROR_OK;
|
||||
if (time(NULL) - start > riscv_command_timeout_sec) {
|
||||
|
@ -1924,9 +1957,12 @@ static int read_memory_progbuf(struct target *target, target_addr_t address,
|
|||
|
||||
/* Wait for the target to finish performing the last abstract command,
|
||||
* and update our copy of cmderr. */
|
||||
uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS);
|
||||
uint32_t abstractcs;
|
||||
if (dmi_read(target, &abstractcs, DMI_ABSTRACTCS) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
while (get_field(abstractcs, DMI_ABSTRACTCS_BUSY))
|
||||
abstractcs = dmi_read(target, DMI_ABSTRACTCS);
|
||||
if (dmi_read(target, &abstractcs, DMI_ABSTRACTCS) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
info->cmderr = get_field(abstractcs, DMI_ABSTRACTCS_CMDERR);
|
||||
|
||||
unsigned cmderr = info->cmderr;
|
||||
|
@ -1975,7 +2011,10 @@ static int read_memory_progbuf(struct target *target, target_addr_t address,
|
|||
/* This is definitely a good version of the value that we
|
||||
* attempted to read when we discovered that the target was
|
||||
* busy. */
|
||||
dmi_data0 = dmi_read(target, DMI_DATA0);
|
||||
if (dmi_read(target, &dmi_data0, DMI_DATA0) != ERROR_OK) {
|
||||
riscv_batch_free(batch);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Clobbers DMI_DATA0. */
|
||||
result = register_read_direct(target, &next_read_addr,
|
||||
|
@ -2035,7 +2074,9 @@ static int read_memory_progbuf(struct target *target, target_addr_t address,
|
|||
|
||||
if (count > 1) {
|
||||
/* Read the penultimate word. */
|
||||
uint64_t value = dmi_read(target, DMI_DATA0);
|
||||
uint32_t value;
|
||||
if (dmi_read(target, &value, DMI_DATA0) != ERROR_OK)
|
||||
goto error;
|
||||
write_to_buf(buffer + receive_addr - address, value, size);
|
||||
log_memory_access(receive_addr, value, size, true);
|
||||
receive_addr += size;
|
||||
|
@ -2292,9 +2333,12 @@ static int write_memory_progbuf(struct target *target, target_addr_t address,
|
|||
* is this read to abstractcs that will cause the dmi_busy_delay
|
||||
* to be incremented if necessary. */
|
||||
|
||||
uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS);
|
||||
uint32_t abstractcs;
|
||||
if (dmi_read(target, &abstractcs, DMI_ABSTRACTCS) != ERROR_OK)
|
||||
goto error;
|
||||
while (get_field(abstractcs, DMI_ABSTRACTCS_BUSY))
|
||||
abstractcs = dmi_read(target, DMI_ABSTRACTCS);
|
||||
if (dmi_read(target, &abstractcs, DMI_ABSTRACTCS) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
info->cmderr = get_field(abstractcs, DMI_ABSTRACTCS_CMDERR);
|
||||
switch (info->cmderr) {
|
||||
case CMDERR_NONE:
|
||||
|
@ -2440,7 +2484,8 @@ static void riscv013_select_current_hart(struct target *target)
|
|||
{
|
||||
RISCV_INFO(r);
|
||||
|
||||
uint64_t dmcontrol = dmi_read(target, DMI_DMCONTROL);
|
||||
uint32_t dmcontrol;
|
||||
dmi_read(target, &dmcontrol, DMI_DMCONTROL);
|
||||
dmcontrol = set_field(dmcontrol, hartsel_mask(target), r->current_hartid);
|
||||
dmi_write(target, DMI_DMCONTROL, dmcontrol);
|
||||
}
|
||||
|
@ -2453,7 +2498,9 @@ static int riscv013_halt_current_hart(struct target *target)
|
|||
LOG_ERROR("Hart %d is already halted!", r->current_hartid);
|
||||
|
||||
/* Issue the halt command, and then wait for the current hart to halt. */
|
||||
uint32_t dmcontrol = dmi_read(target, DMI_DMCONTROL);
|
||||
uint32_t dmcontrol;
|
||||
if (dmi_read(target, &dmcontrol, DMI_DMCONTROL) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
dmcontrol = set_field(dmcontrol, DMI_DMCONTROL_HALTREQ, 1);
|
||||
dmi_write(target, DMI_DMCONTROL, dmcontrol);
|
||||
for (size_t i = 0; i < 256; ++i)
|
||||
|
@ -2464,7 +2511,8 @@ static int riscv013_halt_current_hart(struct target *target)
|
|||
uint32_t dmstatus;
|
||||
if (dmstatus_read(target, &dmstatus, true) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
dmcontrol = dmi_read(target, DMI_DMCONTROL);
|
||||
if (dmi_read(target, &dmcontrol, DMI_DMCONTROL) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
|
||||
LOG_ERROR("unable to halt hart %d", r->current_hartid);
|
||||
LOG_ERROR(" dmcontrol=0x%08x", dmcontrol);
|
||||
|
@ -2546,7 +2594,9 @@ int riscv013_write_debug_buffer(struct target *target, unsigned index, riscv_ins
|
|||
|
||||
riscv_insn_t riscv013_read_debug_buffer(struct target *target, unsigned index)
|
||||
{
|
||||
return dmi_read(target, DMI_PROGBUF0 + index);
|
||||
uint32_t value;
|
||||
dmi_read(target, &value, DMI_PROGBUF0 + index);
|
||||
return value;
|
||||
}
|
||||
|
||||
int riscv013_execute_debug_buffer(struct target *target)
|
||||
|
@ -2638,7 +2688,9 @@ static int riscv013_step_or_resume_current_hart(struct target *target, bool step
|
|||
return ERROR_FAIL;
|
||||
|
||||
/* Issue the resume command, and then wait for the current hart to resume. */
|
||||
uint32_t dmcontrol = dmi_read(target, DMI_DMCONTROL);
|
||||
uint32_t dmcontrol;
|
||||
if (dmi_read(target, &dmcontrol, DMI_DMCONTROL) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
dmcontrol = set_field(dmcontrol, DMI_DMCONTROL_RESUMEREQ, 1);
|
||||
dmi_write(target, DMI_DMCONTROL, dmcontrol);
|
||||
|
||||
|
@ -2659,7 +2711,8 @@ static int riscv013_step_or_resume_current_hart(struct target *target, bool step
|
|||
|
||||
if (dmstatus_read(target, &dmstatus, true) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
dmcontrol = dmi_read(target, DMI_DMCONTROL);
|
||||
if (dmi_read(target, &dmcontrol, DMI_DMCONTROL) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
LOG_ERROR("unable to resume hart %d", r->current_hartid);
|
||||
LOG_ERROR(" dmcontrol=0x%08x", dmcontrol);
|
||||
LOG_ERROR(" dmstatus =0x%08x", dmstatus);
|
||||
|
@ -2677,9 +2730,10 @@ void riscv013_clear_abstract_error(struct target *target)
|
|||
{
|
||||
/* Wait for busy to go away. */
|
||||
time_t start = time(NULL);
|
||||
uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS);
|
||||
uint32_t abstractcs;
|
||||
dmi_read(target, &abstractcs, DMI_ABSTRACTCS);
|
||||
while (get_field(abstractcs, DMI_ABSTRACTCS_BUSY)) {
|
||||
abstractcs = dmi_read(target, DMI_ABSTRACTCS);
|
||||
dmi_read(target, &abstractcs, DMI_ABSTRACTCS);
|
||||
|
||||
if (time(NULL) - start > riscv_command_timeout_sec) {
|
||||
LOG_ERROR("abstractcs.busy is not going low after %d seconds "
|
||||
|
|
|
@ -1361,6 +1361,61 @@ COMMAND_HANDLER(riscv_authdata_write)
|
|||
}
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(riscv_dmi_read)
|
||||
{
|
||||
if (CMD_ARGC != 1) {
|
||||
LOG_ERROR("Command takes 1 parameter");
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
struct target *target = get_current_target(CMD_CTX);
|
||||
if (!target) {
|
||||
LOG_ERROR("target is NULL!");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
RISCV_INFO(r);
|
||||
if (!r) {
|
||||
LOG_ERROR("riscv_info is NULL!");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (r->dmi_read) {
|
||||
uint32_t address, value;
|
||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
|
||||
if (r->dmi_read(target, &value, address) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
command_print(CMD_CTX, "0x%" PRIx32, value);
|
||||
return ERROR_OK;
|
||||
} else {
|
||||
LOG_ERROR("dmi_read is not implemented for this target.");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
COMMAND_HANDLER(riscv_dmi_write)
|
||||
{
|
||||
if (CMD_ARGC != 2) {
|
||||
LOG_ERROR("Command takes exactly 2 arguments");
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
struct target *target = get_current_target(CMD_CTX);
|
||||
RISCV_INFO(r);
|
||||
|
||||
uint32_t address, value;
|
||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
|
||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
|
||||
|
||||
if (r->dmi_write) {
|
||||
return r->dmi_write(target, address, value);
|
||||
} else {
|
||||
LOG_ERROR("dmi_write is not implemented for this target.");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct command_registration riscv_exec_command_handlers[] = {
|
||||
{
|
||||
.name = "set_command_timeout_sec",
|
||||
|
@ -1406,6 +1461,20 @@ static const struct command_registration riscv_exec_command_handlers[] = {
|
|||
.usage = "riscv authdata_write value",
|
||||
.help = "Write the 32-bit value to authdata."
|
||||
},
|
||||
{
|
||||
.name = "dmi_read",
|
||||
.handler = riscv_dmi_read,
|
||||
.mode = COMMAND_ANY,
|
||||
.usage = "riscv dmi_read address",
|
||||
.help = "Perform a 32-bit DMI read at address, returning the value."
|
||||
},
|
||||
{
|
||||
.name = "dmi_write",
|
||||
.handler = riscv_dmi_write,
|
||||
.mode = COMMAND_ANY,
|
||||
.usage = "riscv dmi_write address value",
|
||||
.help = "Perform a 32-bit DMI write of value at address."
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
|
|
|
@ -113,6 +113,9 @@ typedef struct {
|
|||
|
||||
int (*authdata_read)(struct target *target, uint32_t *value);
|
||||
int (*authdata_write)(struct target *target, uint32_t value);
|
||||
|
||||
int (*dmi_read)(struct target *target, uint32_t *value, uint32_t address);
|
||||
int (*dmi_write)(struct target *target, uint32_t address, uint32_t value);
|
||||
} riscv_info_t;
|
||||
|
||||
/* Wall-clock timeout for a command/access. Settable via RISC-V Target commands.*/
|
||||
|
|
Loading…
Reference in New Issue