X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fjtag%2Frlink%2Frlink.c;h=58067fbe35c29b5248d61ff5faba1398a2d24509;hp=4b6dde2fc9ce37d03c978b01c381cd81769fb10f;hb=96413087dcf4bbe015c4e9af8dd982aa2710f29c;hpb=cd05476e6d176e162a673ac7d7171acba258243b diff --git a/src/jtag/rlink/rlink.c b/src/jtag/rlink/rlink.c index 4b6dde2fc9..58067fbe35 100644 --- a/src/jtag/rlink/rlink.c +++ b/src/jtag/rlink/rlink.c @@ -72,25 +72,40 @@ #define DTC_STATUS_POLL_BYTE (ST7_USB_BUF_EP0OUT + 0xff) -/* Symbolic names for some pins */ -#define ST7_PA_NJTAG_TRST ST7_PA1 -#define ST7_PA_NRLINK_RST ST7_PA3 -#define ST7_PA_NLINE_DRIVER_ENABLE ST7_PA5 - -/* mask for negative-logic pins */ -#define ST7_PA_NUNASSERTED (0 \ - | ST7_PA_NJTAG_TRST \ - | ST7_PA_NRLINK_RST \ - | ST7_PA_NLINE_DRIVER_ENABLE \ -) - #define ST7_PD_NBUSY_LED ST7_PD0 -#define ST7_PD_NERROR_LED ST7_PD1 -#define ST7_PD_NRUN_LED ST7_PD7 +#define ST7_PD_NRUN_LED ST7_PD1 +/* low enables VPP at adapter header, high connects it to GND instead */ +#define ST7_PD_VPP_SEL ST7_PD6 +/* low: VPP = 12v, high: VPP <= 5v */ +#define ST7_PD_VPP_SHDN ST7_PD7 +/* These pins are connected together */ #define ST7_PE_ADAPTER_SENSE_IN ST7_PE3 #define ST7_PE_ADAPTER_SENSE_OUT ST7_PE4 +/* Symbolic mapping between port pins and numbered IO lines */ +#define ST7_PA_IO1 ST7_PA1 +#define ST7_PA_IO2 ST7_PA2 +#define ST7_PA_IO4 ST7_PA4 +#define ST7_PA_IO8 ST7_PA6 +#define ST7_PA_IO10 ST7_PA7 +#define ST7_PB_IO5 ST7_PB5 +#define ST7_PC_IO9 ST7_PC1 +#define ST7_PC_IO3 ST7_PC2 +#define ST7_PC_IO7 ST7_PC3 +#define ST7_PE_IO6 ST7_PE5 + +/* Symbolic mapping between numbered IO lines and adapter signals */ +#define ST7_PA_RTCK ST7_PA_IO0 +#define ST7_PA_NTRST ST7_PA_IO1 +#define ST7_PC_TDI ST7_PC_IO3 +#define ST7_PA_DBGRQ ST7_PA_IO4 +#define ST7_PB_NSRST ST7_PB_IO5 +#define ST7_PE_TMS ST7_PE_IO6 +#define ST7_PC_TCK ST7_PC_IO7 +#define ST7_PC_TDO ST7_PC_IO9 +#define ST7_PA_DBGACK ST7_PA_IO10 + static usb_dev_handle *pHDev; @@ -122,7 +137,7 @@ ep1_generic_commandl( *usb_buffer_p++ = va_arg(ap, int); length--; } - + memset( usb_buffer_p, 0, @@ -176,7 +191,7 @@ ep1_memory_read( usb_buffer[2] = addr; usb_buffer[3] = length; - usb_ret = usb_bulk_write( + usb_ret = usb_bulk_write( pHDev, USB_EP1OUT_ADDR, usb_buffer, sizeof(usb_buffer), USB_TIMEOUT_MS @@ -185,7 +200,7 @@ ep1_memory_read( if(usb_ret < sizeof(usb_buffer)) { break; } - + usb_ret = usb_bulk_read( pHDev, USB_EP1IN_ADDR, buffer, length, @@ -195,7 +210,7 @@ ep1_memory_read( if(usb_ret < length) { break; } - + addr += length; buffer += length; count += length; @@ -247,7 +262,7 @@ ep1_memory_write( sizeof(usb_buffer) - 4 - length ); - usb_ret = usb_bulk_write( + usb_ret = usb_bulk_write( pHDev, USB_EP1OUT_ADDR, (char *)usb_buffer, sizeof(usb_buffer), USB_TIMEOUT_MS @@ -256,7 +271,7 @@ ep1_memory_write( if(usb_ret < sizeof(usb_buffer)) { break; } - + addr += length; buffer += length; count += length; @@ -343,7 +358,7 @@ dtc_load_from_buffer( LOG_ERROR("Malformed DTC image\n"); exit(1); } - + header = (struct header_s *)buffer; buffer += sizeof(*header); length -= sizeof(*header); @@ -352,7 +367,7 @@ dtc_load_from_buffer( LOG_ERROR("Malformed DTC image\n"); exit(1); } - + switch(header->type) { case DTCLOAD_COMMENT: break; @@ -365,7 +380,7 @@ dtc_load_from_buffer( break; case DTCLOAD_LOAD: - /* Send the DTC program to ST7 RAM. */ + /* Send the DTC program to ST7 RAM. */ usb_err = ep1_memory_write( pHDev, DTC_LOAD_BUFFER, @@ -398,9 +413,9 @@ dtc_load_from_buffer( case DTCLOAD_LUT_START: lut_start = buffer[0]; break; - + case DTCLOAD_LUT: - usb_err = ep1_memory_write( + usb_err = ep1_memory_write( pHDev, ST7_USB_BUF_EP0OUT + lut_start, header->length + 1, buffer @@ -413,7 +428,7 @@ dtc_load_from_buffer( exit(1); break; } - + buffer += (header->length + 1); length -= (header->length + 1); } @@ -434,7 +449,7 @@ dtc_start_download(void) { /* set up for download mode and make sure EP2 is set up to transmit */ usb_err = ep1_generic_commandl( pHDev, 7, - + EP1_CMD_DTC_STOP, EP1_CMD_SET_UPLOAD, EP1_CMD_SET_DOWNLOAD, @@ -455,7 +470,7 @@ dtc_start_download(void) { usb_err = ep1_generic_commandl( pHDev, 13, - + EP1_CMD_MEMORY_WRITE, /* preinitialize poll byte */ DTC_STATUS_POLL_BYTE >> 8, DTC_STATUS_POLL_BYTE, @@ -682,7 +697,7 @@ dtc_queue_run(void) { 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\n", usb_strerror()); exit(1); @@ -691,7 +706,7 @@ dtc_queue_run(void) { 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\n", usb_strerror()); exit(1); @@ -726,7 +741,7 @@ dtc_queue_run(void) { } else { *tdo_p &=~ tdo_mask; } - + dtc_mask >>= 1; if(dtc_mask == 0) { dtc_p++; @@ -772,7 +787,7 @@ dtc_queue_run(void) { tdo_p++; tdo_mask = 1; } - + } } @@ -825,7 +840,7 @@ tap_state_queue_run(void) { bits = 1; byte = 0; for(i = tap_state_queue.length; i--;) { - + byte <<= 1; if(tap_state_queue.buffer & 1) { byte |= 1; @@ -890,10 +905,10 @@ tap_state_queue_append( static -void rlink_end_state(enum tap_state state) +void rlink_end_state(tap_state_t state) { - if (tap_move_map[state] != -1) - end_state = state; + if (tap_is_state_stable(state)) + tap_set_end_state(state); else { LOG_ERROR("BUG: %i is not a valid end state", state); @@ -906,7 +921,7 @@ static void rlink_state_move(void) { int i=0, tms=0; - u8 tms_scan = TAP_MOVE(cur_state, end_state); + u8 tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state()); for (i = 0; i < 7; i++) { @@ -914,7 +929,7 @@ void rlink_state_move(void) { tap_state_queue_append(tms); } - cur_state = end_state; + tap_set_state(tap_get_end_state()); } static @@ -927,28 +942,28 @@ void rlink_path_move(pathmove_command_t *cmd) state_count = 0; while (num_states) { - if (tap_transitions[cur_state].low == cmd->path[state_count]) + if (tap_state_transition(tap_get_state(), false) == cmd->path[state_count]) { tms = 0; } - else if (tap_transitions[cur_state].high == cmd->path[state_count]) + else if (tap_state_transition(tap_get_state(), true) == cmd->path[state_count]) { tms = 1; } else { - LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", jtag_state_name(cur_state), jtag_state_name(cmd->path[state_count])); + LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name(tap_get_state()), tap_state_name(cmd->path[state_count])); exit(-1); } tap_state_queue_append(tms); - cur_state = cmd->path[state_count]; + tap_set_state(cmd->path[state_count]); state_count++; num_states--; } - end_state = cur_state; + tap_set_end_state(tap_get_state()); } @@ -957,10 +972,10 @@ void rlink_runtest(int num_cycles) { int i; - enum tap_state saved_end_state = end_state; + tap_state_t saved_end_state = tap_get_end_state(); /* only do a state_move when we're not already in RTI */ - if (cur_state != TAP_IDLE) + if (tap_get_state() != TAP_IDLE) { rlink_end_state(TAP_IDLE); rlink_state_move(); @@ -974,7 +989,7 @@ void rlink_runtest(int num_cycles) /* finish in end_state */ rlink_end_state(saved_end_state); - if (cur_state != end_state) + if (tap_get_state() != tap_get_end_state()) rlink_state_move(); } @@ -986,37 +1001,92 @@ void rlink_reset(int trst, int srst) u8 bitmap; int usb_err; - bitmap = ((~(ST7_PA_NLINE_DRIVER_ENABLE)) & ST7_PA_NUNASSERTED); + /* Read port A for bit op */ + usb_err = ep1_generic_commandl( + pHDev, 4, + EP1_CMD_MEMORY_READ, + ST7_PADR >> 8, + ST7_PADR, + 1 + ); + if(usb_err < 0) { + LOG_ERROR("%s", usb_strerror()); + exit(1); + } + + usb_err = usb_bulk_read( + pHDev, USB_EP1IN_ADDR, + (char *)&bitmap, 1, + USB_TIMEOUT_MS + ); + if(usb_err < 1) { + LOG_ERROR("%s", usb_strerror()); + exit(1); + } if(trst) { - bitmap &= ~ST7_PA_NJTAG_TRST; + bitmap &= ~ST7_PA_NTRST; + } else { + bitmap |= ST7_PA_NTRST; } + + /* Write port A and read port B for bit op */ + /* port B has no OR, and we want to emulate open drain on NSRST, so we initialize DR to 0 and assert NSRST by setting DDR to 1. */ + usb_err = ep1_generic_commandl( + pHDev, 9, + EP1_CMD_MEMORY_WRITE, + ST7_PADR >> 8, + ST7_PADR, + 1, + bitmap, + EP1_CMD_MEMORY_READ, + ST7_PBDDR >> 8, + ST7_PBDDR, + 1 + ); + if(usb_err < 0) { + LOG_ERROR("%s", usb_strerror()); + exit(1); + } + + usb_err = usb_bulk_read( + pHDev, USB_EP1IN_ADDR, + (char *)&bitmap, 1, + USB_TIMEOUT_MS + ); + if(usb_err < 1) { + LOG_ERROR("%s", usb_strerror()); + exit(1); + } + if(srst) { - bitmap &= ~ST7_PA_NRLINK_RST; + bitmap |= ST7_PB_NSRST; + } else { + bitmap &= ~ST7_PB_NSRST; } + /* write port B and read dummy to ensure completion before returning */ usb_err = ep1_generic_commandl( pHDev, 6, - EP1_CMD_MEMORY_WRITE, - ST7_PADR >> 8, - ST7_PADR, + ST7_PBDDR >> 8, + ST7_PBDDR, 1, bitmap, EP1_CMD_DTC_GET_CACHED_STATUS ); if(usb_err < 0) { - LOG_ERROR("%s: %s\n", __func__, usb_strerror()); + LOG_ERROR("%s", usb_strerror()); exit(1); } usb_err = usb_bulk_read( pHDev, USB_EP1IN_ADDR, - &bitmap, 1, + (char *)&bitmap, 1, USB_TIMEOUT_MS ); if(usb_err < 1) { - LOG_ERROR("%s: %s\n", __func__, usb_strerror()); + LOG_ERROR("%s", usb_strerror()); exit(1); } } @@ -1031,7 +1101,7 @@ rlink_scan( int scan_size ) { int ir_scan; - enum tap_state saved_end_state; + tap_state_t saved_end_state; int byte_bits; int extra_bits; int chunk_bits; @@ -1051,11 +1121,11 @@ rlink_scan( /* Move to the proper state before starting to shift TDI/TDO. */ if (!( - (!ir_scan && (cur_state == TAP_DRSHIFT)) + (!ir_scan && (tap_get_state() == TAP_DRSHIFT)) || - (ir_scan && (cur_state == TAP_IRSHIFT)) + (ir_scan && (tap_get_state() == TAP_IRSHIFT)) )) { - saved_end_state = end_state; + saved_end_state = tap_get_end_state(); rlink_end_state(ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT); rlink_state_move(); rlink_end_state(saved_end_state); @@ -1102,7 +1172,7 @@ rlink_scan( x = 0; dtc_mask = 1 << (extra_bits - 1); - + while(extra_bits--) { if(*tdi_p & tdi_mask) { x |= dtc_mask; @@ -1170,7 +1240,7 @@ rlink_scan( LOG_ERROR("enqueuing DTC reply entry: %s\n", strerror(errno)); exit(1); } - + tdi_bit_offset += chunk_bits; } @@ -1193,12 +1263,12 @@ rlink_scan( if(type != SCAN_IN) { x = 0; dtc_mask = 1 << (8 - 1); - + while(chunk_bits--) { if(*tdi_p & tdi_mask) { x |= dtc_mask; } - + dtc_mask >>= 1; if(dtc_mask == 0) { dtc_queue.cmd_buffer[dtc_queue.cmd_index++] = x; @@ -1206,7 +1276,7 @@ rlink_scan( x = 0; dtc_mask = 1 << (8 - 1); } - + tdi_mask <<= 1; if(tdi_mask == 0) { tdi_p++; @@ -1235,7 +1305,7 @@ rlink_scan( LOG_ERROR("enqueuing DTC reply entry: %s\n", strerror(errno)); exit(1); } - + tdi_bit_offset += extra_bits; if(type == SCAN_IN) { @@ -1248,14 +1318,14 @@ rlink_scan( x = 0; dtc_mask = 1 << (8 - 1); - + while(extra_bits--) { if(*tdi_p & tdi_mask) { x |= dtc_mask; } - + dtc_mask >>= 1; - + tdi_mask <<= 1; if(tdi_mask == 0) { tdi_p++; @@ -1293,8 +1363,8 @@ rlink_scan( LOG_ERROR("enqueuing DTC reply entry: %s\n", strerror(errno)); exit(1); } - - dtc_queue.cmd_buffer[dtc_queue.cmd_index++] = + + dtc_queue.cmd_buffer[dtc_queue.cmd_index++] = DTC_CMD_SHIFT_TMS_TDI_BIT_PAIR(1, (*tdi_p & tdi_mask), 1); dtc_queue.reply_index++; @@ -1303,8 +1373,8 @@ rlink_scan( /* Move to pause state */ tap_state_queue_append(0); - cur_state = ir_scan ? TAP_IRPAUSE : TAP_DRPAUSE; - if (cur_state != end_state) rlink_state_move(); + tap_set_state(ir_scan ? TAP_IRPAUSE : TAP_DRPAUSE); + if (tap_get_state() != tap_get_end_state()) rlink_state_move(); return(0); } @@ -1363,7 +1433,7 @@ int rlink_execute_queue(void) #endif if ((cmd->cmd.reset->trst == 1) || (cmd->cmd.reset->srst && (jtag_reset_config & RESET_SRST_PULLS_TRST))) { - cur_state = TAP_RESET; + tap_set_state(TAP_RESET); } rlink_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); break; @@ -1451,7 +1521,7 @@ int rlink_speed(int speed) LOG_ERROR("An error occurred while trying to load DTC code for speed \"%d\".\n", speed); exit(1); } - + if(dtc_start_download() < 0) { LOG_ERROR("%s, %d: starting DTC: %s", __FILE__, __LINE__, @@ -1605,7 +1675,7 @@ int rlink_init(void) /* usb_set_configuration required under win32 */ usb_set_configuration(pHDev, dev->config[0].bConfigurationValue); - + retries = 3; do { @@ -1691,9 +1761,9 @@ int rlink_init(void) ST7_PEDR >> 8, ST7_PEDR, 3, - 0x00, - ST7_PE_ADAPTER_SENSE_OUT, - ST7_PE_ADAPTER_SENSE_OUT, + 0x00, /* DR */ + ST7_PE_ADAPTER_SENSE_OUT, /* DDR */ + ST7_PE_ADAPTER_SENSE_OUT, /* OR */ EP1_CMD_MEMORY_READ, /* Read back */ ST7_PEDR >> 8, ST7_PEDR, @@ -1725,9 +1795,9 @@ int rlink_init(void) ST7_PEDR >> 8, ST7_PEDR, 3, - 0x00, - 0x00, - 0x00 + 0x00, /* DR */ + 0x00, /* DDR */ + 0x00 /* OR */ ); usb_bulk_read( @@ -1741,24 +1811,40 @@ int rlink_init(void) LOG_WARNING("target not plugged in\n"); } - /* float port A, make sure DTC is stopped, set upper 2 bits of port D, and set up port A */ + /* float ports A and B */ ep1_generic_commandl( - pHDev, 15, + pHDev, 11, EP1_CMD_MEMORY_WRITE, ST7_PADDR >> 8, ST7_PADDR, 2, 0x00, 0x00, + EP1_CMD_MEMORY_WRITE, + ST7_PBDDR >> 8, + ST7_PBDDR, + 1, + 0x00 + ); + + /* make sure DTC is stopped, set VPP control, set up ports A and B */ + ep1_generic_commandl( + pHDev, 14, EP1_CMD_DTC_STOP, - EP1_CMD_SET_PORTD_UPPER, - ~(ST7_PD_NRUN_LED), + EP1_CMD_SET_PORTD_VPP, + ~(ST7_PD_VPP_SHDN), EP1_CMD_MEMORY_WRITE, ST7_PADR >> 8, ST7_PADR, 2, - ((~(ST7_PA_NLINE_DRIVER_ENABLE)) & ST7_PA_NUNASSERTED), - (ST7_PA_NLINE_DRIVER_ENABLE | ST7_PA_NRLINK_RST | ST7_PA_NJTAG_TRST) + ((~(0)) & (ST7_PA_NTRST)), + (ST7_PA_NTRST), + /* port B has no OR, and we want to emulate open drain on NSRST, so we set DR to 0 here and later assert NSRST by setting DDR bit to 1. */ + EP1_CMD_MEMORY_WRITE, + ST7_PBDR >> 8, + ST7_PBDR, + 1, + 0x00 ); /* set LED updating mode and make sure they're unlit */ @@ -1792,7 +1878,7 @@ int rlink_quit(void) EP1_CMD_LEDUE_NONE, EP1_CMD_SET_PORTD_LEDS, ~0, - EP1_CMD_SET_PORTD_UPPER, + EP1_CMD_SET_PORTD_VPP, ~0 );