openocd/src/target/arm_cti.c

581 lines
14 KiB
C
Raw Normal View History

/***************************************************************************
* Copyright (C) 2016 by Matthias Welwarsky *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <stdint.h>
#include "target/arm_adi_v5.h"
#include "target/arm_cti.h"
#include "target/target.h"
#include "helper/time_support.h"
#include "helper/list.h"
#include "helper/command.h"
struct arm_cti {
struct list_head lh;
char *name;
struct adiv5_mem_ap_spot spot;
};
static LIST_HEAD(all_cti);
const char *arm_cti_name(struct arm_cti *self)
{
return self->name;
}
struct arm_cti *cti_instance_by_jim_obj(Jim_Interp *interp, Jim_Obj *o)
{
struct arm_cti *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;
return NULL;
}
static int arm_cti_mod_reg_bits(struct arm_cti *self, unsigned int reg, uint32_t mask, uint32_t value)
{
struct adiv5_ap *ap = dap_ap(self->spot.dap, self->spot.ap_num);
uint32_t tmp;
/* Read register */
int retval = mem_ap_read_atomic_u32(ap, self->spot.base + reg, &tmp);
if (ERROR_OK != retval)
return retval;
/* clear bitfield */
tmp &= ~mask;
/* put new value */
tmp |= value & mask;
/* write new value */
return mem_ap_write_atomic_u32(ap, self->spot.base + reg, tmp);
}
int arm_cti_enable(struct arm_cti *self, bool enable)
{
struct adiv5_ap *ap = dap_ap(self->spot.dap, self->spot.ap_num);
uint32_t val = enable ? 1 : 0;
return mem_ap_write_atomic_u32(ap, self->spot.base + CTI_CTR, val);
}
int arm_cti_ack_events(struct arm_cti *self, uint32_t event)
{
struct adiv5_ap *ap = dap_ap(self->spot.dap, self->spot.ap_num);
int retval;
uint32_t tmp;
retval = mem_ap_write_atomic_u32(ap, self->spot.base + CTI_INACK, event);
if (retval == ERROR_OK) {
int64_t then = timeval_ms();
for (;;) {
retval = mem_ap_read_atomic_u32(ap, self->spot.base + CTI_TROUT_STATUS, &tmp);
if (retval != ERROR_OK)
break;
if ((tmp & event) == 0)
break;
if (timeval_ms() > then + 1000) {
LOG_ERROR("timeout waiting for target");
retval = ERROR_TARGET_TIMEOUT;
break;
}
}
}
return retval;
}
int arm_cti_gate_channel(struct arm_cti *self, uint32_t channel)
{
if (channel > 31)
return ERROR_COMMAND_ARGUMENT_INVALID;
return arm_cti_mod_reg_bits(self, CTI_GATE, CTI_CHNL(channel), 0);
}
int arm_cti_ungate_channel(struct arm_cti *self, uint32_t channel)
{
if (channel > 31)
return ERROR_COMMAND_ARGUMENT_INVALID;
return arm_cti_mod_reg_bits(self, CTI_GATE, CTI_CHNL(channel), 0xFFFFFFFF);
}
int arm_cti_write_reg(struct arm_cti *self, unsigned int reg, uint32_t value)
{
struct adiv5_ap *ap = dap_ap(self->spot.dap, self->spot.ap_num);
return mem_ap_write_atomic_u32(ap, self->spot.base + reg, value);
}
int arm_cti_read_reg(struct arm_cti *self, unsigned int reg, uint32_t *p_value)
{
struct adiv5_ap *ap = dap_ap(self->spot.dap, self->spot.ap_num);
if (p_value == NULL)
return ERROR_COMMAND_ARGUMENT_INVALID;
return mem_ap_read_atomic_u32(ap, self->spot.base + reg, p_value);
}
int arm_cti_pulse_channel(struct arm_cti *self, uint32_t channel)
{
if (channel > 31)
return ERROR_COMMAND_ARGUMENT_INVALID;
return arm_cti_write_reg(self, CTI_APPPULSE, CTI_CHNL(channel));
}
int arm_cti_set_channel(struct arm_cti *self, uint32_t channel)
{
if (channel > 31)
return ERROR_COMMAND_ARGUMENT_INVALID;
return arm_cti_write_reg(self, CTI_APPSET, CTI_CHNL(channel));
}
int arm_cti_clear_channel(struct arm_cti *self, uint32_t channel)
{
if (channel > 31)
return ERROR_COMMAND_ARGUMENT_INVALID;
return arm_cti_write_reg(self, CTI_APPCLEAR, CTI_CHNL(channel));
}
static uint32_t cti_regs[28];
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] },
{ CTI_APPPULSE, "APPPULSE", &cti_regs[26] },
{ CTI_INACK, "INACK", &cti_regs[27] },
};
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;
}
LOG_ERROR("unknown CTI register %s", name);
return -1;
}
int arm_cti_cleanup_all(void)
{
struct arm_cti *obj, *tmp;
list_for_each_entry_safe(obj, tmp, &all_cti, lh) {
free(obj->name);
free(obj);
}
return ERROR_OK;
}
COMMAND_HANDLER(handle_cti_dump)
{
struct arm_cti *cti = CMD_DATA;
struct adiv5_ap *ap = dap_ap(cti->spot.dap, cti->spot.ap_num);
int retval = ERROR_OK;
for (int i = 0; (retval == ERROR_OK) && (i < (int)ARRAY_SIZE(cti_names)); i++)
retval = mem_ap_read_u32(ap,
cti->spot.base + cti_names[i].offset, cti_names[i].p_val);
if (retval == ERROR_OK)
retval = dap_run(ap->dap);
if (retval != ERROR_OK)
return JIM_ERR;
for (int i = 0; i < (int)ARRAY_SIZE(cti_names); i++)
command_print(CMD, "%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 *cti = CMD_DATA;
bool on_off;
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_ON_OFF(CMD_ARGV[0], on_off);
return arm_cti_enable(cti, on_off);
}
COMMAND_HANDLER(handle_cti_testmode)
{
struct arm_cti *cti = CMD_DATA;
bool on_off;
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
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 *cti = CMD_DATA;
int offset;
uint32_t value;
if (CMD_ARGC != 2)
return ERROR_COMMAND_SYNTAX_ERROR;
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 *cti = CMD_DATA;
int offset;
int retval;
uint32_t value;
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
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, "0x%08"PRIx32, value);
return ERROR_OK;
}
COMMAND_HANDLER(handle_cti_ack)
{
struct arm_cti *cti = CMD_DATA;
uint32_t event;
if (CMD_ARGC != 1)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], event);
int retval = arm_cti_ack_events(cti, 1 << event);
if (retval != ERROR_OK)
return retval;
return ERROR_OK;
}
COMMAND_HANDLER(handle_cti_channel)
{
struct arm_cti *cti = CMD_DATA;
int retval = ERROR_OK;
uint32_t ch_num;
if (CMD_ARGC != 2)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], ch_num);
if (!strcmp(CMD_ARGV[1], "gate"))
retval = arm_cti_gate_channel(cti, ch_num);
else if (!strcmp(CMD_ARGV[1], "ungate"))
retval = arm_cti_ungate_channel(cti, ch_num);
else if (!strcmp(CMD_ARGV[1], "pulse"))
retval = arm_cti_pulse_channel(cti, ch_num);
else if (!strcmp(CMD_ARGV[1], "set"))
retval = arm_cti_set_channel(cti, ch_num);
else if (!strcmp(CMD_ARGV[1], "clear"))
retval = arm_cti_clear_channel(cti, ch_num);
else {
command_print(CMD, "Possible channel operations: gate|ungate|set|clear|pulse");
return ERROR_COMMAND_ARGUMENT_INVALID;
}
if (retval != ERROR_OK)
return retval;
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",
},
{
.name = "ack",
.mode = COMMAND_EXEC,
.handler = handle_cti_ack,
.help = "acknowledge a CTI event",
.usage = "event",
},
{
.name = "channel",
.mode = COMMAND_EXEC,
.handler = handle_cti_channel,
.help = "do an operation on one CTI channel, possible operations: "
"gate, ungate, set, clear and pulse",
.usage = "channel_number operation",
},
COMMAND_REGISTRATION_DONE
};
helper/jim-nvp: comply with coding style [2/2] With the API fixed to comply with OpenOCD coding style, fix all the references in the code. Patch generated automatically with the script below. The list is in reverse order to replace a common prefix after the replacement of the symbols with the same prefix. %<---%<---%<---%<---%<---%<---%<---%<---%<---%<---%<---%<---%<--- (cat << EOF Jim_SetResult_NvpUnknown jim_set_result_nvp_unknown Jim_Nvp_value2name_simple jim_nvp_value2name_simple Jim_Nvp_value2name_obj jim_nvp_value2name_obj Jim_Nvp_value2name jim_nvp_value2name Jim_Nvp_name2value_simple jim_nvp_name2value_simple Jim_Nvp_name2value_obj_nocase jim_nvp_name2value_obj_nocase Jim_Nvp_name2value_obj jim_nvp_name2value_obj Jim_Nvp_name2value_nocase_simple jim_nvp_name2value_nocase_simple Jim_Nvp_name2value_nocase jim_nvp_name2value_nocase Jim_Nvp_name2value jim_nvp_name2value Jim_Nvp struct jim_nvp Jim_GetOpt_Wide jim_getopt_wide Jim_GetOpt_String jim_getopt_string Jim_GetOpt_Setup jim_getopt_setup Jim_GetOpt_Obj jim_getopt_obj Jim_GetOpt_NvpUnknown jim_getopt_nvp_unknown Jim_GetOpt_Nvp jim_getopt_nvp Jim_GetOpt_Enum jim_getopt_enum Jim_GetOpt_Double jim_getopt_double Jim_GetOpt_Debug jim_getopt_debug Jim_GetOptInfo struct jim_getopt_info Jim_GetNvp jim_get_nvp Jim_Debug_ArgvString jim_debug_argv_string EOF ) | while read a b; do sed -i "s/$a/$b/g" $(find src -type f ! -name jim-nvp.\? ) done %<---%<---%<---%<---%<---%<---%<---%<---%<---%<---%<---%<---%<--- Change-Id: I10a12bd64bb8b17575fd9150482c989c92b298a2 Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com> Reviewed-on: http://openocd.zylin.com/6184 Reviewed-by: Marc Schink <dev@zapb.de> Tested-by: jenkins
2021-04-24 22:48:14 +00:00
static int cti_configure(struct jim_getopt_info *goi, struct arm_cti *cti)
{
/* parse config or cget options ... */
while (goi->argc > 0) {
int e = adiv5_jim_mem_ap_spot_configure(&cti->spot, goi);
if (e != JIM_OK)
return e;
}
if (!cti->spot.dap) {
Jim_SetResultString(goi->interp, "-dap required when creating CTI", -1);
return JIM_ERR;
}
return JIM_OK;
}
helper/jim-nvp: comply with coding style [2/2] With the API fixed to comply with OpenOCD coding style, fix all the references in the code. Patch generated automatically with the script below. The list is in reverse order to replace a common prefix after the replacement of the symbols with the same prefix. %<---%<---%<---%<---%<---%<---%<---%<---%<---%<---%<---%<---%<--- (cat << EOF Jim_SetResult_NvpUnknown jim_set_result_nvp_unknown Jim_Nvp_value2name_simple jim_nvp_value2name_simple Jim_Nvp_value2name_obj jim_nvp_value2name_obj Jim_Nvp_value2name jim_nvp_value2name Jim_Nvp_name2value_simple jim_nvp_name2value_simple Jim_Nvp_name2value_obj_nocase jim_nvp_name2value_obj_nocase Jim_Nvp_name2value_obj jim_nvp_name2value_obj Jim_Nvp_name2value_nocase_simple jim_nvp_name2value_nocase_simple Jim_Nvp_name2value_nocase jim_nvp_name2value_nocase Jim_Nvp_name2value jim_nvp_name2value Jim_Nvp struct jim_nvp Jim_GetOpt_Wide jim_getopt_wide Jim_GetOpt_String jim_getopt_string Jim_GetOpt_Setup jim_getopt_setup Jim_GetOpt_Obj jim_getopt_obj Jim_GetOpt_NvpUnknown jim_getopt_nvp_unknown Jim_GetOpt_Nvp jim_getopt_nvp Jim_GetOpt_Enum jim_getopt_enum Jim_GetOpt_Double jim_getopt_double Jim_GetOpt_Debug jim_getopt_debug Jim_GetOptInfo struct jim_getopt_info Jim_GetNvp jim_get_nvp Jim_Debug_ArgvString jim_debug_argv_string EOF ) | while read a b; do sed -i "s/$a/$b/g" $(find src -type f ! -name jim-nvp.\? ) done %<---%<---%<---%<---%<---%<---%<---%<---%<---%<---%<---%<---%<--- Change-Id: I10a12bd64bb8b17575fd9150482c989c92b298a2 Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com> Reviewed-on: http://openocd.zylin.com/6184 Reviewed-by: Marc Schink <dev@zapb.de> Tested-by: jenkins
2021-04-24 22:48:14 +00:00
static int cti_create(struct jim_getopt_info *goi)
{
struct command_context *cmd_ctx;
static struct arm_cti *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 */
helper/jim-nvp: comply with coding style [2/2] With the API fixed to comply with OpenOCD coding style, fix all the references in the code. Patch generated automatically with the script below. The list is in reverse order to replace a common prefix after the replacement of the symbols with the same prefix. %<---%<---%<---%<---%<---%<---%<---%<---%<---%<---%<---%<---%<--- (cat << EOF Jim_SetResult_NvpUnknown jim_set_result_nvp_unknown Jim_Nvp_value2name_simple jim_nvp_value2name_simple Jim_Nvp_value2name_obj jim_nvp_value2name_obj Jim_Nvp_value2name jim_nvp_value2name Jim_Nvp_name2value_simple jim_nvp_name2value_simple Jim_Nvp_name2value_obj_nocase jim_nvp_name2value_obj_nocase Jim_Nvp_name2value_obj jim_nvp_name2value_obj Jim_Nvp_name2value_nocase_simple jim_nvp_name2value_nocase_simple Jim_Nvp_name2value_nocase jim_nvp_name2value_nocase Jim_Nvp_name2value jim_nvp_name2value Jim_Nvp struct jim_nvp Jim_GetOpt_Wide jim_getopt_wide Jim_GetOpt_String jim_getopt_string Jim_GetOpt_Setup jim_getopt_setup Jim_GetOpt_Obj jim_getopt_obj Jim_GetOpt_NvpUnknown jim_getopt_nvp_unknown Jim_GetOpt_Nvp jim_getopt_nvp Jim_GetOpt_Enum jim_getopt_enum Jim_GetOpt_Double jim_getopt_double Jim_GetOpt_Debug jim_getopt_debug Jim_GetOptInfo struct jim_getopt_info Jim_GetNvp jim_get_nvp Jim_Debug_ArgvString jim_debug_argv_string EOF ) | while read a b; do sed -i "s/$a/$b/g" $(find src -type f ! -name jim-nvp.\? ) done %<---%<---%<---%<---%<---%<---%<---%<---%<---%<---%<---%<---%<--- Change-Id: I10a12bd64bb8b17575fd9150482c989c92b298a2 Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com> Reviewed-on: http://openocd.zylin.com/6184 Reviewed-by: Marc Schink <dev@zapb.de> Tested-by: jenkins
2021-04-24 22:48:14 +00:00
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(*cti));
if (cti == NULL)
return JIM_ERR;
adiv5_mem_ap_spot_init(&cti->spot);
/* Do the rest as "configure" options */
goi->isconfigure = 1;
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_with_data(cmd_ctx, NULL, cti_commands, cti);
if (ERROR_OK != e)
return JIM_ERR;
list_add_tail(&cti->lh, &all_cti);
return JIM_OK;
}
static int jim_cti_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
helper/jim-nvp: comply with coding style [2/2] With the API fixed to comply with OpenOCD coding style, fix all the references in the code. Patch generated automatically with the script below. The list is in reverse order to replace a common prefix after the replacement of the symbols with the same prefix. %<---%<---%<---%<---%<---%<---%<---%<---%<---%<---%<---%<---%<--- (cat << EOF Jim_SetResult_NvpUnknown jim_set_result_nvp_unknown Jim_Nvp_value2name_simple jim_nvp_value2name_simple Jim_Nvp_value2name_obj jim_nvp_value2name_obj Jim_Nvp_value2name jim_nvp_value2name Jim_Nvp_name2value_simple jim_nvp_name2value_simple Jim_Nvp_name2value_obj_nocase jim_nvp_name2value_obj_nocase Jim_Nvp_name2value_obj jim_nvp_name2value_obj Jim_Nvp_name2value_nocase_simple jim_nvp_name2value_nocase_simple Jim_Nvp_name2value_nocase jim_nvp_name2value_nocase Jim_Nvp_name2value jim_nvp_name2value Jim_Nvp struct jim_nvp Jim_GetOpt_Wide jim_getopt_wide Jim_GetOpt_String jim_getopt_string Jim_GetOpt_Setup jim_getopt_setup Jim_GetOpt_Obj jim_getopt_obj Jim_GetOpt_NvpUnknown jim_getopt_nvp_unknown Jim_GetOpt_Nvp jim_getopt_nvp Jim_GetOpt_Enum jim_getopt_enum Jim_GetOpt_Double jim_getopt_double Jim_GetOpt_Debug jim_getopt_debug Jim_GetOptInfo struct jim_getopt_info Jim_GetNvp jim_get_nvp Jim_Debug_ArgvString jim_debug_argv_string EOF ) | while read a b; do sed -i "s/$a/$b/g" $(find src -type f ! -name jim-nvp.\? ) done %<---%<---%<---%<---%<---%<---%<---%<---%<---%<---%<---%<---%<--- Change-Id: I10a12bd64bb8b17575fd9150482c989c92b298a2 Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com> Reviewed-on: http://openocd.zylin.com/6184 Reviewed-by: Marc Schink <dev@zapb.de> Tested-by: jenkins
2021-04-24 22:48:14 +00:00
struct jim_getopt_info 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 *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,
.usage = "",
},
COMMAND_REGISTRATION_DONE
};
int cti_register_commands(struct command_context *cmd_ctx)
{
return register_commands(cmd_ctx, NULL, cti_command_handlers);
}