From 6a5e16457e5bf91d554e1055fcdd5bc06b75195a Mon Sep 17 00:00:00 2001 From: Tomek CEDRO Date: Fri, 16 Nov 2012 01:57:38 +0100 Subject: [PATCH] WARNING! This is a very big and serious change to internals and TRANSPORT system of the OpenOCD. It changes Transport mechanism. It makes SWD work, at least on IDCODE detection level. Change-Id: Ieef90f09df089aa16f985d81f6bd5c51ccac27eb Signed-off-by: Tomek CEDRO --- src/jtag/core.c | 79 +++++++++++++++++- src/jtag/drivers/ft2232.c | 5 ++ src/jtag/interface.h | 4 + src/jtag/jtag.h | 5 +- src/jtag/stlink/stlink_transport.c | 53 ++++++------ src/target/adi_v5_jtag.c | 30 +++++-- src/target/adi_v5_swd.c | 163 ++++++++++++++++++++----------------- src/target/arm_adi_v5.c | 6 +- src/target/arm_adi_v5.h | 9 ++ src/transport/Makefile.am | 9 +- src/transport/swd.c | 8 +- src/transport/swd_libswd.c | 2 +- src/transport/swd_libswd.h | 2 +- src/transport/transport.c | 41 ++++++---- src/transport/transport.h | 29 ++----- 15 files changed, 287 insertions(+), 158 deletions(-) diff --git a/src/jtag/core.c b/src/jtag/core.c index 6e8a6a188..f94a8ecd5 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -2,7 +2,7 @@ * Copyright (C) 2009 Zachary T Welch * * zw@superlucidity.net * * * - * Copyright (C) 2007,2008,2009 Øyvind Harboe * + * Copyright (C) 2007,2008,2009 Oyvind Harboe * * oyvind.harboe@zylin.com * * * * Copyright (C) 2009 SoftPLC Corporation * @@ -36,6 +36,7 @@ #include "swd.h" #include "interface.h" #include +#include #ifdef HAVE_STRINGS_H #include @@ -1771,7 +1772,76 @@ unsigned jtag_get_ntrst_assert_width(void) return jtag_ntrst_assert_width; } -static int jtag_select(struct command_context *ctx) +/** + * This is a JTAG Transport setup routine. + * It should find interface-specific features and select them. + * Note that unlike in SWD that works only with ARM, JTAG can work + * with other targets, so we need to prepare all of them here. + */ +int jtag_setup(struct command_context *ctx) +{ + int retval; + retval = jtag_setup_arm(ctx); + if (retval != ERROR_OK) { + LOG_ERROR("Transport - JTAG for ARM setup failed!"); + return retval; + } + return ERROR_OK; +} + +int jtag_setup_arm(struct command_context *ctx) +{ + int retval; + oocd_feature_t *feature_arm_dap; + + jtag_interface->transport = &jtag_transport; + if (jtag_interface->transport->configured) { + LOG_WARNING("Transport - '%s' already configured on '%s' interface, skipping...", \ + jtag_interface->transport->name, jtag_interface->name); + return ERROR_OK; + } + + /* Some interfaces will have arm dap swd feature already defined, seatch for it... */ + feature_arm_dap = oocd_feature_find(jtag_interface->features, OOCD_FEATURE_ARM_DAP); + if (feature_arm_dap == NULL) { + /* If dedicated feature was not found, try to use generic one. */ + LOG_INFO("Transport - selecting generic JTAG transport mechanism and interface features..."); + if (!jtag_interface->features) { + jtag_interface->features = (oocd_feature_t *) calloc(1, sizeof(oocd_feature_t)); + if (!jtag_interface->features) { + LOG_ERROR("Transport - feature allocation memory failed!"); + return ERROR_FAIL; + } + } + oocd_feature_add(jtag_interface->features, &oocd_transport_jtag_arm_dap_feature); + feature_arm_dap = oocd_feature_find(jtag_interface->features, OOCD_FEATURE_ARM_DAP); + if (!feature_arm_dap) { + LOG_WARNING("Transport - features '%s' failed to attach to interface '%s'!", \ + oocd_transport_jtag_arm_dap_feature.name, jtag_interface->name); + LOG_ERROR("Transport - interface '%s' does not provide/accept features required by transport '%s'!", \ + jtag_interface->name, jtag_interface->transport->name); + return ERROR_FAIL; + } + } else + LOG_INFO("Transport - interface '%s' defines its own '%s' features.", \ + jtag_interface->name, feature_arm_dap->name); + LOG_INFO("Transport - using '%s' features of the '%s' interface...", \ + feature_arm_dap->name, jtag_interface->name); + + struct dap_ops *dap = (struct dap_ops *)feature_arm_dap->body; + retval = dap->select(ctx); + if (retval != ERROR_OK) { + LOG_ERROR("Transport - selecting '%s' transport on '%s' interface failed!", \ + jtag_interface->transport->name, jtag_interface->name); + return ERROR_FAIL; + } + + jtag_interface->transport->configured = 1; + return ERROR_OK; +} + + +int jtag_select(struct command_context *ctx) { int retval; @@ -1794,8 +1864,9 @@ static int jtag_select(struct command_context *ctx) oocd_transport_t jtag_transport = { .name = "jtag", - .select = jtag_select, - .init = jtag_init, + .setup = jtag_setup, + .quit = NULL, + .next = NULL }; /* Transport are now setup with oocd_transport_register_all() diff --git a/src/jtag/drivers/ft2232.c b/src/jtag/drivers/ft2232.c index 0ec731265..92d4c44b5 100644 --- a/src/jtag/drivers/ft2232.c +++ b/src/jtag/drivers/ft2232.c @@ -84,7 +84,10 @@ /* project specific includes */ #include +#include #include +#include +#include #include #include @@ -4531,6 +4534,7 @@ struct jtag_interface ft2232_interface = { .supported = DEBUG_CAP_TMS_SEQ, .commands = ft2232_command_handlers, .transports = jtag_only, + .features = &oocd_transport_jtag_arm_dap_feature, .init = ft2232_init, .quit = ft2232_quit, @@ -4546,6 +4550,7 @@ struct jtag_interface ft2232_interface_swd = { .supported = DEBUG_CAP_TMS_SEQ, .commands = ft2232_command_handlers, .transports = swd_only, + .features = &oocd_transport_swd_libswd_arm_dap_feature, .init = ft2232_init, .quit = ft2232_quit, diff --git a/src/jtag/interface.h b/src/jtag/interface.h index 075dabf09..6596924bf 100644 --- a/src/jtag/interface.h +++ b/src/jtag/interface.h @@ -357,6 +357,10 @@ struct jtag_interface { */ struct target *target; + /** + * Dynamic list of features allows adding features at runtime. + */ + oocd_feature_t *features; }; extern const char *jtag_only[]; diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h index efa3cb2b8..5d926a822 100644 --- a/src/jtag/jtag.h +++ b/src/jtag/jtag.h @@ -313,7 +313,10 @@ void jtag_set_flush_queue_sleep(int ms); * Initialize JTAG chain using only a RESET reset. If init fails, * try reset + init. */ -int jtag_init(struct command_context *cmd_ctx); +extern int jtag_init(struct command_context *cmd_ctx); +extern int jtag_select(struct command_context *ctx); +extern int jtag_setup(struct command_context *ctx); +extern int jtag_setup_arm(struct command_context *ctx); /** reset, then initialize JTAG chain */ int jtag_init_reset(struct command_context *cmd_ctx); diff --git a/src/jtag/stlink/stlink_transport.c b/src/jtag/stlink/stlink_transport.c index 3ee83246d..79711f7c2 100644 --- a/src/jtag/stlink/stlink_transport.c +++ b/src/jtag/stlink/stlink_transport.c @@ -140,7 +140,31 @@ static int stlink_transport_register_commands(struct command_context *cmd_ctx) stlink_transport_command_handlers); } -static int stlink_transport_init(struct command_context *cmd_ctx) +static int stlink_transport_select(struct command_context *ctx) +{ + LOG_DEBUG("stlink_transport_select"); + + int retval; + + /* NOTE: interface init must already have been done. + * That works with only C code ... no Tcl glue required. + */ + + retval = stlink_transport_register_commands(ctx); + + if (retval != ERROR_OK) + return retval; + + return ERROR_OK; +} + +/*** TODO: TCedro changed this function because Transport has changed. + * There is not distinction between init/select anymore. + * Transport just needs to be setup(). + * _init() was renamed to _setup() and calls old _select() at the end. + * Please if that does not break STLINK. + */ +static int stlink_transport_setup(struct command_context *cmd_ctx) { LOG_DEBUG("stlink_transport_init"); struct target *t = get_current_target(cmd_ctx); @@ -176,43 +200,26 @@ static int stlink_transport_init(struct command_context *cmd_ctx) if (retval != ERROR_OK) return retval; - return stlink_interface_init_target(t); -} - -static int stlink_transport_select(struct command_context *ctx) -{ - LOG_DEBUG("stlink_transport_select"); - - int retval; - - /* NOTE: interface init must already have been done. - * That works with only C code ... no Tcl glue required. - */ - - retval = stlink_transport_register_commands(ctx); - + retval = stlink_interface_init_target(t); if (retval != ERROR_OK) return retval; - return ERROR_OK; + return stlink_transport_select(cmd_ctx); } static oocd_transport_t stlink_swd_transport = { .name = "stlink_swd", - .select = stlink_transport_select, - .init = stlink_transport_init, + .setup = stlink_transport_setup, }; static oocd_transport_t stlink_jtag_transport = { .name = "stlink_jtag", - .select = stlink_transport_select, - .init = stlink_transport_init, + .setup = stlink_transport_setup, }; static oocd_transport_t stlink_swim_transport = { .name = "stlink_swim", - .select = stlink_transport_select, - .init = stlink_transport_init, + .setup = stlink_transport_setup, }; const char *stlink_transports[] = { "stlink_swd", "stlink_jtag", "stlink_swim", NULL }; diff --git a/src/target/adi_v5_jtag.c b/src/target/adi_v5_jtag.c index 9f37bd553..a0e8e2fba 100644 --- a/src/target/adi_v5_jtag.c +++ b/src/target/adi_v5_jtag.c @@ -39,6 +39,7 @@ #include "arm.h" #include "arm_adi_v5.h" #include +#include /* JTAG instructions/registers for JTAG-DP and SWJ-DP */ #define JTAG_DP_ABORT 0x8 @@ -432,14 +433,27 @@ static int jtag_dp_run(struct adiv5_dap *dap) /* FIXME don't export ... just initialize as * part of DAP setup */ -const struct dap_ops jtag_dp_ops = { - .queue_idcode_read = jtag_idcode_q_read, - .queue_dp_read = jtag_dp_q_read, - .queue_dp_write = jtag_dp_q_write, - .queue_ap_read = jtag_ap_q_read, - .queue_ap_write = jtag_ap_q_write, - .queue_ap_abort = jtag_ap_q_abort, - .run = jtag_dp_run, +const struct dap_ops jtag_dap_ops = { + .select = jtag_select, + .init = jtag_init, + .queue_idcode_read = jtag_idcode_q_read, + .queue_dp_read = jtag_dp_q_read, + .queue_dp_write = jtag_dp_q_write, + .queue_ap_read = jtag_ap_q_read, + .queue_ap_write = jtag_ap_q_write, + .queue_ap_abort = jtag_ap_q_abort, + .run = jtag_dp_run, +}; + +/** + * Interface features that adds JTAG support for an interface. + * Attach to driver feature list by driver setup or interface definition. + */ +oocd_feature_t oocd_transport_jtag_arm_dap_feature = { + .name = OOCD_FEATURE_ARM_DAP, + .description = "JTAG transport feature to work with ARM DAP.", + .body = (void *) &jtag_dap_ops, + .next = NULL }; diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c index 2dc6ea445..1a12a7dbd 100644 --- a/src/target/adi_v5_swd.c +++ b/src/target/adi_v5_swd.c @@ -2,6 +2,9 @@ * * Copyright (C) 2010 by David Brownell * + * Copyright (C) 2011-2012 Tomasz Boleslaw CEDRO + * cederom@tlen.pl, http://www.tomek.cedro.info + * * 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 @@ -113,78 +116,6 @@ static int swd_run(struct adiv5_dap *dap) return ERROR_OK; } -const struct dap_ops swd_dap_ops = { - .is_swd = true, - - .queue_idcode_read = swd_queue_idcode_read, - .queue_dp_read = swd_queue_dp_read, - .queue_dp_write = swd_queue_dp_write, - .queue_ap_read = swd_queue_ap_read, - .queue_ap_write = swd_queue_ap_write, - .queue_ap_abort = swd_queue_ap_abort, - .run = swd_run, -}; - -/* - * This represents the bits which must be sent out on TMS/SWDIO to - * switch a DAP implemented using an SWJ-DP module into SWD mode. - * These bits are stored (and transmitted) LSB-first. - * - * See the DAP-Lite specification, section 2.2.5 for information - * about making the debug link select SWD or JTAG. (Similar info - * is in a few other ARM documents.) - */ -static const uint8_t jtag2swd_bitseq[] = { - /* More than 50 TCK/SWCLK cycles with TMS/SWDIO high, - * putting both JTAG and SWD logic into reset state. - */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - /* Switching sequence enables SWD and disables JTAG - * NOTE: bits in the DP's IDCODE may expose the need for - * an old/obsolete/deprecated sequence (0xb6 0xed). - */ - 0x9e, 0xe7, - /* More than 50 TCK/SWCLK cycles with TMS/SWDIO high, - * putting both JTAG and SWD logic into reset state. - */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -}; - -/** - * Put the debug link into SWD mode, if the target supports it. - * The link's initial mode may be either JTAG (for example, - * with SWJ-DP after reset) or SWD. - * - * @param target Enters SWD mode (if possible). - * - * Note that targets using the JTAG-DP do not support SWD, and that - * some targets which could otherwise support it may have have been - * configured to disable SWD signaling - * - * @return ERROR_OK or else a fault code. - */ -int dap_to_swd(struct target *target) -{ - struct arm *arm = target_to_arm(target); - int retval; - - LOG_DEBUG("Enter SWD mode"); - - /* REVISIT it's ugly to need to make calls to a "jtag" - * subsystem if the link may not be in JTAG mode... - */ - - retval = jtag_add_tms_seq(8 * sizeof(jtag2swd_bitseq), - jtag2swd_bitseq, TAP_INVALID); - if (retval == ERROR_OK) - retval = jtag_execute_queue(); - - /* set up the DAP's ops vector for SWD mode. */ - arm->dap->ops = &swd_dap_ops; - - return retval; -} - COMMAND_HANDLER(handle_swd_wcr) @@ -270,7 +201,7 @@ static const struct command_registration swd_commands[] = { static const struct command_registration swd_handlers[] = { { - .name = "swd", + .name = "oldswd", .mode = COMMAND_ANY, .help = "SWD command group", .chain = swd_commands, @@ -308,6 +239,11 @@ static int swd_select(struct command_context *ctx) return retval; } +static int swd_setup(struct command_context *ctx) +{ + return swd_select(ctx); +} + static int swd_init(struct command_context *ctx) { struct target *target = get_current_target(ctx); @@ -337,11 +273,86 @@ static int swd_init(struct command_context *ctx) } oocd_transport_t swd_transport = { - .name = "oldswd", - .select = swd_select, - .init = swd_init, + .name = "oldswd", + .setup = swd_setup, + .quit = NULL, + .next = NULL +}; + +const struct dap_ops swd_dap_ops = { + .is_swd = true, + .select = swd_select, + .init = swd_init, + .queue_idcode_read = swd_queue_idcode_read, + .queue_dp_read = swd_queue_dp_read, + .queue_dp_write = swd_queue_dp_write, + .queue_ap_read = swd_queue_ap_read, + .queue_ap_write = swd_queue_ap_write, + .queue_ap_abort = swd_queue_ap_abort, + .run = swd_run, +}; + +/* + * This represents the bits which must be sent out on TMS/SWDIO to + * switch a DAP implemented using an SWJ-DP module into SWD mode. + * These bits are stored (and transmitted) LSB-first. + * + * See the DAP-Lite specification, section 2.2.5 for information + * about making the debug link select SWD or JTAG. (Similar info + * is in a few other ARM documents.) + */ +static const uint8_t jtag2swd_bitseq[] = { + /* More than 50 TCK/SWCLK cycles with TMS/SWDIO high, + * putting both JTAG and SWD logic into reset state. + */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + /* Switching sequence enables SWD and disables JTAG + * NOTE: bits in the DP's IDCODE may expose the need for + * an old/obsolete/deprecated sequence (0xb6 0xed). + */ + 0x9e, 0xe7, + /* More than 50 TCK/SWCLK cycles with TMS/SWDIO high, + * putting both JTAG and SWD logic into reset state. + */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; +/** + * Put the debug link into SWD mode, if the target supports it. + * The link's initial mode may be either JTAG (for example, + * with SWJ-DP after reset) or SWD. + * + * @param target Enters SWD mode (if possible). + * + * Note that targets using the JTAG-DP do not support SWD, and that + * some targets which could otherwise support it may have have been + * configured to disable SWD signaling + * + * @return ERROR_OK or else a fault code. + */ +int dap_to_swd(struct target *target) +{ + struct arm *arm = target_to_arm(target); + int retval; + + LOG_DEBUG("Enter SWD mode"); + + /* REVISIT it's ugly to need to make calls to a "jtag" + * subsystem if the link may not be in JTAG mode... + */ + + retval = jtag_add_tms_seq(8 * sizeof(jtag2swd_bitseq), + jtag2swd_bitseq, TAP_INVALID); + if (retval == ERROR_OK) + retval = jtag_execute_queue(); + + /* set up the DAP's ops vector for SWD mode. */ + arm->dap->ops = &swd_dap_ops; + + return retval; +} + + /* TC: Transport registration moved to function from constructors... static void swd_constructor(void) __attribute__((constructor)); static void swd_constructor(void) diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index a0fd4cb4a..7d8f2481d 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -74,6 +74,10 @@ #include "arm_adi_v5.h" #include +/* These two below are to be removed when transport is finished... */ +extern const struct dap_ops jtag_dap_ops; +extern struct jtag_interface *jtag_interface; + /* ARM ADI Specification requires at least 10 bits used for TAR autoincrement */ /* @@ -1102,7 +1106,7 @@ int ahbap_debugport_init(struct adiv5_dap *dap) * of link switchover */ if (!dap->ops) - dap->ops = &jtag_dp_ops; + dap->ops = &jtag_dap_ops; /* Default MEM-AP setup. * diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index e99461e80..1194d6ae3 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -35,6 +35,7 @@ */ #include "arm_jtag.h" +#include /* FIXME remove these JTAG-specific decls when mem_ap_read_buf_u32() * is no longer JTAG-specific @@ -205,6 +206,12 @@ struct dap_ops { */ bool is_swd; + /** Transport dependent selection routine, setup mainly. */ + int (*select)(struct command_context *ctx); + + /** Transport dependent DAP initialization and detection routine. */ + int (*init)(struct command_context *ctx); + /** Reads the DAP's IDCODe register. */ int (*queue_idcode_read)(struct adiv5_dap *dap, uint8_t *ack, uint32_t *data); @@ -230,6 +237,8 @@ struct dap_ops { int (*run)(struct adiv5_dap *dap); }; +extern oocd_feature_t oocd_transport_jtag_arm_dap_feature; + /** * Queue an IDCODE register read. This is primarily useful for SWD * transports, where it is required as part of link initialization. diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am index faed7592e..908e83457 100644 --- a/src/transport/Makefile.am +++ b/src/transport/Makefile.am @@ -2,9 +2,14 @@ include $(top_srcdir)/common.mk noinst_LTLIBRARIES = liboocdtransport.la liboocdtransport_la_SOURCES = \ - transport.c + transport.c \ + swd.c \ + swd_tcl.c \ + swd_libswd.c noinst_HEADERS = \ - transport.h + transport.h \ + swd.h \ + swd_libswd.h MAINTAINERCLEANFILES = $(srcdir)/Makefile.in diff --git a/src/transport/swd.c b/src/transport/swd.c index fa08f15da..3df8f4a7b 100644 --- a/src/transport/swd.c +++ b/src/transport/swd.c @@ -90,15 +90,15 @@ int oocd_transport_swd_setup(struct command_context *ctx) if (!jtag_interface->features) { jtag_interface->features = (oocd_feature_t *)calloc(1, sizeof(oocd_feature_t)); if (!jtag_interface->features) { - LOG_ERROR("Feature allocation memory failed!"); + LOG_ERROR("Transport - feature allocation memory failed!"); return ERROR_FAIL; } } - oocd_feature_add(jtag_interface->features, &oocd_transport_swd_libswd_feature); + oocd_feature_add(jtag_interface->features, &oocd_transport_swd_libswd_arm_dap_feature); feature_arm_dap = oocd_feature_find(jtag_interface->features, OOCD_FEATURE_ARM_DAP); if (!feature_arm_dap) { LOG_WARNING("Transport features '%s' failed to attach to interface '%s'!", \ - oocd_transport_swd_libswd_feature.name, jtag_interface->name); + oocd_transport_swd_libswd_arm_dap_feature.name, jtag_interface->name); LOG_ERROR("Interface '%s' does not provide/accept features required by transport '%s'!", \ jtag_interface->name, jtag_interface->transport->name); return ERROR_FAIL; @@ -148,7 +148,7 @@ const struct dap_ops oocd_target_arm_dap_ops_swd_default = { /** * Interface features template to add SWD support for your interface. - * Attach to driver feature list by driver setup routine. + * Attach to driver feature list by driver setup or interface definition. */ oocd_feature_t oocd_transport_swd_template_feature = { .name = OOCD_FEATURE_ARM_DAP, diff --git a/src/transport/swd_libswd.c b/src/transport/swd_libswd.c index 65e2c0e95..5e2a45255 100644 --- a/src/transport/swd_libswd.c +++ b/src/transport/swd_libswd.c @@ -264,7 +264,7 @@ const struct dap_ops oocd_dap_ops_swd_libswd = { /** * Interface features adds SWD support using LibSWD as middleware. */ -oocd_feature_t oocd_transport_swd_libswd_feature = { +oocd_feature_t oocd_transport_swd_libswd_arm_dap_feature = { .name = OOCD_FEATURE_ARM_DAP, .description = "ARM DAP SWD transport features based on LibSWD.", .body = (void *)&oocd_dap_ops_swd_libswd, diff --git a/src/transport/swd_libswd.h b/src/transport/swd_libswd.h index 85e1e2494..16a88241a 100644 --- a/src/transport/swd_libswd.h +++ b/src/transport/swd_libswd.h @@ -44,7 +44,7 @@ #define OOCD_TRANSPORT_SWD_LIBSWD_H extern const struct dap_ops oocd_dap_ops_swd_libswd; -extern oocd_feature_t oocd_transport_swd_libswd_feature; +extern oocd_feature_t oocd_transport_swd_libswd_arm_dap_feature; int oocd_transport_swd_libswd_register_commands(struct command_context *cmd_ctx); diff --git a/src/transport/transport.c b/src/transport/transport.c index aad0cfc58..d33788269 100644 --- a/src/transport/transport.c +++ b/src/transport/transport.c @@ -47,6 +47,8 @@ #include #include +#include +#include #include #include #include @@ -56,6 +58,8 @@ extern struct command_context *global_cmd_ctx; /*-----------------------------------------------------------------------*/ +extern struct jtag_interface *jtag_interface; + /* * Infrastructure internals */ @@ -84,29 +88,29 @@ int oocd_transport_register_all(void){ return ERROR_FAIL; if (oocd_transport_register(&swd_transport) != ERROR_OK) return ERROR_FAIL; + if (oocd_transport_register(&oocd_transport_swd) != ERROR_OK) + return ERROR_FAIL; return ERROR_OK; } +/** + * Set and setup transport for current session. + * This will find transport by given name, verify its configuration, + * then call driver specific select() routine. + * Note that select() sets up the internals, init() talks to hardware. + */ int oocd_transport_select(struct command_context *ctx, const char *name) { - LOG_INFO("TRANSPORT SELECT: %s", name); - /* name may only identify a known transport; - * caller guarantees session's transport isn't yet set.*/ for (oocd_transport_t *t = oocd_transport_list_all; t; t = t->next) { if (strcmp(t->name, name) == 0) { - int retval = t->select(ctx); - /* select() registers commands specific to this transport. - * init() will make hardware talk and initialize the target. - */ - if (retval == ERROR_OK) - session = t; - else - LOG_ERROR("Error selecting '%s' as transport", t->name); - return retval; + if (t->setup(ctx) == ERROR_FAIL) + return ERROR_FAIL; + session = t; + return ERROR_OK; } } - LOG_ERROR("No transport named '%s' is available.", name); + LOG_ERROR("Transport '%s' is not available!", name); return ERROR_FAIL; } @@ -179,7 +183,7 @@ int oocd_transport_register(oocd_transport_t *new_transport) } } - if (!new_transport->select || !new_transport->init) + if (!new_transport->setup) LOG_ERROR("invalid transport %s", new_transport->name); /* splice this into the list */ @@ -271,7 +275,14 @@ COMMAND_HANDLER(handle_oocd_transport_init) return ERROR_FAIL; } - return session->init(CMD_CTX); + oocd_feature_t *arm_dap_ops; + arm_dap_ops = oocd_feature_find(jtag_interface->features, OOCD_FEATURE_ARM_DAP); + if (arm_dap_ops == NULL) { + LOG_ERROR("Transport features '%s' not found!", OOCD_FEATURE_ARM_DAP); + return ERROR_FAIL; + } + struct dap_ops *dap = (struct dap_ops *) arm_dap_ops->body; + return dap->init(CMD_CTX); } COMMAND_HANDLER(handle_oocd_transport_list) diff --git a/src/transport/transport.h b/src/transport/transport.h index cc4c1a520..286fb3da9 100644 --- a/src/transport/transport.h +++ b/src/transport/transport.h @@ -50,31 +50,16 @@ typedef struct oocd_transport { */ const char *name; - /** - * When a transport is selected, this method registers - * its commands and activates the transport (e.g. resets - * the link). - * - * After those commands are registered, they will often - * be used for further configuration of the debug link. - */ - int (*select)(struct command_context *ctx); - - /** - * server startup uses this method to validate transport - * configuration. (For example, with JTAG this interrogates - * the scan chain against the list of expected TAPs.) - */ - int (*init)(struct command_context *ctx); + /** Internal transport setup routines. */ + int (*setup)(struct command_context *ctx); - /** - * Quit makes resources free and destroys transport. - */ + /** Internal transport deinitialization routines. */ int (*quit)(struct command_context *ctx); - /** - * Transports are stored in a singly linked list. - */ + /** Transport is configured and ready when this flag is set. */ + int configured; + + /** Transports are stored in a singly linked list. */ struct oocd_transport *next; } oocd_transport_t; -- 2.11.4.GIT