From a61ec3c1d73dc0c9915662f7b9383b6f786a5fea Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Wed, 23 Jan 2019 10:52:28 +0100 Subject: [PATCH] adi_v5_dapdirect: add support for adapter drivers that provide DAP API Some high level adapters, like STLINK-V3 and new firmware for ST-Link/V2, provide API to directly access the DAP registers hiding the details of the physical transport JTAG or SWD. OpenOCD has already the intermediate API in struct dap_ops that are suitable for such adapters, but are not exposed to the adapter drivers. Add in struct adapter_driver two independent struct dap_ops for the cases of physical JTAG and SWD transport. Add new transport names "dapdirect_jtag" and "dapdirect_swd", to be used by the drivers that provide one or both DAP API. Add the necessarily glue in target/adi_v5_dapdirect.c Change-Id: I2bb8e3a80fba750f2c218d877cfa5888428e3c28 Signed-off-by: Antonio Borneo Reviewed-on: http://openocd.zylin.com/4903 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/jtag/core.c | 6 +- src/jtag/interface.h | 6 + src/target/Makefile.am | 1 + src/target/adi_v5_dapdirect.c | 223 ++++++++++++++++++++++++++++++++++ src/target/arm_dap.c | 4 + src/transport/transport.h | 2 + 6 files changed, 240 insertions(+), 2 deletions(-) create mode 100644 src/target/adi_v5_dapdirect.c diff --git a/src/jtag/core.c b/src/jtag/core.c index 6239573d10..111b122d95 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -2052,7 +2052,8 @@ int adapter_assert_reset(void) else jtag_add_reset(0, 1); return ERROR_OK; - } else if (transport_is_swd() || transport_is_hla()) + } else if (transport_is_swd() || transport_is_hla() || + transport_is_dapdirect_jtag() || transport_is_dapdirect_swd()) return adapter_system_reset(1); else if (get_current_transport() != NULL) LOG_ERROR("reset is not supported on %s", @@ -2067,7 +2068,8 @@ int adapter_deassert_reset(void) if (transport_is_jtag()) { jtag_add_reset(0, 0); return ERROR_OK; - } else if (transport_is_swd() || transport_is_hla()) + } else if (transport_is_swd() || transport_is_hla() || + transport_is_dapdirect_jtag() || transport_is_dapdirect_swd()) return adapter_system_reset(0); else if (get_current_transport() != NULL) LOG_ERROR("reset is not supported on %s", diff --git a/src/jtag/interface.h b/src/jtag/interface.h index feda35699e..f4c6a98ba7 100644 --- a/src/jtag/interface.h +++ b/src/jtag/interface.h @@ -351,6 +351,12 @@ struct adapter_driver { /** Low-level SWD APIs */ const struct swd_driver *swd_ops; + + /* DAP APIs over JTAG transport */ + const struct dap_ops *dap_jtag_ops; + + /* DAP APIs over SWD transport */ + const struct dap_ops *dap_swd_ops; }; extern const char * const jtag_only[]; diff --git a/src/target/Makefile.am b/src/target/Makefile.am index 08a4b961f1..5a16def55b 100644 --- a/src/target/Makefile.am +++ b/src/target/Makefile.am @@ -98,6 +98,7 @@ ARM_DEBUG_SRC = \ %D%/arm_dap.c \ %D%/armv7a_cache.c \ %D%/armv7a_cache_l2x.c \ + %D%/adi_v5_dapdirect.c \ %D%/adi_v5_jtag.c \ %D%/adi_v5_swd.c \ %D%/embeddedice.c \ diff --git a/src/target/adi_v5_dapdirect.c b/src/target/adi_v5_dapdirect.c new file mode 100644 index 0000000000..f120151986 --- /dev/null +++ b/src/target/adi_v5_dapdirect.c @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2019, STMicroelectronics - All Rights Reserved + * Author(s): Antonio Borneo for STMicroelectronics + * + * 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, see . + */ + +/** + * @file + * Utilities to support in-circuit debuggers that provide APIs to access + * directly ARM DAP, hiding the access to the underlining transport used + * for the physical connection (either JTAG or SWD). + * E.g. STMicroelectronics ST-Link/V2 (from version V2J24) and STLINK-V3. + * + * Single-DAP support only. + * + * For details, see "ARM IHI 0031A" + * ARM Debug Interface v5 Architecture Specification + * + * FIXME: in JTAG mode, trst is not managed + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +COMMAND_HANDLER(dapdirect_jtag_empty_command) +{ + LOG_DEBUG("dapdirect_jtag_empty_command(\"%s\")", CMD_NAME); + + return ERROR_OK; +} + +COMMAND_HANDLER(dapdirect_jtag_reset_command) +{ + enum reset_types jtag_reset_config = jtag_get_reset_config(); + + /* + * in case the adapter has not already handled asserting srst + * we will attempt it again + */ + if (jtag_reset_config & RESET_CNCT_UNDER_SRST) { + if (jtag_reset_config & RESET_SRST_NO_GATING) { + adapter_assert_reset(); + return ERROR_OK; + } + LOG_WARNING("\'srst_nogate\' reset_config option is required"); + } + adapter_deassert_reset(); + return ERROR_OK; +} + +static const struct command_registration dapdirect_jtag_subcommand_handlers[] = { + { + .name = "newtap", + .mode = COMMAND_CONFIG, + .jim_handler = jim_jtag_newtap, + .help = "declare a new TAP" + }, + { + .name = "init", + .mode = COMMAND_ANY, + .handler = dapdirect_jtag_empty_command, + .usage = "" + }, + { + .name = "arp_init", + .mode = COMMAND_ANY, + .handler = dapdirect_jtag_empty_command, + .usage = "" + }, + { + .name = "arp_init-reset", + .mode = COMMAND_ANY, + .handler = dapdirect_jtag_reset_command, + .usage = "" + }, + { + .name = "tapisenabled", + .mode = COMMAND_EXEC, + .jim_handler = jim_jtag_tap_enabler, + }, + { + .name = "tapenable", + .mode = COMMAND_EXEC, + .jim_handler = jim_jtag_tap_enabler, + }, + { + .name = "tapdisable", + .mode = COMMAND_EXEC, + .handler = dapdirect_jtag_empty_command, + .usage = "", + }, + { + .name = "configure", + .mode = COMMAND_ANY, + .handler = dapdirect_jtag_empty_command, + .usage = "", + }, + { + .name = "cget", + .mode = COMMAND_EXEC, + .jim_handler = jim_jtag_configure, + }, + { + .name = "names", + .mode = COMMAND_ANY, + .handler = dapdirect_jtag_empty_command, + .usage = "", + }, + COMMAND_REGISTRATION_DONE +}; + +static const struct command_registration dapdirect_jtag_handlers[] = { + { + .name = "jtag", + .mode = COMMAND_ANY, + .chain = dapdirect_jtag_subcommand_handlers, + .usage = "", + }, + { + .name = "jtag_ntrst_delay", + .mode = COMMAND_ANY, + .handler = dapdirect_jtag_empty_command, + .usage = "", + }, + COMMAND_REGISTRATION_DONE +}; + +static const struct command_registration dapdirect_swd_subcommand_handlers[] = { + { + .name = "newdap", + .mode = COMMAND_CONFIG, + .jim_handler = jim_jtag_newtap, + .help = "declare a new SWD DAP", + }, + COMMAND_REGISTRATION_DONE +}; + +static const struct command_registration dapdirect_swd_handlers[] = { + { + .name = "swd", + .mode = COMMAND_ANY, + .help = "SWD command group", + .usage = "", + .chain = dapdirect_swd_subcommand_handlers, + }, + COMMAND_REGISTRATION_DONE +}; + +static int dapdirect_jtag_select(struct command_context *ctx) +{ + LOG_DEBUG("dapdirect_jtag_select()"); + + return register_commands(ctx, NULL, dapdirect_jtag_handlers); +} + +static int dapdirect_swd_select(struct command_context *ctx) +{ + LOG_DEBUG("dapdirect_swd_select()"); + + return register_commands(ctx, NULL, dapdirect_swd_handlers); +} + +static int dapdirect_init(struct command_context *ctx) +{ + LOG_DEBUG("dapdirect_init()"); + + adapter_deassert_reset(); + return ERROR_OK; +} + +static struct transport dapdirect_jtag_transport = { + .name = "dapdirect_jtag", + .select = dapdirect_jtag_select, + .init = dapdirect_init, +}; + +static struct transport dapdirect_swd_transport = { + .name = "dapdirect_swd", + .select = dapdirect_swd_select, + .init = dapdirect_init, +}; + +static void dapdirect_constructor(void) __attribute__((constructor)); +static void dapdirect_constructor(void) +{ + transport_register(&dapdirect_jtag_transport); + transport_register(&dapdirect_swd_transport); +} + +/** + * Returns true if the current debug session + * is using JTAG as its transport. + */ +bool transport_is_dapdirect_jtag(void) +{ + return get_current_transport() == &dapdirect_jtag_transport; +} + +/** + * Returns true if the current debug session + * is using SWD as its transport. + */ +bool transport_is_dapdirect_swd(void) +{ + return get_current_transport() == &dapdirect_swd_transport; +} diff --git a/src/target/arm_dap.c b/src/target/arm_dap.c index 4be94b41bd..56442f1835 100644 --- a/src/target/arm_dap.c +++ b/src/target/arm_dap.c @@ -119,6 +119,10 @@ static int dap_init_all(void) if (transport_is_swd()) { dap->ops = &swd_dap_ops; obj->swd = adapter_driver->swd_ops; + } else if (transport_is_dapdirect_swd()) { + dap->ops = adapter_driver->dap_swd_ops; + } else if (transport_is_dapdirect_jtag()) { + dap->ops = adapter_driver->dap_jtag_ops; } else dap->ops = &jtag_dp_ops; diff --git a/src/transport/transport.h b/src/transport/transport.h index 140ef503d7..4effca5d5e 100644 --- a/src/transport/transport.h +++ b/src/transport/transport.h @@ -96,6 +96,8 @@ bool transports_are_declared(void); bool transport_is_jtag(void); bool transport_is_swd(void); +bool transport_is_dapdirect_jtag(void); +bool transport_is_dapdirect_swd(void); #if BUILD_HLADAPTER bool transport_is_hla(void); -- 2.30.2