* 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
* 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 <http://www.gnu.org/licenses/>.
+ *
*/
/*
* | 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
*/
#define BUF_LEN 4096
+/* USB-Blaster II specific command */
+#define CMD_COPY_TDO_BUFFER 0x5F
+
+enum gpio_steer {
+ FIXED_0 = 0,
+ FIXED_1,
+ SRST,
+ TRST,
+};
+
struct ublast_info {
- int pin6;
- int pin8;
+ enum gpio_steer pin6;
+ enum gpio_steer pin8;
int tms;
int tdi;
+ bool trst_asserted;
+ bool srst_asserted;
uint8_t buf[BUF_LEN];
int bufidx;
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;
};
/*
.ublast_vid = 0x09fb, /* Altera */
.ublast_pid = 0x6001, /* USB-Blaster */
.lowlevel_name = NULL,
+ .srst_asserted = false,
+ .trst_asserted = false,
+ .pin6 = FIXED_1,
+ .pin8 = FIXED_1,
};
/*
};
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 },
};
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;
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;
#define SHMODE (1 << 7)
#define READ_TDO (1 << 0)
-/**
- * ublast_reset - reset the JTAG device is possible
- * @trst: 1 if TRST is to be asserted
- * @srst: 1 if SRST is to be asserted
- *
- * This is not implemented yet. If pin6 or pin8 controlls the TRST/SRST, code
- * should be added so that this function makes use of it.
- */
-static void ublast_reset(int trst, int srst)
-{
- DEBUG_JTAG_IO("TODO: ublast_reset(%d,%d) isn't implemented!",
- trst, srst);
-}
-
/**
* ublast_queue_byte - queue one 'bitbang mode' byte for USB Blaster
* @abyte: the byte to queue
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);
+}
+
+/**
+ * ublast_compute_pin - compute if gpio should be asserted
+ * @steer: control (ie. TRST driven, SRST driven, of fixed)
+ *
+ * Returns pin value (1 means driven high, 0 mean driven low)
+ */
+bool ublast_compute_pin(enum gpio_steer steer)
+{
+ switch (steer) {
+ case FIXED_0:
+ return 0;
+ case FIXED_1:
+ return 1;
+ case SRST:
+ return !info.srst_asserted;
+ case TRST:
+ return !info.trst_asserted;
+ default:
+ return 1;
+ }
}
/**
uint8_t abyte = 0;
abyte |= info.tms ? TMS : 0;
- abyte |= info.pin6 ? NCE : 0;
- abyte |= info.pin8 ? NCS : 0;
+ abyte |= ublast_compute_pin(info.pin6) ? NCE : 0;
+ abyte |= ublast_compute_pin(info.pin8) ? NCS : 0;
abyte |= info.tdi ? TDI : 0;
abyte |= LED;
if (type == SCAN_IN || type == SCAN_IO)
return abyte;
}
+/**
+ * ublast_reset - reset the JTAG device is possible
+ * @trst: 1 if TRST is to be asserted
+ * @srst: 1 if SRST is to be asserted
+ */
+static void ublast_reset(int trst, int srst)
+{
+ uint8_t out_value;
+
+ info.trst_asserted = trst;
+ info.srst_asserted = srst;
+ out_value = ublast_build_out(SCAN_OUT);
+ ublast_queue_byte(out_value);
+ ublast_flush_buffer();
+}
+
/**
* ublast_clock_tms - clock a TMS transition
* @tms: the TMS to be sent
{
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);
{
uint8_t out = ublast_build_out(SCAN_OUT);
- DEBUG_JTAG_IO(".");
+ LOG_DEBUG_IO(".");
ublast_queue_byte(out);
}
{
uint8_t out;
- DEBUG_JTAG_IO("(tdi=%d)", !!tdi);
+ LOG_DEBUG_IO("(tdi=%d)", !!tdi);
info.tdi = !!tdi;
out = ublast_build_out(SCAN_OUT);
{
uint8_t out;
- DEBUG_JTAG_IO("(tdi=%d)", !!tdi);
+ LOG_DEBUG_IO("(tdi=%d)", !!tdi);
info.tdi = !!tdi;
info.tms = !info.tms;
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);
* 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=<new_state>, TDI=<???>
* 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();
}
*/
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);
}
/**
{
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])
/**
* 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);
}
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);
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
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);
+ }
}
/*
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));
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);
}
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);
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) {
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);
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);
break;
+ default:
+ LOG_ERROR("BUG: unknown JTAG command type 0x%X",
+ cmd->type);
+ ret = ERROR_FAIL;
+ break;
}
}
*
* 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;
}
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 <description>");
+ 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;
}
COMMAND_HANDLER(ublast_handle_pin_command)
{
uint8_t out_value;
+ const char * const pin_name = CMD_ARGV[0];
+ enum gpio_steer *steer = NULL;
+ static const char * const pin_val_str[] = {
+ [FIXED_0] = "0",
+ [FIXED_1] = "1",
+ [SRST] = "SRST driven",
+ [TRST] = "TRST driven",
+ };
- if (CMD_ARGC == 2) {
- const char * const pin_name = CMD_ARGV[0];
- unsigned int state;
+ if (CMD_ARGC > 2) {
+ LOG_ERROR("%s takes exactly one or two arguments", CMD_NAME);
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ }
- COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], state);
- if ((state != 0) && (state != 1)) {
- LOG_ERROR("%s: pin state must be 0 or 1", CMD_NAME);
- return ERROR_COMMAND_SYNTAX_ERROR;
- }
+ if (!strcmp(pin_name, "pin6"))
+ steer = &info.pin6;
+ if (!strcmp(pin_name, "pin8"))
+ steer = &info.pin8;
+ if (!steer) {
+ LOG_ERROR("%s: pin name must be \"pin6\" or \"pin8\"",
+ CMD_NAME);
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ }
- if (!strcmp(pin_name, "pin6")) {
- info.pin6 = state;
- } else if (!strcmp(pin_name, "pin8")) {
- info.pin8 = state;
- } else {
- LOG_ERROR("%s: pin name must be \"pin6\" or \"pin8\"",
- CMD_NAME);
+ if (CMD_ARGC == 1) {
+ LOG_INFO("%s: %s is set as %s\n", CMD_NAME, pin_name,
+ pin_val_str[*steer]);
+ }
+
+ if (CMD_ARGC == 2) {
+ const char * const pin_value = CMD_ARGV[1];
+ char val = pin_value[0];
+
+ if (strlen(pin_value) > 1)
+ val = '?';
+ switch (tolower((unsigned char)val)) {
+ case '0':
+ *steer = FIXED_0;
+ break;
+ case '1':
+ *steer = FIXED_1;
+ break;
+ case 't':
+ *steer = TRST;
+ break;
+ case 's':
+ *steer = SRST;
+ break;
+ default:
+ LOG_ERROR("%s: pin value must be 0, 1, s (SRST) or t (TRST)",
+ pin_value);
return ERROR_COMMAND_SYNTAX_ERROR;
}
ublast_queue_byte(out_value);
ublast_flush_buffer();
}
- return ERROR_OK;
- } else {
- LOG_ERROR("%s takes exactly two arguments", CMD_NAME);
- return ERROR_COMMAND_SYNTAX_ERROR;
}
+ return ERROR_OK;
}
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",
.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",
+ .name = "usb_blaster_pin",
.handler = ublast_handle_pin_command,
.mode = COMMAND_ANY,
- .help = "set pin state for the unused GPIO pins",
- .usage = "(pin6|pin8) (0|1)",
+ .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,