This is an automated email from Gerrit. "Evgeniy Naydanov <[email protected]>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/9665
-- gerrit commit 0a6ae573c5a9dee840934a5326f836a543ca09f7 Author: Evgeniy Naydanov <[email protected]> Date: Mon Mar 23 15:06:22 2026 +0300 jtag: fix behavior of Tcl commands before init Running ``` openocd -c 'adapter driver dummy' -c 'jtag arp_init' ``` used to result in an assertion failure: ``` ... openocd: ../../src/jtag/core.c:350: jtag_checks: Assertion `jtag_trst == 0' failed. ``` This is due to the fact that `jtag init` was not called and therefore `jtaf_init()` has not called `jtag_add_reset()`, so that `jtag_trst == -1`. Similar issues can be observed for other JTAG commands. This patch splits all commands in two groups -- pre-init and post-init. Pre-init commands are registered once the JTAG transport is selected. Post-ini commands become registered after the JTAG state is reset in `jtag_init()`. Change-Id: I21a1877e1eb3cfa59a43129216117ac397d09b95 Signed-off-by: Evgeniy Naydanov <[email protected]> diff --git a/src/jtag/core.c b/src/jtag/core.c index 650f283901..c620fbfbd5 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -1688,10 +1688,11 @@ int jtag_init(struct command_context *cmd_ctx) if (retval != ERROR_OK) return retval; + int reg_res = jtag_register_post_init_commands(cmd_ctx); if (Jim_Eval_Named(cmd_ctx->interp, "jtag_init", __FILE__, __LINE__) != JIM_OK) return ERROR_FAIL; - return ERROR_OK; + return reg_res; } void jtag_set_verify(bool enable) @@ -1798,7 +1799,7 @@ static int jtag_select(struct command_context *ctx) * That works with only C code ... no Tcl glue required. */ - retval = jtag_register_commands(ctx); + retval = jtag_register_pre_init_commands(ctx); if (retval != ERROR_OK) return retval; diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h index 47efdff37c..4fe93c5b7f 100644 --- a/src/jtag/jtag.h +++ b/src/jtag/jtag.h @@ -266,7 +266,8 @@ int jtag_init(struct command_context *cmd_ctx); /** reset, then initialize JTAG chain */ int jtag_init_reset(struct command_context *cmd_ctx); -int jtag_register_commands(struct command_context *cmd_ctx); +int jtag_register_pre_init_commands(struct command_context *cmd_ctx); +int jtag_register_post_init_commands(struct command_context *cmd_ctx); int jtag_init_inner(struct command_context *cmd_ctx); /** diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c index f4feb9ad16..8c9863c8db 100644 --- a/src/jtag/tcl.c +++ b/src/jtag/tcl.c @@ -266,7 +266,19 @@ COMMAND_HANDLER(handle_jtag_flush_count) * * The "irscan" command (for example) doesn't show twice. */ -static const struct command_registration jtag_command_handlers_to_move[] = { +static const struct command_registration jtag_pre_init_command_handlers_to_move[] = { + { + .name = "flush_count", + .mode = COMMAND_ANY, + .handler = handle_jtag_flush_count, + .help = "Returns the number of times the JTAG queue " + "has been flushed.", + .usage = "", + }, + COMMAND_REGISTRATION_DONE +}; + +static const struct command_registration jtag_post_init_command_handlers_to_move[] = { { .name = "drscan", .mode = COMMAND_EXEC, @@ -275,14 +287,6 @@ static const struct command_registration jtag_command_handlers_to_move[] = { "Other TAPs must be in BYPASS mode.", .usage = "tap_name (num_bits value)+ ['-endstate' state_name]", }, - { - .name = "flush_count", - .mode = COMMAND_EXEC, - .handler = handle_jtag_flush_count, - .help = "Returns the number of times the JTAG queue " - "has been flushed.", - .usage = "", - }, { .name = "pathmove", .mode = COMMAND_EXEC, @@ -724,7 +728,7 @@ COMMAND_HANDLER(handle_jtag_init_command) return jtag_init(CMD_CTX); } -static const struct command_registration jtag_subcommand_handlers[] = { +static const struct command_registration jtag_pre_init_subcommand_handlers[] = { { .name = "init", .mode = COMMAND_ANY, @@ -732,23 +736,6 @@ static const struct command_registration jtag_subcommand_handlers[] = { .help = "initialize jtag scan chain", .usage = "" }, - { - .name = "arp_init", - .mode = COMMAND_ANY, - .handler = handle_jtag_arp_init, - .help = "Validates JTAG scan chain against the list of " - "declared TAPs using just the four standard JTAG " - "signals.", - .usage = "", - }, - { - .name = "arp_init-reset", - .mode = COMMAND_ANY, - .handler = handle_jtag_arp_init_reset, - .help = "Uses TRST and SRST to try resetting everything on " - "the JTAG scan chain, then performs 'jtag arp_init'.", - .usage = "", - }, { .name = "newtap", .mode = COMMAND_CONFIG, @@ -813,7 +800,7 @@ static const struct command_registration jtag_subcommand_handlers[] = { .usage = "", }, { - .chain = jtag_command_handlers_to_move, + .chain = jtag_pre_init_command_handlers_to_move, }, COMMAND_REGISTRATION_DONE }; @@ -1139,8 +1126,7 @@ COMMAND_HANDLER(handle_wait_srst_deassert) return ERROR_OK; } -static const struct command_registration jtag_command_handlers[] = { - +static const struct command_registration jtag_pre_init_command_handlers[] = { { .name = "jtag_flush_queue_sleep", .handler = handle_jtag_flush_queue_sleep, @@ -1179,22 +1165,6 @@ static const struct command_registration jtag_command_handlers[] = { .help = "print current scan chain configuration", .usage = "" }, - { - .name = "runtest", - .handler = handle_runtest_command, - .mode = COMMAND_EXEC, - .help = "Move to Run-Test/Idle, and issue TCK for num_cycles.", - .usage = "num_cycles" - }, - { - .name = "irscan", - .handler = handle_irscan_command, - .mode = COMMAND_EXEC, - .help = "Execute Instruction Register (IR) scan. The " - "specified opcodes are put into each TAP's IR, " - "and other TAPs are put in BYPASS.", - .usage = "[tap_name instruction]* ['-endstate' state_name]", - }, { .name = "verify_ircapture", .handler = handle_verify_ircapture_command, @@ -1236,15 +1206,75 @@ static const struct command_registration jtag_command_handlers[] = { .help = "perform jtag tap actions", .usage = "", - .chain = jtag_subcommand_handlers, + .chain = jtag_pre_init_subcommand_handlers, }, { - .chain = jtag_command_handlers_to_move, + .chain = jtag_pre_init_command_handlers_to_move, }, COMMAND_REGISTRATION_DONE }; -int jtag_register_commands(struct command_context *cmd_ctx) +static const struct command_registration jtag_post_init_subcommand_handlers[] = { + { + .name = "arp_init", + .mode = COMMAND_ANY, + .handler = handle_jtag_arp_init, + .help = "Validates JTAG scan chain against the list of " + "declared TAPs using just the four standard JTAG " + "signals.", + .usage = "", + }, + { + .name = "arp_init-reset", + .mode = COMMAND_ANY, + .handler = handle_jtag_arp_init_reset, + .help = "Uses TRST and SRST to try resetting everything on " + "the JTAG scan chain, then performs 'jtag arp_init'.", + .usage = "", + }, + { + .name = "irscan", + .handler = handle_irscan_command, + .mode = COMMAND_EXEC, + .help = "Execute Instruction Register (IR) scan. The " + "specified opcodes are put into each TAP's IR, " + "and other TAPs are put in BYPASS.", + .usage = "[tap_name instruction]* ['-endstate' state_name]", + }, + { + .chain = jtag_post_init_command_handlers_to_move, + }, + COMMAND_REGISTRATION_DONE +}; + +static const struct command_registration jtag_post_init_command_handlers[] = { + { + .name = "runtest", + .handler = handle_runtest_command, + .mode = COMMAND_EXEC, + .help = "Move to Run-Test/Idle, and issue TCK for num_cycles.", + .usage = "num_cycles" + }, + { + .name = "jtag", + .mode = COMMAND_ANY, + .help = "perform jtag tap actions", + .usage = "", + + .chain = jtag_post_init_subcommand_handlers, + }, + { + .chain = jtag_post_init_command_handlers_to_move, + }, + COMMAND_REGISTRATION_DONE +}; + +int jtag_register_pre_init_commands(struct command_context *cmd_ctx) +{ + return register_commands(cmd_ctx, NULL, jtag_pre_init_command_handlers); +} + +int jtag_register_post_init_commands(struct command_context *cmd_ctx) { - return register_commands(cmd_ctx, NULL, jtag_command_handlers); + return register_commands(cmd_ctx, NULL, jtag_post_init_command_handlers); } diff --git a/testing/tcl_commands/Makefile.am b/testing/tcl_commands/Makefile.am index b0eee4dc96..3565178f67 100644 --- a/testing/tcl_commands/Makefile.am +++ b/testing/tcl_commands/Makefile.am @@ -6,7 +6,10 @@ if DUMMY TESTS += \ test-target-create-command.cfg \ test-target-configure-cget-command.cfg \ - test-jtag-pathmove.cfg + test-irscan-command.cfg \ + test-drscan-command.cfg \ + test-jtag-pathmove.cfg \ + test-jtag-before-init.cfg endif EXTRA_DIST = utils.tcl $(TESTS) diff --git a/testing/tcl_commands/test-jtag-before-init.cfg b/testing/tcl_commands/test-jtag-before-init.cfg new file mode 100644 index 0000000000..178df4dcae --- /dev/null +++ b/testing/tcl_commands/test-jtag-before-init.cfg @@ -0,0 +1,61 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +namespace import testing_helpers::* + +adapter driver dummy +noinit + +jtag newtap the tap -irlen 2 + +set tap [lindex [jtag names] 0] + +scan_chain + +flush_count + +# FIXME: this command times out. Currently, there is no robust way to check it. +proc check_wait_srst_deassert_timeout {} { + set code [catch {wait_srst_deassert 1} msg] + if {$msg ne ""} {error "Expecting empty message, got '$msg'"} + if {$code != -4} {error "Expecting ERROR_FAIL, got $code"} +} +check_wait_srst_deassert_timeout + +check_generic_error {drscan $tap 1 0} +check_generic_error {jtag arp_init} +check_generic_error {jtag arp_init-reset} +check_generic_error {runtest 1} +check_generic_error {jtag pathmove RESET} +check_generic_error {jtag tapisenabled $tap} +check_generic_error {jtag tapenable $tap} +check_generic_error {jtag tapdisable $tap} +check_generic_error {jtag cget $tap -event post-reset} + +jtag configure $tap -event post-reset {} + +jtag_flush_queue_sleep 0 + +tms_sequence +tms_sequence short + +proc check_jtag_rclk_default {} { + # FIXME: the current behavior is not great. + set code [catch jtag_rclk msg] + if {$msg ne ""} {error "Expecting empty message, got '$msg'"} + if {$code != -4} {error "Expecting ERROR_FAIL, got $code"} +} +check_jtag_rclk_default +jtag_rclk 1000 +jtag_rclk + +jtag_ntrst_delay +jtag_ntrst_delay 1 + +jtag_ntrst_assert_width + +verify_ircapture +verify_ircapture enable + +verify_jtag +verify_jtag enable + +shutdown --
