From ba16fdc1c645bda82adb5a06b4403e7501e150c4 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Tue, 7 Nov 2023 14:45:45 +0100 Subject: [PATCH] drivers/cmsis_dap: use quirk workarounds optionally Introduce 'cmsis-dap quirk' command to enable and disable quirk mode. If enabled, disconnect and connect before a switch sequence and do not use multiple packets pipelining. Change-Id: I6576f7de9f6c98a25c3cf9eec9a456a23610d00d Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/7966 Tested-by: jenkins --- doc/openocd.texi | 12 ++++++++++++ src/jtag/drivers/cmsis_dap.c | 33 ++++++++++++++++++++++++++++----- src/jtag/drivers/cmsis_dap.h | 1 + 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index de990c538..db7315fe4 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2569,6 +2569,18 @@ In most cases need not to be specified and interfaces are searched by interface string or for user class interface. @end deffn +@deffn {Command} {cmsis-dap quirk} [@option{enable}|@option{disable}] +Enables or disables the following workarounds of known CMSIS-DAP adapter +quirks: +@itemize @minus +@item disconnect and re-connect before sending a switch sequence +@item packets pipelining is suppressed, only one packet at a time is +submitted to the adapter +@end itemize +The quirk workarounds are disabled by default. +The command without a parameter displays current setting. +@end deffn + @deffn {Command} {cmsis-dap info} Display various device information, like hardware version, firmware version, current bus status. @end deffn diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c index 5d060bdad..caacc9b91 100644 --- a/src/jtag/drivers/cmsis_dap.c +++ b/src/jtag/drivers/cmsis_dap.c @@ -861,9 +861,10 @@ static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap) goto skip; } - dap->pending_fifo_put_idx = (dap->pending_fifo_put_idx + 1) % dap->packet_count; + unsigned int packet_count = dap->quirk_mode ? 1 : dap->packet_count; + dap->pending_fifo_put_idx = (dap->pending_fifo_put_idx + 1) % packet_count; dap->pending_fifo_block_count++; - if (dap->pending_fifo_block_count > dap->packet_count) + if (dap->pending_fifo_block_count > packet_count) LOG_ERROR("internal: too much pending writes %u", dap->pending_fifo_block_count); return; @@ -984,7 +985,8 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, enum cmsis_dap_blo skip: block->transfer_count = 0; - dap->pending_fifo_get_idx = (dap->pending_fifo_get_idx + 1) % dap->packet_count; + if (!dap->quirk_mode && dap->packet_count > 1) + dap->pending_fifo_get_idx = (dap->pending_fifo_get_idx + 1) % dap->packet_count; dap->pending_fifo_block_count--; } @@ -1079,7 +1081,8 @@ static void cmsis_dap_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data) /* Not enough room in the queue. Run the queue. */ cmsis_dap_swd_write_from_queue(cmsis_dap_handle); - if (cmsis_dap_handle->pending_fifo_block_count >= cmsis_dap_handle->packet_count) + unsigned int packet_count = cmsis_dap_handle->quirk_mode ? 1 : cmsis_dap_handle->packet_count; + if (cmsis_dap_handle->pending_fifo_block_count >= packet_count) cmsis_dap_swd_read_process(cmsis_dap_handle, CMSIS_DAP_BLOCKING); } @@ -1222,7 +1225,7 @@ static int cmsis_dap_swd_switch_seq(enum swd_special_seq seq) if (swd_mode) queued_retval = cmsis_dap_swd_run_queue(); - if (seq != LINE_RESET && + if (cmsis_dap_handle->quirk_mode && seq != LINE_RESET && (output_pins & (SWJ_PIN_SRST | SWJ_PIN_TRST)) == (SWJ_PIN_SRST | SWJ_PIN_TRST)) { /* Following workaround deasserts reset on most adapters. @@ -2220,6 +2223,19 @@ COMMAND_HANDLER(cmsis_dap_handle_backend_command) return ERROR_OK; } +COMMAND_HANDLER(cmsis_dap_handle_quirk_command) +{ + if (CMD_ARGC > 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + if (CMD_ARGC == 1) + COMMAND_PARSE_ENABLE(CMD_ARGV[0], cmsis_dap_handle->quirk_mode); + + command_print(CMD, "CMSIS-DAP quirk workarounds %s", + cmsis_dap_handle->quirk_mode ? "enabled" : "disabled"); + return ERROR_OK; +} + static const struct command_registration cmsis_dap_subcommand_handlers[] = { { .name = "info", @@ -2249,6 +2265,13 @@ static const struct command_registration cmsis_dap_subcommand_handlers[] = { .help = "set the communication backend to use (USB bulk or HID).", .usage = "(auto | usb_bulk | hid)", }, + { + .name = "quirk", + .handler = &cmsis_dap_handle_quirk_command, + .mode = COMMAND_ANY, + .help = "allow expensive workarounds of known adapter quirks.", + .usage = "[enable | disable]", + }, #if BUILD_CMSIS_DAP_USB { .name = "usb", diff --git a/src/jtag/drivers/cmsis_dap.h b/src/jtag/drivers/cmsis_dap.h index 817636f34..e47697d1f 100644 --- a/src/jtag/drivers/cmsis_dap.h +++ b/src/jtag/drivers/cmsis_dap.h @@ -52,6 +52,7 @@ struct cmsis_dap { unsigned int pending_fifo_block_count; uint16_t caps; + bool quirk_mode; /* enable expensive workarounds */ uint32_t swo_buf_sz; bool trace_enabled;