diff --git a/src/jtag/adapter.c b/src/jtag/adapter.c index 29a961338..d23f79ec4 100644 --- a/src/jtag/adapter.c +++ b/src/jtag/adapter.c @@ -411,6 +411,92 @@ COMMAND_HANDLER(handle_adapter_khz_command) return retval; } +COMMAND_HANDLER(handle_adapter_reset_de_assert) +{ + enum values { + VALUE_UNDEFINED = -1, + VALUE_DEASSERT = 0, + VALUE_ASSERT = 1, + }; + enum values value; + enum values srst = VALUE_UNDEFINED; + enum values trst = VALUE_UNDEFINED; + enum reset_types jtag_reset_config = jtag_get_reset_config(); + char *signal; + + if (CMD_ARGC == 0) { + if (transport_is_jtag()) { + if (jtag_reset_config & RESET_HAS_TRST) + signal = jtag_get_trst() ? "asserted" : "deasserted"; + else + signal = "not present"; + command_print(CMD, "trst %s", signal); + } + + if (jtag_reset_config & RESET_HAS_SRST) + signal = jtag_get_srst() ? "asserted" : "deasserted"; + else + signal = "not present"; + command_print(CMD, "srst %s", signal); + + return ERROR_OK; + } + + if (CMD_ARGC != 1 && CMD_ARGC != 3) + return ERROR_COMMAND_SYNTAX_ERROR; + + value = (strcmp(CMD_NAME, "assert") == 0) ? VALUE_ASSERT : VALUE_DEASSERT; + if (strcmp(CMD_ARGV[0], "srst") == 0) + srst = value; + else if (strcmp(CMD_ARGV[0], "trst") == 0) + trst = value; + else + return ERROR_COMMAND_SYNTAX_ERROR; + + if (CMD_ARGC == 3) { + if (strcmp(CMD_ARGV[1], "assert") == 0) + value = VALUE_ASSERT; + else if (strcmp(CMD_ARGV[1], "deassert") == 0) + value = VALUE_DEASSERT; + else + return ERROR_COMMAND_SYNTAX_ERROR; + + if (strcmp(CMD_ARGV[2], "srst") == 0 && srst == VALUE_UNDEFINED) + srst = value; + else if (strcmp(CMD_ARGV[2], "trst") == 0 && trst == VALUE_UNDEFINED) + trst = value; + else + return ERROR_COMMAND_SYNTAX_ERROR; + } + + if (trst == VALUE_UNDEFINED) { + if (transport_is_jtag()) + trst = jtag_get_trst() ? VALUE_ASSERT : VALUE_DEASSERT; + else + trst = VALUE_DEASSERT; /* unused, safe value */ + } + + if (srst == VALUE_UNDEFINED) { + if (jtag_reset_config & RESET_HAS_SRST) + srst = jtag_get_srst() ? VALUE_ASSERT : VALUE_DEASSERT; + else + srst = VALUE_DEASSERT; /* unused, safe value */ + } + + if (trst == VALUE_ASSERT && !transport_is_jtag()) { + LOG_ERROR("transport has no trst signal"); + return ERROR_FAIL; + } + + if (srst == VALUE_ASSERT && !(jtag_reset_config & RESET_HAS_SRST)) { + LOG_ERROR("adapter has no srst signal"); + return ERROR_FAIL; + } + + return adapter_resets((trst == VALUE_DEASSERT) ? TRST_DEASSERT : TRST_ASSERT, + (srst == VALUE_DEASSERT) ? SRST_DEASSERT : SRST_ASSERT); +} + #ifndef HAVE_JTAG_MINIDRIVER_H #ifdef HAVE_LIBUSB_GET_PORT_NUMBERS COMMAND_HANDLER(handle_usb_location_command) @@ -448,6 +534,20 @@ static const struct command_registration adapter_command_handlers[] = { .chain = adapter_usb_command_handlers, }, #endif /* MINIDRIVER */ + { + .name = "assert", + .handler = handle_adapter_reset_de_assert, + .mode = COMMAND_EXEC, + .help = "Controls SRST and TRST lines.", + .usage = "|deassert [srst|trst [assert|deassert srst|trst]]", + }, + { + .name = "deassert", + .handler = handle_adapter_reset_de_assert, + .mode = COMMAND_EXEC, + .help = "Controls SRST and TRST lines.", + .usage = "|assert [srst|trst [deassert|assert srst|trst]]", + }, COMMAND_REGISTRATION_DONE }; diff --git a/src/jtag/core.c b/src/jtag/core.c index a498a8cf4..871b4d2bd 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -35,6 +35,8 @@ #include "interface.h" #include #include +#include +#include #ifdef HAVE_STRINGS_H #include @@ -1888,6 +1890,57 @@ bool transport_is_jtag(void) return get_current_transport() == &jtag_transport; } +int adapter_resets(int trst, int srst) +{ + if (get_current_transport() == NULL) { + LOG_ERROR("transport is not selected"); + return ERROR_FAIL; + } + + if (transport_is_jtag()) { + if (srst == SRST_ASSERT && !(jtag_reset_config & RESET_HAS_SRST)) { + LOG_ERROR("adapter has no srst signal"); + return ERROR_FAIL; + } + + /* adapters without trst signal will eventually use tlr sequence */ + jtag_add_reset(trst, srst); + return ERROR_OK; + } else if (transport_is_swd()) { + if (trst == TRST_ASSERT) { + LOG_ERROR("transport swd has no trst signal"); + return ERROR_FAIL; + } + + if (srst == SRST_ASSERT && !(jtag_reset_config & RESET_HAS_SRST)) { + LOG_ERROR("adapter has no srst signal"); + return ERROR_FAIL; + } + swd_add_reset(srst); + return ERROR_OK; + } else if (transport_is_hla()) { + if (trst == TRST_ASSERT) { + LOG_ERROR("transport %s has no trst signal", + get_current_transport()->name); + return ERROR_FAIL; + } + + if (srst == SRST_ASSERT && !(jtag_reset_config & RESET_HAS_SRST)) { + LOG_ERROR("adapter has no srst signal"); + return ERROR_FAIL; + } + return hl_interface_reset(srst); + } + + if (trst == TRST_DEASSERT && srst == SRST_DEASSERT) + return ERROR_OK; + + LOG_ERROR("reset is not supported on transport %s", + get_current_transport()->name); + + return ERROR_FAIL; +} + void adapter_assert_reset(void) { if (transport_is_jtag()) { diff --git a/src/jtag/hla/hla_interface.c b/src/jtag/hla/hla_interface.c index 7d9dea05e..b50cb9c0f 100644 --- a/src/jtag/hla/hla_interface.c +++ b/src/jtag/hla/hla_interface.c @@ -148,6 +148,21 @@ int hl_interface_init_reset(void) return ERROR_OK; } +/* FIXME: hla abuses of jtag_add_reset() to track srst status and for timings */ +int hl_interface_reset(int srst) +{ + int result; + + if (srst == 1) { + jtag_add_reset(0, 1); + result = hl_if.layout->api->assert_srst(hl_if.handle, 0); + } else { + result = hl_if.layout->api->assert_srst(hl_if.handle, 1); + jtag_add_reset(0, 0); + } + return result; +} + static int hl_interface_khz(int khz, int *jtag_speed) { if (hl_if.layout->api->speed == NULL) diff --git a/src/jtag/hla/hla_interface.h b/src/jtag/hla/hla_interface.h index 262025e98..84b0098b6 100644 --- a/src/jtag/hla/hla_interface.h +++ b/src/jtag/hla/hla_interface.h @@ -67,4 +67,13 @@ int hl_interface_init_target(struct target *t); int hl_interface_init_reset(void); int hl_interface_override_target(const char **targetname); +#if BUILD_HLADAPTER == 1 +int hl_interface_reset(int srst); +#else +static inline int hl_interface_reset(int srst) +{ + return ERROR_OK; +} +#endif + #endif /* OPENOCD_JTAG_HLA_HLA_INTERFACE_H */ diff --git a/src/jtag/interface.h b/src/jtag/interface.h index ba3dea6d7..410eef980 100644 --- a/src/jtag/interface.h +++ b/src/jtag/interface.h @@ -326,6 +326,7 @@ struct jtag_interface { extern const char * const jtag_only[]; +int adapter_resets(int assert_trst, int assert_srst); void adapter_assert_reset(void); void adapter_deassert_reset(void); int adapter_config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol, diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h index c93243c47..ff1783158 100644 --- a/src/jtag/jtag.h +++ b/src/jtag/jtag.h @@ -76,6 +76,14 @@ typedef enum tap_state { #endif } tap_state_t; +/** + * Defines arguments for reset functions + */ +#define SRST_DEASSERT 0 +#define SRST_ASSERT 1 +#define TRST_DEASSERT 0 +#define TRST_ASSERT 1 + /** * Function tap_state_name * Returns a string suitable for display representing the JTAG tap_state