Skip to content

Commit 173e8e1

Browse files
author
Phillip Pearson
committed
First attempt at JTAG support for the CMSIS-DAP adapter. It compiles! Haven't tested it yet.
Change-Id: I88d918d6576e9d875c3b611f29f255581e6a5424
1 parent 2587e5a commit 173e8e1

1 file changed

Lines changed: 187 additions & 14 deletions

File tree

src/jtag/drivers/cmsis_dap_usb.c

Lines changed: 187 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,15 @@ static bool swd_mode;
122122
#define CMD_DAP_JTAG_CONFIGURE 0x15
123123
#define CMD_DAP_JTAG_IDCODE 0x16
124124

125+
/* CMSIS-DAP JTAG sequence info masks */
126+
/* Number of bits to clock through (0 means 64) */
127+
#define DAP_JTAG_SEQ_TCK 0x3F
128+
/* TMS will be set during the sequence if this bit is set */
129+
#define DAP_JTAG_SEQ_TMS 0x40
130+
/* TDO output will be captured if this bit is set */
131+
#define DAP_JTAG_SEQ_TDO 0x80
132+
133+
125134
/* CMSIS-DAP Transfer Commands */
126135
#define CMD_DAP_TFER_CONFIGURE 0x04
127136
#define CMD_DAP_TFER 0x05
@@ -377,6 +386,25 @@ static int cmsis_dap_cmd_DAP_SWJ_Clock(uint32_t swj_clock)
377386
return ERROR_OK;
378387
}
379388

389+
/* clock a sequence of bits out on TMS, to change JTAG states */
390+
static int cmsis_dap_cmd_DAP_SWJ_Sequence(uint8_t s_len, const uint8_t* sequence)
391+
{
392+
int retval;
393+
uint8_t *buffer = cmsis_dap_handle->packet_buffer;
394+
395+
buffer[0] = 0; /* report number */
396+
buffer[1] = CMD_DAP_SWJ_SEQ;
397+
buffer[2] = s_len;
398+
bit_copy(&buffer[3], 0, sequence, 0, s_len);
399+
400+
retval = cmsis_dap_usb_xfer(cmsis_dap_handle, DIV_ROUND_UP(s_len, 8) + 3);
401+
402+
if (retval != ERROR_OK || buffer[1] != DAP_OK)
403+
return ERROR_FAIL;
404+
405+
return ERROR_OK;
406+
}
407+
380408
static int cmsis_dap_cmd_DAP_Info(uint8_t info, uint8_t **data)
381409
{
382410
int retval;
@@ -711,7 +739,6 @@ static int cmsis_dap_get_status(void)
711739

712740
static int cmsis_dap_swd_switch_seq(enum swd_special_seq seq)
713741
{
714-
uint8_t *buffer = cmsis_dap_handle->packet_buffer;
715742
const uint8_t *s;
716743
unsigned int s_len;
717744
int retval;
@@ -747,17 +774,7 @@ static int cmsis_dap_swd_switch_seq(enum swd_special_seq seq)
747774
return ERROR_FAIL;
748775
}
749776

750-
buffer[0] = 0; /* report number */
751-
buffer[1] = CMD_DAP_SWJ_SEQ;
752-
buffer[2] = s_len;
753-
bit_copy(&buffer[3], 0, s, 0, s_len);
754-
755-
retval = cmsis_dap_usb_xfer(cmsis_dap_handle, DIV_ROUND_UP(s_len, 8) + 3);
756-
757-
if (retval != ERROR_OK || buffer[1] != DAP_OK)
758-
return ERROR_FAIL;
759-
760-
return ERROR_OK;
777+
return cmsis_dap_cmd_DAP_SWJ_Sequence(s_len, s);
761778
}
762779

763780
static int cmsis_dap_swd_open(void)
@@ -950,6 +967,151 @@ static void cmsis_dap_execute_sleep(struct jtag_command *cmd)
950967
jtag_sleep(cmd->cmd.sleep->us);
951968
}
952969

