- buffer[0] = 0; /* report number */
- buffer[1] = CMD_DAP_TFER;
- buffer[2] = 0x00;
- buffer[3] = 0x01;
- buffer[4] = cmd;
- retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 5);
-
- /* TODO - need better response checking */
- if (retval != ERROR_OK || buffer[1] != 0x01) {
- LOG_ERROR("CMSIS-DAP: Read Error (0x%02" PRIx8 ")", buffer[2]);
- queued_retval = buffer[2];
- return;
+ if (queued_retval != ERROR_OK) {
+ LOG_DEBUG("Skipping due to previous errors: %d", queued_retval);
+ goto skip;
+ }
+
+ if (!pending_transfer_count)
+ goto skip;
+
+ size_t idx = 0;
+ buffer[idx++] = 0; /* report number */
+ buffer[idx++] = CMD_DAP_TFER;
+ buffer[idx++] = 0x00; /* DAP Index */
+ buffer[idx++] = pending_transfer_count;
+
+ for (int i = 0; i < pending_transfer_count; i++) {
+ uint8_t cmd = pending_transfers[i].cmd;
+ uint32_t data = pending_transfers[i].data;
+
+ LOG_DEBUG("%s %s reg %x %"PRIx32,
+ cmd & SWD_CMD_APnDP ? "AP" : "DP",
+ cmd & SWD_CMD_RnW ? "read" : "write",
+ (cmd & SWD_CMD_A32) >> 1, data);
+
+ /* When proper WAIT handling is implemented in the
+ * common SWD framework, this kludge can be
+ * removed. However, this might lead to minor
+ * performance degradation as the adapter wouldn't be
+ * able to automatically retry anything (because ARM
+ * has forgotten to implement sticky error flags
+ * clearing). See also comments regarding
+ * cmsis_dap_cmd_DAP_TFER_Configure() and
+ * cmsis_dap_cmd_DAP_SWD_Configure() in
+ * cmsis_dap_init().
+ */
+ if (!(cmd & SWD_CMD_RnW) &&
+ !(cmd & SWD_CMD_APnDP) &&
+ (cmd & SWD_CMD_A32) >> 1 == DP_CTRL_STAT &&
+ (data & CORUNDETECT)) {
+ LOG_DEBUG("refusing to enable sticky overrun detection");
+ data &= ~CORUNDETECT;
+ }
+
+ buffer[idx++] = (cmd >> 1) & 0x0f;
+ if (!(cmd & SWD_CMD_RnW)) {
+ buffer[idx++] = (data) & 0xff;
+ buffer[idx++] = (data >> 8) & 0xff;
+ buffer[idx++] = (data >> 16) & 0xff;
+ buffer[idx++] = (data >> 24) & 0xff;
+ }
+ }
+
+ queued_retval = cmsis_dap_usb_xfer(cmsis_dap_handle, idx);
+ if (queued_retval != ERROR_OK)
+ goto skip;
+
+ idx = 2;
+ uint8_t ack = buffer[idx] & 0x07;
+ if (ack != SWD_ACK_OK || (buffer[idx] & 0x08)) {
+ LOG_DEBUG("SWD ack not OK: %d %s", buffer[idx-1],
+ ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK");
+ queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL;
+ goto skip;