mirror of
https://github.com/openocd-org/openocd.git
synced 2025-10-16 23:26:38 +08:00
transport: use a bitmask for the transport
Move the transport's names in a local array in the transport framework. Replace the string struct transport::name, that identifies the transport, with a bitmask where each bit corresponds to one of the available transports. Change-Id: I6bdf7264d5979c355299f63fcf80bf54dcd95cee Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com> Reviewed-on: https://review.openocd.org/c/openocd/+/8674 Tested-by: jenkins Reviewed-by: zapb <dev@zapb.de>
This commit is contained in:
@@ -1823,7 +1823,7 @@ static int jtag_select(struct command_context *ctx)
|
||||
}
|
||||
|
||||
static struct transport jtag_transport = {
|
||||
.name = "jtag",
|
||||
.id = TRANSPORT_JTAG,
|
||||
.select = jtag_select,
|
||||
.init = jtag_init,
|
||||
};
|
||||
@@ -1868,7 +1868,7 @@ int adapter_resets(int trst, int srst)
|
||||
transport_is_swim()) {
|
||||
if (trst == TRST_ASSERT) {
|
||||
LOG_ERROR("transport %s has no trst signal",
|
||||
get_current_transport()->name);
|
||||
get_current_transport_name());
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
@@ -1884,7 +1884,7 @@ int adapter_resets(int trst, int srst)
|
||||
return ERROR_OK;
|
||||
|
||||
LOG_ERROR("reset is not supported on transport %s",
|
||||
get_current_transport()->name);
|
||||
get_current_transport_name());
|
||||
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
@@ -1903,7 +1903,7 @@ int adapter_assert_reset(void)
|
||||
return adapter_system_reset(1);
|
||||
else if (get_current_transport())
|
||||
LOG_ERROR("reset is not supported on %s",
|
||||
get_current_transport()->name);
|
||||
get_current_transport_name());
|
||||
else
|
||||
LOG_ERROR("transport is not selected");
|
||||
return ERROR_FAIL;
|
||||
@@ -1920,7 +1920,7 @@ int adapter_deassert_reset(void)
|
||||
return adapter_system_reset(0);
|
||||
else if (get_current_transport())
|
||||
LOG_ERROR("reset is not supported on %s",
|
||||
get_current_transport()->name);
|
||||
get_current_transport_name());
|
||||
else
|
||||
LOG_ERROR("transport is not selected");
|
||||
return ERROR_FAIL;
|
||||
|
@@ -177,15 +177,20 @@ static int hl_transport_init(struct command_context *cmd_ctx)
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
LOG_DEBUG("current transport %s", transport->name);
|
||||
LOG_DEBUG("current transport %s", get_current_transport_name());
|
||||
|
||||
/* get selected transport as enum */
|
||||
tr = HL_TRANSPORT_UNKNOWN;
|
||||
|
||||
if (strcmp(transport->name, "hla_swd") == 0)
|
||||
switch (transport->id) {
|
||||
case TRANSPORT_HLA_SWD:
|
||||
tr = HL_TRANSPORT_SWD;
|
||||
else if (strcmp(transport->name, "hla_jtag") == 0)
|
||||
break;
|
||||
case TRANSPORT_HLA_JTAG:
|
||||
tr = HL_TRANSPORT_JTAG;
|
||||
break;
|
||||
default:
|
||||
tr = HL_TRANSPORT_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
int retval = hl_interface_open(tr);
|
||||
|
||||
@@ -213,14 +218,14 @@ static int hl_swd_transport_select(struct command_context *cmd_ctx)
|
||||
}
|
||||
|
||||
static struct transport hl_swd_transport = {
|
||||
.name = "hla_swd",
|
||||
.id = TRANSPORT_HLA_SWD,
|
||||
.select = hl_swd_transport_select,
|
||||
.init = hl_transport_init,
|
||||
.override_target = hl_interface_override_target,
|
||||
};
|
||||
|
||||
static struct transport hl_jtag_transport = {
|
||||
.name = "hla_jtag",
|
||||
.id = TRANSPORT_HLA_JTAG,
|
||||
.select = hl_jtag_transport_select,
|
||||
.init = hl_transport_init,
|
||||
.override_target = hl_interface_override_target,
|
||||
|
@@ -136,7 +136,7 @@ static int swim_transport_init(struct command_context *cmd_ctx)
|
||||
}
|
||||
|
||||
static struct transport swim_transport = {
|
||||
.name = "swim",
|
||||
.id = TRANSPORT_SWIM,
|
||||
.select = swim_transport_select,
|
||||
.init = swim_transport_init,
|
||||
};
|
||||
|
@@ -207,13 +207,13 @@ static int dapdirect_init(struct command_context *ctx)
|
||||
}
|
||||
|
||||
static struct transport dapdirect_jtag_transport = {
|
||||
.name = "dapdirect_jtag",
|
||||
.id = TRANSPORT_DAPDIRECT_JTAG,
|
||||
.select = dapdirect_jtag_select,
|
||||
.init = dapdirect_init,
|
||||
};
|
||||
|
||||
static struct transport dapdirect_swd_transport = {
|
||||
.name = "dapdirect_swd",
|
||||
.id = TRANSPORT_DAPDIRECT_SWD,
|
||||
.select = dapdirect_swd_select,
|
||||
.init = dapdirect_init,
|
||||
};
|
||||
|
@@ -756,7 +756,7 @@ static int swd_init(struct command_context *ctx)
|
||||
}
|
||||
|
||||
static struct transport swd_transport = {
|
||||
.name = "swd",
|
||||
.id = TRANSPORT_SWD,
|
||||
.select = swd_select,
|
||||
.init = swd_init,
|
||||
};
|
||||
|
@@ -30,6 +30,8 @@
|
||||
* messaging and error handling.
|
||||
*/
|
||||
|
||||
#include <helper/align.h>
|
||||
#include <helper/bits.h>
|
||||
#include <helper/log.h>
|
||||
#include <helper/replacements.h>
|
||||
#include <transport/transport.h>
|
||||
@@ -43,6 +45,20 @@ extern struct command_context *global_cmd_ctx;
|
||||
*/
|
||||
|
||||
/** List of transports known to OpenOCD. */
|
||||
static const struct {
|
||||
unsigned int id;
|
||||
const char *name;
|
||||
} transport_names[] = {
|
||||
{ TRANSPORT_JTAG, "jtag", },
|
||||
{ TRANSPORT_SWD, "swd", },
|
||||
{ TRANSPORT_HLA_JTAG, "hla_jtag", },
|
||||
{ TRANSPORT_HLA_SWD, "hla_swd", },
|
||||
{ TRANSPORT_DAPDIRECT_JTAG, "dapdirect_jtag", },
|
||||
{ TRANSPORT_DAPDIRECT_SWD, "dapdirect_swd", },
|
||||
{ TRANSPORT_SWIM, "swim", },
|
||||
};
|
||||
|
||||
/** List of transports registered in OpenOCD. */
|
||||
static struct transport *transport_list;
|
||||
|
||||
/**
|
||||
@@ -60,12 +76,26 @@ static bool transport_single_is_autoselected;
|
||||
/** * The transport being used for the current OpenOCD session. */
|
||||
static struct transport *session;
|
||||
|
||||
static const char *transport_name(unsigned int id)
|
||||
{
|
||||
for (unsigned int i = 0; i < ARRAY_SIZE(transport_names); i++)
|
||||
if (id == transport_names[i].id)
|
||||
return transport_names[i].name;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool is_transport_id_valid(unsigned int id)
|
||||
{
|
||||
return (id != 0) && ((id & ~TRANSPORT_VALID_MASK) == 0) && IS_PWR_OF_2(id);
|
||||
}
|
||||
|
||||
static int transport_select(struct command_context *ctx, const char *name)
|
||||
{
|
||||
/* name may only identify a known transport;
|
||||
* caller guarantees session's transport isn't yet set.*/
|
||||
for (struct transport *t = transport_list; t; t = t->next) {
|
||||
if (strcmp(t->name, name) == 0) {
|
||||
if (!strcmp(transport_name(t->id), name)) {
|
||||
int retval = t->select(ctx);
|
||||
/* select() registers commands specific to this
|
||||
* transport, and may also reset the link, e.g.
|
||||
@@ -74,7 +104,7 @@ static int transport_select(struct command_context *ctx, const char *name)
|
||||
if (retval == ERROR_OK)
|
||||
session = t;
|
||||
else
|
||||
LOG_ERROR("Error selecting '%s' as transport", t->name);
|
||||
LOG_ERROR("Error selecting '%s' as transport", name);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
@@ -136,20 +166,28 @@ int transport_register(struct transport *new_transport)
|
||||
{
|
||||
struct transport *t;
|
||||
|
||||
if (!is_transport_id_valid(new_transport->id)) {
|
||||
LOG_ERROR("invalid transport ID 0x%x", new_transport->id);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
for (t = transport_list; t; t = t->next) {
|
||||
if (strcmp(t->name, new_transport->name) == 0) {
|
||||
LOG_ERROR("transport name already used");
|
||||
if (t->id == new_transport->id) {
|
||||
LOG_ERROR("transport '%s' already registered",
|
||||
transport_name(t->id));
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!new_transport->select || !new_transport->init)
|
||||
LOG_ERROR("invalid transport %s", new_transport->name);
|
||||
LOG_ERROR("invalid transport %s",
|
||||
transport_name(new_transport->id));
|
||||
|
||||
/* splice this into the list */
|
||||
new_transport->next = transport_list;
|
||||
transport_list = new_transport;
|
||||
LOG_DEBUG("register '%s'", new_transport->name);
|
||||
LOG_DEBUG("register '%s' (ID %d)",
|
||||
transport_name(new_transport->id), new_transport->id);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
@@ -166,6 +204,14 @@ struct transport *get_current_transport(void)
|
||||
return session;
|
||||
}
|
||||
|
||||
const char *get_current_transport_name(void)
|
||||
{
|
||||
if (!session || !is_transport_id_valid(session->id))
|
||||
NULL;
|
||||
|
||||
return transport_name(session->id);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
@@ -191,7 +237,7 @@ COMMAND_HANDLER(handle_transport_init)
|
||||
if (transport_single_is_autoselected)
|
||||
LOG_WARNING("DEPRECATED: auto-selecting transport \"%s\". "
|
||||
"Use 'transport select %s' to suppress this message.",
|
||||
session->name, session->name);
|
||||
transport_name(session->id), transport_name(session->id));
|
||||
|
||||
return session->init(CMD_CTX);
|
||||
}
|
||||
@@ -204,7 +250,7 @@ COMMAND_HANDLER(handle_transport_list)
|
||||
command_print(CMD, "The following transports are available:");
|
||||
|
||||
for (struct transport *t = transport_list; t; t = t->next)
|
||||
command_print(CMD, "\t%s", t->name);
|
||||
command_print(CMD, "\t%s", transport_name(t->id));
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
@@ -234,19 +280,19 @@ COMMAND_HANDLER(handle_transport_select)
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
}
|
||||
command_print(CMD, "%s", session->name);
|
||||
command_print(CMD, "%s", transport_name(session->id));
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* assign transport */
|
||||
if (session) {
|
||||
if (!strcmp(session->name, CMD_ARGV[0])) {
|
||||
if (!strcmp(transport_name(session->id), CMD_ARGV[0])) {
|
||||
if (transport_single_is_autoselected) {
|
||||
/* Nothing to do, but also nothing to complain */
|
||||
transport_single_is_autoselected = false;
|
||||
return ERROR_OK;
|
||||
}
|
||||
LOG_WARNING("Transport \"%s\" was already selected", session->name);
|
||||
LOG_WARNING("Transport \"%s\" was already selected", CMD_ARGV[0]);
|
||||
return ERROR_OK;
|
||||
}
|
||||
command_print(CMD, "Can't change session's transport after the initial selection was made");
|
||||
|
@@ -12,8 +12,27 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "helper/bits.h"
|
||||
#include "helper/command.h"
|
||||
|
||||
#define TRANSPORT_JTAG BIT(0)
|
||||
#define TRANSPORT_SWD BIT(1)
|
||||
#define TRANSPORT_HLA_JTAG BIT(2)
|
||||
#define TRANSPORT_HLA_SWD BIT(3)
|
||||
#define TRANSPORT_DAPDIRECT_JTAG BIT(4)
|
||||
#define TRANSPORT_DAPDIRECT_SWD BIT(5)
|
||||
#define TRANSPORT_SWIM BIT(6)
|
||||
|
||||
/* mask for valid ID */
|
||||
#define TRANSPORT_VALID_MASK \
|
||||
(TRANSPORT_JTAG | \
|
||||
TRANSPORT_SWD | \
|
||||
TRANSPORT_HLA_JTAG | \
|
||||
TRANSPORT_HLA_SWD | \
|
||||
TRANSPORT_DAPDIRECT_JTAG | \
|
||||
TRANSPORT_DAPDIRECT_SWD | \
|
||||
TRANSPORT_SWIM)
|
||||
|
||||
/**
|
||||
* Wrapper for transport lifecycle operations.
|
||||
*
|
||||
@@ -34,11 +53,10 @@
|
||||
*/
|
||||
struct transport {
|
||||
/**
|
||||
* Each transport has a unique name, used to select it
|
||||
* from among the alternatives. Examples might include
|
||||
* "jtag", * "swd", "AVR_ISP" and more.
|
||||
* Each transport has a unique ID, used to select it
|
||||
* from among the alternatives.
|
||||
*/
|
||||
const char *name;
|
||||
unsigned int id;
|
||||
|
||||
/**
|
||||
* When a transport is selected, this method registers
|
||||
@@ -75,6 +93,8 @@ int transport_register(struct transport *new_transport);
|
||||
|
||||
struct transport *get_current_transport(void);
|
||||
|
||||
const char *get_current_transport_name(void);
|
||||
|
||||
int transport_register_commands(struct command_context *ctx);
|
||||
|
||||
int allow_transports(struct command_context *ctx, const char * const *vector);
|
||||
|
Reference in New Issue
Block a user