ipdbg: fix double free of virtual-ir data
[openocd.git] / src / jtag / adapter.c
index 991338be8ad63346ac9773ddf3ea6a731421b9cc..bbf1cb3d2e2e8c4a8f04c3fd53697058579fb048 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright (C) 2005 by Dominic Rath <Dominic.Rath@gmx.de>
  * Copyright (C) 2007-2010 Ã˜yvind Harboe <oyvind.harboe@zylin.com>
 #include "interfaces.h"
 #include <transport/transport.h>
 
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-
 /**
  * @file
  * Holds support for configuring debug adapters from TCl scripts.
@@ -36,22 +32,87 @@ enum adapter_clk_mode {
        CLOCK_MODE_RCLK
 };
 
+#define DEFAULT_CLOCK_SPEED_KHZ                100U
+
 /**
  * Adapter configuration
  */
 static struct {
        bool adapter_initialized;
        char *usb_location;
+       char *serial;
        enum adapter_clk_mode clock_mode;
        int speed_khz;
        int rclk_fallback_speed_khz;
+       struct adapter_gpio_config gpios[ADAPTER_GPIO_IDX_NUM];
+       bool gpios_initialized; /* Initialization of GPIOs to their unset values performed at run time */
 } adapter_config;
 
+static const struct gpio_map {
+       const char *name;
+       enum adapter_gpio_direction direction;
+       bool permit_drive_option;
+       bool permit_init_state_option;
+} gpio_map[ADAPTER_GPIO_IDX_NUM] = {
+       [ADAPTER_GPIO_IDX_TDO] = { "tdo", ADAPTER_GPIO_DIRECTION_INPUT, false, true, },
+       [ADAPTER_GPIO_IDX_TDI] = { "tdi", ADAPTER_GPIO_DIRECTION_OUTPUT, true, true, },
+       [ADAPTER_GPIO_IDX_TMS] = { "tms", ADAPTER_GPIO_DIRECTION_OUTPUT, true, true, },
+       [ADAPTER_GPIO_IDX_TCK] = { "tck", ADAPTER_GPIO_DIRECTION_OUTPUT, true, true, },
+       [ADAPTER_GPIO_IDX_SWDIO] = { "swdio", ADAPTER_GPIO_DIRECTION_BIDIRECTIONAL, true, true, },
+       [ADAPTER_GPIO_IDX_SWDIO_DIR] = { "swdio_dir", ADAPTER_GPIO_DIRECTION_OUTPUT, true, false, },
+       [ADAPTER_GPIO_IDX_SWCLK] = { "swclk", ADAPTER_GPIO_DIRECTION_OUTPUT, true, true, },
+       [ADAPTER_GPIO_IDX_TRST] = { "trst", ADAPTER_GPIO_DIRECTION_OUTPUT, false, true, },
+       [ADAPTER_GPIO_IDX_SRST] = { "srst", ADAPTER_GPIO_DIRECTION_OUTPUT, false, true, },
+       [ADAPTER_GPIO_IDX_LED] = { "led", ADAPTER_GPIO_DIRECTION_OUTPUT, true, true, },
+};
+
 bool is_adapter_initialized(void)
 {
        return adapter_config.adapter_initialized;
 }
 
