From 66391d28373fef090999b253b193d19dbdc11217 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sun, 20 Nov 2022 21:01:17 +0100 Subject: [PATCH] jtag/drivers/cmsis_dap: implement canceling of pending USB requests Use it whenever an out-of-sync response is detected to clean USB bulk transfer state. USB hidapi does not offer any means to cancel a pending request, therefore cmsis_dap_hid_cancel_all() does nothing. Signed-off-by: Tomas Vanek Change-Id: Ie36fa760c1643ae10be0e87fc633068965a72242 Reviewed-on: https://review.openocd.org/c/openocd/+/7366 Tested-by: jenkins Reviewed-by: zapb --- src/jtag/drivers/cmsis_dap.c | 18 +++++++++++++++--- src/jtag/drivers/cmsis_dap.h | 1 + src/jtag/drivers/cmsis_dap_usb_bulk.c | 14 ++++++++++++++ src/jtag/drivers/cmsis_dap_usb_hid.c | 5 +++++ 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c index bc86eb46a..5d060bdad 100644 --- a/src/jtag/drivers/cmsis_dap.c +++ b/src/jtag/drivers/cmsis_dap.c @@ -365,6 +365,7 @@ static int cmsis_dap_xfer(struct cmsis_dap *dap, int txlen) LOG_ERROR("CMSIS-DAP command mismatch. Sent 0x%" PRIx8 " received 0x%" PRIx8, current_cmd, resp[0]); + dap->backend->cancel_all(dap); cmsis_dap_flush_read(dap); return ERROR_FAIL; } @@ -758,7 +759,6 @@ static int cmsis_dap_cmd_dap_swo_data( return ERROR_OK; } - static void cmsis_dap_swd_discard_all_pending(struct cmsis_dap *dap) { for (unsigned int i = 0; i < MAX_PENDING_REQUESTS; i++) @@ -769,6 +769,13 @@ static void cmsis_dap_swd_discard_all_pending(struct cmsis_dap *dap) dap->pending_fifo_block_count = 0; } +static void cmsis_dap_swd_cancel_transfers(struct cmsis_dap *dap) +{ + dap->backend->cancel_all(dap); + cmsis_dap_flush_read(dap); + cmsis_dap_swd_discard_all_pending(dap); +} + static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap) { uint8_t *command = dap->command; @@ -913,8 +920,9 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, enum cmsis_dap_blo if (resp[0] != block->command) { LOG_ERROR("CMSIS-DAP command mismatch. Expected 0x%x received 0x%" PRIx8, block->command, resp[0]); + cmsis_dap_swd_cancel_transfers(dap); queued_retval = ERROR_FAIL; - goto skip; + return; } unsigned int transfer_count; @@ -940,9 +948,13 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, enum cmsis_dap_blo goto skip; } - if (block->transfer_count != transfer_count) + if (block->transfer_count != transfer_count) { LOG_ERROR("CMSIS-DAP transfer count mismatch: expected %d, got %d", block->transfer_count, transfer_count); + cmsis_dap_swd_cancel_transfers(dap); + queued_retval = ERROR_FAIL; + return; + } LOG_DEBUG_IO("Received results of %d queued transactions FIFO index %u, %s mode", transfer_count, dap->pending_fifo_get_idx, diff --git a/src/jtag/drivers/cmsis_dap.h b/src/jtag/drivers/cmsis_dap.h index 187aeb54d..817636f34 100644 --- a/src/jtag/drivers/cmsis_dap.h +++ b/src/jtag/drivers/cmsis_dap.h @@ -66,6 +66,7 @@ struct cmsis_dap_backend { int (*write)(struct cmsis_dap *dap, int len, int timeout_ms); int (*packet_buffer_alloc)(struct cmsis_dap *dap, unsigned int pkt_sz); void (*packet_buffer_free)(struct cmsis_dap *dap); + void (*cancel_all)(struct cmsis_dap *dap); }; extern const struct cmsis_dap_backend cmsis_dap_hid_backend; diff --git a/src/jtag/drivers/cmsis_dap_usb_bulk.c b/src/jtag/drivers/cmsis_dap_usb_bulk.c index aaab5804d..17e490f05 100644 --- a/src/jtag/drivers/cmsis_dap_usb_bulk.c +++ b/src/jtag/drivers/cmsis_dap_usb_bulk.c @@ -634,6 +634,19 @@ static void cmsis_dap_usb_free(struct cmsis_dap *dap) dap->response = NULL; } +static void cmsis_dap_usb_cancel_all(struct cmsis_dap *dap) +{ + for (unsigned int i = 0; i < MAX_PENDING_REQUESTS; i++) { + if (dap->bdata->command_transfers[i].status == CMSIS_DAP_TRANSFER_PENDING) + libusb_cancel_transfer(dap->bdata->command_transfers[i].transfer); + if (dap->bdata->response_transfers[i].status == CMSIS_DAP_TRANSFER_PENDING) + libusb_cancel_transfer(dap->bdata->response_transfers[i].transfer); + + dap->bdata->command_transfers[i].status = CMSIS_DAP_TRANSFER_IDLE; + dap->bdata->response_transfers[i].status = CMSIS_DAP_TRANSFER_IDLE; + } +} + COMMAND_HANDLER(cmsis_dap_handle_usb_interface_command) { if (CMD_ARGC == 1) @@ -663,4 +676,5 @@ const struct cmsis_dap_backend cmsis_dap_usb_backend = { .write = cmsis_dap_usb_write, .packet_buffer_alloc = cmsis_dap_usb_alloc, .packet_buffer_free = cmsis_dap_usb_free, + .cancel_all = cmsis_dap_usb_cancel_all, }; diff --git a/src/jtag/drivers/cmsis_dap_usb_hid.c b/src/jtag/drivers/cmsis_dap_usb_hid.c index 6338886c8..1decc7156 100644 --- a/src/jtag/drivers/cmsis_dap_usb_hid.c +++ b/src/jtag/drivers/cmsis_dap_usb_hid.c @@ -236,6 +236,10 @@ static void cmsis_dap_hid_free(struct cmsis_dap *dap) dap->packet_buffer = NULL; } +static void cmsis_dap_hid_cancel_all(struct cmsis_dap *dap) +{ +} + const struct cmsis_dap_backend cmsis_dap_hid_backend = { .name = "hid", .open = cmsis_dap_hid_open, @@ -244,4 +248,5 @@ const struct cmsis_dap_backend cmsis_dap_hid_backend = { .write = cmsis_dap_hid_write, .packet_buffer_alloc = cmsis_dap_hid_alloc, .packet_buffer_free = cmsis_dap_hid_free, + .cancel_all = cmsis_dap_hid_cancel_all, };