This is an automated email from Gerrit. "zapb <[email protected]>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/9087
-- gerrit commit b1d8a7c7789d0a786e94c9b6969b2e9ea0ef65fe Author: Marc Schink <[email protected]> Date: Sun Jun 15 10:52:49 2025 +0000 adapter: Add support for 'exit state' of GPIO signal In addition to a signal's 'init state', add support to configure its 'exit state'. This option determines the state and configuration of a pin when the adapter terminates its operation. Change-Id: I0577ed9e3bc79715290b4e6a21e3f64c66f2ff9a Signed-off-by: Marc Schink <[email protected]> diff --git a/doc/openocd.texi b/doc/openocd.texi index 01ca7adfb3..c8aa922db1 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2443,6 +2443,7 @@ dict get [adapter list] ftdi @option{-push-pull} | @option{-open-drain} | @option{-open-source} | @ @option{-pull-none} | @option{-pull-up} | @option{-pull-down} | @ @option{-init-inactive} | @option{-init-active} | @option{-init-input} @ + @option{-exit-inactive} | @option{-exit-active} | @option{-exit-input} | @option{-exit-no-change} @ ] ]} Define the GPIO mapping that the adapter will use. The following signals can be @@ -2477,11 +2478,14 @@ equivalent to issuing the single command @command{gpio led 7 -chip 1 signals which are inputs. The drive mode for the srst and trst signals must be set with the @command{adapter reset_config} command. It is not permissible to set the initial state of swdio_dir as it is derived from the initial state of -swdio. The command @command{adapter gpio} prints the current configuration for -all GPIOs while the command @command{adapter gpio gpio_name} prints the current -configuration for gpio_name. Not all adapters support this generic GPIO mapping, -some require their own commands to define the GPIOs used. Adapters that support -the generic mapping may not support all of the listed options. +swdio. Accordingly, the final state before the adapter terminates its operation, +so-called “exit state”, can be set. By default the state and configuration of an +output pin is not changed when the driver terminates its operation. The +command @command{adapter gpio} prints the current configuration for all GPIOs +while the command @command{adapter gpio gpio_name} prints the current configuration +for gpio_name. Not all adapters support this generic GPIO mapping, some require +their own commands to define the GPIOs used. Adapters that support the generic +mapping may not support all of the listed options. @end deffn @deffn {Command} {adapter name} diff --git a/src/jtag/adapter.c b/src/jtag/adapter.c index 6785a74ef1..173e6ee6b2 100644 --- a/src/jtag/adapter.c +++ b/src/jtag/adapter.c @@ -53,17 +53,18 @@ static const struct gpio_map { enum adapter_gpio_direction direction; bool permit_drive_option; bool permit_init_state_option; + bool permit_exit_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, }, + [ADAPTER_GPIO_IDX_TDO] = { "tdo", ADAPTER_GPIO_DIRECTION_INPUT, false, true, true }, + [ADAPTER_GPIO_IDX_TDI] = { "tdi", ADAPTER_GPIO_DIRECTION_OUTPUT, true, true, true }, + [ADAPTER_GPIO_IDX_TMS] = { "tms", ADAPTER_GPIO_DIRECTION_OUTPUT, true, true, true }, + [ADAPTER_GPIO_IDX_TCK] = { "tck", ADAPTER_GPIO_DIRECTION_OUTPUT, true, true, true }, + [ADAPTER_GPIO_IDX_SWDIO] = { "swdio", ADAPTER_GPIO_DIRECTION_BIDIRECTIONAL, true, true, true }, + [ADAPTER_GPIO_IDX_SWDIO_DIR] = { "swdio_dir", ADAPTER_GPIO_DIRECTION_OUTPUT, true, false, false }, + [ADAPTER_GPIO_IDX_SWCLK] = { "swclk", ADAPTER_GPIO_DIRECTION_OUTPUT, true, true, true }, + [ADAPTER_GPIO_IDX_TRST] = { "trst", ADAPTER_GPIO_DIRECTION_OUTPUT, false, true, true }, + [ADAPTER_GPIO_IDX_SRST] = { "srst", ADAPTER_GPIO_DIRECTION_OUTPUT, false, true, true }, + [ADAPTER_GPIO_IDX_LED] = { "led", ADAPTER_GPIO_DIRECTION_OUTPUT, true, true, true }, }; static int adapter_config_khz(unsigned int khz); @@ -850,6 +851,7 @@ static COMMAND_HELPER(helper_adapter_gpio_print_config, enum adapter_gpio_config const char *drive = ""; const char *pull = ""; const char *init_state = ""; + const char *exit_state = ""; if (gpio_config->gpio_num == ADAPTER_GPIO_NOT_SET) { command_print(CMD, "adapter gpio %s: not configured", gpio_map[gpio_idx].name); @@ -908,9 +910,27 @@ static COMMAND_HELPER(helper_adapter_gpio_print_config, enum adapter_gpio_config } } - command_print(CMD, "adapter gpio %s (%s): num %u, chip %d, active-%s%s%s%s", + if (gpio_map[gpio_idx].permit_exit_state_option) { + switch (gpio_config->exit_state) { + case ADAPTER_GPIO_EXIT_STATE_NO_CHANGE: + exit_state = ", exit-state no-change"; + break; + case ADAPTER_GPIO_EXIT_STATE_INACTIVE: + exit_state = ", exit-state inactive"; + break; + case ADAPTER_GPIO_EXIT_STATE_ACTIVE: + exit_state = ", exit-state active"; + break; + case ADAPTER_GPIO_EXIT_STATE_INPUT: + exit_state = ", exit-state input"; + break; + } + } + + + command_print(CMD, "adapter gpio %s (%s): num %u, chip %d, active-%s%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); + drive, pull, init_state, exit_state); return ERROR_OK; } @@ -1031,6 +1051,31 @@ COMMAND_HANDLER(adapter_gpio_config_handler) } } + if (gpio_map[gpio_idx].permit_exit_state_option) { + if (strcmp(CMD_ARGV[i], "-exit-no-change") == 0) { + ++i; + gpio_config->exit_state = ADAPTER_GPIO_EXIT_STATE_NO_CHANGE; + continue; + } + if (strcmp(CMD_ARGV[i], "-exit-inactive") == 0) { + ++i; + gpio_config->exit_state = ADAPTER_GPIO_EXIT_STATE_INACTIVE; + continue; + } + if (strcmp(CMD_ARGV[i], "-exit-active") == 0) { + ++i; + gpio_config->exit_state = ADAPTER_GPIO_EXIT_STATE_ACTIVE; + continue; + } + + if (gpio_map[gpio_idx].direction == ADAPTER_GPIO_DIRECTION_BIDIRECTIONAL && + strcmp(CMD_ARGV[i], "-exit-input") == 0) { + ++i; + gpio_config->exit_state = ADAPTER_GPIO_EXIT_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; @@ -1168,7 +1213,8 @@ static const struct command_registration adapter_command_handlers[] = { "[-active-high|-active-low] " "[-push-pull|-open-drain|-open-source] " "[-pull-none|-pull-up|-pull-down]" - "[-init-inactive|-init-active|-init-input] ]", + "[-init-inactive|-init-active|-init-input] ]" + "[-exit-no-change,exit-inactive|-exit-active|-exit-input] ]", }, COMMAND_REGISTRATION_DONE }; diff --git a/src/jtag/adapter.h b/src/jtag/adapter.h index 556952f8d7..ed58fe5aaa 100644 --- a/src/jtag/adapter.h +++ b/src/jtag/adapter.h @@ -33,6 +33,14 @@ enum adapter_gpio_init_state { ADAPTER_GPIO_INIT_STATE_INPUT, }; +/** Supported exit states for GPIO */ +enum adapter_gpio_exit_state { + ADAPTER_GPIO_EXIT_STATE_NO_CHANGE, /* Should be zero so it is the default state */ + ADAPTER_GPIO_EXIT_STATE_INACTIVE, + ADAPTER_GPIO_EXIT_STATE_ACTIVE, + ADAPTER_GPIO_EXIT_STATE_INPUT, +}; + /** Supported pull directions for GPIO */ enum adapter_gpio_pull { ADAPTER_GPIO_PULL_NONE, @@ -61,6 +69,7 @@ struct adapter_gpio_config { unsigned int chip_num; enum adapter_gpio_drive_mode drive; /* For outputs only */ enum adapter_gpio_init_state init_state; + enum adapter_gpio_exit_state exit_state; bool active_low; enum adapter_gpio_pull pull; }; --