+/* For convenience of the bit-banging drivers keep the gpio_config drive
+ * settings for srst and trst in sync with values set by the "adapter
+ * reset_config" command.
+ */
+static void sync_adapter_reset_with_gpios(void)
+{
+       enum reset_types cfg = jtag_get_reset_config();
+       if (cfg & RESET_SRST_PUSH_PULL)
+               adapter_config.gpios[ADAPTER_GPIO_IDX_SRST].drive = ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL;
+       else
+               adapter_config.gpios[ADAPTER_GPIO_IDX_SRST].drive = ADAPTER_GPIO_DRIVE_MODE_OPEN_DRAIN;
+       if (cfg & RESET_TRST_OPEN_DRAIN)
+               adapter_config.gpios[ADAPTER_GPIO_IDX_TRST].drive = ADAPTER_GPIO_DRIVE_MODE_OPEN_DRAIN;
+       else
+               adapter_config.gpios[ADAPTER_GPIO_IDX_TRST].drive = ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL;
+}
+
+static void adapter_driver_gpios_init(void)
+{
+       if (adapter_config.gpios_initialized)
+               return;
+
+       for (int i = 0; i < ADAPTER_GPIO_IDX_NUM; ++i) {
+               /* Use ADAPTER_GPIO_NOT_SET as the sentinel 'unset' value. */
+               adapter_config.gpios[i].gpio_num = ADAPTER_GPIO_NOT_SET;
+               adapter_config.gpios[i].chip_num = ADAPTER_GPIO_NOT_SET;
+               if (gpio_map[i].direction == ADAPTER_GPIO_DIRECTION_INPUT)
+                       adapter_config.gpios[i].init_state = ADAPTER_GPIO_INIT_STATE_INPUT;
+       }
+
+       /* Drivers assume active low, and this is the normal behaviour for reset
+        * lines so should be the default. */
+       adapter_config.gpios[ADAPTER_GPIO_IDX_SRST].active_low = true;
+       adapter_config.gpios[ADAPTER_GPIO_IDX_TRST].active_low = true;
+       sync_adapter_reset_with_gpios();
+
+       /* JTAG GPIOs should be inactive except for tms */
+       adapter_config.gpios[ADAPTER_GPIO_IDX_TMS].init_state = ADAPTER_GPIO_INIT_STATE_ACTIVE;
+
+       adapter_config.gpios_initialized = true;
+}
+
 /**
  * Do low-level setup like initializing registers, output signals,
  * and clocking.
@@ -68,35 +129,45 @@ int adapter_init(struct command_context *cmd_ctx)
                return ERROR_JTAG_INVALID_INTERFACE;
        }
 
+       adapter_driver_gpios_init();
+
        int retval;
+
+       /* If the adapter supports configurable speed but the speed is not configured,
+        * provide a hint to the user. */
+       if (adapter_driver->speed && adapter_config.clock_mode == CLOCK_MODE_UNSELECTED) {
+               LOG_WARNING("An adapter speed is not selected in the init scripts."
+                       " OpenOCD will try to run the adapter at very low speed (%d kHz).",
+                       DEFAULT_CLOCK_SPEED_KHZ);
+               LOG_WARNING("To remove this warnings and achieve reasonable communication speed with the target,"
+                   " set \"adapter speed\" or \"jtag_rclk\" in the init scripts.");
+               retval = adapter_config_khz(DEFAULT_CLOCK_SPEED_KHZ);
+               if (retval != ERROR_OK)
+                       return ERROR_JTAG_INIT_FAILED;
+       }
+
        retval = adapter_driver->init();
        if (retval != ERROR_OK)
                return retval;
        adapter_config.adapter_initialized = true;
 
        if (!adapter_driver->speed) {
-               LOG_INFO("This adapter doesn't support configurable speed");
+               LOG_INFO("Note: The adapter \"%s\" doesn't support configurable speed", adapter_driver->name);
                return ERROR_OK;
        }
 
-       if (adapter_config.clock_mode == CLOCK_MODE_UNSELECTED) {
-               LOG_ERROR("An adapter speed is not selected in the init script."
-                       " Insert a call to \"adapter speed\" or \"jtag_rclk\" to proceed.");
-               return ERROR_JTAG_INIT_FAILED;
-       }
-
-       int requested_khz = jtag_get_speed_khz();
+       int requested_khz = adapter_get_speed_khz();
        int actual_khz = requested_khz;
-       int jtag_speed_var = 0;
-       retval = jtag_get_speed(&jtag_speed_var);
+       int speed_var = 0;
+       retval = adapter_get_speed(&speed_var);
        if (retval != ERROR_OK)
                return retval;
-       retval = adapter_driver->speed(jtag_speed_var);
+       retval = adapter_driver->speed(speed_var);
        if (retval != ERROR_OK)
                return retval;
