Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: CMSIS-DAP transfer failure handling #1564

Merged
merged 4 commits into from
Jul 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions src/platforms/hosted/cmsis_dap.c
Original file line number Diff line number Diff line change
Expand Up @@ -351,9 +351,14 @@ uint32_t dap_dp_low_access(

uint32_t dap_dp_read_reg(adiv5_debug_port_s *const target_dp, const uint16_t addr)
{
uint32_t res = dap_dp_low_access(target_dp, ADIV5_LOW_READ, addr, 0);
DEBUG_PROBE("dp_read %04x %08" PRIx32 "\n", addr, res);
return res;
uint32_t result = dap_dp_low_access(target_dp, ADIV5_LOW_READ, addr, 0);
if (target_dp->fault == DAP_TRANSFER_NO_RESPONSE) {
DEBUG_WARN("Recovering and re-trying access\n");
target_dp->error(target_dp, true);
result = dap_dp_low_access(target_dp, ADIV5_LOW_READ, addr, 0);
}
DEBUG_PROBE("dp_read %04x %08" PRIx32 "\n", addr, result);
return result;
}

void dap_exit_function(void)
Expand Down
41 changes: 35 additions & 6 deletions src/platforms/hosted/dap_command.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <string.h>
#include "dap.h"
#include "dap_command.h"
#include "exception.h"
#include "buffer_utils.h"

#define DAP_TRANSFER_APnDP (1U << 0U)
Expand All @@ -60,6 +61,31 @@ static size_t dap_encode_transfer(
return 5U;
}

static void dap_dispatch_status(adiv5_debug_port_s *const dp, const dap_transfer_status_e status)
{
switch (status) {
case DAP_TRANSFER_OK:
break;
case DAP_TRANSFER_WAIT:
DEBUG_ERROR("Access resulted in wait, aborting\n");
dp->abort(dp, ADIV5_DP_ABORT_DAPABORT);
dp->fault = status;
break;
case DAP_TRANSFER_FAULT:
DEBUG_ERROR("Access resulted in fault\n");
dp->fault = status;
break;
case DAP_TRANSFER_NO_RESPONSE:
DEBUG_ERROR("Access resulted in no response\n");
dp->fault = status;
break;
default:
DEBUG_ERROR("Access has invalid ack %x\n", status);
raise_exception(EXCEPTION_ERROR, "Invalid ACK");
break;
}
}

/* https://www.keil.com/pack/doc/CMSIS/DAP/html/group__DAP__Transfer.html */
bool perform_dap_transfer(adiv5_debug_port_s *const target_dp, const dap_transfer_request_s *const transfer_requests,
const size_t requests, uint32_t *const response_data, const size_t responses)
Expand All @@ -80,20 +106,22 @@ bool perform_dap_transfer(adiv5_debug_port_s *const target_dp, const dap_transfe
for (size_t i = 0; i < requests; ++i)
offset += dap_encode_transfer(&transfer_requests[i], request, offset);

dap_transfer_response_s response;
dap_transfer_response_s response = {.processed = 0, .status = DAP_TRANSFER_OK};
/* Run the request */
if (!dap_run_cmd(request, offset, &response, 2U + (responses * 4U)))
if (!dap_run_cmd(request, offset, &response, 2U + (responses * 4U))) {
dap_dispatch_status(target_dp, response.status);
return false;
}

/* Look at the response and decipher what went on */
if (response.processed == requests && response.status == DAP_TRANSFER_OK) {
for (size_t i = 0; i < responses; ++i)
response_data[i] = read_le4(response.data[i], 0);
return true;
}
target_dp->fault = response.status;

DEBUG_PROBE("-> transfer failed with %u after processing %u requests\n", response.status, response.processed);
dap_dispatch_status(target_dp, response.status);
return false;
}

Expand All @@ -105,6 +133,7 @@ bool perform_dap_transfer_recoverable(adiv5_debug_port_s *const target_dp,
/* If all went well, or we can't recover, we get to early return */
if (result || target_dp->fault != DAP_TRANSFER_NO_RESPONSE)
return result;
DEBUG_WARN("Recovering and re-trying access\n");
/* Otherwise clear the error and try again as our best and final answer */
target_dp->error(target_dp, true);
return perform_dap_transfer(target_dp, transfer_requests, requests, response_data, responses);
Expand Down Expand Up @@ -198,7 +227,7 @@ bool perform_dap_swj_sequence(size_t clock_cycles, const uint8_t *data)
/* Calculate the number of bytes needed to represent the requested number of clock cycles */
const size_t bytes = (clock_cycles + 7U) >> 3U;
/* And copy the data into the buffer */
memcpy(request + 2, data, bytes);
memcpy(request + 2U, data, bytes);

/* Sequence response is a single byte */
uint8_t response = DAP_RESPONSE_OK;
Expand Down Expand Up @@ -239,8 +268,8 @@ bool perform_dap_jtag_sequence(
};
/* Copy in a suitable amount of data from the source buffer */
const size_t sequence_length = (cycles + 7U) >> 3U;
memcpy(request + 3, data_in, sequence_length);
size_t offset = 3 + sequence_length;
memcpy(request + 3U, data_in, sequence_length);
size_t offset = 3U + sequence_length;
/* Figure out where the final bit is */
const uint8_t final_byte = cycles >> 3U;
const uint8_t final_bit = cycles & 7U;
Expand Down