Skip to content

Commit e3c62ba

Browse files
author
Phillip Pearson
committed
Fixed some JTAG bugs, and made it support sequences longer than 64 bit (which happen all the time, esp when enumerating the scan chain)
Change-Id: Ic4f0d959408244d4ca6b5766f65a44d6facb7eb8
1 parent 173e8e1 commit e3c62ba

1 file changed

Lines changed: 129 additions & 55 deletions

File tree

src/jtag/drivers/cmsis_dap_usb.c

Lines changed: 129 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
/***************************************************************************
2+
* Copyright (C) 2016 by Phillip Pearson *
3+
* pp@myelin.co.nz *
4+
* *
25
* Copyright (C) 2014 by Paul Fertser *
36
* fercerpav@gmail.com *
47
* *
@@ -989,15 +992,58 @@ static void cmsis_dap_end_state(tap_state_t state)
989992
}
990993
}
991994

995+
static void print_binary(const uint8_t* buf, int offset, int len) {
996+
for (int i = offset; i < offset + len; ++i) {
997+
putchar((buf[i / 8] & (1 << (i % 8))) ? '1' : '0');
998+
}
999+
}
1000+
1001+
static void bit_copy_debug(uint8_t *dst, unsigned dst_offset, const uint8_t *src, unsigned src_offset, unsigned bit_count) {
1002+
LOG_INFO("bit copy dst_offset=%d src_offset=%d bit_count=%d", dst_offset, src_offset, bit_count);
1003+
print_binary(src, src_offset, bit_count);
1004+
LOG_INFO(" <-- bits");
1005+
bit_copy(dst, dst_offset, src, src_offset, bit_count);
1006+
}
1007+
9921008
/* Move to the end state by clocking bits into TMS as appropriate using
9931009
* the CMSIS-DAP DAP_SWJ_Sequence command.
9941010
*/
9951011
static void cmsis_dap_state_move()
9961012
{
1013+
LOG_DEBUG("cmsis_dap_state_move from %s to %s", tap_state_name(tap_get_state()), tap_state_name(tap_get_end_state()));
1014+
1015+
/* tap_get_tms_path() can only handle moving between stable states, so if we're in an unstable state,
1016+
* move to a stable state first.
1017+
*/
1018+
bool exit_to_pause = false;
1019+
int extra_bit = 1;
1020+
switch (tap_get_state()) {
1021+
case TAP_DREXIT1:
1022+
LOG_DEBUG("moving out of DREXIT1");
1023+
exit_to_pause = true;
1024+
tap_set_state(TAP_DRPAUSE);
1025+
break;
1026+
case TAP_IREXIT1:
1027+
LOG_DEBUG("moving out of IREXIT1");
1028+
exit_to_pause = true;
1029+
tap_set_state(TAP_IRPAUSE);
1030+
break;
1031+
default:
1032+
break;
1033+
}
1034+
9971035
uint8_t tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state());
9981036
int tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
9991037

1000-
cmsis_dap_cmd_DAP_SWJ_Sequence(tms_count, &tms_scan);
1038+
if (exit_to_pause) {
1039+
/* need to shift in an extra bit before the usual sequence */
1040+
uint8_t scan[2];
1041+
scan[0] = (uint8_t)(tms_scan << 1) | extra_bit;
1042+
scan[1] = (uint8_t)(tms_scan >> 7);
1043+
cmsis_dap_cmd_DAP_SWJ_Sequence(tms_count + 1, &tms_scan);
1044+
} else {
1045+
cmsis_dap_cmd_DAP_SWJ_Sequence(tms_count, &tms_scan);
1046+
}
10011047

10021048
tap_set_state(tap_get_end_state());
10031049
}
@@ -1019,66 +1065,95 @@ static int cmsis_dap_scan(bool ir_scan, enum scan_type type, uint8_t *sequence,
10191065
cmsis_dap_end_state(saved_end_state);
10201066
}
10211067