-       retval = jtag_get_speed_readable(&actual_khz);
+       retval = adapter_get_speed_readable(&actual_khz);
        if (retval != ERROR_OK)
-               LOG_INFO("adapter-specific clock speed value %d", jtag_speed_var);
+               LOG_INFO("adapter-specific clock speed value %d", speed_var);
        else if (actual_khz) {
                /* Adaptive clocking -- JTAG-specific */
                if ((adapter_config.clock_mode == CLOCK_MODE_RCLK)
@@ -120,6 +191,9 @@ int adapter_quit(void)
                        LOG_ERROR("failed: %d", result);
        }
 
+       free(adapter_config.serial);
+       free(adapter_config.usb_location);
+
        struct jtag_tap *t = jtag_all_taps();
        while (t) {
                struct jtag_tap *n = t->next_tap;
@@ -130,31 +204,31 @@ int adapter_quit(void)
        return ERROR_OK;
 }
 
-unsigned jtag_get_speed_khz(void)
+unsigned int adapter_get_speed_khz(void)
 {
        return adapter_config.speed_khz;
 }
 
-static int adapter_khz_to_speed(unsigned khz, int *speed)
+static int adapter_khz_to_speed(unsigned int khz, int *speed)
 {
-       LOG_DEBUG("convert khz to interface specific speed value");
+       LOG_DEBUG("convert khz to adapter specific speed value");
        adapter_config.speed_khz = khz;
        if (!is_adapter_initialized())
                return ERROR_OK;
-       LOG_DEBUG("have interface set up");
+       LOG_DEBUG("have adapter set up");
        if (!adapter_driver->khz) {
-               LOG_ERROR("Translation from khz to jtag_speed not implemented");
+               LOG_ERROR("Translation from khz to adapter speed not implemented");
                return ERROR_FAIL;
        }
        int speed_div1;
-       int retval = adapter_driver->khz(jtag_get_speed_khz(), &speed_div1);
+       int retval = adapter_driver->khz(adapter_get_speed_khz(), &speed_div1);
        if (retval != ERROR_OK)
                return retval;
        *speed = speed_div1;
        return ERROR_OK;
 }
 
-static int jtag_rclk_to_speed(unsigned fallback_speed_khz, int *speed)
+static int adapter_rclk_to_speed(unsigned int fallback_speed_khz, int *speed)
 {
        int retval = adapter_khz_to_speed(0, speed);
        if ((retval != ERROR_OK) && fallback_speed_khz) {
@@ -164,61 +238,66 @@ static int jtag_rclk_to_speed(unsigned fallback_speed_khz, int *speed)
        return retval;
 }
 
-static int jtag_set_speed(int speed)
+static int adapter_set_speed(int speed)
 {
        /* this command can be called during CONFIG,
-        * in which case jtag isn't initialized */
+        * in which case adapter isn't initialized */
        return is_adapter_initialized() ? adapter_driver->speed(speed) : ERROR_OK;
 }
 
-int jtag_config_khz(unsigned khz)
+int adapter_config_khz(unsigned int khz)
 {
-       LOG_DEBUG("handle jtag khz");
+       LOG_DEBUG("handle adapter khz");
        adapter_config.clock_mode = CLOCK_MODE_KHZ;
        int speed = 0;
        int retval = adapter_khz_to_speed(khz, &speed);
-       return (retval != ERROR_OK) ? retval : jtag_set_speed(speed);
+       return (retval != ERROR_OK) ? retval : adapter_set_speed(speed);
 }
 
-int jtag_config_rclk(unsigned fallback_speed_khz)
+int adapter_config_rclk(unsigned int fallback_speed_khz)
 {
-       LOG_DEBUG("handle jtag rclk");
+       LOG_DEBUG("handle adapter rclk");
        adapter_config.clock_mode = CLOCK_MODE_RCLK;
        adapter_config.rclk_fallback_speed_khz = fallback_speed_khz;
        int speed = 0;
-       int retval = jtag_rclk_to_speed(fallback_speed_khz, &speed);
-       return (retval != ERROR_OK) ? retval : jtag_set_speed(speed);
+       int retval = adapter_rclk_to_speed(fallback_speed_khz, &speed);
+       return (retval != ERROR_OK) ? retval : adapter_set_speed(speed);
 }
 
-int jtag_get_speed(int *speed)
+int adapter_get_speed(int *speed)
 {
        switch (adapter_config.clock_mode) {
                case CLOCK_MODE_KHZ:
-                       adapter_khz_to_speed(jtag_get_speed_khz(), speed);
+                       adapter_khz_to_speed(adapter_get_speed_khz(), speed);
                        break;
                case CLOCK_MODE_RCLK:
-                       jtag_rclk_to_speed(adapter_config.rclk_fallback_speed_khz, speed);
+                       adapter_rclk_to_speed(adapter_config.rclk_fallback_speed_khz, speed);
                        break;
                default:
-                       LOG_ERROR("BUG: unknown jtag clock mode");
+                       LOG_ERROR("BUG: unknown adapter clock mode");
                        return ERROR_FAIL;
        }
        return ERROR_OK;
 }
 
-int jtag_get_speed_readable(int *khz)
+int adapter_get_speed_readable(int *khz)
 {
-       int jtag_speed_var = 0;
-       int retval = jtag_get_speed(&jtag_speed_var);
+       int speed_var = 0;
+       int retval = adapter_get_speed(&speed_var);
        if (retval != ERROR_OK)
                return retval;
        if (!is_adapter_initialized())
                return ERROR_OK;
        if (!adapter_driver->speed_div) {
-               LOG_ERROR("Translation from jtag_speed to khz not implemented");
+               LOG_ERROR("Translation from adapter speed to khz not implemented");
                return ERROR_FAIL;
        }
-       return adapter_driver->speed_div(jtag_speed_var, khz);
+       return adapter_driver->speed_div(speed_var, khz);
+}
+
+const char *adapter_get_required_serial(void)
+{
+       return adapter_config.serial;
 }
 
 /*
@@ -296,21 +375,18 @@ done:
        return equal;
 }
 
-static int jim_adapter_name(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
+COMMAND_HANDLER(handle_adapter_name)
 {
-       struct jim_getopt_info goi;
-       jim_getopt_setup(&goi, interp, argc-1, argv + 1);
-
        /* return the name of the interface */
        /* TCL code might need to know the exact type... */
        /* FUTURE: we allow this as a means to "set" the interface. */
-       if (goi.argc != 0) {
-               Jim_WrongNumArgs(goi.interp, 1, goi.argv-1, "(no params)");
-               return JIM_ERR;
-       }
-       const char *name = adapter_driver ? adapter_driver->name : NULL;
-       Jim_SetResultString(goi.interp, name ? name : "undefined", -1);
-       return JIM_OK;
+
+       if (CMD_ARGC != 0)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       command_print(CMD, "%s", adapter_driver ? adapter_driver->name : "undefined");
+
+       return ERROR_OK;
 }
 
 COMMAND_HANDLER(adapter_transports_command)
@@ -365,8 +441,7 @@ COMMAND_HANDLER(handle_adapter_driver_command)
                        continue;
 
                if (adapter_drivers[i]->commands) {
-                       retval = register_commands(CMD_CTX, NULL,
-                                       adapter_drivers[i]->commands);
+                       retval = register_commands(CMD_CTX, NULL, adapter_drivers[i]->commands);
                        if (retval != ERROR_OK)
                                return retval;
                }
@@ -524,6 +599,8 @@ next:
                old_cfg &= ~mask;
                new_cfg |= old_cfg;
                jtag_set_reset_config(new_cfg);
+               sync_adapter_reset_with_gpios();
+
        } else
                new_cfg = jtag_get_reset_config();
 
