target/riscv: Add support for external triggers
Add support for associating a halt group with an external trigger via a newly exposed configuration option "riscv set_external_trigger". Change-Id: If10c67d2e14d8bc7cd6d59011b3215fda4ff4b02 Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
This commit is contained in:
parent
eb1ecd7d10
commit
cfd4dc2b0a
|
@ -11476,6 +11476,11 @@ The second argument configures how OpenOCD should use the selected trigger featu
|
|||
With no parameters, prints current trigger features configuration.
|
||||
@end deffn
|
||||
|
||||
@deffn {Command} {riscv set_external_trigger} value
|
||||
Associate the supplied external trigger with the halt group for the harts. When
|
||||
the external trigger fires the harts in the halt group will be halted.
|
||||
@end deffn
|
||||
|
||||
@subsection RISC-V Authentication Commands
|
||||
|
||||
The following commands can be used to authenticate to a RISC-V system. Eg. a
|
||||
|
|
|
@ -1703,6 +1703,32 @@ static void deinit_target(struct target *target)
|
|||
info->version_specific = NULL;
|
||||
}
|
||||
|
||||
static int set_external_trigger(struct target *target, unsigned int group,
|
||||
grouptype_t grouptype, unsigned int external_trigger)
|
||||
{
|
||||
uint32_t write_val = DM_DMCS2_HGWRITE | DM_DMCS2_HGSELECT;
|
||||
assert(group <= 31);
|
||||
assert(external_trigger < 16);
|
||||
write_val = set_field(write_val, DM_DMCS2_GROUP, group);
|
||||
write_val = set_field(write_val, DM_DMCS2_GROUPTYPE, (grouptype == HALT_GROUP) ? 0 : 1);
|
||||
write_val = set_field(write_val, DM_DMCS2_DMEXTTRIGGER, external_trigger);
|
||||
if (dm_write(target, DM_DMCS2, write_val) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
uint32_t read_val;
|
||||
if (dm_read(target, &read_val, DM_DMCS2) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
if (get_field(read_val, DM_DMCS2_GROUP) == group &&
|
||||
get_field(read_val, DM_DMCS2_DMEXTTRIGGER) == external_trigger &&
|
||||
get_field(read_val, DM_DMCS2_HGSELECT) == 1) {
|
||||
LOG_TARGET_INFO(target, "External trigger %d added to group %d", external_trigger,
|
||||
group);
|
||||
} else {
|
||||
LOG_TARGET_ERROR(target, "External trigger %d not supported", external_trigger);
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int set_group(struct target *target, bool *supported, unsigned int group,
|
||||
grouptype_t grouptype)
|
||||
{
|
||||
|
@ -2051,6 +2077,9 @@ static int examine(struct target *target)
|
|||
else
|
||||
LOG_TARGET_INFO(target, "Core %d could not be made part of halt group %d.",
|
||||
info->index, target->smp);
|
||||
if (r->external_trigger)
|
||||
if (set_external_trigger(target, target->smp, HALT_GROUP, r->external_trigger) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
/* Some regression suites rely on seeing 'Examined RISC-V core' to know
|
||||
|
|
|
@ -5262,6 +5262,26 @@ COMMAND_HANDLER(handle_riscv_virt2phys_mode)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(riscv_set_external_trigger)
|
||||
{
|
||||
struct target *target = get_current_target(CMD_CTX);
|
||||
RISCV_INFO(r);
|
||||
|
||||
if (CMD_ARGC != 1) {
|
||||
LOG_ERROR("Command takes exactly 1 parameter.");
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
int value = atoi(CMD_ARGV[0]);
|
||||
if (value <= 0 || value > 16) {
|
||||
LOG_ERROR("%s is not a valid integer argument for command.", CMD_ARGV[0]);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
r->external_trigger = value;
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static const struct command_registration riscv_exec_command_handlers[] = {
|
||||
{
|
||||
.name = "dump_sample_buf",
|
||||
|
@ -5524,6 +5544,13 @@ static const struct command_registration riscv_exec_command_handlers[] = {
|
|||
"When off, users need to take care of memory coherency themselves, for example by using "
|
||||
"`riscv exec_progbuf` to execute fence or CMO instructions."
|
||||
},
|
||||
{
|
||||
.name = "set_external_trigger",
|
||||
.handler = riscv_set_external_trigger,
|
||||
.mode = COMMAND_CONFIG,
|
||||
.usage = "value",
|
||||
.help = "Add the given external trigger to the halt group"
|
||||
},
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
|
|
|
@ -191,6 +191,9 @@ struct riscv_info {
|
|||
/* The configured approach to translate virtual addresses to physical */
|
||||
riscv_virt2phys_mode_t virt2phys_mode;
|
||||
|
||||
/* Halt group may be associated with an external trigger */
|
||||
unsigned int external_trigger;
|
||||
|
||||
bool triggers_enumerated;
|
||||
|
||||
/* Decremented every scan, and when it reaches 0 we clear the learned
|
||||
|
|
Loading…
Reference in New Issue