uint8_t *reply_buffer,
int reply_buffer_size
) {
- uint8_t ep2_buffer[USB_EP2IN_SIZE];
+ char dtc_status;
int usb_err;
int i;
- LOG_DEBUG(": %d/%d", command_buffer_size, reply_buffer_size);
+ LOG_DEBUG("%d/%d", command_buffer_size, reply_buffer_size);
usb_err = usb_bulk_write(
pHDev_param,
usb_err = usb_bulk_read(
pHDev_param,
USB_EP1IN_ADDR,
- (char *)ep2_buffer, 1,
+ &dtc_status, 1,
USB_TIMEOUT_MS
);
if (usb_err < 0) return(usb_err);
- if (ep2_buffer[0] & 0x01) break;
+ if (dtc_status & 0x01) break;
if (!--i) {
- LOG_ERROR("%s, %d: too many retries waiting for DTC status",
- __FILE__, __LINE__
- );
+ LOG_ERROR("too many retries waiting for DTC status");
return(-ETIMEDOUT);
}
}
- if (!reply_buffer) reply_buffer_size = 0;
- if (reply_buffer_size) {
+ if (reply_buffer && reply_buffer_size) {
usb_err = usb_bulk_read(
pHDev_param,
USB_EP2IN_ADDR,
- (char *)ep2_buffer, sizeof(ep2_buffer),
+ (char *)reply_buffer, reply_buffer_size,
USB_TIMEOUT_MS
);
- if (usb_err < (int)sizeof(ep2_buffer)) {
- LOG_ERROR("%s, %d: Read of endpoint 2 returned %d",
- __FILE__, __LINE__, usb_err
+ if (usb_err < reply_buffer_size) {
+ LOG_ERROR("Read of endpoint 2 returned %d, expected %d",
+ usb_err, reply_buffer_size
);
return(usb_err);
}
-
- memcpy(reply_buffer, ep2_buffer, reply_buffer_size);
-
}
return(usb_err);
uint8_t dtc_mask, tdo_mask;
uint8_t reply_buffer[USB_EP2IN_SIZE];
+ assert((dtc_queue.rq_head != 0) == (dtc_queue.reply_index > 0));
+ assert(dtc_queue.cmd_index < USB_EP2BANK_SIZE);
+ assert(dtc_queue.reply_index <= USB_EP2IN_SIZE);
+
retval = ERROR_OK;
if (dtc_queue.cmd_index < 1) return(retval);
dtc_queue.cmd_buffer[dtc_queue.cmd_index++] = DTC_CMD_STOP;
- /* run the cmd */
- if (dtc_queue.rq_head == NULL) {
- usb_err = dtc_run_download(pHDev,
- dtc_queue.cmd_buffer, dtc_queue.cmd_index,
- NULL, 0
- );
- if (usb_err < 0) {
- LOG_ERROR("dtc_run_download: %s", usb_strerror());
- exit(1);
- }
- } else {
- usb_err = dtc_run_download(pHDev,
- dtc_queue.cmd_buffer, dtc_queue.cmd_index,
- reply_buffer, dtc_queue.reply_index
- );
- if (usb_err < 0) {
- LOG_ERROR("dtc_run_download: %s", usb_strerror());
- exit(1);
- } else {
- /* process the reply, which empties the reply queue and frees its entries */
- dtc_p = reply_buffer;
+ usb_err = dtc_run_download(pHDev,
+ dtc_queue.cmd_buffer, dtc_queue.cmd_index,
+ reply_buffer, dtc_queue.reply_index
+ );
+ if (usb_err < 0) {
+ LOG_ERROR("dtc_run_download: %s", usb_strerror());
+ exit(1);
+ }
- /* The rigamarole with the masks and doing it bit-by-bit is due to the fact that the scan buffer is LSb-first and the DTC code is MSb-first for hardware reasons. It was that or craft a function to do the reversal, and that wouldn't work with bit-stuffing (supplying extra bits to use mostly byte operations), or any other scheme which would throw the byte alignment off. */
+ if (dtc_queue.rq_head != NULL) {
+ /* process the reply, which empties the reply queue and frees its entries */
+ dtc_p = reply_buffer;
- for (
- rq_p = dtc_queue.rq_head;
- rq_p != NULL;
- rq_p = rq_next
- ) {
- tdo_p = rq_p->scan.buffer + (rq_p->scan.offset / 8);
- tdo_mask = 1 << (rq_p->scan.offset % 8);
+ /* The rigamarole with the masks and doing it bit-by-bit is due to the fact that the scan buffer is LSb-first and the DTC code is MSb-first for hardware reasons. It was that or craft a function to do the reversal, and that wouldn't work with bit-stuffing (supplying extra bits to use mostly byte operations), or any other scheme which would throw the byte alignment off. */
+ for (
+ rq_p = dtc_queue.rq_head;
+ rq_p != NULL;
+ rq_p = rq_next
+ ) {
+ tdo_p = rq_p->scan.buffer + (rq_p->scan.offset / 8);
+ tdo_mask = 1 << (rq_p->scan.offset % 8);
- bit_cnt = rq_p->scan.length;
- if (bit_cnt >= 8) {
- /* bytes */
- dtc_mask = 1 << (8 - 1);
+ bit_cnt = rq_p->scan.length;
+ if (bit_cnt >= 8) {
+ /* bytes */
- for (
- ;
- bit_cnt;
- bit_cnt--
- ) {
- if (*dtc_p & dtc_mask) {
- *tdo_p |= tdo_mask;
- } else {
- *tdo_p &=~ tdo_mask;
- }
-
- dtc_mask >>= 1;
- if (dtc_mask == 0) {
- dtc_p++;
- dtc_mask = 1 << (8 - 1);
- }
-
- tdo_mask <<= 1;
- if (tdo_mask == 0) {
- tdo_p++;
- tdo_mask = 1;
- }
- }
- } else {
- /* extra bits or last bit */
-
- x = *dtc_p++;
- if ((
- rq_p->scan.type == SCAN_IN
- ) && (
- rq_p->scan.offset != rq_p->scan.size - 1
- )) {
- /* extra bits were sent as a full byte with padding on the end */
- dtc_mask = 1 << (8 - 1);
+ dtc_mask = 1 << (8 - 1);
+
+ for (
+ ;
+ bit_cnt;
+ bit_cnt--
+ ) {
+ if (*dtc_p & dtc_mask) {
+ *tdo_p |= tdo_mask;
} else {
- dtc_mask = 1 << (bit_cnt - 1);
+ *tdo_p &=~ tdo_mask;
}
- for (
- ;
- bit_cnt;
- bit_cnt--
- ) {
- if (x & dtc_mask) {
- *tdo_p |= tdo_mask;
- } else {
- *tdo_p &=~ tdo_mask;
- }
-
- dtc_mask >>= 1;
-
- tdo_mask <<= 1;
- if (tdo_mask == 0) {
- tdo_p++;
- tdo_mask = 1;
- }
+ dtc_mask >>= 1;
+ if (dtc_mask == 0) {
+ dtc_p++;
+ dtc_mask = 1 << (8 - 1);
+ }
+ tdo_mask <<= 1;
+ if (tdo_mask == 0) {
+ tdo_p++;
+ tdo_mask = 1;
}
}
+ } else {
+ /* extra bits or last bit */
+
+ x = *dtc_p++;
+ if ((
+ rq_p->scan.type == SCAN_IN
+ ) && (
+ rq_p->scan.offset != rq_p->scan.size - 1
+ )) {
+ /* extra bits were sent as a full byte with padding on the end */
+ dtc_mask = 1 << (8 - 1);
+ } else {
+ dtc_mask = 1 << (bit_cnt - 1);
+ }
+
+ for (
+ ;
+ bit_cnt;
+ bit_cnt--
+ ) {
+ if (x & dtc_mask) {
+ *tdo_p |= tdo_mask;
+ } else {
+ *tdo_p &=~ tdo_mask;
+ }
+
+ dtc_mask >>= 1;
- if ((rq_p->scan.offset + rq_p->scan.length) >= rq_p->scan.size) {
- /* feed scan buffer back into openocd and free it */
- if (jtag_read_buffer(rq_p->scan.buffer, rq_p->cmd->cmd.scan) != ERROR_OK) {
- retval = ERROR_JTAG_QUEUE_FAILED;
+ tdo_mask <<= 1;
+ if (tdo_mask == 0) {
+ tdo_p++;
+ tdo_mask = 1;
}
- free(rq_p->scan.buffer);
+
}
+ }
- rq_next = rq_p->next;
- free(rq_p);
+ if ((rq_p->scan.offset + rq_p->scan.length) >= rq_p->scan.size) {
+ /* feed scan buffer back into openocd and free it */
+ if (jtag_read_buffer(rq_p->scan.buffer, rq_p->cmd->cmd.scan) != ERROR_OK) {
+ retval = ERROR_JTAG_QUEUE_FAILED;
+ }
+ free(rq_p->scan.buffer);
}
- dtc_queue.rq_head = NULL;
- dtc_queue.rq_tail = NULL;
- }
+ rq_next = rq_p->next;
+ free(rq_p);
+ }
+ dtc_queue.rq_head = NULL;
+ dtc_queue.rq_tail = NULL;
}
return(retval);
}
+/* runs the queue if it cannot take reserved_cmd bytes of command data
+ * or reserved_reply bytes of reply data */
+static
+int
+dtc_queue_run_if_full(
+ int reserved_cmd,
+ int reserved_reply
+) {
+ /* reserve one additional byte for the STOP cmd appended during run */
+ if (dtc_queue.cmd_index + reserved_cmd + 1 > USB_EP2BANK_SIZE)
+ return dtc_queue_run();
+ if (dtc_queue.reply_index + reserved_reply > USB_EP2IN_SIZE)
+ return dtc_queue_run();
+
+ return ERROR_OK;
+}
static
int
if ((bits >= 8) || !i) {
byte_param <<= (8 - bits);
- /* make sure there's room for stop, byte op, and one byte */
- if (dtc_queue.cmd_index >= (sizeof(dtc_queue.cmd_buffer) - (1 + 1 + 1))) {
- dtc_queue.cmd_buffer[dtc_queue.cmd_index++] =
- DTC_CMD_STOP;
- dtc_queue_run();
- }
+ /* make sure there's room for two cmd bytes */
+ dtc_queue_run_if_full(2, 0);
#ifdef USE_HARDWARE_SHIFTER_FOR_TMS
if (bits == 8) {
if (extra_bits && (type == SCAN_OUT)) {
/* Schedule any extra bits into the DTC command buffer, padding as needed */
/* For SCAN_OUT, this comes before the full bytes so the (leading) padding bits will fall off the end */
- /* make sure there's room for stop, byte op, and one byte */
- if (
- (dtc_queue.cmd_index >= sizeof(dtc_queue.cmd_buffer) - (1 + 1 + 1))
- ) {
- dtc_queue_run();
- }
+
+ /* make sure there's room for two cmd bytes */
+ dtc_queue_run_if_full(2, 0);
x = 0;
dtc_mask = 1 << (extra_bits - 1);
/* Loop scheduling full bytes into the DTC command buffer */
while (byte_bits) {
- if (type == SCAN_IN) {
- /* make sure there's room for stop and byte op */
- x = (dtc_queue.cmd_index >= sizeof(dtc_queue.cmd_buffer) - (1 + 1));
- } else {
- /* make sure there's room for stop, byte op, and at least one byte */
- x = (dtc_queue.cmd_index >= sizeof(dtc_queue.cmd_buffer) - (1 + 1 + 1));
- }
-
- if (type != SCAN_OUT) {
- /* make sure there's room for at least one reply byte */
- x |= (dtc_queue.reply_index >= USB_EP2IN_SIZE - (1));
- }
-
- if (x) {
- dtc_queue_run();
- }
+ /* make sure there's room for one (for in scans) or two cmd bytes and
+ * at least one reply byte for in or inout scans*/
+ dtc_queue_run_if_full(type == SCAN_IN ? 1 : 2, type != SCAN_OUT ? 1 : 0);
chunk_bits = byte_bits;
/* we can only use up to 16 bytes at a time */
LOG_ERROR("enqueuing DTC reply entry: %s", strerror(errno));
exit(1);
}
+ dtc_queue.reply_index += (chunk_bits + 7) / 8;
tdi_bit_offset += chunk_bits;
}
dtc_mask >>= 1;
if (dtc_mask == 0) {
dtc_queue.cmd_buffer[dtc_queue.cmd_index++] = x;
- dtc_queue.reply_index++;
x = 0;
dtc_mask = 1 << (8 - 1);
}
if (extra_bits && (type != SCAN_OUT)) {
/* Schedule any extra bits into the DTC command buffer */
- /* make sure there's room for stop, byte op, and one byte */
- if (
- (dtc_queue.cmd_index >= sizeof(dtc_queue.cmd_buffer) - (1 + 1 + 1))
- ||
- (dtc_queue.reply_index >= USB_EP2IN_SIZE - (1))
- ) {
- dtc_queue_run();
- }
+
+ /* make sure there's room for one (for in scans) or two cmd bytes
+ * and one reply byte */
+ dtc_queue_run_if_full(type == SCAN_IN ? 1 : 2, 1);
if (dtc_queue_enqueue_reply(
type, buffer, scan_size, tdi_bit_offset,
exit(1);
}
+ dtc_queue.reply_index++;
+
tdi_bit_offset += extra_bits;
if (type == SCAN_IN) {
dtc_queue.cmd_buffer[dtc_queue.cmd_index++] = x;
}
-
- dtc_queue.reply_index++;
}
/* Schedule the last bit into the DTC command buffer */
- {
- /* make sure there's room for stop, and bit pair command */
- if (
- (dtc_queue.cmd_index >= sizeof(dtc_queue.cmd_buffer) - (1 + 1))
- ||
- (dtc_queue.reply_index >= USB_EP2IN_SIZE - (1))
- ) {
- dtc_queue_run();
- }
- if (type == SCAN_OUT) {
- dtc_queue.cmd_buffer[dtc_queue.cmd_index++] =
- DTC_CMD_SHIFT_TMS_TDI_BIT_PAIR(1, (*tdi_p & tdi_mask), 0);
-
- } else {
- if (dtc_queue_enqueue_reply(
- type, buffer, scan_size, tdi_bit_offset,
- 1,
- cmd
- ) == NULL) {
- LOG_ERROR("enqueuing DTC reply entry: %s", strerror(errno));
- exit(1);
- }
+ /* make sure there's room for one cmd byte and one reply byte
+ * for in or inout scans*/
+ dtc_queue_run_if_full(1, type == SCAN_OUT ? 0 : 1);
- dtc_queue.cmd_buffer[dtc_queue.cmd_index++] =
- DTC_CMD_SHIFT_TMS_TDI_BIT_PAIR(1, (*tdi_p & tdi_mask), 1);
+ if (type == SCAN_OUT) {
+ dtc_queue.cmd_buffer[dtc_queue.cmd_index++] =
+ DTC_CMD_SHIFT_TMS_TDI_BIT_PAIR(1, (*tdi_p & tdi_mask), 0);
- dtc_queue.reply_index++;
+ } else {
+ if (dtc_queue_enqueue_reply(
+ type, buffer, scan_size, tdi_bit_offset,
+ 1,
+ cmd
+ ) == NULL) {
+ LOG_ERROR("enqueuing DTC reply entry: %s", strerror(errno));
+ exit(1);
}
+
+ dtc_queue.reply_index++;
+
+ dtc_queue.cmd_buffer[dtc_queue.cmd_index++] =
+ DTC_CMD_SHIFT_TMS_TDI_BIT_PAIR(1, (*tdi_p & tdi_mask), 1);
}
/* Move to pause state */
}
if (dtc_start_download() < 0) {
- LOG_ERROR("%s, %d: starting DTC: %s",
- __FILE__, __LINE__,
- usb_strerror()
- );
+ LOG_ERROR("starting DTC: %s", usb_strerror());
exit(1);
}