@@ -640,13 +717,13 @@ COMMAND_HANDLER(handle_adapter_speed_command)
                unsigned khz = 0;
                COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], khz);
 
-               retval = jtag_config_khz(khz);
+               retval = adapter_config_khz(khz);
                if (retval != ERROR_OK)
                        return retval;
        }
 
-       int cur_speed = jtag_get_speed_khz();
-       retval = jtag_get_speed_readable(&cur_speed);
+       int cur_speed = adapter_get_speed_khz();
+       retval = adapter_get_speed_readable(&cur_speed);
        if (retval != ERROR_OK)
                return retval;
 
@@ -658,6 +735,16 @@ COMMAND_HANDLER(handle_adapter_speed_command)
        return retval;
 }
 
+COMMAND_HANDLER(handle_adapter_serial_command)
+{
+       if (CMD_ARGC != 1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       free(adapter_config.serial);
+       adapter_config.serial = strdup(CMD_ARGV[0]);
+       return ERROR_OK;
+}
+
 COMMAND_HANDLER(handle_adapter_reset_de_assert)
 {
        enum values {
@@ -744,6 +831,219 @@ COMMAND_HANDLER(handle_adapter_reset_de_assert)
                                                  (srst == VALUE_DEASSERT) ? SRST_DEASSERT : SRST_ASSERT);
 }
 
+static int get_gpio_index(const char *signal_name)
+{
+       for (int i = 0; i < ADAPTER_GPIO_IDX_NUM; ++i) {
+               if (strcmp(gpio_map[i].name, signal_name) == 0)
+                       return i;
+       }
+       return -1;
+}
+
+static COMMAND_HELPER(helper_adapter_gpio_print_config, enum adapter_gpio_config_index gpio_idx)
+{
+       struct adapter_gpio_config *gpio_config = &adapter_config.gpios[gpio_idx];
+       const char *active_state = gpio_config->active_low ? "low" : "high";
+       const char *dir = "";
+       const char *drive = "";
+       const char *pull = "";
+       const char *init_state = "";
+
+       if (gpio_config->gpio_num == ADAPTER_GPIO_NOT_SET) {
+               command_print(CMD, "adapter gpio %s: not configured", gpio_map[gpio_idx].name);
+               return ERROR_OK;
+       }
+
+       switch (gpio_map[gpio_idx].direction) {
+       case ADAPTER_GPIO_DIRECTION_INPUT:
+               dir = "input";
+               break;
+       case ADAPTER_GPIO_DIRECTION_OUTPUT:
+               dir = "output";
+               break;
+       case ADAPTER_GPIO_DIRECTION_BIDIRECTIONAL:
+               dir = "bidirectional";
+               break;
+       }
+
+       if (gpio_map[gpio_idx].permit_drive_option) {
+               switch (gpio_config->drive) {
+               case ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL:
+                       drive = ", push-pull";
+                       break;
+               case ADAPTER_GPIO_DRIVE_MODE_OPEN_DRAIN:
+                       drive = ", open-drain";
+                       break;
+               case ADAPTER_GPIO_DRIVE_MODE_OPEN_SOURCE:
+                       drive = ", open-source";
+                       break;
+               }
+       }
+
+       switch (gpio_config->pull) {
+       case ADAPTER_GPIO_PULL_NONE:
+               pull = ", pull-none";
+               break;
+       case ADAPTER_GPIO_PULL_UP:
+               pull = ", pull-up";
+               break;
+       case ADAPTER_GPIO_PULL_DOWN:
+               pull = ", pull-down";
+               break;
+       }
+
+       if (gpio_map[gpio_idx].permit_init_state_option) {
+               switch (gpio_config->init_state) {
+               case ADAPTER_GPIO_INIT_STATE_INACTIVE:
+                       init_state = ", init-state inactive";
+                       break;
+               case ADAPTER_GPIO_INIT_STATE_ACTIVE:
+                       init_state = ", init-state active";
+                       break;
+               case ADAPTER_GPIO_INIT_STATE_INPUT:
+                       init_state = ", init-state input";
+                       break;
+               }
+       }
+
+       command_print(CMD, "adapter gpio %s (%s): num %u, chip %d, active-%s%s%s%s",
+               gpio_map[gpio_idx].name, dir, gpio_config->gpio_num, (int)gpio_config->chip_num, active_state,
+               drive, pull, init_state);
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(helper_adapter_gpio_print_all_configs)
+{
+       for (int i = 0; i < ADAPTER_GPIO_IDX_NUM; ++i)
+               CALL_COMMAND_HANDLER(helper_adapter_gpio_print_config, i);
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(adapter_gpio_config_handler)
+{
+       unsigned int i = 1;
+       struct adapter_gpio_config *gpio_config;
+
+       adapter_driver_gpios_init();
+
+       if (CMD_ARGC == 0) {
+               CALL_COMMAND_HANDLER(helper_adapter_gpio_print_all_configs);
+               return ERROR_OK;
+       }
+
+       int gpio_idx = get_gpio_index(CMD_ARGV[0]);
+       if (gpio_idx == -1) {
+               LOG_ERROR("adapter has no gpio named %s", CMD_ARGV[0]);
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       if (CMD_ARGC == 1) {
+               CALL_COMMAND_HANDLER(helper_adapter_gpio_print_config, gpio_idx);
+               return ERROR_OK;
+       }
+
+       gpio_config = &adapter_config.gpios[gpio_idx];
+       while (i < CMD_ARGC) {
+               LOG_DEBUG("Processing %s", CMD_ARGV[i]);
+
+               if (isdigit(*CMD_ARGV[i])) {
+                       COMMAND_PARSE_NUMBER(uint, CMD_ARGV[i], gpio_config->gpio_num);
+                       ++i;
+                       continue;
+               }
+
+               if (strcmp(CMD_ARGV[i], "-chip") == 0) {
+                       if (CMD_ARGC - i < 2) {
+                               LOG_ERROR("-chip option requires a parameter");
+                               return ERROR_FAIL;
+                       }
+                       LOG_DEBUG("-chip arg is %s", CMD_ARGV[i + 1]);
+                       COMMAND_PARSE_NUMBER(uint, CMD_ARGV[i + 1], gpio_config->chip_num);
+                       i += 2;
+                       continue;
+               }
+
+               if (strcmp(CMD_ARGV[i], "-active-high") == 0) {
+                       ++i;
+                       gpio_config->active_low = false;
+                       continue;
+               }
+               if (strcmp(CMD_ARGV[i], "-active-low") == 0) {
+                       ++i;
+                       gpio_config->active_low = true;
+                       continue;
+               }
+
+               if (gpio_map[gpio_idx].permit_drive_option) {
+                       if (strcmp(CMD_ARGV[i], "-push-pull") == 0) {
+                               ++i;
+                               gpio_config->drive = ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL;
+                               continue;
+                       }
+                       if (strcmp(CMD_ARGV[i], "-open-drain") == 0) {
+                               ++i;
+                               gpio_config->drive = ADAPTER_GPIO_DRIVE_MODE_OPEN_DRAIN;
+                               continue;
+                       }
+                       if (strcmp(CMD_ARGV[i], "-open-source") == 0) {
+                               ++i;
+                               gpio_config->drive = ADAPTER_GPIO_DRIVE_MODE_OPEN_SOURCE;
+                               continue;
+                       }
+               }
+
+               if (strcmp(CMD_ARGV[i], "-pull-none") == 0) {
+                       ++i;
+                       gpio_config->pull = ADAPTER_GPIO_PULL_NONE;
+                       continue;
+               }
+               if (strcmp(CMD_ARGV[i], "-pull-up") == 0) {
+                       ++i;
+                       gpio_config->pull = ADAPTER_GPIO_PULL_UP;
+                       continue;
+               }
+               if (strcmp(CMD_ARGV[i], "-pull-down") == 0) {
+                       ++i;
+                       gpio_config->pull = ADAPTER_GPIO_PULL_DOWN;
+                       continue;
+               }
+
+               if (gpio_map[gpio_idx].permit_init_state_option) {
+                       if (strcmp(CMD_ARGV[i], "-init-inactive") == 0) {
+                               ++i;
+                               gpio_config->init_state = ADAPTER_GPIO_INIT_STATE_INACTIVE;
+                               continue;
+                       }
+                       if (strcmp(CMD_ARGV[i], "-init-active") == 0) {
+                               ++i;
+                               gpio_config->init_state = ADAPTER_GPIO_INIT_STATE_ACTIVE;
+                               continue;
+                       }
+
+                       if (gpio_map[gpio_idx].direction == ADAPTER_GPIO_DIRECTION_BIDIRECTIONAL &&
+                                       strcmp(CMD_ARGV[i], "-init-input") == 0) {
+                               ++i;
+                               gpio_config->init_state = ADAPTER_GPIO_INIT_STATE_INPUT;
+                               continue;
+                       }
+               }
+
+               LOG_ERROR("illegal option for adapter %s %s: %s",
+                               CMD_NAME, gpio_map[gpio_idx].name, CMD_ARGV[i]);
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       /* Force swdio_dir init state to be compatible with swdio init state */
+       if (gpio_idx == ADAPTER_GPIO_IDX_SWDIO)
+               adapter_config.gpios[ADAPTER_GPIO_IDX_SWDIO_DIR].init_state =
+               (gpio_config->init_state == ADAPTER_GPIO_INIT_STATE_INPUT) ?
+               ADAPTER_GPIO_INIT_STATE_INACTIVE :
+               ADAPTER_GPIO_INIT_STATE_ACTIVE;
+
+       return ERROR_OK;
+}
+
 #ifdef HAVE_LIBUSB_GET_PORT_NUMBERS
 COMMAND_HANDLER(handle_usb_location_command)
 {
@@ -805,6 +1105,13 @@ static const struct command_registration adapter_command_handlers[] = {
                        "With or without argument, display current setting.",
                .usage = "[khz]",
        },
+       {
+               .name = "serial",
+               .handler = handle_adapter_serial_command,
+               .mode = COMMAND_CONFIG,
+               .help = "Set the serial number of the adapter",
+               .usage = "serial_string",
+       },
        {
                .name = "list",
                .handler = handle_adapter_list_command,
@@ -815,9 +1122,10 @@ static const struct command_registration adapter_command_handlers[] = {
        {
                .name = "name",
                .mode = COMMAND_ANY,
-               .jim_handler = jim_adapter_name,
+               .handler = handle_adapter_name,
                .help = "Returns the name of the currently "
                        "selected adapter (driver)",
+               .usage = "",
        },
        {
                .name = "srst",
@@ -854,6 +1162,19 @@ static const struct command_registration adapter_command_handlers[] = {
                .help = "Controls SRST and TRST lines.",
                .usage = "|assert [srst|trst [deassert|assert srst|trst]]",
        },
+       {
+               .name = "gpio",
+               .handler = adapter_gpio_config_handler,
+               .mode = COMMAND_CONFIG,
+               .help = "gpio adapter command group",
+               .usage = "[ tdo|tdi|tms|tck|trst|swdio|swdio_dir|swclk|srst|led"
+                       "[gpio_number] "
+                       "[-chip chip_number] "
+                       "[-active-high|-active-low] "
+                       "[-push-pull|-open-drain|-open-source] "
+                       "[-pull-none|-pull-up|-pull-down]"
+                       "[-init-inactive|-init-active|-init-input] ]",
+       },
        COMMAND_REGISTRATION_DONE
 };
 
@@ -886,7 +1207,18 @@ static const struct command_registration interface_command_handlers[] = {
  * @todo Remove internal assumptions that all debug adapters use JTAG for
  * transport.  Various types and data structures are not named generically.
  */
-int interface_register_commands(struct command_context *ctx)
+int adapter_register_commands(struct command_context *ctx)
 {
        return register_commands(ctx, NULL, interface_command_handlers);
 }
+
+const char *adapter_gpio_get_name(enum adapter_gpio_config_index idx)
+{
+       return gpio_map[idx].name;
+}
+
+/* Allow drivers access to the GPIO configuration */
+const struct adapter_gpio_config *adapter_gpio_get_config(void)
+{
+       return adapter_config.gpios;
+}

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)