X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fjtag%2Fdrivers%2Fusb_blaster%2Fusb_blaster.c;h=165ebdcd35a75e93064542987fbb6b72ef9e569a;hp=ccbed0e2be58439f2a7ece61612f607961f5156e;hb=159f11fefc194743a0af6e29e134b184bf26650d;hpb=18e15390df676636cd2f29093ef78ec6e757036a diff --git a/src/jtag/drivers/usb_blaster/usb_blaster.c b/src/jtag/drivers/usb_blaster/usb_blaster.c index ccbed0e2be..165ebdcd35 100644 --- a/src/jtag/drivers/usb_blaster/usb_blaster.c +++ b/src/jtag/drivers/usb_blaster/usb_blaster.c @@ -4,6 +4,7 @@ * Inspired from original code from Kolja Waschk's USB-JTAG project * (http://www.ixo.de/info/usb_jtag/), and from openocd project. * + * Copyright (C) 2013 Franck Jullien franck.jullien@gmail.com * Copyright (C) 2012 Robert Jarzmik robert.jarzmik@free.fr * Copyright (C) 2011 Ali Lown ali@lown.me.uk * Copyright (C) 2009 Catalin Patulea cat@vv.carleton.ca @@ -19,6 +20,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * */ /* @@ -48,6 +52,16 @@ * | 6 MHz XTAL | | 24 MHz Osc. | * |_____________| |_____________| * + * USB-JTAG, Altera USB-Blaster II are typically implemented as a Cypress + * EZ-USB FX2LP followed by a CPLD. + * _____________ _________ + * | | | | + * USB__| EZ-USB FX2 |__| EPM570 |__JTAG (B_TDO,B_TDI,B_TMS,B_TCK) + * |_____________| |_________| + * __|__________ + * | | + * | 24 MHz XTAL | + * |_____________| */ #ifdef HAVE_CONFIG_H @@ -82,6 +96,9 @@ */ #define BUF_LEN 4096 +/* USB-Blaster II specific command */ +#define CMD_COPY_TDO_BUFFER 0x5F + enum gpio_steer { FIXED_0 = 0, FIXED_1, @@ -103,6 +120,9 @@ struct ublast_info { struct ublast_lowlevel *drv; char *ublast_device_desc; uint16_t ublast_vid, ublast_pid; + uint16_t ublast_vid_uninit, ublast_pid_uninit; + int flags; + char *firmware_path; }; /* @@ -127,11 +147,11 @@ struct drvs_map { }; static struct drvs_map lowlevel_drivers_map[] = { -#if BUILD_USB_BLASTER_LIBFTDI +#if BUILD_USB_BLASTER { .name = "ftdi", .drv_register = ublast_register_ftdi }, #endif -#if BUILD_USB_BLASTER_FTD2XX - { .name = "ftd2xx", .drv_register = ublast_register_ftd2xx }, +#if BUILD_USB_BLASTER_2 + { .name = "ublast2", .drv_register = ublast2_register_libusb }, #endif { NULL, NULL }, }; @@ -154,7 +174,7 @@ static int ublast_buf_read(uint8_t *buf, unsigned size, uint32_t *bytes_read) int ret = info.drv->read(info.drv, buf, size, bytes_read); char *str = hexdump(buf, *bytes_read); - DEBUG_JTAG_IO("(size=%d, buf=[%s]) -> %u", size, str, + LOG_DEBUG_IO("(size=%d, buf=[%s]) -> %u", size, str, *bytes_read); free(str); return ret; @@ -165,7 +185,7 @@ static int ublast_buf_write(uint8_t *buf, int size, uint32_t *bytes_written) int ret = info.drv->write(info.drv, buf, size, bytes_written); char *str = hexdump(buf, *bytes_written); - DEBUG_JTAG_IO("(size=%d, buf=[%s]) -> %u", size, str, + LOG_DEBUG_IO("(size=%d, buf=[%s]) -> %u", size, str, *bytes_written); free(str); return ret; @@ -246,7 +266,7 @@ static void ublast_queue_byte(uint8_t abyte) info.buf[info.bufidx++] = abyte; if (nb_buf_remaining() == 0) ublast_flush_buffer(); - DEBUG_JTAG_IO("(byte=0x%02x)", abyte); + LOG_DEBUG_IO("(byte=0x%02x)", abyte); } /** @@ -317,7 +337,7 @@ static void ublast_clock_tms(int tms) { uint8_t out; - DEBUG_JTAG_IO("(tms=%d)", !!tms); + LOG_DEBUG_IO("(tms=%d)", !!tms); info.tms = !!tms; info.tdi = 0; out = ublast_build_out(SCAN_OUT); @@ -334,7 +354,7 @@ static void ublast_idle_clock(void) { uint8_t out = ublast_build_out(SCAN_OUT); - DEBUG_JTAG_IO("."); + LOG_DEBUG_IO("."); ublast_queue_byte(out); } @@ -355,7 +375,7 @@ static void ublast_clock_tdi(int tdi, enum scan_type type) { uint8_t out; - DEBUG_JTAG_IO("(tdi=%d)", !!tdi); + LOG_DEBUG_IO("(tdi=%d)", !!tdi); info.tdi = !!tdi; out = ublast_build_out(SCAN_OUT); @@ -380,7 +400,7 @@ static void ublast_clock_tdi_flip_tms(int tdi, enum scan_type type) { uint8_t out; - DEBUG_JTAG_IO("(tdi=%d)", !!tdi); + LOG_DEBUG_IO("(tdi=%d)", !!tdi); info.tdi = !!tdi; info.tms = !info.tms; @@ -410,7 +430,7 @@ static void ublast_queue_bytes(uint8_t *bytes, int nb_bytes) info.bufidx + nb_bytes); exit(-1); } - DEBUG_JTAG_IO("(nb_bytes=%d, bytes=[0x%02x, ...])", nb_bytes, + LOG_DEBUG_IO("(nb_bytes=%d, bytes=[0x%02x, ...])", nb_bytes, bytes ? bytes[0] : 0); if (bytes) memcpy(&info.buf[info.bufidx], bytes, nb_bytes); @@ -425,6 +445,7 @@ static void ublast_queue_bytes(uint8_t *bytes, int nb_bytes) * ublast_tms_seq - write a TMS sequence transition to JTAG * @bits: TMS bits to be written (bit0, bit1 .. bitN) * @nb_bits: number of TMS bits (between 1 and 8) + * @skip: number of TMS bits to skip at the beginning of the series * * Write a serie of TMS transitions, where each transition consists in : * - writing out TCK=0, TMS=, TDI= @@ -432,12 +453,12 @@ static void ublast_queue_bytes(uint8_t *bytes, int nb_bytes) * The function ensures that at the end of the sequence, the clock (TCK) is put * low. */ -static void ublast_tms_seq(const uint8_t *bits, int nb_bits) +static void ublast_tms_seq(const uint8_t *bits, int nb_bits, int skip) { int i; - DEBUG_JTAG_IO("(bits=%02x..., nb_bits=%d)", bits[0], nb_bits); - for (i = 0; i < nb_bits; i++) + LOG_DEBUG_IO("(bits=%02x..., nb_bits=%d)", bits[0], nb_bits); + for (i = skip; i < nb_bits; i++) ublast_clock_tms((bits[i / 8] >> (i % 8)) & 0x01); ublast_idle_clock(); } @@ -448,8 +469,8 @@ static void ublast_tms_seq(const uint8_t *bits, int nb_bits) */ static void ublast_tms(struct tms_command *cmd) { - DEBUG_JTAG_IO("(num_bits=%d)", cmd->num_bits); - ublast_tms_seq(cmd->bits, cmd->num_bits); + LOG_DEBUG_IO("(num_bits=%d)", cmd->num_bits); + ublast_tms_seq(cmd->bits, cmd->num_bits, 0); } /** @@ -466,7 +487,7 @@ static void ublast_path_move(struct pathmove_command *cmd) { int i; - DEBUG_JTAG_IO("(num_states=%d, last_state=%d)", + LOG_DEBUG_IO("(num_states=%d, last_state=%d)", cmd->num_states, cmd->path[cmd->num_states - 1]); for (i = 0; i < cmd->num_states; i++) { if (tap_state_transition(tap_get_state(), false) == cmd->path[i]) @@ -481,22 +502,23 @@ static void ublast_path_move(struct pathmove_command *cmd) /** * ublast_state_move - move JTAG state to the target state * @state: the target state + * @skip: number of bits to skip at the beginning of the path * * Input the correct TMS sequence to the JTAG TAP so that we end up in the * target state. This assumes the current state (tap_get_state()) is correct. */ -static void ublast_state_move(tap_state_t state) +static void ublast_state_move(tap_state_t state, int skip) { uint8_t tms_scan; int tms_len; - DEBUG_JTAG_IO("(from %s to %s)", tap_state_name(tap_get_state()), + LOG_DEBUG_IO("(from %s to %s)", tap_state_name(tap_get_state()), tap_state_name(state)); if (tap_get_state() == state) return; tms_scan = tap_get_tms_path(tap_get_state(), state); tms_len = tap_get_tms_path_len(tap_get_state(), state); - ublast_tms_seq(&tms_scan, tms_len); + ublast_tms_seq(&tms_scan, tms_len, skip); tap_set_state(state); } @@ -519,7 +541,7 @@ static int ublast_read_byteshifted_tdos(uint8_t *buf, int nb_bytes) unsigned int retlen; int ret = ERROR_OK; - DEBUG_JTAG_IO("%s(buf=%p, num_bits=%d)", __func__, buf, nb_bytes * 8); + LOG_DEBUG_IO("%s(buf=%p, num_bits=%d)", __func__, buf, nb_bytes * 8); ublast_flush_buffer(); while (ret == ERROR_OK && nb_bytes > 0) { ret = ublast_buf_read(buf, nb_bytes, &retlen); @@ -551,7 +573,7 @@ static int ublast_read_bitbang_tdos(uint8_t *buf, int nb_bits) unsigned int retlen; uint8_t tmp[8]; - DEBUG_JTAG_IO("%s(buf=%p, num_bits=%d)", __func__, buf, nb_bits); + LOG_DEBUG_IO("%s(buf=%p, num_bits=%d)", __func__, buf, nb_bits); /* * Ensure all previous bitbang writes were issued to the dongle, so that @@ -631,8 +653,11 @@ static void ublast_queue_tdi(uint8_t *bits, int nb_bits, enum scan_type scan) ublast_queue_bytes(&bits[i], trans); else ublast_queue_bytes(byte0, trans); - if (read_tdos) + if (read_tdos) { + if (info.flags & COPY_TDO_BUFFER) + ublast_queue_byte(CMD_COPY_TDO_BUFFER); ublast_read_byteshifted_tdos(&tdos[i], trans); + } } /* @@ -645,8 +670,11 @@ static void ublast_queue_tdi(uint8_t *bits, int nb_bits, enum scan_type scan) else ublast_clock_tdi(tdi, scan); } - if (nb1 && read_tdos) + if (nb1 && read_tdos) { + if (info.flags & COPY_TDO_BUFFER) + ublast_queue_byte(CMD_COPY_TDO_BUFFER); ublast_read_bitbang_tdos(&tdos[nb8], nb1); + } if (bits) memcpy(bits, tdos, DIV_ROUND_UP(nb_bits, 8)); @@ -660,16 +688,16 @@ static void ublast_queue_tdi(uint8_t *bits, int nb_bits, enum scan_type scan) static void ublast_runtest(int cycles, tap_state_t state) { - DEBUG_JTAG_IO("%s(cycles=%i, end_state=%d)", __func__, cycles, state); + LOG_DEBUG_IO("%s(cycles=%i, end_state=%d)", __func__, cycles, state); - ublast_state_move(TAP_IDLE); + ublast_state_move(TAP_IDLE, 0); ublast_queue_tdi(NULL, cycles, SCAN_OUT); - ublast_state_move(state); + ublast_state_move(state, 0); } static void ublast_stableclocks(int cycles) { - DEBUG_JTAG_IO("%s(cycles=%i)", __func__, cycles); + LOG_DEBUG_IO("%s(cycles=%i)", __func__, cycles); ublast_queue_tdi(NULL, cycles, SCAN_OUT); } @@ -694,12 +722,12 @@ static int ublast_scan(struct scan_command *cmd) scan_bits = jtag_build_buffer(cmd, &buf); if (cmd->ir_scan) - ublast_state_move(TAP_IRSHIFT); + ublast_state_move(TAP_IRSHIFT, 0); else - ublast_state_move(TAP_DRSHIFT); + ublast_state_move(TAP_DRSHIFT, 0); log_buf = hexdump(buf, DIV_ROUND_UP(scan_bits, 8)); - DEBUG_JTAG_IO("%s(scan=%s, type=%s, bits=%d, buf=[%s], end_state=%d)", __func__, + LOG_DEBUG_IO("%s(scan=%s, type=%s, bits=%d, buf=[%s], end_state=%d)", __func__, cmd->ir_scan ? "IRSCAN" : "DRSCAN", type2str[type], scan_bits, log_buf, cmd->end_state); @@ -707,34 +735,59 @@ static int ublast_scan(struct scan_command *cmd) ublast_queue_tdi(buf, scan_bits, type); - /* - * As our JTAG is in an unstable state (IREXIT1 or DREXIT1), move it - * forward to a stable IRPAUSE or DRPAUSE. - */ - ublast_clock_tms(0); - if (cmd->ir_scan) - tap_set_state(TAP_IRPAUSE); - else - tap_set_state(TAP_DRPAUSE); - ret = jtag_read_buffer(buf, cmd); if (buf) free(buf); - ublast_state_move(cmd->end_state); + /* + * ublast_queue_tdi sends the last bit with TMS=1. We are therefore + * already in Exit1-DR/IR and have to skip the first step on our way + * to end_state. + */ + ublast_state_move(cmd->end_state, 1); return ret; } -static void ublast_msleep(int ms) +static void ublast_usleep(int us) { - DEBUG_JTAG_IO("%s(ms=%d)", __func__, ms); - jtag_sleep(ms); + LOG_DEBUG_IO("%s(us=%d)", __func__, us); + jtag_sleep(us); +} + +static void ublast_initial_wipeout(void) +{ + static uint8_t tms_reset = 0xff; + uint8_t out_value; + uint32_t retlen; + int i; + + out_value = ublast_build_out(SCAN_OUT); + for (i = 0; i < BUF_LEN; i++) + info.buf[i] = out_value | ((i % 2) ? TCK : 0); + + /* + * Flush USB-Blaster queue fifos + * - empty the write FIFO (128 bytes) + * - empty the read FIFO (384 bytes) + */ + ublast_buf_write(info.buf, BUF_LEN, &retlen); + /* + * Put JTAG in RESET state (five 1 on TMS) + */ + ublast_tms_seq(&tms_reset, 5, 0); + tap_set_state(TAP_RESET); } static int ublast_execute_queue(void) { struct jtag_command *cmd; + static int first_call = 1; int ret = ERROR_OK; + if (first_call) { + first_call--; + ublast_initial_wipeout(); + } + for (cmd = jtag_command_queue; ret == ERROR_OK && cmd != NULL; cmd = cmd->next) { switch (cmd->type) { @@ -749,7 +802,7 @@ static int ublast_execute_queue(void) ublast_stableclocks(cmd->cmd.stableclocks->num_cycles); break; case JTAG_TLR_RESET: - ublast_state_move(cmd->cmd.statemove->end_state); + ublast_state_move(cmd->cmd.statemove->end_state, 0); break; case JTAG_PATHMOVE: ublast_path_move(cmd->cmd.pathmove); @@ -758,7 +811,7 @@ static int ublast_execute_queue(void) ublast_tms(cmd->cmd.tms); break; case JTAG_SLEEP: - ublast_msleep(cmd->cmd.sleep->us); + ublast_usleep(cmd->cmd.sleep->us); break; case JTAG_SCAN: ret = ublast_scan(cmd->cmd.scan); @@ -775,57 +828,60 @@ static int ublast_execute_queue(void) * * Initialize the device : * - open the USB device - * - empty the write FIFO (128 bytes) - * - empty the read FIFO (384 bytes) + * - pretend it's initialized while actual init is delayed until first jtag command * * Returns ERROR_OK if USB device found, error if not. */ static int ublast_init(void) { - static uint8_t tms_reset = 0xff; int ret, i; - if (info.lowlevel_name) { - for (i = 0; lowlevel_drivers_map[i].name; i++) - if (!strcmp(lowlevel_drivers_map[i].name, info.lowlevel_name)) + for (i = 0; lowlevel_drivers_map[i].name; i++) { + if (info.lowlevel_name) { + if (!strcmp(lowlevel_drivers_map[i].name, info.lowlevel_name)) { + info.drv = lowlevel_drivers_map[i].drv_register(); + if (!info.drv) { + LOG_ERROR("Error registering lowlevel driver \"%s\"", + info.lowlevel_name); + return ERROR_JTAG_DEVICE_ERROR; + } break; - if (lowlevel_drivers_map[i].name) - info.drv = lowlevel_drivers_map[i].drv_register(); - if (!info.drv) { - LOG_ERROR("no lowlevel driver found for %s or lowlevel driver opening error", - info.lowlevel_name); - return ERROR_JTAG_DEVICE_ERROR; - } - } else { - LOG_INFO("No lowlevel driver configured, will try them all"); - for (i = 0; !info.drv && lowlevel_drivers_map[i].name; i++) + } + } else { info.drv = lowlevel_drivers_map[i].drv_register(); - if (!info.drv) { - LOG_ERROR("no lowlevel driver found"); - return ERROR_JTAG_DEVICE_ERROR; + if (info.drv) { + info.lowlevel_name = strdup(lowlevel_drivers_map[i].name); + LOG_INFO("No lowlevel driver configured, using %s", info.lowlevel_name); + break; + } } } + if (!info.drv) { + LOG_ERROR("No lowlevel driver available"); + return ERROR_JTAG_DEVICE_ERROR; + } + /* * Register the lowlevel driver */ info.drv->ublast_vid = info.ublast_vid; info.drv->ublast_pid = info.ublast_pid; + info.drv->ublast_vid_uninit = info.ublast_vid_uninit; + info.drv->ublast_pid_uninit = info.ublast_pid_uninit; info.drv->ublast_device_desc = info.ublast_device_desc; + info.drv->firmware_path = info.firmware_path; + + info.flags |= info.drv->flags; ret = info.drv->open(info.drv); - if (ret == ERROR_OK) { - /* - * Flush USB-Blaster queue fifos - */ - uint32_t retlen; - ublast_buf_write(info.buf, BUF_LEN, &retlen); - /* - * Put JTAG in RESET state (five 1 on TMS) - */ - ublast_tms_seq(&tms_reset, 5); - tap_set_state(TAP_RESET); - } + + /* + * Let lie here : the TAP is in an unknown state, but the first + * execute_queue() will trigger a ublast_initial_wipeout(), which will + * put the TAP in RESET. + */ + tap_set_state(TAP_RESET); return ret; } @@ -849,29 +905,36 @@ static int ublast_quit(void) COMMAND_HANDLER(ublast_handle_device_desc_command) { - if (CMD_ARGC == 1) - info.ublast_device_desc = strdup(CMD_ARGV[0]); - else - LOG_ERROR("require exactly one argument to " - "ublast_device_desc "); + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + info.ublast_device_desc = strdup(CMD_ARGV[0]); return ERROR_OK; } COMMAND_HANDLER(ublast_handle_vid_pid_command) { - if (CMD_ARGC > 2) { + if (CMD_ARGC > 4) { LOG_WARNING("ignoring extra IDs in ublast_vid_pid " - "(maximum is 1 pair)"); - CMD_ARGC = 2; + "(maximum is 2 pairs)"); + CMD_ARGC = 4; } - if (CMD_ARGC == 2) { + + if (CMD_ARGC >= 2) { COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], info.ublast_vid); COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], info.ublast_pid); } else { LOG_WARNING("incomplete ublast_vid_pid configuration"); } + if (CMD_ARGC == 4) { + COMMAND_PARSE_NUMBER(u16, CMD_ARGV[2], info.ublast_vid_uninit); + COMMAND_PARSE_NUMBER(u16, CMD_ARGV[3], info.ublast_pid_uninit); + } else { + LOG_WARNING("incomplete ublast_vid_pid configuration"); + } + return ERROR_OK; } @@ -913,7 +976,7 @@ COMMAND_HANDLER(ublast_handle_pin_command) if (strlen(pin_value) > 1) val = '?'; - switch (tolower(val)) { + switch (tolower((unsigned char)val)) { case '0': *steer = FIXED_0; break; @@ -943,14 +1006,25 @@ COMMAND_HANDLER(ublast_handle_pin_command) COMMAND_HANDLER(ublast_handle_lowlevel_drv_command) { - if (CMD_ARGC == 1) - info.lowlevel_name = strdup(CMD_ARGV[0]); - else - LOG_ERROR("require exactly one argument to " - "usb_blaster_lowlevel_driver (ftdi|ftd2xx)"); + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + info.lowlevel_name = strdup(CMD_ARGV[0]); + return ERROR_OK; } +COMMAND_HANDLER(ublast_firmware_command) +{ + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + info.firmware_path = strdup(CMD_ARGV[0]); + + return ERROR_OK; +} + + static const struct command_registration ublast_command_handlers[] = { { .name = "usb_blaster_device_desc", @@ -963,15 +1037,17 @@ static const struct command_registration ublast_command_handlers[] = { .name = "usb_blaster_vid_pid", .handler = ublast_handle_vid_pid_command, .mode = COMMAND_CONFIG, - .help = "the vendor ID and product ID of the USB-Blaster", - .usage = "vid pid", + .help = "the vendor ID and product ID of the USB-Blaster and " \ + "vendor ID and product ID of the uninitialized device " \ + "for USB-Blaster II", + .usage = "vid pid vid_uninit pid_uninit", }, { .name = "usb_blaster_lowlevel_driver", .handler = ublast_handle_lowlevel_drv_command, .mode = COMMAND_CONFIG, - .help = "set the lowlevel access for the USB Blaster (ftdi, ftd2xx)", - .usage = "(ftdi|ftd2xx)", + .help = "set the lowlevel access for the USB Blaster (ftdi, ublast2)", + .usage = "(ftdi|ublast2)", }, { .name = "usb_blaster_pin", @@ -979,12 +1055,20 @@ static const struct command_registration ublast_command_handlers[] = { .mode = COMMAND_ANY, .help = "show or set pin state for the unused GPIO pins", .usage = "(pin6|pin8) (0|1|s|t)", + }, + { + .name = "usb_blaster_firmware", + .handler = &ublast_firmware_command, + .mode = COMMAND_CONFIG, + .help = "configure the USB-Blaster II firmware location", + .usage = "path/to/blaster_xxxx.hex", }, COMMAND_REGISTRATION_DONE }; struct jtag_interface usb_blaster_interface = { .name = "usb_blaster", + .transports = jtag_only, .commands = ublast_command_handlers, .supported = DEBUG_CAP_TMS_SEQ,