970+
/* Set TMS high for five TCK clocks, to move the TAP to the Test-Logic-Reset state */
971+
static int cmsis_dap_execute_tlr_reset(struct jtag_command *cmd)
972+
{
973+
LOG_INFO("cmsis-dap JTAG TLR_RESET");
974+
uint8_t seq = 0x1f;
975+
int ret = cmsis_dap_cmd_DAP_SWJ_Sequence(5, &seq);
976+
if (ret == ERROR_OK)
977+
tap_set_state(TAP_RESET);
978+
return ret;
979+
}
980+
981+
/* Set new end state */
982+
static void cmsis_dap_end_state(tap_state_t state)
983+
{
984+
if (tap_is_state_stable(state))
985+
tap_set_end_state(state);
986+
else {
987+
LOG_ERROR("BUG: %i is not a valid end state", state);
988+
exit(-1);
989+
}
990+
}
991+
992+
/* Move to the end state by clocking bits into TMS as appropriate using
993+
* the CMSIS-DAP DAP_SWJ_Sequence command.
994+
*/
995+
static void cmsis_dap_state_move()
996+
{
997+
uint8_t tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state());
998+
int tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
999+
1000+
cmsis_dap_cmd_DAP_SWJ_Sequence(tms_count, &tms_scan);
1001+
1002+
tap_set_state(tap_get_end_state());
1003+
}
1004+
1005+
/* Execute a scan: move to the TAP_IRSHIFT or TAP_DRSHIFT state, clock in/out some data, then move to the end state */
1006+
static int cmsis_dap_scan(bool ir_scan, enum scan_type type, uint8_t *sequence, int scan_size)
1007+
{
1008+
tap_state_t saved_end_state = tap_get_end_state();
1009+
1010+
if (!((!ir_scan &&
1011+
(tap_get_state() == TAP_DRSHIFT)) ||
1012+
(ir_scan && (tap_get_state() == TAP_IRSHIFT)))) {
1013+
if (ir_scan)
1014+
cmsis_dap_end_state(TAP_IRSHIFT);
1015+
else
1016+
cmsis_dap_end_state(TAP_DRSHIFT);
1017+
1018+
cmsis_dap_state_move();
1019+
cmsis_dap_end_state(saved_end_state);
1020+
}
1021+
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
1038+
*/
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;
1056+
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);
1060+
1061+
/* Figure out how many bytes we just used in the buffer */
1062+
buf_ptr += ((scan_size - 1) + 7) / 8;
1063+
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+
}
1068+
1069+
/* Send command */
1070+
int retval = cmsis_dap_usb_xfer(cmsis_dap_handle, buf_ptr);
1071+
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+
}
1076+
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);
1082+
}
1083+
}
1084+
1085+
/* The final bit will have transitioned us to Exit1-DR or Exit1-IR */
1086+
tap_set_state(tap_get_state() == TAP_DRSHIFT ? TAP_DREXIT1 : TAP_IREXIT1);
1087+
1088+
if (tap_get_state() != tap_get_end_state()) {
1089+
cmsis_dap_state_move();
1090+
}
1091+
1092+
return ERROR_OK;
1093+
}
1094+
1095+
static int cmsis_dap_execute_scan(struct jtag_command *cmd)
1096+
{
1097+
LOG_INFO("cmsis-dap JTAG SCAN");
1098+
#ifdef _DEBUG_JTAG_IO_
1099+
LOG_DEBUG("%s scan end in %s",
1100+
(cmd->cmd.scan->ir_scan) ? "IR" : "DR",
1101+
tap_state_name(cmd->cmd.scan->end_state));
1102+
#endif
1103+
cmsis_dap_end_state(cmd->cmd.scan->end_state);
1104+
uint8_t *buffer;
1105+
int scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
1106+
int type = jtag_scan_type(cmd->cmd.scan);
1107+
int retval = cmsis_dap_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
1108+
if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
1109+
retval = ERROR_JTAG_QUEUE_FAILED;
1110+
if (buffer)
1111+
free(buffer);
1112+
return retval;
1113+
}
1114+
9531115
static void cmsis_dap_execute_command(struct jtag_command *cmd)
9541116
{
9551117
switch (cmd->type) {
@@ -959,8 +1121,18 @@ static void cmsis_dap_execute_command(struct jtag_command *cmd)
9591121
case JTAG_SLEEP:
9601122
cmsis_dap_execute_sleep(cmd);
9611123
break;
1124+
case JTAG_TLR_RESET:
1125+
cmsis_dap_execute_tlr_reset(cmd);
1126+
break;
1127+
case JTAG_SCAN:
1128+
cmsis_dap_execute_scan(cmd);
1129+
break;
1130+
case JTAG_RUNTEST:
1131+
case JTAG_PATHMOVE:
1132+
case JTAG_STABLECLOCKS:
1133+
case JTAG_TMS:
9621134
default:
963-
LOG_ERROR("BUG: unknown JTAG command type encountered");
1135+
LOG_ERROR("BUG: unknown JTAG command type 0x%X encountered", cmd->type);
9641136
exit(-1);
9651137
}
9661138
}
@@ -1012,6 +1184,7 @@ static int_least32_t cmsis_dap_swd_frequency(int_least32_t hz)
10121184
return hz;
10131185
}
10141186

1187+
10151188
COMMAND_HANDLER(cmsis_dap_handle_info_command)
10161189
{
10171190
if (cmsis_dap_get_version_info() == ERROR_OK)
@@ -1116,7 +1289,7 @@ static const struct swd_driver cmsis_dap_swd_driver = {
11161289
.run = cmsis_dap_swd_run_queue,
11171290
};
11181291

1119-
static const char * const cmsis_dap_transport[] = { "swd", NULL };
1292+
static const char * const cmsis_dap_transport[] = { "swd", "jtag", NULL };
11201293

11211294
struct jtag_interface cmsis_dap_interface = {
11221295
.name = "cmsis-dap",

0 commit comments

Comments
 (0)