1022-
if (scan_size > 64) {
1023-
LOG_ERROR("Splitting > 64 bit scans into multiple sequences for CMSIS-DAP is not implemented");
1024-
exit(-1);
1025-
}
1026-
1027-
/* Prepare CMSIS-DAP JTAG Sequence command:
1028-
*
1029-
* #0 = 0 (report number)
1030-
* #1 = CMD_DAP_JTAG_SEQ
1031-
* #2 = number of sequences
1032-
* #3 = sequence info 1
1033-
* #4...4+n_bytes-1 = sequence 1
1034-
* #4+n_bytes = sequence info 2
1035-
* #5+n_bytes = sequence 2 (single bit)
1036-
*
1037-
* so a 32-bit sequence will go in #4-7, leaving #8 and #9 for sequence 2
1068+
/* Split scan up into 64-bit chunks and issue a new USB request for each one. This is suboptimal,
1069+
* but if we only use it for the inital scan chain enumeration, it doesn't matter. If it turns out
1070+
* that drivers habitually make long scan requests, modify this to pack as much as possible into
1071+
* each USB request.
10381072
*/
1039-
uint8_t *buffer = cmsis_dap_handle->packet_buffer;
1040-
uint8_t buf_ptr = 0;
1041-
buffer[buf_ptr++] = 0; /* report number */
1042-
buffer[buf_ptr++] = CMD_DAP_JTAG_SEQ;
1043-
1044-
if (scan_size == 0) {
1045-
LOG_ERROR("Empty scan");
1046-
exit(-1);
1047-
} else if (scan_size == 1) {
1048-
/* Just one sequence */
1049-
buffer[buf_ptr++] = 1;
1050-
/* Just clock out one bit with TMS=1 */
1051-
buffer[buf_ptr++] = DAP_JTAG_SEQ_TDO | DAP_JTAG_SEQ_TMS | 1;
1052-
bit_copy(&buffer[buf_ptr++], 0, buffer, 0, 1);
1053-
} else {
1054-
/* Split our scan into two sequences, one with TMS=0 and (scan_size-1) bits, and one with TMS=0 and 1 bit. */
1055-
buffer[buf_ptr++] = 2;
1073+
for (int scan_start = 0; scan_start < scan_size; scan_start += 64) {
1074+
1075+
/* If this is the last chunk, we need to set TMS when sending the final bit */
1076+
bool last_chunk = (scan_start + 64) >= scan_size;
1077+
/* Number of bits to send/receive in this chunk */
1078+
int chunk_bits = last_chunk ? (scan_size - scan_start) : 64;
1079+
LOG_INFO("cmsis-dap jtag chunk: scan_start %d scan_size %d chunk_bits %d last_chunk %d", scan_start, scan_size, chunk_bits, last_chunk ? 1 : 0);
1080+
1081+
/* Prepare CMSIS-DAP JTAG Sequence command:
1082+
*
1083+
* #0 = 0 (report number)
1084+
* #1 = CMD_DAP_JTAG_SEQ
1085+
* #2 = number of sequences
1086+
* #3 = sequence info 1
1087+
* #4...4+n_bytes-1 = sequence 1
1088+
* #4+n_bytes = sequence info 2
1089+
* #5+n_bytes = sequence 2 (single bit)
1090+
*
1091+
* so a 32-bit sequence will go in #4-7, leaving #8 and #9 for sequence 2
1092+
*/
1093+
uint8_t *buffer = cmsis_dap_handle->packet_buffer;
1094+
buffer[0] = 0; /* report number */
1095+
buffer[1] = CMD_DAP_JTAG_SEQ;
1096+
buffer[2] = 1; /* default 1 sequence */
1097+
uint8_t buf_ptr = 3; /* data blocks start at buffer[3] */
1098+
uint8_t first_seq_start = 4; /* start of first buffer */
1099+
uint8_t second_seq_start = 0; /* start of second data buffer if we use one */
1100+
1101+
LOG_INFO("setup chunk");
1102+
if (chunk_bits == 0) {
1103+
LOG_ERROR("BUG: Empty scan chunk");
1104+
exit(-1);
1105+
} else if (chunk_bits > 64) {
1106+
LOG_ERROR("BUG: Scan chunk > 64 bits");
1107+
exit(-1);
1108+
} else if (!last_chunk) {
1109+
/* We're only sending part of the scan request, so don't raise TMS on the final bit */
1110+
/* 64 bits with TMS=0 */
1111+
buffer[buf_ptr++] = DAP_JTAG_SEQ_TDO;
1112+
/* copying 64 bits from sequence, starting at scan_start, into buffer[3...] */
1113+
bit_copy_debug(&buffer[buf_ptr++], 0, sequence, scan_start, 64);
1114+
} else if (chunk_bits == 1) {
1115+
/* Just clock out one bit with TMS=1 */
1116+
buffer[buf_ptr++] = DAP_JTAG_SEQ_TDO | DAP_JTAG_SEQ_TMS | 1;
1117+
bit_copy_debug(&buffer[buf_ptr++], 0, sequence, scan_start, 1);
1118+
} else {
1119+
/* Split our scan into two sequences, one with TMS=0 and (scan_size-1) bits, and one with TMS=0 and 1 bit. */
1120+
buffer[2] = 2;
10561121

1057-
/* Sequence 1 */
1058-
buffer[buf_ptr++] = DAP_JTAG_SEQ_TDO | (scan_size - 1);
1059-
bit_copy(&buffer[buf_ptr], 0, buffer, 0, scan_size - 1);
1122+
/* Sequence 1 */
1123+
buffer[buf_ptr++] = DAP_JTAG_SEQ_TDO | (chunk_bits - 1);
1124+
bit_copy_debug(&buffer[buf_ptr], 0, sequence, scan_start, chunk_bits - 1);
10601125

1061-
/* Figure out how many bytes we just used in the buffer */
1062-
buf_ptr += ((scan_size - 1) + 7) / 8;
1126+
/* Figure out how many bytes we just used in the buffer */
1127+
buf_ptr += ((chunk_bits - 1) + 7) / 8;
10631128

1064-
/* Sequence 2: the final bit */
1065-
buffer[buf_ptr++] = DAP_JTAG_SEQ_TDO | DAP_JTAG_SEQ_TMS | 1;
1066-
bit_copy(&buffer[buf_ptr++], 0, sequence, scan_size - 1, 1);
1067-
}
1129+
/* Sequence 2: the final bit */
1130+
buffer[buf_ptr++] = DAP_JTAG_SEQ_TDO | DAP_JTAG_SEQ_TMS | 1;
1131+
second_seq_start = buf_ptr;
1132+
bit_copy_debug(&buffer[buf_ptr++], 0, sequence, scan_start + chunk_bits - 1, 1);
1133+
}
10681134

1069-
/* Send command */
1070-
int retval = cmsis_dap_usb_xfer(cmsis_dap_handle, buf_ptr);
1135+
/* Send command */
1136+
int retval = cmsis_dap_usb_xfer(cmsis_dap_handle, buf_ptr);
10711137

1072-
if (retval != ERROR_OK || buffer[1] != DAP_OK) {
1073-
LOG_ERROR("CMSIS-DAP command CMD_DAP_JTAG_SEQ failed.");
1074-
return ERROR_JTAG_DEVICE_ERROR;
1075-
}
1138+
if (retval != ERROR_OK || buffer[1] != DAP_OK) {
1139+
LOG_ERROR("CMSIS-DAP command CMD_DAP_JTAG_SEQ failed.");
1140+
return ERROR_JTAG_DEVICE_ERROR;
1141+
}
10761142

1077-
/* Copy results into the sequence buffer if we want them */
1078-
if (type == SCAN_IN || type == SCAN_IO) {
1079-
bit_copy(sequence, 0, &buffer[4], 0, (scan_size == 1) ? 1 : (scan_size - 1));
1080-
if (scan_size > 1) {
1081-
bit_copy(sequence, scan_size - 1, &buffer[5 + (scan_size - 1 + 7) / 8], 0, 1);
1143+
/* Copy results into the sequence buffer if we want them */
1144+
if (type == SCAN_IN || type == SCAN_IO) {
1145+
LOG_INFO("copy scan results out");
1146+
if (!last_chunk) {
1147+
/* 64 bit chunk, single sequence */
1148+
bit_copy_debug(sequence, scan_start, &buffer[first_seq_start], 0, 64);
1149+
} else if (chunk_bits == 1) {
1150+
/* 1 bit chunk, single sequence */
1151+
bit_copy_debug(sequence, scan_start, &buffer[first_seq_start], 0, 1);
1152+
} else {
1153+
/* last chunk, two sequences */
1154+
bit_copy_debug(sequence, scan_start, &buffer[first_seq_start], 0, chunk_bits - 1);
1155+
bit_copy_debug(sequence, scan_start + chunk_bits - 1, &buffer[second_seq_start], 0, 1);
1156+
}
10821157
}
10831158
}
10841159

@@ -1094,7 +1169,6 @@ static int cmsis_dap_scan(bool ir_scan, enum scan_type type, uint8_t *sequence,
10941169

10951170
static int cmsis_dap_execute_scan(struct jtag_command *cmd)
10961171
{
1097-
LOG_INFO("cmsis-dap JTAG SCAN");
10981172
#ifdef _DEBUG_JTAG_IO_
10991173
LOG_DEBUG("%s scan end in %s",
11001174
(cmd->cmd.scan->ir_scan) ? "IR" : "DR",

0 commit comments

Comments
 (0)