arm_cti: add cti command group
Extend the CTI abstraction to be accessible from TCL and change the 'target' command to accept a cti 'object' instead of a base address. This also allows accessing CTI instances that are not related to a configured target. Change-Id: Iac9ed0edca6f1be00fe93783a35c26077f6bc80a Signed-off-by: Matthias Welwarsky <matthias.welwarsky@sysgo.com> Reviewed-on: http://openocd.zylin.com/4031 Tested-by: jenkins Reviewed-by: Matthias Welwarsky <matthias@welwarsky.de>riscv-compliance-dev
parent
1756f393e4
commit
f444c57bf2
|
@ -4290,9 +4290,11 @@ access the target for debugging.
|
||||||
Use this option with systems where multiple, independent cores are connected
|
Use this option with systems where multiple, independent cores are connected
|
||||||
to separate access ports of the same DAP.
|
to separate access ports of the same DAP.
|
||||||
|
|
||||||
@item @code{-ctibase} @var{address} -- set base address of Cross-Trigger interface (CTI) connected
|
@item @code{-cti} @var{cti_name} -- set Cross-Trigger Interface (CTI) connected
|
||||||
to the target. Currently, only the @code{aarch64} target makes use of this option, where it is
|
to the target. Currently, only the @code{aarch64} target makes use of this option,
|
||||||
a mandatory configuration for the target run control.
|
where it is a mandatory configuration for the target run control.
|
||||||
|
@xref{armcrosstrigger,,ARM Cross-Trigger Interface},
|
||||||
|
for instruction on how to declare and control a CTI instance.
|
||||||
@end itemize
|
@end itemize
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
@ -7781,6 +7783,50 @@ Reports whether the capture clock is locked or not.
|
||||||
@end deffn
|
@end deffn
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
@anchor{armcrosstrigger}
|
||||||
|
@section ARM Cross-Trigger Interface
|
||||||
|
@cindex CTI
|
||||||
|
|
||||||
|
The ARM Cross-Trigger Interface (CTI) is a generic CoreSight component
|
||||||
|
that connects event sources like tracing components or CPU cores with each
|
||||||
|
other through a common trigger matrix (CTM). For ARMv8 architecture, a
|
||||||
|
CTI is mandatory for core run control and each core has an individual
|
||||||
|
CTI instance attached to it. OpenOCD has limited support for CTI using
|
||||||
|
the @emph{cti} group of commands.
|
||||||
|
|
||||||
|
@deffn Command {cti create} @var{cti_name} -chain-position @var{tap_name} -ap-num @var{apn} -ctibase @var{base_address}
|
||||||
|
Creates a CTI object @var{cti_name} on the JTAG tap @var{tap_name} on MEM-AP
|
||||||
|
@var{apn} of the DAP reachable through @var{tap}. The @var{base_address} must match
|
||||||
|
the base address of the CTI on the respective MEM-AP. All arguments are
|
||||||
|
mandatory. This creates a new command (@command{@var{cti_name}}) which
|
||||||
|
is used for various purposes including additional configuration.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn Command {$cti_name enable} @option{on|off}
|
||||||
|
Enable (@option{on}) or disable (@option{off}) the CTI.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn Command {$cti_name dump}
|
||||||
|
Displays a register dump of the CTI.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn Command {$cti_name write } @var{reg_name} @var{value}
|
||||||
|
Write @var{value} to the CTI register with the symbolic name @var{reg_name}.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn Command {$cti_name read} @var{reg_name}
|
||||||
|
Print the value read from the CTI register with the symbolic name @var{reg_name}.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn Command {$cti_name testmode} @option{on|off}
|
||||||
|
Enable (@option{on}) or disable (@option{off}) the integration test mode
|
||||||
|
of the CTI.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn Command {cti names}
|
||||||
|
Prints a list of names of all CTI objects created. This command is mainly
|
||||||
|
useful in TCL scripting.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
@section Generic ARM
|
@section Generic ARM
|
||||||
@cindex ARM
|
@cindex ARM
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include <flash/nand/core.h>
|
#include <flash/nand/core.h>
|
||||||
#include <pld/pld.h>
|
#include <pld/pld.h>
|
||||||
#include <flash/mflash.h>
|
#include <flash/mflash.h>
|
||||||
|
#include <target/arm_cti.h>
|
||||||
|
|
||||||
#include <server/server.h>
|
#include <server/server.h>
|
||||||
#include <server/gdb_server.h>
|
#include <server/gdb_server.h>
|
||||||
|
@ -252,6 +253,7 @@ struct command_context *setup_command_handler(Jim_Interp *interp)
|
||||||
&nand_register_commands,
|
&nand_register_commands,
|
||||||
&pld_register_commands,
|
&pld_register_commands,
|
||||||
&mflash_register_commands,
|
&mflash_register_commands,
|
||||||
|
&cti_register_commands,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
for (unsigned i = 0; NULL != command_registrants[i]; i++) {
|
for (unsigned i = 0; NULL != command_registrants[i]; i++) {
|
||||||
|
|
|
@ -40,6 +40,10 @@ enum halt_mode {
|
||||||
HALT_SYNC,
|
HALT_SYNC,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct aarch64_private_config {
|
||||||
|
struct arm_cti *cti;
|
||||||
|
};
|
||||||
|
|
||||||
static int aarch64_poll(struct target *target);
|
static int aarch64_poll(struct target *target);
|
||||||
static int aarch64_debug_entry(struct target *target);
|
static int aarch64_debug_entry(struct target *target);
|
||||||
static int aarch64_restore_context(struct target *target, bool bpwp);
|
static int aarch64_restore_context(struct target *target, bool bpwp);
|
||||||
|
@ -2198,7 +2202,7 @@ static int aarch64_examine_first(struct target *target)
|
||||||
struct aarch64_common *aarch64 = target_to_aarch64(target);
|
struct aarch64_common *aarch64 = target_to_aarch64(target);
|
||||||
struct armv8_common *armv8 = &aarch64->armv8_common;
|
struct armv8_common *armv8 = &aarch64->armv8_common;
|
||||||
struct adiv5_dap *swjdp = armv8->arm.dap;
|
struct adiv5_dap *swjdp = armv8->arm.dap;
|
||||||
uint32_t cti_base;
|
struct aarch64_private_config *pc;
|
||||||
int i;
|
int i;
|
||||||
int retval = ERROR_OK;
|
int retval = ERROR_OK;
|
||||||
uint64_t debug, ttypr;
|
uint64_t debug, ttypr;
|
||||||
|
@ -2289,17 +2293,15 @@ static int aarch64_examine_first(struct target *target)
|
||||||
LOG_DEBUG("ttypr = 0x%08" PRIx64, ttypr);
|
LOG_DEBUG("ttypr = 0x%08" PRIx64, ttypr);
|
||||||
LOG_DEBUG("debug = 0x%08" PRIx64, debug);
|
LOG_DEBUG("debug = 0x%08" PRIx64, debug);
|
||||||
|
|
||||||
if (target->ctibase == 0) {
|
if (target->private_config == NULL)
|
||||||
/* assume a v8 rom table layout */
|
|
||||||
cti_base = armv8->debug_base + 0x10000;
|
|
||||||
LOG_INFO("Target ctibase is not set, assuming 0x%0" PRIx32, cti_base);
|
|
||||||
} else
|
|
||||||
cti_base = target->ctibase;
|
|
||||||
|
|
||||||
armv8->cti = arm_cti_create(armv8->debug_ap, cti_base);
|
|
||||||
if (armv8->cti == NULL)
|
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
pc = (struct aarch64_private_config *)target->private_config;
|
||||||
|
if (pc->cti == NULL)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
armv8->cti = pc->cti;
|
||||||
|
|
||||||
retval = aarch64_dpm_setup(aarch64, debug);
|
retval = aarch64_dpm_setup(aarch64, debug);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -2405,6 +2407,63 @@ static int aarch64_virt2phys(struct target *target, target_addr_t virt,
|
||||||
return armv8_mmu_translate_va_pa(target, virt, phys, 1);
|
return armv8_mmu_translate_va_pa(target, virt, phys, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int aarch64_jim_configure(struct target *target, Jim_GetOptInfo *goi)
|
||||||
|
{
|
||||||
|
struct aarch64_private_config *pc;
|
||||||
|
const char *arg;
|
||||||
|
int e;
|
||||||
|
|
||||||
|
/* check if argv[0] is for us */
|
||||||
|
arg = Jim_GetString(goi->argv[0], NULL);
|
||||||
|
if (strcmp(arg, "-cti"))
|
||||||
|
return JIM_CONTINUE;
|
||||||
|
|
||||||
|
/* pop the argument from argv */
|
||||||
|
e = Jim_GetOpt_String(goi, &arg, NULL);
|
||||||
|
if (e != JIM_OK)
|
||||||
|
return e;
|
||||||
|
|
||||||
|
/* check if we have another option */
|
||||||
|
if (goi->argc == 0) {
|
||||||
|
Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-cti ?cti-name?");
|
||||||
|
return JIM_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
pc = (struct aarch64_private_config *)target->private_config;
|
||||||
|
|
||||||
|
if (goi->isconfigure) {
|
||||||
|
Jim_Obj *o_cti;
|
||||||
|
struct arm_cti *cti;
|
||||||
|
e = Jim_GetOpt_Obj(goi, &o_cti);
|
||||||
|
if (e != JIM_OK)
|
||||||
|
return e;
|
||||||
|
cti = cti_instance_by_jim_obj(goi->interp, o_cti);
|
||||||
|
if (cti == NULL)
|
||||||
|
return JIM_ERR;
|
||||||
|
|
||||||
|
if (pc == NULL) {
|
||||||
|
pc = calloc(1, sizeof(struct aarch64_private_config));
|
||||||
|
target->private_config = pc;
|
||||||
|
}
|
||||||
|
pc->cti = cti;
|
||||||
|
} else {
|
||||||
|
if (goi->argc != 0) {
|
||||||
|
Jim_WrongNumArgs(goi->interp,
|
||||||
|
goi->argc, goi->argv,
|
||||||
|
"NO PARAMS");
|
||||||
|
return JIM_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pc == NULL || pc->cti == NULL) {
|
||||||
|
Jim_SetResultString(goi->interp, "CTI not configured", -1);
|
||||||
|
return JIM_ERR;
|
||||||
|
}
|
||||||
|
Jim_SetResultString(goi->interp, arm_cti_name(pc->cti), -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return JIM_OK;
|
||||||
|
}
|
||||||
|
|
||||||
COMMAND_HANDLER(aarch64_handle_cache_info_command)
|
COMMAND_HANDLER(aarch64_handle_cache_info_command)
|
||||||
{
|
{
|
||||||
struct target *target = get_current_target(CMD_CTX);
|
struct target *target = get_current_target(CMD_CTX);
|
||||||
|
@ -2570,6 +2629,7 @@ struct target_type aarch64_target = {
|
||||||
|
|
||||||
.commands = aarch64_command_handlers,
|
.commands = aarch64_command_handlers,
|
||||||
.target_create = aarch64_target_create,
|
.target_create = aarch64_target_create,
|
||||||
|
.target_jim_configure = aarch64_jim_configure,
|
||||||
.init_target = aarch64_init_target,
|
.init_target = aarch64_init_target,
|
||||||
.examine = aarch64_examine,
|
.examine = aarch64_examine,
|
||||||
|
|
||||||
|
|
|
@ -27,21 +27,47 @@
|
||||||
#include "target/arm_cti.h"
|
#include "target/arm_cti.h"
|
||||||
#include "target/target.h"
|
#include "target/target.h"
|
||||||
#include "helper/time_support.h"
|
#include "helper/time_support.h"
|
||||||
|
#include "helper/list.h"
|
||||||
|
#include "helper/command.h"
|
||||||
|
|
||||||
struct arm_cti {
|
struct arm_cti {
|
||||||
uint32_t base;
|
target_addr_t base;
|
||||||
struct adiv5_ap *ap;
|
struct adiv5_ap *ap;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct arm_cti *arm_cti_create(struct adiv5_ap *ap, uint32_t base)
|
struct arm_cti_object {
|
||||||
{
|
struct list_head lh;
|
||||||
struct arm_cti *self = calloc(1, sizeof(struct arm_cti));
|
struct arm_cti cti;
|
||||||
if (!self)
|
int ap_num;
|
||||||
return NULL;
|
char *name;
|
||||||
|
};
|
||||||
|
|
||||||
self->base = base;
|
static LIST_HEAD(all_cti);
|
||||||
self->ap = ap;
|
|
||||||
return self;
|
const char *arm_cti_name(struct arm_cti *self)
|
||||||
|
{
|
||||||
|
struct arm_cti_object *obj = container_of(self, struct arm_cti_object, cti);
|
||||||
|
return obj->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct arm_cti *cti_instance_by_jim_obj(Jim_Interp *interp, Jim_Obj *o)
|
||||||
|
{
|
||||||
|
struct arm_cti_object *obj = NULL;
|
||||||
|
const char *name;
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
name = Jim_GetString(o, NULL);
|
||||||
|
|
||||||
|
list_for_each_entry(obj, &all_cti, lh) {
|
||||||
|
if (!strcmp(name, obj->name)) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found)
|
||||||
|
return &obj->cti;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int arm_cti_mod_reg_bits(struct arm_cti *self, unsigned int reg, uint32_t mask, uint32_t value)
|
static int arm_cti_mod_reg_bits(struct arm_cti *self, unsigned int reg, uint32_t mask, uint32_t value)
|
||||||
|
@ -146,3 +172,404 @@ int arm_cti_clear_channel(struct arm_cti *self, uint32_t channel)
|
||||||
|
|
||||||
return arm_cti_write_reg(self, CTI_APPCLEAR, CTI_CHNL(channel));
|
return arm_cti_write_reg(self, CTI_APPCLEAR, CTI_CHNL(channel));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t cti_regs[26];
|
||||||
|
|
||||||
|
static const struct {
|
||||||
|
uint32_t offset;
|
||||||
|
const char *label;
|
||||||
|
uint32_t *p_val;
|
||||||
|
} cti_names[] = {
|
||||||
|
{ CTI_CTR, "CTR", &cti_regs[0] },
|
||||||
|
{ CTI_GATE, "GATE", &cti_regs[1] },
|
||||||
|
{ CTI_INEN0, "INEN0", &cti_regs[2] },
|
||||||
|
{ CTI_INEN1, "INEN1", &cti_regs[3] },
|
||||||
|
{ CTI_INEN2, "INEN2", &cti_regs[4] },
|
||||||
|
{ CTI_INEN3, "INEN3", &cti_regs[5] },
|
||||||
|
{ CTI_INEN4, "INEN4", &cti_regs[6] },
|
||||||
|
{ CTI_INEN5, "INEN5", &cti_regs[7] },
|
||||||
|
{ CTI_INEN6, "INEN6", &cti_regs[8] },
|
||||||
|
{ CTI_INEN7, "INEN7", &cti_regs[9] },
|
||||||
|
{ CTI_INEN8, "INEN8", &cti_regs[10] },
|
||||||
|
{ CTI_OUTEN0, "OUTEN0", &cti_regs[11] },
|
||||||
|
{ CTI_OUTEN1, "OUTEN1", &cti_regs[12] },
|
||||||
|
{ CTI_OUTEN2, "OUTEN2", &cti_regs[13] },
|
||||||
|
{ CTI_OUTEN3, "OUTEN3", &cti_regs[14] },
|
||||||
|
{ CTI_OUTEN4, "OUTEN4", &cti_regs[15] },
|
||||||
|
{ CTI_OUTEN5, "OUTEN5", &cti_regs[16] },
|
||||||
|
{ CTI_OUTEN6, "OUTEN6", &cti_regs[17] },
|
||||||
|
{ CTI_OUTEN7, "OUTEN7", &cti_regs[18] },
|
||||||
|
{ CTI_OUTEN8, "OUTEN8", &cti_regs[19] },
|
||||||
|
{ CTI_TRIN_STATUS, "TRIN", &cti_regs[20] },
|
||||||
|
{ CTI_TROUT_STATUS, "TROUT", &cti_regs[21] },
|
||||||
|
{ CTI_CHIN_STATUS, "CHIN", &cti_regs[22] },
|
||||||
|
{ CTI_CHOU_STATUS, "CHOUT", &cti_regs[23] },
|
||||||
|
{ CTI_APPSET, "APPSET", &cti_regs[24] },
|
||||||
|
{ CTI_APPCLEAR, "APPCLR", &cti_regs[25] },
|
||||||
|
};
|
||||||
|
|
||||||
|
static int cti_find_reg_offset(const char *name)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(cti_names); i++) {
|
||||||
|
if (!strcmp(name, cti_names[i].label))
|
||||||
|
return cti_names[i].offset;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
COMMAND_HANDLER(handle_cti_dump)
|
||||||
|
{
|
||||||
|
struct arm_cti_object *obj = CMD_DATA;
|
||||||
|
struct arm_cti *cti = &obj->cti;
|
||||||
|
int retval = ERROR_OK;
|
||||||
|
|
||||||
|
for (int i = 0; (retval == ERROR_OK) && (i < (int)ARRAY_SIZE(cti_names)); i++)
|
||||||
|
retval = mem_ap_read_u32(cti->ap,
|
||||||
|
cti->base + cti_names[i].offset, cti_names[i].p_val);
|
||||||
|
|
||||||
|
if (retval == ERROR_OK)
|
||||||
|
retval = dap_run(cti->ap->dap);
|
||||||
|
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return JIM_ERR;
|
||||||
|
|
||||||
|
for (int i = 0; i < (int)ARRAY_SIZE(cti_names); i++)
|
||||||
|
command_print(CMD_CTX, "%8.8s (0x%04"PRIx32") 0x%08"PRIx32,
|
||||||
|
cti_names[i].label, cti_names[i].offset, *cti_names[i].p_val);
|
||||||
|
|
||||||
|
return JIM_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
COMMAND_HANDLER(handle_cti_enable)
|
||||||
|
{
|
||||||
|
struct arm_cti_object *obj = CMD_DATA;
|
||||||
|
Jim_Interp *interp = CMD_CTX->interp;
|
||||||
|
struct arm_cti *cti = &obj->cti;
|
||||||
|
bool on_off;
|
||||||
|
|
||||||
|
if (CMD_ARGC != 1) {
|
||||||
|
Jim_SetResultString(interp, "wrong number of args", -1);
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
COMMAND_PARSE_ON_OFF(CMD_ARGV[0], on_off);
|
||||||
|
|
||||||
|
return arm_cti_enable(cti, on_off);
|
||||||
|
}
|
||||||
|
|
||||||
|
COMMAND_HANDLER(handle_cti_testmode)
|
||||||
|
{
|
||||||
|
struct arm_cti_object *obj = CMD_DATA;
|
||||||
|
Jim_Interp *interp = CMD_CTX->interp;
|
||||||
|
struct arm_cti *cti = &obj->cti;
|
||||||
|
bool on_off;
|
||||||
|
|
||||||
|
if (CMD_ARGC != 1) {
|
||||||
|
Jim_SetResultString(interp, "wrong number of args", -1);
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
COMMAND_PARSE_ON_OFF(CMD_ARGV[0], on_off);
|
||||||
|
|
||||||
|
return arm_cti_write_reg(cti, 0xf00, on_off ? 0x1 : 0x0);
|
||||||
|
}
|
||||||
|
|
||||||
|
COMMAND_HANDLER(handle_cti_write)
|
||||||
|
{
|
||||||
|
struct arm_cti_object *obj = CMD_DATA;
|
||||||
|
Jim_Interp *interp = CMD_CTX->interp;
|
||||||
|
struct arm_cti *cti = &obj->cti;
|
||||||
|
int offset;
|
||||||
|
uint32_t value;
|
||||||
|
|
||||||
|
if (CMD_ARGC != 2) {
|
||||||
|
Jim_SetResultString(interp, "Wrong numer of args", -1);
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = cti_find_reg_offset(CMD_ARGV[0]);
|
||||||
|
if (offset < 0)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
|
||||||
|
|
||||||
|
return arm_cti_write_reg(cti, offset, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
COMMAND_HANDLER(handle_cti_read)
|
||||||
|
{
|
||||||
|
struct arm_cti_object *obj = CMD_DATA;
|
||||||
|
Jim_Interp *interp = CMD_CTX->interp;
|
||||||
|
struct arm_cti *cti = &obj->cti;
|
||||||
|
int offset;
|
||||||
|
int retval;
|
||||||
|
uint32_t value;
|
||||||
|
|
||||||
|
if (CMD_ARGC != 1) {
|
||||||
|
Jim_SetResultString(interp, "Wrong numer of args", -1);
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = cti_find_reg_offset(CMD_ARGV[0]);
|
||||||
|
if (offset < 0)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
retval = arm_cti_read_reg(cti, offset, &value);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
command_print(CMD_CTX, "0x%08"PRIx32, value);
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct command_registration cti_instance_command_handlers[] = {
|
||||||
|
{
|
||||||
|
.name = "dump",
|
||||||
|
.mode = COMMAND_EXEC,
|
||||||
|
.handler = handle_cti_dump,
|
||||||
|
.help = "dump CTI registers",
|
||||||
|
.usage = "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "enable",
|
||||||
|
.mode = COMMAND_EXEC,
|
||||||
|
.handler = handle_cti_enable,
|
||||||
|
.help = "enable or disable the CTI",
|
||||||
|
.usage = "'on'|'off'",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "testmode",
|
||||||
|
.mode = COMMAND_EXEC,
|
||||||
|
.handler = handle_cti_testmode,
|
||||||
|
.help = "enable or disable integration test mode",
|
||||||
|
.usage = "'on'|'off'",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "write",
|
||||||
|
.mode = COMMAND_EXEC,
|
||||||
|
.handler = handle_cti_write,
|
||||||
|
.help = "write to a CTI register",
|
||||||
|
.usage = "register_name value",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "read",
|
||||||
|
.mode = COMMAND_EXEC,
|
||||||
|
.handler = handle_cti_read,
|
||||||
|
.help = "read a CTI register",
|
||||||
|
.usage = "register_name",
|
||||||
|
},
|
||||||
|
COMMAND_REGISTRATION_DONE
|
||||||
|
};
|
||||||
|
|
||||||
|
enum cti_cfg_param {
|
||||||
|
CFG_CHAIN_POSITION,
|
||||||
|
CFG_AP_NUM,
|
||||||
|
CFG_CTIBASE
|
||||||
|
};
|
||||||
|
|
||||||
|
static const Jim_Nvp nvp_config_opts[] = {
|
||||||
|
{ .name = "-chain-position", .value = CFG_CHAIN_POSITION },
|
||||||
|
{ .name = "-ctibase", .value = CFG_CTIBASE },
|
||||||
|
{ .name = "-ap-num", .value = CFG_AP_NUM },
|
||||||
|
{ .name = NULL, .value = -1 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static int cti_configure(Jim_GetOptInfo *goi, struct arm_cti_object *cti)
|
||||||
|
{
|
||||||
|
struct jtag_tap *tap = NULL;
|
||||||
|
struct adiv5_dap *dap;
|
||||||
|
Jim_Nvp *n;
|
||||||
|
jim_wide w;
|
||||||
|
int e;
|
||||||
|
|
||||||
|
/* parse config or cget options ... */
|
||||||
|
while (goi->argc > 0) {
|
||||||
|
Jim_SetEmptyResult(goi->interp);
|
||||||
|
|
||||||
|
e = Jim_GetOpt_Nvp(goi, nvp_config_opts, &n);
|
||||||
|
if (e != JIM_OK) {
|
||||||
|
Jim_GetOpt_NvpUnknown(goi, nvp_config_opts, 0);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
switch (n->value) {
|
||||||
|
case CFG_CHAIN_POSITION: {
|
||||||
|
Jim_Obj *o_t;
|
||||||
|
e = Jim_GetOpt_Obj(goi, &o_t);
|
||||||
|
if (e != JIM_OK)
|
||||||
|
return e;
|
||||||
|
tap = jtag_tap_by_jim_obj(goi->interp, o_t);
|
||||||
|
if (tap == NULL) {
|
||||||
|
Jim_SetResultString(goi->interp, "-chain-position is invalid", -1);
|
||||||
|
return JIM_ERR;
|
||||||
|
}
|
||||||
|
/* loop for more */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CFG_CTIBASE:
|
||||||
|
e = Jim_GetOpt_Wide(goi, &w);
|
||||||
|
if (e != JIM_OK)
|
||||||
|
return e;
|
||||||
|
cti->cti.base = (uint32_t)w;
|
||||||
|
/* loop for more */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CFG_AP_NUM:
|
||||||
|
e = Jim_GetOpt_Wide(goi, &w);
|
||||||
|
if (e != JIM_OK)
|
||||||
|
return e;
|
||||||
|
cti->ap_num = (uint32_t)w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tap == NULL) {
|
||||||
|
Jim_SetResultString(goi->interp, "-chain-position required when creating CTI", -1);
|
||||||
|
return JIM_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tap->dap == NULL) {
|
||||||
|
dap = dap_init();
|
||||||
|
dap->tap = tap;
|
||||||
|
tap->dap = dap;
|
||||||
|
} else
|
||||||
|
dap = tap->dap;
|
||||||
|
|
||||||
|
cti->cti.ap = dap_ap(dap, cti->ap_num);
|
||||||
|
|
||||||
|
return JIM_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cti_create(Jim_GetOptInfo *goi)
|
||||||
|
{
|
||||||
|
struct command_context *cmd_ctx;
|
||||||
|
static struct arm_cti_object *cti;
|
||||||
|
Jim_Obj *new_cmd;
|
||||||
|
Jim_Cmd *cmd;
|
||||||
|
const char *cp;
|
||||||
|
int e;
|
||||||
|
|
||||||
|
cmd_ctx = current_command_context(goi->interp);
|
||||||
|
assert(cmd_ctx != NULL);
|
||||||
|
|
||||||
|
if (goi->argc < 3) {
|
||||||
|
Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ..options...");
|
||||||
|
return JIM_ERR;
|
||||||
|
}
|
||||||
|
/* COMMAND */
|
||||||
|
Jim_GetOpt_Obj(goi, &new_cmd);
|
||||||
|
/* does this command exist? */
|
||||||
|
cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_ERRMSG);
|
||||||
|
if (cmd) {
|
||||||
|
cp = Jim_GetString(new_cmd, NULL);
|
||||||
|
Jim_SetResultFormatted(goi->interp, "Command: %s Exists", cp);
|
||||||
|
return JIM_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create it */
|
||||||
|
cti = calloc(1, sizeof(struct arm_cti_object));
|
||||||
|
if (cti == NULL)
|
||||||
|
return JIM_ERR;
|
||||||
|
|
||||||
|
e = cti_configure(goi, cti);
|
||||||
|
if (e != JIM_OK) {
|
||||||
|
free(cti);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
cp = Jim_GetString(new_cmd, NULL);
|
||||||
|
cti->name = strdup(cp);
|
||||||
|
|
||||||
|
/* now - create the new cti name command */
|
||||||
|
const struct command_registration cti_subcommands[] = {
|
||||||
|
{
|
||||||
|
.chain = cti_instance_command_handlers,
|
||||||
|
},
|
||||||
|
COMMAND_REGISTRATION_DONE
|
||||||
|
};
|
||||||
|
const struct command_registration cti_commands[] = {
|
||||||
|
{
|
||||||
|
.name = cp,
|
||||||
|
.mode = COMMAND_ANY,
|
||||||
|
.help = "cti instance command group",
|
||||||
|
.usage = "",
|
||||||
|
.chain = cti_subcommands,
|
||||||
|
},
|
||||||
|
COMMAND_REGISTRATION_DONE
|
||||||
|
};
|
||||||
|
e = register_commands(cmd_ctx, NULL, cti_commands);
|
||||||
|
if (ERROR_OK != e)
|
||||||
|
return JIM_ERR;
|
||||||
|
|
||||||
|
struct command *c = command_find_in_context(cmd_ctx, cp);
|
||||||
|
assert(c);
|
||||||
|
command_set_handler_data(c, cti);
|
||||||
|
|
||||||
|
list_add_tail(&cti->lh, &all_cti);
|
||||||
|
|
||||||
|
return (ERROR_OK == e) ? JIM_OK : JIM_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int jim_cti_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||||
|
{
|
||||||
|
Jim_GetOptInfo goi;
|
||||||
|
Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
|
||||||
|
if (goi.argc < 2) {
|
||||||
|
Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv,
|
||||||
|
"<name> [<cti_options> ...]");
|
||||||
|
return JIM_ERR;
|
||||||
|
}
|
||||||
|
return cti_create(&goi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int jim_cti_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||||
|
{
|
||||||
|
struct arm_cti_object *obj;
|
||||||
|
|
||||||
|
if (argc != 1) {
|
||||||
|
Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
|
||||||
|
return JIM_ERR;
|
||||||
|
}
|
||||||
|
Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
|
||||||
|
list_for_each_entry(obj, &all_cti, lh) {
|
||||||
|
Jim_ListAppendElement(interp, Jim_GetResult(interp),
|
||||||
|
Jim_NewStringObj(interp, obj->name, -1));
|
||||||
|
}
|
||||||
|
return JIM_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const struct command_registration cti_subcommand_handlers[] = {
|
||||||
|
{
|
||||||
|
.name = "create",
|
||||||
|
.mode = COMMAND_ANY,
|
||||||
|
.jim_handler = jim_cti_create,
|
||||||
|
.usage = "name '-chain-position' name [options ...]",
|
||||||
|
.help = "Creates a new CTI object",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "names",
|
||||||
|
.mode = COMMAND_ANY,
|
||||||
|
.jim_handler = jim_cti_names,
|
||||||
|
.usage = "",
|
||||||
|
.help = "Lists all registered CTI objects by name",
|
||||||
|
},
|
||||||
|
COMMAND_REGISTRATION_DONE
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct command_registration cti_command_handlers[] = {
|
||||||
|
{
|
||||||
|
.name = "cti",
|
||||||
|
.mode = COMMAND_CONFIG,
|
||||||
|
.help = "CTI commands",
|
||||||
|
.chain = cti_subcommand_handlers,
|
||||||
|
},
|
||||||
|
COMMAND_REGISTRATION_DONE
|
||||||
|
};
|
||||||
|
|
||||||
|
int cti_register_commands(struct command_context *cmd_ctx)
|
||||||
|
{
|
||||||
|
return register_commands(cmd_ctx, NULL, cti_command_handlers);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#define CTI_INEN5 0x34
|
#define CTI_INEN5 0x34
|
||||||
#define CTI_INEN6 0x38
|
#define CTI_INEN6 0x38
|
||||||
#define CTI_INEN7 0x3C
|
#define CTI_INEN7 0x3C
|
||||||
|
#define CTI_INEN8 0x40
|
||||||
#define CTI_INEN(n) (0x20 + 4 * n)
|
#define CTI_INEN(n) (0x20 + 4 * n)
|
||||||
#define CTI_OUTEN0 0xA0
|
#define CTI_OUTEN0 0xA0
|
||||||
#define CTI_OUTEN1 0xA4
|
#define CTI_OUTEN1 0xA4
|
||||||
|
@ -43,6 +44,7 @@
|
||||||
#define CTI_OUTEN5 0xB4
|
#define CTI_OUTEN5 0xB4
|
||||||
#define CTI_OUTEN6 0xB8
|
#define CTI_OUTEN6 0xB8
|
||||||
#define CTI_OUTEN7 0xBC
|
#define CTI_OUTEN7 0xBC
|
||||||
|
#define CTI_OUTEN8 0xC0
|
||||||
#define CTI_OUTEN(n) (0xA0 + 4 * n)
|
#define CTI_OUTEN(n) (0xA0 + 4 * n)
|
||||||
#define CTI_TRIN_STATUS 0x130
|
#define CTI_TRIN_STATUS 0x130
|
||||||
#define CTI_TROUT_STATUS 0x134
|
#define CTI_TROUT_STATUS 0x134
|
||||||
|
@ -58,8 +60,10 @@
|
||||||
|
|
||||||
/* forward-declare arm_cti struct */
|
/* forward-declare arm_cti struct */
|
||||||
struct arm_cti;
|
struct arm_cti;
|
||||||
|
struct adiv5_ap;
|
||||||
|
|
||||||
extern struct arm_cti *arm_cti_create(struct adiv5_ap *ap, uint32_t base);
|
extern const char *arm_cti_name(struct arm_cti *self);
|
||||||
|
extern struct arm_cti *cti_instance_by_jim_obj(Jim_Interp *interp, Jim_Obj *o);
|
||||||
extern int arm_cti_enable(struct arm_cti *self, bool enable);
|
extern int arm_cti_enable(struct arm_cti *self, bool enable);
|
||||||
extern int arm_cti_ack_events(struct arm_cti *self, uint32_t event);
|
extern int arm_cti_ack_events(struct arm_cti *self, uint32_t event);
|
||||||
extern int arm_cti_gate_channel(struct arm_cti *self, uint32_t channel);
|
extern int arm_cti_gate_channel(struct arm_cti *self, uint32_t channel);
|
||||||
|
@ -70,4 +74,6 @@ extern int arm_cti_pulse_channel(struct arm_cti *self, uint32_t channel);
|
||||||
extern int arm_cti_set_channel(struct arm_cti *self, uint32_t channel);
|
extern int arm_cti_set_channel(struct arm_cti *self, uint32_t channel);
|
||||||
extern int arm_cti_clear_channel(struct arm_cti *self, uint32_t channel);
|
extern int arm_cti_clear_channel(struct arm_cti *self, uint32_t channel);
|
||||||
|
|
||||||
|
extern int cti_register_commands(struct command_context *cmd_ctx);
|
||||||
|
|
||||||
#endif /* OPENOCD_TARGET_ARM_CTI_H */
|
#endif /* OPENOCD_TARGET_ARM_CTI_H */
|
||||||
|
|
|
@ -54,6 +54,7 @@
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
#include "rtos/rtos.h"
|
#include "rtos/rtos.h"
|
||||||
#include "transport/transport.h"
|
#include "transport/transport.h"
|
||||||
|
#include "arm_cti.h"
|
||||||
|
|
||||||
/* default halt wait timeout (ms) */
|
/* default halt wait timeout (ms) */
|
||||||
#define DEFAULT_HALT_TIMEOUT 5000
|
#define DEFAULT_HALT_TIMEOUT 5000
|
||||||
|
@ -4513,7 +4514,6 @@ enum target_cfg_param {
|
||||||
TCFG_COREID,
|
TCFG_COREID,
|
||||||
TCFG_CHAIN_POSITION,
|
TCFG_CHAIN_POSITION,
|
||||||
TCFG_DBGBASE,
|
TCFG_DBGBASE,
|
||||||
TCFG_CTIBASE,
|
|
||||||
TCFG_RTOS,
|
TCFG_RTOS,
|
||||||
TCFG_DEFER_EXAMINE,
|
TCFG_DEFER_EXAMINE,
|
||||||
};
|
};
|
||||||
|
@ -4529,7 +4529,6 @@ static Jim_Nvp nvp_config_opts[] = {
|
||||||
{ .name = "-coreid", .value = TCFG_COREID },
|
{ .name = "-coreid", .value = TCFG_COREID },
|
||||||
{ .name = "-chain-position", .value = TCFG_CHAIN_POSITION },
|
{ .name = "-chain-position", .value = TCFG_CHAIN_POSITION },
|
||||||
{ .name = "-dbgbase", .value = TCFG_DBGBASE },
|
{ .name = "-dbgbase", .value = TCFG_DBGBASE },
|
||||||
{ .name = "-ctibase", .value = TCFG_CTIBASE },
|
|
||||||
{ .name = "-rtos", .value = TCFG_RTOS },
|
{ .name = "-rtos", .value = TCFG_RTOS },
|
||||||
{ .name = "-defer-examine", .value = TCFG_DEFER_EXAMINE },
|
{ .name = "-defer-examine", .value = TCFG_DEFER_EXAMINE },
|
||||||
{ .name = NULL, .value = -1 }
|
{ .name = NULL, .value = -1 }
|
||||||
|
@ -4796,20 +4795,6 @@ no_params:
|
||||||
Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->dbgbase));
|
Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->dbgbase));
|
||||||
/* loop for more */
|
/* loop for more */
|
||||||
break;
|
break;
|
||||||
case TCFG_CTIBASE:
|
|
||||||
if (goi->isconfigure) {
|
|
||||||
e = Jim_GetOpt_Wide(goi, &w);
|
|
||||||
if (e != JIM_OK)
|
|
||||||
return e;
|
|
||||||
target->ctibase = (uint32_t)w;
|
|
||||||
target->ctibase_set = true;
|
|
||||||
} else {
|
|
||||||
if (goi->argc != 0)
|
|
||||||
goto no_params;
|
|
||||||
}
|
|
||||||
Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->ctibase));
|
|
||||||
/* loop for more */
|
|
||||||
break;
|
|
||||||
case TCFG_RTOS:
|
case TCFG_RTOS:
|
||||||
/* RTOS */
|
/* RTOS */
|
||||||
{
|
{
|
||||||
|
|
|
@ -186,10 +186,6 @@ struct target {
|
||||||
* system in place to support target specific options
|
* system in place to support target specific options
|
||||||
* currently. */
|
* currently. */
|
||||||
|
|
||||||
bool ctibase_set; /* By default the debug base is not set */
|
|
||||||
uint32_t ctibase; /* Really a Cortex-A specific option, but there is no
|
|
||||||
* system in place to support target specific options
|
|
||||||
* currently. */
|
|
||||||
struct rtos *rtos; /* Instance of Real Time Operating System support */
|
struct rtos *rtos; /* Instance of Real Time Operating System support */
|
||||||
bool rtos_auto_detect; /* A flag that indicates that the RTOS has been specified as "auto"
|
bool rtos_auto_detect; /* A flag that indicates that the RTOS has been specified as "auto"
|
||||||
* and must be detected when symbols are offered */
|
* and must be detected when symbols are offered */
|
||||||
|
|
|
@ -30,6 +30,8 @@ set $_TARGETNAME.cti(3) 0x80320000
|
||||||
set _cores 4
|
set _cores 4
|
||||||
for { set _core 0 } { $_core < $_cores } { incr _core 1 } {
|
for { set _core 0 } { $_core < $_cores } { incr _core 1 } {
|
||||||
|
|
||||||
|
cti create cti$_core -dap $_CHIPNAME.dap -ctibase [set $_TARGETNAME.cti($_core)] -ap-num 0
|
||||||
|
|
||||||
set _command "target create ${_TARGETNAME}$_core aarch64 \
|
set _command "target create ${_TARGETNAME}$_core aarch64 \
|
||||||
-chain-position $_CHIPNAME.dap -coreid $_core -ctibase [set $_TARGETNAME.cti($_core)]"
|
-chain-position $_CHIPNAME.dap -coreid $_core -ctibase [set $_TARGETNAME.cti($_core)]"
|
||||||
|
|
||||||
|
|
|
@ -34,8 +34,10 @@ set $_TARGETNAME.cti(7) 0x801DB000
|
||||||
set _cores 8
|
set _cores 8
|
||||||
for { set _core 0 } { $_core < $_cores } { incr _core 1 } {
|
for { set _core 0 } { $_core < $_cores } { incr _core 1 } {
|
||||||
|
|
||||||
|
cti create cti$_core -chain-position $_CHIPNAME.dap -ctibase [set $_TARGETNAME.cti($_core)] -ap-num 0
|
||||||
|
|
||||||
set _command "target create ${_TARGETNAME}$_core aarch64 \
|
set _command "target create ${_TARGETNAME}$_core aarch64 \
|
||||||
-chain-position $_CHIPNAME.dap -coreid $_core -ctibase [set $_TARGETNAME.cti($_core)]"
|
-chain-position $_CHIPNAME.dap -coreid $_core -cti cti$_core"
|
||||||
|
|
||||||
if { $_core != 0 } {
|
if { $_core != 0 } {
|
||||||
# non-boot core examination may fail
|
# non-boot core examination may fail
|
||||||
|
@ -52,5 +54,10 @@ for { set _core 0 } { $_core < $_cores } { incr _core 1 } {
|
||||||
|
|
||||||
eval $_smp_command
|
eval $_smp_command
|
||||||
|
|
||||||
|
cti create cti.sys -chain-position hi6220.dap -ap-num 0 -ctibase 0x80003000
|
||||||
|
|
||||||
# declare the auxiliary Cortex-M3 core on AP #2 (runs mcuimage.bin)
|
# declare the auxiliary Cortex-M3 core on AP #2 (runs mcuimage.bin)
|
||||||
target create ${_TARGETNAME}.m3 cortex_m -chain-position $_CHIPNAME.dap -ap-num 2 -defer-examine
|
target create ${_TARGETNAME}.m3 cortex_m -chain-position $_CHIPNAME.dap -ap-num 2 -defer-examine
|
||||||
|
|
||||||
|
# declare the auxiliary Cortex-A7 core
|
||||||
|
target create ${_TARGETNAME}.a7 cortex_a -chain-position $_CHIPNAME.dap -dbgbase 0x80210000 -defer-examine
|
||||||
|
|
|
@ -43,9 +43,11 @@ set _smp_command ""
|
||||||
|
|
||||||
for { set _core 0 } { $_core < $_cores } { incr _core 1 } {
|
for { set _core 0 } { $_core < $_cores } { incr _core 1 } {
|
||||||
|
|
||||||
|
cti create cti$_core -chain-position $_CHIPNAME.dap -ctibase [lindex $_ctis $_core] -ap-num 0
|
||||||
|
|
||||||
set _command "target create ${_TARGETNAME}$_core aarch64 \
|
set _command "target create ${_TARGETNAME}$_core aarch64 \
|
||||||
-chain-position $_CHIPNAME.dap -coreid $_core \
|
-chain-position $_CHIPNAME.dap -coreid $_core \
|
||||||
-ctibase [lindex $_ctis $_core]"
|
-cti cti$_core"
|
||||||
|
|
||||||
if { $_core != 0 } {
|
if { $_core != 0 } {
|
||||||
# non-boot core examination may fail
|
# non-boot core examination may fail
|
||||||
|
|
Loading…
Reference in New Issue