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 <vanekt@fbl.cz>
Change-Id: Ie36fa760c1643ae10be0e87fc633068965a72242
Reviewed-on: https://review.openocd.org/c/openocd/+/7366
Tested-by: jenkins
Reviewed-by: zapb <dev@zapb.de>
This commit is contained in:
Tomas Vanek 2022-11-20 21:01:17 +01:00
parent fd75e9e542
commit 66391d2837
4 changed files with 35 additions and 3 deletions

View File

@ -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,

View File

@ -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;

View File

@ -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,
};

View File

@ -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,
};