From: SimonQian Date: Mon, 11 Jul 2011 17:48:05 +0000 (+0800) Subject: versaloon driver update X-Git-Tag: v0.6.0-rc1~610 X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=commitdiff_plain;h=54fc164d3a2e3b83f5a91533cac7829f019a14f2;hp=42b85f76f7950528754c4e988441167f2f54c003 versaloon driver update Signed-off-by: Spencer Oliver --- diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am index 1e523581dc..805d1a4902 100644 --- a/src/jtag/drivers/Makefile.am +++ b/src/jtag/drivers/Makefile.am @@ -67,6 +67,12 @@ DRIVERFILES += ulink.c nobase_dist_pkglib_DATA += $(ULINK_FIRMWARE)/ulink_firmware.hex endif if VSLLINK +DRIVERFILES += versaloon/usbtoxxx/usbtogpio.c +DRIVERFILES += versaloon/usbtoxxx/usbtojtagraw.c +DRIVERFILES += versaloon/usbtoxxx/usbtoswd.c +DRIVERFILES += versaloon/usbtoxxx/usbtopwr.c +DRIVERFILES += versaloon/usbtoxxx/usbtoxxx.c +DRIVERFILES += versaloon/versaloon.c DRIVERFILES += vsllink.c endif if ARMJTAGEW diff --git a/src/jtag/drivers/versaloon/usbtoxxx/usbtogpio.c b/src/jtag/drivers/versaloon/usbtoxxx/usbtogpio.c new file mode 100644 index 0000000000..5be515f64e --- /dev/null +++ b/src/jtag/drivers/versaloon/usbtoxxx/usbtogpio.c @@ -0,0 +1,100 @@ +/*************************************************************************** + * Copyright (C) 2009 - 2010 by Simon Qian * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * 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, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "../versaloon_include.h" +#include "../versaloon.h" +#include "../versaloon_internal.h" +#include "usbtoxxx.h" +#include "usbtoxxx_internal.h" + +RESULT usbtogpio_init(uint8_t interface_index) +{ + return usbtoxxx_init_command(USB_TO_GPIO, interface_index); +} + +RESULT usbtogpio_fini(uint8_t interface_index) +{ + return usbtoxxx_fini_command(USB_TO_GPIO, interface_index); +} + +RESULT usbtogpio_config(uint8_t interface_index, uint32_t mask, + uint32_t dir_mask, uint32_t pull_en_mask, + uint32_t input_pull_mask) +{ + uint8_t conf[8]; + +#if PARAM_CHECK + if (interface_index > 7) + { + LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index); + return ERROR_FAIL; + } +#endif + + dir_mask &= mask; + SET_LE_U16(&conf[0], mask); + SET_LE_U16(&conf[2], dir_mask); + SET_LE_U16(&conf[4], pull_en_mask); + SET_LE_U16(&conf[6], input_pull_mask); + + return usbtoxxx_conf_command(USB_TO_GPIO, interface_index, conf, + sizeof(conf)); +} + +RESULT usbtogpio_in(uint8_t interface_index, uint32_t mask, uint32_t *value) +{ + uint8_t buf[2]; + +#if PARAM_CHECK + if (interface_index > 7) + { + LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index); + return ERROR_FAIL; + } +#endif + + SET_LE_U16(&buf[0], mask); + + return usbtoxxx_in_command(USB_TO_GPIO, interface_index, buf, 2, 2, + (uint8_t*)value, 0, 2, 0); +} + +RESULT usbtogpio_out(uint8_t interface_index, uint32_t mask, uint32_t value) +{ + uint8_t buf[4]; + +#if PARAM_CHECK + if (interface_index > 7) + { + LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index); + return ERROR_FAIL; + } +#endif + + SET_LE_U16(&buf[0], mask); + SET_LE_U16(&buf[2], value); + + return usbtoxxx_out_command(USB_TO_GPIO, interface_index, buf, 4, 0); +} + diff --git a/src/jtag/drivers/versaloon/usbtoxxx/usbtojtagraw.c b/src/jtag/drivers/versaloon/usbtoxxx/usbtojtagraw.c new file mode 100644 index 0000000000..11e8064d56 --- /dev/null +++ b/src/jtag/drivers/versaloon/usbtoxxx/usbtojtagraw.c @@ -0,0 +1,84 @@ +/*************************************************************************** + * Copyright (C) 2009 - 2010 by Simon Qian * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * 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, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "../versaloon_include.h" +#include "../versaloon.h" +#include "../versaloon_internal.h" +#include "usbtoxxx.h" +#include "usbtoxxx_internal.h" + +RESULT usbtojtagraw_init(uint8_t interface_index) +{ + return usbtoxxx_init_command(USB_TO_JTAG_RAW, interface_index); +} + +RESULT usbtojtagraw_fini(uint8_t interface_index) +{ + return usbtoxxx_fini_command(USB_TO_JTAG_RAW, interface_index); +} + +RESULT usbtojtagraw_config(uint8_t interface_index, uint32_t kHz) +{ + uint8_t cfg_buf[4]; + +#if PARAM_CHECK + if (interface_index > 7) + { + LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index); + return ERROR_FAIL; + } +#endif + + SET_LE_U32(&cfg_buf[0], kHz); + + return usbtoxxx_conf_command(USB_TO_JTAG_RAW, interface_index, cfg_buf, 4); +} + +RESULT usbtojtagraw_execute(uint8_t interface_index, uint8_t *tdi, + uint8_t *tms, uint8_t *tdo, uint32_t bitlen) +{ + uint16_t bytelen; + +#if PARAM_CHECK + if (interface_index > 7) + { + LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index); + return ERROR_FAIL; + } +#endif + + if (bitlen > 8 * 0xFFFF) + { + return ERROR_FAIL; + } + bytelen = (uint16_t)((bitlen + 7) >> 3); + + SET_LE_U32(&versaloon_cmd_buf[0], bitlen); + memcpy(versaloon_cmd_buf + 4, tdi, bytelen); + memcpy(versaloon_cmd_buf + 4 + bytelen, tms, bytelen); + + return usbtoxxx_inout_command(USB_TO_JTAG_RAW, interface_index, + versaloon_cmd_buf, 4 + bytelen * 2, bytelen, tdo, 0, bytelen, 0); +} + diff --git a/src/jtag/drivers/versaloon/usbtoxxx/usbtopwr.c b/src/jtag/drivers/versaloon/usbtoxxx/usbtopwr.c new file mode 100644 index 0000000000..13f7f153b4 --- /dev/null +++ b/src/jtag/drivers/versaloon/usbtoxxx/usbtopwr.c @@ -0,0 +1,67 @@ +/*************************************************************************** + * Copyright (C) 2009 - 2010 by Simon Qian * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * 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, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "../versaloon_include.h" +#include "../versaloon.h" +#include "../versaloon_internal.h" +#include "usbtoxxx.h" +#include "usbtoxxx_internal.h" + +RESULT usbtopwr_init(uint8_t interface_index) +{ + return usbtoxxx_init_command(USB_TO_POWER, interface_index); +} + +RESULT usbtopwr_fini(uint8_t interface_index) +{ + return usbtoxxx_fini_command(USB_TO_POWER, interface_index); +} + +RESULT usbtopwr_config(uint8_t interface_index) +{ +#if PARAM_CHECK + if (interface_index > 7) + { + LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index); + return ERROR_FAIL; + } +#endif + + return usbtoxxx_conf_command(USB_TO_POWER, interface_index, NULL, 0); +} + +RESULT usbtopwr_output(uint8_t interface_index, uint16_t mV) +{ +#if PARAM_CHECK + if (interface_index > 7) + { + LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index); + return ERROR_FAIL; + } +#endif + + return usbtoxxx_out_command(USB_TO_POWER, interface_index, (uint8_t *)&mV, + 2, 0); +} + diff --git a/src/jtag/drivers/versaloon/usbtoxxx/usbtoswd.c b/src/jtag/drivers/versaloon/usbtoxxx/usbtoswd.c new file mode 100644 index 0000000000..93333f088b --- /dev/null +++ b/src/jtag/drivers/versaloon/usbtoxxx/usbtoswd.c @@ -0,0 +1,158 @@ +/*************************************************************************** + * Copyright (C) 2009 - 2010 by Simon Qian * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * 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, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "../versaloon_include.h" +#include "../versaloon.h" +#include "../versaloon_internal.h" +#include "usbtoxxx.h" +#include "usbtoxxx_internal.h" + +RESULT usbtoswd_callback(void *p, uint8_t *src, uint8_t *processed) +{ + struct versaloon_pending_t *pending = (struct versaloon_pending_t *)p; + + processed = processed; + + if (pending->extra_data != NULL) + { + *((uint8_t *)pending->extra_data) = src[0]; + } + + return ERROR_OK; +} + +RESULT usbtoswd_init(uint8_t interface_index) +{ + return usbtoxxx_init_command(USB_TO_SWD, interface_index); +} + +RESULT usbtoswd_fini(uint8_t interface_index) +{ + return usbtoxxx_fini_command(USB_TO_SWD, interface_index); +} + +RESULT usbtoswd_config(uint8_t interface_index, uint8_t trn, uint16_t retry, + uint16_t dly) +{ + uint8_t cfg_buf[5]; + +#if PARAM_CHECK + if (interface_index > 7) + { + LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index); + return ERROR_FAIL; + } +#endif + + cfg_buf[0] = trn; + SET_LE_U16(&cfg_buf[1], retry); + SET_LE_U16(&cfg_buf[3], dly); + + return usbtoxxx_conf_command(USB_TO_SWD, interface_index, cfg_buf, 5); +} + +RESULT usbtoswd_seqout(uint8_t interface_index, uint8_t *data, uint16_t bitlen) +{ + uint16_t bytelen = (bitlen + 7) >> 3; + +#if PARAM_CHECK + if (interface_index > 7) + { + LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index); + return ERROR_FAIL; + } +#endif + + SET_LE_U16(&versaloon_cmd_buf[0], bitlen); + memcpy(versaloon_cmd_buf + 2, data, bytelen); + + return usbtoxxx_out_command(USB_TO_SWD, interface_index, + versaloon_cmd_buf, bytelen + 2, 0); +} + +RESULT usbtoswd_seqin(uint8_t interface_index, uint8_t *data, uint16_t bitlen) +{ + uint16_t bytelen = (bitlen + 7) >> 3; + uint8_t buff[2]; + +#if PARAM_CHECK + if (interface_index > 7) + { + LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index); + return ERROR_FAIL; + } +#endif + + SET_LE_U16(&buff[0], bitlen); + + return usbtoxxx_in_command(USB_TO_SWD, interface_index, buff, 2, bytelen, + data, 0, bytelen, 0); +} + +RESULT usbtoswd_transact(uint8_t interface_index, uint8_t request, + uint32_t *data, uint8_t *ack) +{ + uint8_t parity; + uint8_t buff[5]; + +#if PARAM_CHECK + if (interface_index > 7) + { + LOG_BUG(ERRMSG_INVALID_INTERFACE_NUM, interface_index); + return ERROR_FAIL; + } +#endif + + parity = (request >> 1) & 1; + parity += (request >> 2) & 1; + parity += (request >> 3) & 1; + parity += (request >> 4) & 1; + parity &= 1; + buff[0] = (request | 0x81 | (parity << 5)) & ~0x40; + if (data != NULL) + { + SET_LE_U32(&buff[1], *data); + } + else + { + memset(buff + 1, 0, 4); + } + + versaloon_set_extra_data(ack); + versaloon_set_callback(usbtoswd_callback); + if (request & 0x04) + { + // read + return usbtoxxx_inout_command(USB_TO_SWD, interface_index, buff, 5, 5, + (uint8_t *)data, 1, 4, 0); + } + else + { + // write + return usbtoxxx_inout_command(USB_TO_SWD, interface_index, buff, 5, 5, + NULL, 0, 0, 0); + } +} + diff --git a/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx.c b/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx.c new file mode 100644 index 0000000000..64e31a6552 --- /dev/null +++ b/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx.c @@ -0,0 +1,652 @@ +/*************************************************************************** + * Copyright (C) 2009 - 2010 by Simon Qian * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * 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, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "../versaloon_include.h" +#include "../versaloon.h" +#include "../versaloon_internal.h" +#include "usbtoxxx.h" +#include "usbtoxxx_internal.h" + +#define N_A "n/a" +const char* types_name[96] = +{ +"usbtousart", "usbtospi", "usbtoi2c", "usbtogpio", "usbtocan", "usbtopwm", + "usbtoadc", "usbtodac", +"usbtomicrowire", "usbtoswim", "usbtodusi", N_A, N_A, N_A, "usbtopower", "usbtodelay", +N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, +N_A, N_A, N_A, N_A, N_A, N_A, N_A, +"usbtojtagll", "usbtojtaghl", "usbtoissp", "usbtoc2", "usbtosbw", + "usbtolpcicp", "usbtoswd", "usbtojtagraw", +"usbtobdm", N_A, N_A, N_A, N_A, N_A, N_A, N_A, +N_A, N_A, N_A, N_A, N_A, N_A, N_A, N_A, +"usbtomsp430jtag", N_A, N_A, N_A, N_A, N_A, N_A, N_A, +"usbtopower", "usbtodelay", "usbtopoll", N_A, N_A, N_A, N_A, N_A, +N_A, N_A, N_A, N_A, N_A, N_A, N_A, "usbtoall" +}; + +uint8_t usbtoxxx_abilities[USB_TO_XXX_ABILITIES_LEN]; + +#define usbtoxxx_get_type_name(type) \ + types_name[((type) - VERSALOON_USB_TO_XXX_CMD_START) \ + % (sizeof(types_name) / sizeof(types_name[0]))] + +static uint8_t type_pre = 0; +static uint16_t usbtoxxx_buffer_index = 0; +static uint16_t usbtoxxx_current_cmd_index = 0; +static uint8_t *usbtoxxx_buffer = NULL; + +uint16_t collect_index = 0; +uint8_t collect_cmd; +static uint8_t poll_nesting = 0; + +struct usbtoxxx_context_t +{ + uint8_t type_pre; + uint8_t *usbtoxxx_buffer; + uint16_t usbtoxxx_current_cmd_index; + uint16_t usbtoxxx_buffer_index; + uint16_t versaloon_pending_idx; +}; +static struct usbtoxxx_context_t poll_context; + +static void usbtoxxx_save_context(struct usbtoxxx_context_t *c) +{ + c->type_pre = type_pre; + c->usbtoxxx_buffer = usbtoxxx_buffer; + c->usbtoxxx_buffer_index = usbtoxxx_buffer_index; + c->usbtoxxx_current_cmd_index = usbtoxxx_current_cmd_index; + c->versaloon_pending_idx = versaloon_pending_idx; +} + +static void usbtoxxx_pop_context(struct usbtoxxx_context_t *c) +{ + type_pre = c->type_pre; + usbtoxxx_buffer = c->usbtoxxx_buffer; + usbtoxxx_buffer_index = c->usbtoxxx_buffer_index; + usbtoxxx_current_cmd_index = c->usbtoxxx_current_cmd_index; + versaloon_pending_idx = c->versaloon_pending_idx; +} + +RESULT usbtoxxx_validate_current_command_type(void) +{ + if (type_pre > 0) + { + // not the first command + if (NULL == usbtoxxx_buffer) + { + LOG_BUG(ERRMSG_INVALID_BUFFER, TO_STR(usbtoxxx_buffer)); + return ERRCODE_INVALID_BUFFER; + } + + usbtoxxx_buffer[0] = type_pre; + SET_LE_U16(&usbtoxxx_buffer[1], usbtoxxx_current_cmd_index); + + usbtoxxx_buffer_index += usbtoxxx_current_cmd_index; + } + else + { + // first command + usbtoxxx_buffer_index = 3; + } + + // prepare for next command + usbtoxxx_current_cmd_index = 3; + usbtoxxx_buffer = versaloon_buf + usbtoxxx_buffer_index; + + collect_index = 0; + collect_cmd = 0; + + return ERROR_OK; +} + + + +RESULT usbtoxxx_execute_command(void) +{ + uint16_t i; + uint16_t inlen; + RESULT result = ERROR_OK; + + if (poll_nesting) + { + LOG_BUG(ERRMSG_INVALID_USAGE, "USB_TO_POLL"); + versaloon_free_want_pos(); + return ERROR_FAIL; + } + + if (ERROR_OK != usbtoxxx_validate_current_command_type()) + { + LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands"); + versaloon_free_want_pos(); + return ERRCODE_FAILURE_OPERATION; + } + if (3 == usbtoxxx_buffer_index) + { + versaloon_free_want_pos(); + return ERROR_OK; + } + + versaloon_buf[0] = USB_TO_ALL; + SET_LE_U16(&versaloon_buf[1], usbtoxxx_buffer_index); + + if (ERROR_OK != versaloon_send_command(usbtoxxx_buffer_index, &inlen)) + { + versaloon_free_want_pos(); + return ERROR_FAIL; + } + + // process return data + usbtoxxx_buffer_index = 0; + for (i = 0; i < versaloon_pending_idx; i++) + { + // check result + if ((0 == i) || !((versaloon_pending[i].collect) + && (versaloon_pending[i - 1].collect) + && (versaloon_pending[i].cmd + == versaloon_pending[i - 1].cmd))) + { + if (USB_TO_XXX_CMD_NOT_SUPPORT + == versaloon_buf[usbtoxxx_buffer_index]) + { + LOG_ERROR(ERRMSG_NOT_SUPPORT_BY, + usbtoxxx_get_type_name(versaloon_pending[i].type), + "current dongle"); + result = ERROR_FAIL; + break; + } + else if (USB_TO_XXX_OK != versaloon_buf[usbtoxxx_buffer_index]) + { + LOG_ERROR("%s command 0x%02x failed with 0x%02x", + usbtoxxx_get_type_name(versaloon_pending[i].type), + versaloon_pending[i].cmd, + versaloon_buf[usbtoxxx_buffer_index]); + result = ERROR_FAIL; + break; + } + usbtoxxx_buffer_index++; + } + + // get result data + if (versaloon_pending[i].pos != NULL) + { + uint8_t processed = 0; + + if (versaloon_pending[i].callback != NULL) + { + versaloon_pending[i].callback(&versaloon_pending[i], + versaloon_buf + usbtoxxx_buffer_index, &processed); + } + if (!processed) + { + struct versaloon_want_pos_t *tmp, *free_tmp; + + free_tmp = tmp = versaloon_pending[i].pos; + while (tmp != NULL) + { + if ((tmp->buff != NULL) && (tmp->size > 0)) + { + memcpy(tmp->buff, versaloon_buf + usbtoxxx_buffer_index + + tmp->offset, tmp->size); + } + free_tmp = tmp; + tmp = tmp->next; + free(free_tmp); + } + versaloon_pending[i].pos = NULL; + } + } + else if ((versaloon_pending[i].want_data_size > 0) + && (versaloon_pending[i].data_buffer != NULL)) + { + uint8_t processed = 0; + + if (versaloon_pending[i].callback != NULL) + { + versaloon_pending[i].callback(&versaloon_pending[i], + versaloon_buf + usbtoxxx_buffer_index, &processed); + } + if (!processed) + { + memcpy(versaloon_pending[i].data_buffer, + versaloon_buf + usbtoxxx_buffer_index + + versaloon_pending[i].want_data_pos, + versaloon_pending[i].want_data_size); + } + } + usbtoxxx_buffer_index += versaloon_pending[i].actual_data_size; + if (usbtoxxx_buffer_index > inlen) + { + LOG_BUG("%s command 0x%02x process error", + usbtoxxx_get_type_name(versaloon_pending[i].type), + versaloon_pending[i].cmd); + result = ERROR_FAIL; + break; + } + } + + // data is not the right size + if (inlen != usbtoxxx_buffer_index) + { + LOG_ERROR(ERRMSG_INVALID_TARGET, "length of return data"); + result = ERROR_FAIL; + } + + if (versaloon_pending_idx > 0) + { + versaloon_pending_idx = 0; + } + else + { + // no receive data, avoid collision + sleep_ms(10); + } + + type_pre = 0; + collect_cmd = 0; + collect_index = 0; + versaloon_free_want_pos(); + return result; +} + +RESULT usbtoxxx_init(void) +{ + versaloon_pending_idx = 0; + + if ((ERROR_OK != usbtoinfo_get_abilities(usbtoxxx_abilities)) || + (ERROR_OK != usbtoxxx_execute_command())) + { + return ERROR_FAIL; + } + LOG_INFO("USB_TO_XXX abilities: 0x%08X:0x%08X:0x%08X", + GET_LE_U32(&usbtoxxx_abilities[0]), + GET_LE_U32(&usbtoxxx_abilities[4]), + GET_LE_U32(&usbtoxxx_abilities[8])); + return ERROR_OK; +} + +RESULT usbtoxxx_fini(void) +{ + usbtoxxx_buffer = NULL; + type_pre = 0; + return ERROR_OK; +} + +bool usbtoxxx_interface_supported(uint8_t cmd) +{ + if ((cmd < VERSALOON_USB_TO_XXX_CMD_START) || + (cmd > VERSALOON_USB_TO_XXX_CMD_END)) + { + return false; + } + + cmd -= VERSALOON_USB_TO_XXX_CMD_START; + return (usbtoxxx_abilities[cmd / 8] & (1 << (cmd % 8))) > 0; +} + + + +RESULT usbtoxxx_ensure_buffer_size(uint16_t cmdlen) +{ + // check free space, commit if not enough + if (((usbtoxxx_buffer_index + usbtoxxx_current_cmd_index + cmdlen) + >= versaloon_buf_size) + || (versaloon_pending_idx >= VERSALOON_MAX_PENDING_NUMBER)) + { + struct usbtoxxx_context_t context_tmp; + uint8_t poll_nesting_tmp = 0; + + memset(&context_tmp, 0, sizeof(context_tmp)); + if (poll_nesting) + { + if (0 == poll_context.type_pre) + { + LOG_BUG("USB_TO_POLL toooooo long"); + return ERROR_OK; + } + + usbtoxxx_save_context(&context_tmp); + usbtoxxx_pop_context(&poll_context); + poll_nesting_tmp = poll_nesting; + poll_nesting = 0; + } + + if (usbtoxxx_execute_command() != ERROR_OK) + { + return ERROR_FAIL; + } + + if (poll_nesting_tmp) + { + uint16_t newlen, oldlen; + + newlen = context_tmp.versaloon_pending_idx + - poll_context.versaloon_pending_idx; + memcpy(&versaloon_pending[0], + &versaloon_pending[poll_context.versaloon_pending_idx], + sizeof(versaloon_pending[0]) * newlen); + context_tmp.versaloon_pending_idx = newlen; + oldlen = poll_context.usbtoxxx_buffer_index + + poll_context.usbtoxxx_current_cmd_index; + newlen = context_tmp.usbtoxxx_buffer_index + + context_tmp.usbtoxxx_current_cmd_index; + memcpy(versaloon_buf + 3, versaloon_buf + oldlen, newlen - oldlen); + oldlen -= 3; + context_tmp.usbtoxxx_buffer -= oldlen; + context_tmp.usbtoxxx_buffer_index -= oldlen; + usbtoxxx_pop_context(&context_tmp); + poll_nesting = poll_nesting_tmp; + } + } + return ERROR_OK; +} + +RESULT usbtoxxx_add_command(uint8_t type, uint8_t cmd, uint8_t *cmdbuf, + uint16_t cmdlen, uint16_t retlen, uint8_t *wantbuf, + uint16_t wantpos, uint16_t wantlen, uint8_t collect) +{ + uint16_t len_tmp; + + // 3 more bytes by usbtoxxx_validate_current_command_type + // 3 more bytes when ((0 == collect_index) || (collect_cmd != cmd)) + if (ERROR_OK != usbtoxxx_ensure_buffer_size(cmdlen + 6)) + { + return ERROR_FAIL; + } + + if ((type_pre != type) || (NULL == usbtoxxx_buffer)) + { + if (ERROR_OK != usbtoxxx_validate_current_command_type()) + { + LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands"); + return ERRCODE_FAILURE_OPERATION; + } + type_pre = type; + } + + if ((0 == collect_index) || (collect_cmd != cmd)) + { + usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = cmd; + + if (collect) + { + collect_index = usbtoxxx_current_cmd_index; + collect_cmd = cmd; + } + else + { + collect_index = 0; + collect_cmd = 0; + } + SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], cmdlen); + usbtoxxx_current_cmd_index += 2; + } + else + { + len_tmp = GET_LE_U16(&usbtoxxx_buffer[collect_index]) + cmdlen; + SET_LE_U16(&usbtoxxx_buffer[collect_index], len_tmp); + } + + if (cmdbuf != NULL) + { + memcpy(usbtoxxx_buffer + usbtoxxx_current_cmd_index, cmdbuf, cmdlen); + usbtoxxx_current_cmd_index += cmdlen; + } + + return versaloon_add_pending(type, cmd, retlen, wantpos, wantlen, + wantbuf, collect); +} + + + + + +RESULT usbtoinfo_get_abilities(uint8_t abilities[USB_TO_XXX_ABILITIES_LEN]) +{ + if (ERROR_OK != usbtoxxx_ensure_buffer_size(3)) + { + return ERROR_FAIL; + } + + if (ERROR_OK != usbtoxxx_validate_current_command_type()) + { + LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands"); + return ERRCODE_FAILURE_OPERATION; + } + type_pre = USB_TO_INFO; + + return versaloon_add_pending(USB_TO_INFO, 0, USB_TO_XXX_ABILITIES_LEN, 0, + USB_TO_XXX_ABILITIES_LEN, abilities, 0); +} + + + + +RESULT usbtopoll_start(uint16_t retry_cnt, uint16_t interval_us) +{ + if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 5)) + { + return ERROR_FAIL; + } + if (!poll_nesting) + { + usbtoxxx_save_context(&poll_context); + } + + if (ERROR_OK != usbtoxxx_validate_current_command_type()) + { + LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands"); + return ERRCODE_FAILURE_OPERATION; + } + poll_nesting++; + type_pre = USB_TO_POLL; + + usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_START; + SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], retry_cnt); + usbtoxxx_current_cmd_index += 2; + SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], interval_us); + usbtoxxx_current_cmd_index += 2; + + return versaloon_add_pending(USB_TO_POLL, 0, 0, 0, 0, NULL, 0); +} + +RESULT usbtopoll_end(void) +{ + if (!poll_nesting) + { + LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting"); + return ERRCODE_FAILURE_OPERATION; + } + if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 1)) + { + return ERROR_FAIL; + } + + if (ERROR_OK != usbtoxxx_validate_current_command_type()) + { + LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands"); + return ERRCODE_FAILURE_OPERATION; + } + + poll_nesting--; + type_pre = USB_TO_POLL; + + usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_END; + + return versaloon_add_pending(USB_TO_POLL, 0, 0, 0, 0, NULL, 0); +} + +RESULT usbtopoll_checkok(uint8_t equ, uint16_t offset, uint8_t size, + uint32_t mask, uint32_t value) +{ + uint8_t i; + + if (size > 4) + { + LOG_BUG(ERRMSG_INVALID_PARAMETER, __FUNCTION__); + return ERRCODE_INVALID_PARAMETER; + } + if (!poll_nesting) + { + LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting"); + return ERRCODE_FAILURE_OPERATION; + } + if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 4 + 2 * size)) + { + return ERROR_FAIL; + } + + if (ERROR_OK != usbtoxxx_validate_current_command_type()) + { + LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands"); + return ERRCODE_FAILURE_OPERATION; + } + + type_pre = USB_TO_POLL; + + usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_CHECKOK; + SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], offset); + usbtoxxx_current_cmd_index += 2; + usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = size; + usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = equ; + for (i =0; i < size; i++) + { + usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (mask >> (8 * i)) & 0xFF; + } + for (i =0; i < size; i++) + { + usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (value >> (8 * i)) & 0xFF; + } + + return ERROR_OK; +} + +RESULT usbtopoll_checkfail(uint8_t equ, uint16_t offset, uint8_t size, + uint32_t mask, uint32_t value) +{ + uint8_t i; + + if (size > 4) + { + LOG_BUG(ERRMSG_INVALID_PARAMETER, __FUNCTION__); + return ERRCODE_INVALID_PARAMETER; + } + if (!poll_nesting) + { + LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting"); + return ERRCODE_FAILURE_OPERATION; + } + if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 4 + 2 * size)) + { + return ERROR_FAIL; + } + + if (ERROR_OK != usbtoxxx_validate_current_command_type()) + { + LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands"); + return ERRCODE_FAILURE_OPERATION; + } + + type_pre = USB_TO_POLL; + + usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_CHECKFAIL; + SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], offset); + usbtoxxx_current_cmd_index += 2; + usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = size; + usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = equ; + for (i =0; i < size; i++) + { + usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (mask >> (8 * i)) & 0xFF; + } + for (i =0; i < size; i++) + { + usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = (value >> (8 * i)) & 0xFF; + } + + return ERROR_OK; +} + +RESULT usbtopoll_verifybuff(uint16_t offset, uint16_t size, uint8_t *buff) +{ + if (!poll_nesting) + { + LOG_BUG(ERRMSG_FAILURE_OPERATION, "check poll nesting"); + return ERRCODE_FAILURE_OPERATION; + } + if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 5 + size)) + { + return ERROR_FAIL; + } + + if (ERROR_OK != usbtoxxx_validate_current_command_type()) + { + LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands"); + return ERRCODE_FAILURE_OPERATION; + } + + type_pre = USB_TO_POLL; + + usbtoxxx_buffer[usbtoxxx_current_cmd_index++] = USB_TO_POLL_VERIFYBUFF; + SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], offset); + usbtoxxx_current_cmd_index += 2; + SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], size); + usbtoxxx_current_cmd_index += 2; + memcpy(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], buff, size); + usbtoxxx_current_cmd_index += size; + + return ERROR_OK; +} + + + + +RESULT usbtodelay_delay(uint16_t dly) +{ + if (ERROR_OK != usbtoxxx_ensure_buffer_size(3 + 2)) + { + return ERROR_FAIL; + } + + if (ERROR_OK != usbtoxxx_validate_current_command_type()) + { + LOG_BUG(ERRMSG_FAILURE_OPERATION, "validate previous commands"); + return ERRCODE_FAILURE_OPERATION; + } + type_pre = USB_TO_DELAY; + + SET_LE_U16(&usbtoxxx_buffer[usbtoxxx_current_cmd_index], dly); + usbtoxxx_current_cmd_index += 2; + + return versaloon_add_pending(USB_TO_DELAY, 0, 0, 0, 0, NULL, 0); +} + +RESULT usbtodelay_delayms(uint16_t ms) +{ + return usbtodelay_delay(ms | 0x8000); +} + +RESULT usbtodelay_delayus(uint16_t us) +{ + return usbtodelay_delay(us & 0x7FFF); +} + diff --git a/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx.h b/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx.h new file mode 100644 index 0000000000..092368ebae --- /dev/null +++ b/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx.h @@ -0,0 +1,278 @@ +/*************************************************************************** + * Copyright (C) 2009 - 2010 by Simon Qian * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * 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, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef __USBTOXXX_H_INCLUDED__ +#define __USBTOXXX_H_INCLUDED__ + +RESULT usbtoxxx_init(void); +RESULT usbtoxxx_fini(void); +RESULT usbtoxxx_execute_command(void); + +#define USB_TO_XXX_ABILITIES_LEN 12 +extern uint8_t usbtoxxx_abilities[USB_TO_XXX_ABILITIES_LEN]; +bool usbtoxxx_interface_supported(uint8_t cmd); + +// USB_TO_INFO +RESULT usbtoinfo_get_abilities(uint8_t abilities[USB_TO_XXX_ABILITIES_LEN]); + +// USB_TO_DELAY +RESULT usbtodelay_delay(uint16_t dly); +RESULT usbtodelay_delayms(uint16_t ms); +RESULT usbtodelay_delayus(uint16_t us); + + + +// USB_TO_USART +RESULT usbtousart_init(uint8_t interface_index); +RESULT usbtousart_fini(uint8_t interface_index); +RESULT usbtousart_config(uint8_t interface_index, uint32_t baudrate, + uint8_t datalength, uint8_t mode); +RESULT usbtousart_send(uint8_t interface_index, uint8_t *buf, uint16_t len); +RESULT usbtousart_receive(uint8_t interface_index, uint8_t *buf, uint16_t len); +RESULT usbtousart_status(uint8_t interface_index, + struct usart_status_t *status); + +// USB_TO_SPI +RESULT usbtospi_init(uint8_t interface_index); +RESULT usbtospi_fini(uint8_t interface_index); +RESULT usbtospi_config(uint8_t interface_index, uint32_t kHz, uint8_t mode); +RESULT usbtospi_io(uint8_t interface_index, uint8_t *out, uint8_t *in, + uint16_t bytelen); + + + +// USB_TO_GPIO +RESULT usbtogpio_init(uint8_t interface_index); +RESULT usbtogpio_fini(uint8_t interface_index); +RESULT usbtogpio_config(uint8_t interface_index, uint32_t mask, + uint32_t dir_mask, uint32_t pull_en_mask, + uint32_t input_pull_mask); +RESULT usbtogpio_in(uint8_t interface_index, uint32_t mask, uint32_t *value); +RESULT usbtogpio_out(uint8_t interface_index, uint32_t mask, uint32_t value); + + + +// USB_TO_ISSP +RESULT usbtoissp_init(uint8_t interface_index); +RESULT usbtoissp_fini(uint8_t interface_index); +RESULT usbtoissp_enter_program_mode(uint8_t interface_index, uint8_t mode); +RESULT usbtoissp_leave_program_mode(uint8_t interface_index, uint8_t mode); +RESULT usbtoissp_wait_and_poll(uint8_t interface_index); +RESULT usbtoissp_vector(uint8_t interface_index, uint8_t operate, uint8_t addr, + uint8_t data, uint8_t *buf); + + + +// USB_TO_LPCICP +RESULT usbtolpcicp_init(uint8_t interface_index); +RESULT usbtolpcicp_fini(uint8_t interface_index); +RESULT usbtolpcicp_config(uint8_t interface_index); +RESULT usbtolpcicp_enter_program_mode(uint8_t interface_index); +RESULT usbtolpcicp_in(uint8_t interface_index, uint8_t *buff, uint16_t len); +RESULT usbtolpcicp_out(uint8_t interface_index, uint8_t *buff, uint16_t len); +RESULT usbtolpcicp_poll_ready(uint8_t interface_index, uint8_t data, + uint8_t *ret, uint8_t setmask, uint8_t clearmask, uint16_t pollcnt); + + + +// USB_TO_JTAG_LL +RESULT usbtojtagll_init(uint8_t interface_index); +RESULT usbtojtagll_fini(uint8_t interface_index); +RESULT usbtojtagll_config(uint8_t interface_index, uint32_t kHz); +RESULT usbtojtagll_tms(uint8_t interface_index, uint8_t *tms, uint8_t bytelen); +RESULT usbtojtagll_tms_clocks(uint8_t interface_index, uint32_t bytelen, + uint8_t tms); +RESULT usbtojtagll_scan(uint8_t interface_index, uint8_t* data, + uint16_t bitlen, uint8_t tms_before_valid, + uint8_t tms_before, uint8_t tms_after0, + uint8_t tms_after1); + + + +// USB_TO_JTAG_HL +RESULT usbtojtaghl_init(uint8_t interface_index); +RESULT usbtojtaghl_fini(uint8_t interface_index); +RESULT usbtojtaghl_config(uint8_t interface_index, uint32_t kHz, uint8_t ub, + uint8_t ua, uint16_t bb, uint16_t ba); +RESULT usbtojtaghl_ir(uint8_t interface_index, uint8_t *ir, uint16_t bitlen, + uint8_t idle, uint8_t want_ret); +RESULT usbtojtaghl_dr(uint8_t interface_index, uint8_t *dr, uint16_t bitlen, + uint8_t idle, uint8_t want_ret); +RESULT usbtojtaghl_tms(uint8_t interface_index, uint8_t *tms, uint16_t bitlen); +RESULT usbtojtaghl_runtest(uint8_t interface_index, uint32_t cycles); +RESULT usbtojtaghl_register_callback(uint8_t index, jtag_callback_t send_callback, + jtag_callback_t receive_callback); + + + +// USB_TO_JTAG_RAW +RESULT usbtojtagraw_init(uint8_t interface_index); +RESULT usbtojtagraw_fini(uint8_t interface_index); +RESULT usbtojtagraw_config(uint8_t interface_index, uint32_t kHz); +RESULT usbtojtagraw_execute(uint8_t interface_index, uint8_t *tdi, + uint8_t *tms, uint8_t *tdo, uint32_t bitlen); + + + + +// USB_TO_C2 +RESULT usbtoc2_init(uint8_t interface_index); +RESULT usbtoc2_fini(uint8_t interface_index); +RESULT usbtoc2_writeaddr(uint8_t interface_index, uint8_t addr); +RESULT usbtoc2_readaddr(uint8_t interface_index, uint8_t *data); +RESULT usbtoc2_writedata(uint8_t interface_index, uint8_t *buf, uint8_t len); +RESULT usbtoc2_readdata(uint8_t interface_index, uint8_t *buf, uint8_t len); + + + +// USB_TO_I2C +RESULT usbtoi2c_init(uint8_t interface_index); +RESULT usbtoi2c_fini(uint8_t interface_index); +RESULT usbtoi2c_config(uint8_t interface_index, uint16_t kHz, + uint16_t byte_interval, uint16_t max_dly); +RESULT usbtoi2c_read(uint8_t interface_index, uint16_t chip_addr, + uint8_t *data, uint16_t data_len, uint8_t stop, + bool nacklast); +RESULT usbtoi2c_write(uint8_t interface_index, uint16_t chip_addr, + uint8_t *data, uint16_t data_len, uint8_t stop); + + + +// USB_TO_MSP430_JTAG +RESULT usbtomsp430jtag_init(uint8_t interface_index); +RESULT usbtomsp430jtag_fini(uint8_t interface_index); +RESULT usbtomsp430jtag_config(uint8_t interface_index, uint8_t has_test); +RESULT usbtomsp430jtag_ir(uint8_t interface_index, uint8_t *ir, + uint8_t want_ret); +RESULT usbtomsp430jtag_dr(uint8_t interface_index, uint32_t *dr, + uint8_t bitlen, uint8_t want_ret); +RESULT usbtomsp430jtag_tclk(uint8_t interface_index, uint8_t value); +RESULT usbtomsp430jtag_tclk_strobe(uint8_t interface_index, uint16_t cnt); +RESULT usbtomsp430jtag_reset(uint8_t interface_index); +RESULT usbtomsp430jtag_poll(uint8_t interface_index, uint32_t dr, + uint32_t mask, uint32_t value, uint8_t len, + uint16_t poll_cnt, uint8_t toggle_tclk); + + + +// USB_TO_MSP430_SBW +RESULT usbtomsp430sbw_init(uint8_t interface_index); +RESULT usbtomsp430sbw_fini(uint8_t interface_index); +RESULT usbtomsp430sbw_config(uint8_t interface_index, uint8_t has_test); +RESULT usbtomsp430sbw_ir(uint8_t interface_index, uint8_t *ir, + uint8_t want_ret); +RESULT usbtomsp430sbw_dr(uint8_t interface_index, uint32_t *dr, + uint8_t bitlen, uint8_t want_ret); +RESULT usbtomsp430sbw_tclk(uint8_t interface_index, uint8_t value); +RESULT usbtomsp430sbw_tclk_strobe(uint8_t interface_index, uint16_t cnt); +RESULT usbtomsp430sbw_reset(uint8_t interface_index); +RESULT usbtomsp430sbw_poll(uint8_t interface_index, uint32_t dr, uint32_t mask, + uint32_t value, uint8_t len, uint16_t poll_cnt, + uint8_t toggle_tclk); + + + +// USB_TO_POWER +RESULT usbtopwr_init(uint8_t interface_index); +RESULT usbtopwr_fini(uint8_t interface_index); +RESULT usbtopwr_config(uint8_t interface_index); +RESULT usbtopwr_output(uint8_t interface_index, uint16_t mV); + + + +// USB_TO_POLL +RESULT usbtopoll_start(uint16_t retry_cnt, uint16_t interval_us); +RESULT usbtopoll_end(void); +RESULT usbtopoll_checkok(uint8_t equ, uint16_t offset, uint8_t size, + uint32_t mask, uint32_t value); +RESULT usbtopoll_checkfail(uint8_t equ, uint16_t offset, uint8_t size, + uint32_t mask, uint32_t value); +RESULT usbtopoll_verifybuff(uint16_t offset, uint16_t size, uint8_t *buff); + + + +// USB_TO_SWD +RESULT usbtoswd_init(uint8_t interface_index); +RESULT usbtoswd_fini(uint8_t interface_index); +RESULT usbtoswd_config(uint8_t interface_index, uint8_t trn, uint16_t retry, + uint16_t dly); +RESULT usbtoswd_seqout(uint8_t interface_index, uint8_t *data, uint16_t bitlen); +RESULT usbtoswd_seqin(uint8_t interface_index, uint8_t *data, uint16_t bitlen); +RESULT usbtoswd_transact(uint8_t interface_index, uint8_t request, + uint32_t *data, uint8_t *ack); + + + +// USB_TO_SWIM +RESULT usbtoswim_init(uint8_t interface_index); +RESULT usbtoswim_fini(uint8_t interface_index); +RESULT usbtoswim_config(uint8_t interface_index, uint8_t mHz, uint8_t cnt0, + uint8_t cnt1); +RESULT usbtoswim_srst(uint8_t interface_index); +RESULT usbtoswim_wotf(uint8_t interface_index, uint8_t *data, + uint16_t bytelen, uint32_t addr); +RESULT usbtoswim_rotf(uint8_t interface_index, uint8_t *data, + uint16_t bytelen, uint32_t addr); +RESULT usbtoswim_sync(uint8_t interface_index, uint8_t mHz); +RESULT usbtoswim_enable(uint8_t interface_index); + + + + +// USB_TO_BDM +RESULT usbtobdm_init(uint8_t interface_index); +RESULT usbtobdm_fini(uint8_t interface_index); +RESULT usbtobdm_sync(uint8_t interface_index, uint16_t *khz); +RESULT usbtobdm_transact(uint8_t interface_index, uint8_t *out, + uint8_t outlen, uint8_t *in, uint8_t inlen, uint8_t delay, uint8_t ack); + + + +// USB_TO_DUSI +RESULT usbtodusi_init(uint8_t interface_index); +RESULT usbtodusi_fini(uint8_t interface_index); +RESULT usbtodusi_config(uint8_t interface_index, uint32_t kHz, uint8_t mode); +RESULT usbtodusi_io(uint8_t interface_index, uint8_t *mo, uint8_t *mi, + uint8_t *so, uint8_t *si, uint32_t bitlen); + + + +// USB_TO_MICROWIRE +RESULT usbtomicrowire_init(uint8_t interface_index); +RESULT usbtomicrowire_fini(uint8_t interface_index); +RESULT usbtomicrowire_config(uint8_t interface_index, uint16_t kHz, + uint8_t sel_polarity); +RESULT usbtomicrowire_transport(uint8_t interface_index, + uint32_t opcode, uint8_t opcode_bitlen, + uint32_t addr, uint8_t addr_bitlen, + uint32_t data, uint8_t data_bitlen, + uint8_t *reply, uint8_t reply_bitlen); +RESULT usbtomicrowire_poll(uint8_t interface_index, uint16_t interval_us, + uint16_t retry_cnt); + + + +// USB_TO_PWM +RESULT usbtopwm_init(uint8_t interface_index); +RESULT usbtopwm_fini(uint8_t interface_index); +RESULT usbtopwm_config(uint8_t interface_index, uint16_t kHz, uint8_t mode); +RESULT usbtopwm_out(uint8_t interface_index, uint16_t count, uint16_t *rate); +RESULT usbtopwm_in(uint8_t interface_index, uint16_t count, uint16_t *rate); + +#endif /* __USBTOXXX_H_INCLUDED__ */ + diff --git a/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx_internal.h b/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx_internal.h new file mode 100644 index 0000000000..837d6949e1 --- /dev/null +++ b/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx_internal.h @@ -0,0 +1,169 @@ +/*************************************************************************** + * Copyright (C) 2009 - 2010 by Simon Qian * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * 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, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef __USBTOXXX_INTERNAL_H_INCLUDED__ +#define __USBTOXXX_INTERNAL_H_INCLUDED__ + +// USB_TO_XXX USB Commands +// Page0 +#define USB_TO_USART (VERSALOON_USB_TO_XXX_CMD_START + 0x00) +#define USB_TO_SPI (VERSALOON_USB_TO_XXX_CMD_START + 0x01) +#define USB_TO_I2C (VERSALOON_USB_TO_XXX_CMD_START + 0x02) +#define USB_TO_GPIO (VERSALOON_USB_TO_XXX_CMD_START + 0x03) +#define USB_TO_CAN (VERSALOON_USB_TO_XXX_CMD_START + 0x04) +#define USB_TO_PWM (VERSALOON_USB_TO_XXX_CMD_START + 0x05) +#define USB_TO_ADC (VERSALOON_USB_TO_XXX_CMD_START + 0x06) +#define USB_TO_DAC (VERSALOON_USB_TO_XXX_CMD_START + 0x07) +#define USB_TO_MICROWIRE (VERSALOON_USB_TO_XXX_CMD_START + 0x08) +#define USB_TO_SWIM (VERSALOON_USB_TO_XXX_CMD_START + 0x09) +#define USB_TO_DUSI (VERSALOON_USB_TO_XXX_CMD_START + 0x0A) +// Page1 +#define USB_TO_JTAG_LL (VERSALOON_USB_TO_XXX_CMD_START + 0x20) +#define USB_TO_JTAG_HL (VERSALOON_USB_TO_XXX_CMD_START + 0x21) +#define USB_TO_ISSP (VERSALOON_USB_TO_XXX_CMD_START + 0x22) +#define USB_TO_C2 (VERSALOON_USB_TO_XXX_CMD_START + 0x23) +#define USB_TO_SBW (VERSALOON_USB_TO_XXX_CMD_START + 0x24) +#define USB_TO_LPCICP (VERSALOON_USB_TO_XXX_CMD_START + 0x25) +#define USB_TO_SWD (VERSALOON_USB_TO_XXX_CMD_START + 0x26) +#define USB_TO_JTAG_RAW (VERSALOON_USB_TO_XXX_CMD_START + 0x27) +#define USB_TO_BDM (VERSALOON_USB_TO_XXX_CMD_START + 0x28) +#define USB_TO_MSP430_JTAG (VERSALOON_USB_TO_XXX_CMD_START + 0x38) +// Page2 +#define USB_TO_POWER (VERSALOON_USB_TO_XXX_CMD_START + 0x40) +#define USB_TO_DELAY (VERSALOON_USB_TO_XXX_CMD_START + 0x41) +#define USB_TO_POLL (VERSALOON_USB_TO_XXX_CMD_START + 0x42) +#define USB_TO_INFO (VERSALOON_USB_TO_XXX_CMD_START + 0x5E) +#define USB_TO_ALL (VERSALOON_USB_TO_XXX_CMD_START + 0x5F) + + + +// USB_TO_XXX Masks +#define USB_TO_XXX_CMDMASK 0xF8 +#define USB_TO_XXX_CMDSHIFT 3 +#define USB_TO_XXX_IDXMASK 0x07 +// USB_TO_XXX Sub Commands +// Common Sub Commands +#define USB_TO_XXX_INIT (0x00 << USB_TO_XXX_CMDSHIFT) +#define USB_TO_XXX_FINI (0x01 << USB_TO_XXX_CMDSHIFT) +#define USB_TO_XXX_CONFIG (0x02 << USB_TO_XXX_CMDSHIFT) +#define USB_TO_XXX_GETHWINFO (0x03 << USB_TO_XXX_CMDSHIFT) +#define USB_TO_XXX_STATUS (0X04 << USB_TO_XXX_CMDSHIFT) +#define USB_TO_XXX_IN_OUT (0x05 << USB_TO_XXX_CMDSHIFT) +#define USB_TO_XXX_IN (0x06 << USB_TO_XXX_CMDSHIFT) +#define USB_TO_XXX_OUT (0x07 << USB_TO_XXX_CMDSHIFT) +#define USB_TO_XXX_POLL (0x08 << USB_TO_XXX_CMDSHIFT) +#define USB_TO_XXX_SPECIAL (0x09 << USB_TO_XXX_CMDSHIFT) +#define USB_TO_XXX_RESET (0x0A << USB_TO_XXX_CMDSHIFT) +#define USB_TO_XXX_SYNC (0x0B << USB_TO_XXX_CMDSHIFT) +#define USB_TO_XXX_ENABLE (0x0C << USB_TO_XXX_CMDSHIFT) +#define USB_TO_XXX_DISABLE (0x0D << USB_TO_XXX_CMDSHIFT) +// USB_TO_POLL +#define USB_TO_POLL_START 0x00 +#define USB_TO_POLL_END 0x01 +#define USB_TO_POLL_CHECKOK 0x02 +#define USB_TO_POLL_CHECKFAIL 0x03 +#define USB_TO_POLL_VERIFYBUFF 0x04 + + + +// USB_TO_XXX Replys +#define USB_TO_XXX_OK 0x00 +#define USB_TO_XXX_FAILED 0x01 +#define USB_TO_XXX_TIME_OUT 0x02 +#define USB_TO_XXX_INVALID_INDEX 0x03 +#define USB_TO_XXX_INVALID_PARA 0x04 +#define USB_TO_XXX_INVALID_CMD 0x05 +#define USB_TO_XXX_CMD_NOT_SUPPORT 0x06 + + + +// USB_TO_XXX +RESULT usbtoxxx_add_pending(uint8_t type, uint8_t cmd, uint16_t + actual_szie, uint16_t want_pos, + uint16_t want_size, uint8_t *buffer); + +RESULT usbtoxxx_add_command(uint8_t type, uint8_t cmd, uint8_t *cmdbuf, + uint16_t cmdlen, uint16_t retlen, + uint8_t *wantbuf, uint16_t wantpos, + uint16_t wantlen, uint8_t collect); + +#define usbtoxxx_init_command(type, port) \ + usbtoxxx_add_command((type), (USB_TO_XXX_INIT | (port)), \ + NULL, 0, 0, NULL, 0, 0, 0) +#define usbtoxxx_fini_command(type, port) \ + usbtoxxx_add_command((type), (USB_TO_XXX_FINI | (port)), \ + NULL, 0, 0, NULL, 0, 0, 0) +#define usbtoxxx_conf_command(type, port, cmdbuf, cmdlen) \ + usbtoxxx_add_command((type), (USB_TO_XXX_CONFIG | (port)), \ + (cmdbuf), (cmdlen), 0, NULL, 0, 0, 0) +#define usbtoxxx_inout_command(type, port, cmdbuf, cmdlen, retlen, wantbuf, \ + wantpos, wantlen, c) \ + usbtoxxx_add_command((type), (USB_TO_XXX_IN_OUT | (port)), \ + (cmdbuf), (cmdlen), (retlen), (wantbuf), \ + (wantpos), (wantlen), (c)) +#define usbtoxxx_in_command(type, port, cmdbuf, cmdlen, retlen, wantbuf, \ + wantpos, wantlen, c) \ + usbtoxxx_add_command((type), (USB_TO_XXX_IN | (port)), (cmdbuf), \ + (cmdlen), (retlen), (wantbuf), (wantpos), \ + (wantlen), (c)) +#define usbtoxxx_out_command(type, port, cmdbuf, cmdlen, c) \ + usbtoxxx_add_command((type), (USB_TO_XXX_OUT | (port)), (cmdbuf), \ + (cmdlen), 0, NULL, 0, 0, (c)) +#define usbtoxxx_poll_command(type, port, cmdbuf, cmdlen, retbuf, retlen) \ + usbtoxxx_add_command((type), (USB_TO_XXX_POLL | (port)), (cmdbuf),\ + (cmdlen), (retlen), (retbuf), 0, (retlen), 0) +#define usbtoxxx_status_command(type, port, retlen, wantbuf, wantpos, wantlen, c)\ + usbtoxxx_add_command((type), (USB_TO_XXX_STATUS | (port)), \ + NULL, 0, (retlen), (wantbuf), (wantpos), \ + (wantlen), (c)) +#define usbtoxxx_special_command(type, port, cmdbuf, cmdlen, retlen, wantbuf, \ + wantpos, wantlen, c) \ + usbtoxxx_add_command((type), (USB_TO_XXX_SPECIAL | (port)), \ + (cmdbuf), (cmdlen), retlen, wantbuf, \ + wantpos, wantlen, (c)) +#define usbtoxxx_reset_command(type, port, cmdbuf, cmdlen) \ + usbtoxxx_add_command((type), (USB_TO_XXX_RESET | (port)), \ + (cmdbuf), (cmdlen), 0, NULL, 0, 0, 0) +#define usbtoxxx_sync_command(type, port, cmdbuf, cmdlen, retlen, wantbuf) \ + usbtoxxx_add_command((type), (USB_TO_XXX_SYNC | (port)), \ + (cmdbuf), (cmdlen), (retlen), (wantbuf), 0, \ + (retlen), 0) +#define usbtoxxx_enable_command(type, port, cmdbuf, cmdlen) \ + usbtoxxx_add_command((type), (USB_TO_XXX_ENABLE | (port)), \ + (cmdbuf), (cmdlen), 0, NULL, 0, 0, 0) +#define usbtoxxx_disable_command(type, port, cmdbuf, cmdlen) \ + usbtoxxx_add_command((type), (USB_TO_XXX_DISABLE | (port)), \ + (cmdbuf), (cmdlen), 0, NULL, 0, 0, 0) + +// USB_TO_SPI +#define USB_TO_SPI_BAUDRATE_MSK 0x1F +#define USB_TO_SPI_CPOL_MSK 0x20 +#define USB_TO_SPI_CPHA_MSK 0x40 +#define USB_TO_SPI_MSB_FIRST 0x80 + +// USB_TO_DUSI +#define USB_TO_DUSI_BAUDRATE_MSK 0x1F +#define USB_TO_DUSI_CPOL_MSK 0x20 +#define USB_TO_DUSI_CPHA_MSK 0x40 +#define USB_TO_DUSI_MSB_FIRST 0x80 + +// USB_TO_GPIO +#define USB_TO_GPIO_DIR_MSK 0x01 + +#endif /* __USBTOXXX_INTERNAL_H_INCLUDED__ */ + diff --git a/src/jtag/drivers/versaloon/versaloon.c b/src/jtag/drivers/versaloon/versaloon.c new file mode 100644 index 0000000000..dbb8e4fb03 --- /dev/null +++ b/src/jtag/drivers/versaloon/versaloon.c @@ -0,0 +1,398 @@ +/*************************************************************************** + * Copyright (C) 2009 - 2010 by Simon Qian * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * 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, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "versaloon_include.h" +#include "versaloon.h" +#include "versaloon_internal.h" +#include "usbtoxxx/usbtoxxx.h" + +uint8_t *versaloon_buf = NULL; +uint8_t *versaloon_cmd_buf = NULL; +uint16_t versaloon_buf_size; + +struct versaloon_pending_t versaloon_pending[VERSALOON_MAX_PENDING_NUMBER]; +uint16_t versaloon_pending_idx = 0; + +usb_dev_handle *versaloon_usb_device_handle = NULL; +static uint32_t versaloon_usb_to = VERSALOON_TIMEOUT; + +RESULT versaloon_init(void); +RESULT versaloon_fini(void); +RESULT versaloon_get_target_voltage(uint16_t *voltage); +RESULT versaloon_set_target_voltage(uint16_t voltage); +RESULT versaloon_delay_ms(uint16_t ms); +RESULT versaloon_delay_us(uint16_t us); +struct versaloon_interface_t versaloon_interface = +{ + .init = versaloon_init, + .fini = versaloon_fini, + {// adaptors + {// target_voltage + .get = versaloon_get_target_voltage, + .set = versaloon_set_target_voltage, + }, + {// gpio + .init = usbtogpio_init, + .fini = usbtogpio_fini, + .config = usbtogpio_config, + .out = usbtogpio_out, + .in = usbtogpio_in, + }, + {// delay + .delayms = versaloon_delay_ms, + .delayus = versaloon_delay_us, + }, + {// swd + .init = usbtoswd_init, + .fini = usbtoswd_fini, + .config = usbtoswd_config, + .seqout = usbtoswd_seqout, + .seqin = usbtoswd_seqin, + .transact = usbtoswd_transact, + }, + {// jtag_raw + .init = usbtojtagraw_init, + .fini = usbtojtagraw_fini, + .config = usbtojtagraw_config, + .execute = usbtojtagraw_execute, + }, + .peripheral_commit = usbtoxxx_execute_command, + }, + {// usb_setting + .vid = VERSALOON_VID, + .pid = VERSALOON_PID, + .ep_out = VERSALOON_OUTP, + .ep_in = VERSALOON_INP, + .interface = VERSALOON_IFACE, + .serialstring = NULL, + .buf_size = 256, + } +}; + +// programmer_cmd +static uint32_t versaloon_pending_id = 0; +static versaloon_callback_t versaloon_callback = NULL; +static void *versaloon_extra_data = NULL; +static struct versaloon_want_pos_t *versaloon_want_pos = NULL; +void versaloon_set_pending_id(uint32_t id) +{ + versaloon_pending_id = id; +} +void versaloon_set_callback(versaloon_callback_t callback) +{ + versaloon_callback = callback; +} +void versaloon_set_extra_data(void * p) +{ + versaloon_extra_data = p; +} + +void versaloon_free_want_pos(void) +{ + uint16_t i; + struct versaloon_want_pos_t *tmp, *free_tmp; + + tmp = versaloon_want_pos; + while (tmp != NULL) + { + free_tmp = tmp; + tmp = tmp->next; + free(free_tmp); + } + versaloon_want_pos = NULL; + + for (i = 0; i < dimof(versaloon_pending); i++) + { + tmp = versaloon_pending[i].pos; + while (tmp != NULL) + { + free_tmp = tmp; + tmp = tmp->next; + free(free_tmp); + } + versaloon_pending[i].pos = NULL; + } +} + +RESULT versaloon_add_want_pos(uint16_t offset, uint16_t size, uint8_t *buff) +{ + struct versaloon_want_pos_t *new_pos = NULL; + + new_pos = (struct versaloon_want_pos_t *)malloc(sizeof(*new_pos)); + if (NULL == new_pos) + { + LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY); + return ERRCODE_NOT_ENOUGH_MEMORY; + } + new_pos->offset = offset; + new_pos->size = size; + new_pos->buff = buff; + new_pos->next = NULL; + + if (NULL == versaloon_want_pos) + { + versaloon_want_pos = new_pos; + } + else + { + struct versaloon_want_pos_t *tmp = versaloon_want_pos; + + while (tmp->next != NULL) + { + tmp = tmp->next; + } + tmp->next = new_pos; + } + + return ERROR_OK; +} + +RESULT versaloon_add_pending(uint8_t type, uint8_t cmd, uint16_t actual_szie, + uint16_t want_pos, uint16_t want_size, uint8_t *buffer, uint8_t collect) +{ +#if PARAM_CHECK + if (versaloon_pending_idx >= VERSALOON_MAX_PENDING_NUMBER) + { + LOG_BUG(ERRMSG_INVALID_INDEX, versaloon_pending_idx, + "versaloon pending data"); + return ERROR_FAIL; + } +#endif + + versaloon_pending[versaloon_pending_idx].type = type; + versaloon_pending[versaloon_pending_idx].cmd = cmd; + versaloon_pending[versaloon_pending_idx].actual_data_size = actual_szie; + versaloon_pending[versaloon_pending_idx].want_data_pos = want_pos; + versaloon_pending[versaloon_pending_idx].want_data_size = want_size; + versaloon_pending[versaloon_pending_idx].data_buffer = buffer; + versaloon_pending[versaloon_pending_idx].collect = collect; + versaloon_pending[versaloon_pending_idx].id = versaloon_pending_id; + versaloon_pending_id = 0; + versaloon_pending[versaloon_pending_idx].extra_data = versaloon_extra_data; + versaloon_extra_data = NULL; + versaloon_pending[versaloon_pending_idx].callback = versaloon_callback; + versaloon_callback = NULL; + versaloon_pending[versaloon_pending_idx].pos = versaloon_want_pos; + versaloon_want_pos = NULL; + versaloon_pending_idx++; + + return ERROR_OK; +} + +RESULT versaloon_send_command(uint16_t out_len, uint16_t *inlen) +{ + int ret; + +#if PARAM_CHECK + if (NULL == versaloon_buf) + { + LOG_BUG(ERRMSG_INVALID_BUFFER, TO_STR(versaloon_buf)); + return ERRCODE_INVALID_BUFFER; + } + if ((0 == out_len) || (out_len > versaloon_interface.usb_setting.buf_size)) + { + LOG_BUG(ERRMSG_INVALID_PARAMETER, __FUNCTION__); + return ERRCODE_INVALID_PARAMETER; + } +#endif + + ret = usb_bulk_write(versaloon_usb_device_handle, + versaloon_interface.usb_setting.ep_out, (char *)versaloon_buf, + out_len, versaloon_usb_to); + if (ret != out_len) + { + LOG_ERROR(ERRMSG_FAILURE_OPERATION_ERRSTRING, "send usb data", + usb_strerror()); + return ERRCODE_FAILURE_OPERATION; + } + + if (inlen != NULL) + { + ret = usb_bulk_read(versaloon_usb_device_handle, + versaloon_interface.usb_setting.ep_in, (char *)versaloon_buf, + versaloon_interface.usb_setting.buf_size, versaloon_usb_to); + if (ret > 0) + { + *inlen = (uint16_t)ret; + return ERROR_OK; + } + else + { + LOG_ERROR(ERRMSG_FAILURE_OPERATION_ERRSTRING, "receive usb data", + usb_strerror()); + return ERROR_FAIL; + } + } + else + { + return ERROR_OK; + } +} + +#define VERSALOON_RETRY_CNT 10 +RESULT versaloon_init(void) +{ + uint16_t ret = 0; + uint8_t retry; + uint32_t timeout_tmp; + + // malloc temporary buffer + versaloon_buf = + (uint8_t *)malloc(versaloon_interface.usb_setting.buf_size); + if (NULL == versaloon_buf) + { + LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY); + return ERRCODE_NOT_ENOUGH_MEMORY; + } + + // connect to versaloon + timeout_tmp = versaloon_usb_to; + // not output error message when connectting + // 100ms delay when connect + versaloon_usb_to = 100; + for (retry = 0; retry < VERSALOON_RETRY_CNT; retry++) + { + versaloon_buf[0] = VERSALOON_GET_INFO; + if ((ERROR_OK == versaloon_send_command(1, &ret)) && (ret >= 3)) + { + break; + } + } + versaloon_usb_to = timeout_tmp; + if (VERSALOON_RETRY_CNT == retry) + { + versaloon_fini(); + LOG_ERROR(ERRMSG_FAILURE_OPERATION, "communicate with versaloon"); + return ERRCODE_FAILURE_OPERATION; + } + + versaloon_buf[ret] = 0; + versaloon_buf_size = versaloon_buf[0] + (versaloon_buf[1] << 8); + versaloon_interface.usb_setting.buf_size = versaloon_buf_size; + LOG_INFO("%s", versaloon_buf + 2); + + // free temporary buffer + free(versaloon_buf); + versaloon_buf = NULL; + + versaloon_buf = + (uint8_t *)malloc(versaloon_interface.usb_setting.buf_size); + if (NULL == versaloon_buf) + { + versaloon_fini(); + LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY); + return ERRCODE_NOT_ENOUGH_MEMORY; + } + versaloon_cmd_buf = + (uint8_t *)malloc(versaloon_interface.usb_setting.buf_size - 3); + if (NULL == versaloon_cmd_buf) + { + versaloon_fini(); + LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY); + return ERRCODE_NOT_ENOUGH_MEMORY; + } + if (ERROR_OK != usbtoxxx_init()) + { + LOG_ERROR(ERRMSG_FAILURE_OPERATION, "initialize usbtoxxx"); + return ERROR_FAIL; + } + return versaloon_get_target_voltage(&ret); +} + +RESULT versaloon_fini(void) +{ + if (versaloon_usb_device_handle != NULL) + { + usbtoxxx_fini(); + versaloon_free_want_pos(); + + versaloon_usb_device_handle = NULL; + + if (versaloon_buf != NULL) + { + free(versaloon_buf); + versaloon_buf = NULL; + } + if (versaloon_cmd_buf != NULL) + { + free(versaloon_cmd_buf); + versaloon_cmd_buf = NULL; + } + } + + return ERROR_OK; +} + +RESULT versaloon_set_target_voltage(uint16_t voltage) +{ + usbtopwr_init(0); + usbtopwr_config(0); + usbtopwr_output(0, voltage); + usbtopwr_fini(0); + + return usbtoxxx_execute_command(); +} + +RESULT versaloon_get_target_voltage(uint16_t *voltage) +{ + uint16_t inlen; + +#if PARAM_CHECK + if (NULL == versaloon_buf) + { + LOG_BUG(ERRMSG_INVALID_BUFFER, TO_STR(versaloon_buf)); + return ERRCODE_INVALID_BUFFER; + } + if (NULL == voltage) + { + LOG_BUG(ERRMSG_INVALID_PARAMETER, __FUNCTION__); + return ERRCODE_INVALID_PARAMETER; + } +#endif + + versaloon_buf[0] = VERSALOON_GET_TVCC; + + if ((ERROR_OK != versaloon_send_command(1, &inlen)) || (inlen != 2)) + { + LOG_ERROR(ERRMSG_FAILURE_OPERATION, "communicate with versaloon"); + return ERRCODE_FAILURE_OPERATION; + } + else + { + *voltage = versaloon_buf[0] + (versaloon_buf[1] << 8); + return ERROR_OK; + } +} + +RESULT versaloon_delay_ms(uint16_t ms) +{ + return usbtodelay_delay(ms | 0x8000); +} + +RESULT versaloon_delay_us(uint16_t us) +{ + return usbtodelay_delay(us & 0x7FFF); +} + diff --git a/src/jtag/drivers/versaloon/versaloon.h b/src/jtag/drivers/versaloon/versaloon.h new file mode 100644 index 0000000000..18ccbea424 --- /dev/null +++ b/src/jtag/drivers/versaloon/versaloon.h @@ -0,0 +1,119 @@ +/*************************************************************************** + * Copyright (C) 2009 by Simon Qian * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * 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, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef __VERSALOON_H_INCLUDED__ +#define __VERSALOON_H_INCLUDED__ + +struct usart_status_t +{ + uint32_t tx_buff_avail; + uint32_t tx_buff_size; + uint32_t rx_buff_avail; + uint32_t rx_buff_size; +}; + +#include "usbtoxxx/usbtoxxx.h" + +// GPIO pins +#define GPIO_SRST (1 << 0) +#define GPIO_TRST (1 << 1) +#define GPIO_USR1 (1 << 2) +#define GPIO_USR2 (1 << 3) +#define GPIO_TCK (1 << 4) +#define GPIO_TDO (1 << 5) +#define GPIO_TDI (1 << 6) +#define GPIO_RTCK (1 << 7) +#define GPIO_TMS (1 << 8) +struct interface_gpio_t +{ + RESULT (*init)(uint8_t interface_index); + RESULT (*fini)(uint8_t interface_index); + RESULT (*config)(uint8_t interface_index, uint32_t pin_mask, uint32_t io, + uint32_t pull_en_mask, uint32_t input_pull_mask); + RESULT (*out)(uint8_t interface_index, uint32_t pin_mask, uint32_t value); + RESULT (*in)(uint8_t interface_index, uint32_t pin_mask, uint32_t *value); +}; + +struct interface_delay_t +{ + RESULT (*delayms)(uint16_t ms); + RESULT (*delayus)(uint16_t us); +}; + +struct interface_swd_t +{ + RESULT (*init)(uint8_t interface_index); + RESULT (*fini)(uint8_t interface_index); + RESULT (*config)(uint8_t interface_index, uint8_t trn, uint16_t retry, + uint16_t dly); + RESULT (*seqout)(uint8_t interface_index, uint8_t *data, uint16_t bitlen); + RESULT (*seqin)(uint8_t interface_index, uint8_t *data, uint16_t bitlen); + RESULT (*transact)(uint8_t interface_index, uint8_t request, + uint32_t *data, uint8_t *ack); +}; + +struct interface_jtag_raw_t +{ + RESULT (*init)(uint8_t interface_index); + RESULT (*fini)(uint8_t interface_index); + RESULT (*config)(uint8_t interface_index, uint32_t kHz); + RESULT (*execute)(uint8_t interface_index, uint8_t* tdi, uint8_t* tms, + uint8_t *tdo, uint32_t bitlen); +}; + +struct interface_target_voltage_t +{ + RESULT (*get)(uint16_t *voltage); + RESULT (*set)(uint16_t voltage); +}; + +struct versaloon_adaptors_t +{ + struct interface_target_voltage_t target_voltage; + struct interface_gpio_t gpio; + struct interface_delay_t delay; + struct interface_swd_t swd; + struct interface_jtag_raw_t jtag_raw; + RESULT (*peripheral_commit)(void); +}; + +struct versaloon_usb_setting_t +{ + uint16_t vid; + uint16_t pid; + uint8_t ep_out; + uint8_t ep_in; + uint8_t interface; + char *serialstring; + + uint16_t buf_size; +}; + +struct versaloon_interface_t +{ + RESULT (*init)(void); + RESULT (*fini)(void); + struct versaloon_adaptors_t adaptors; + struct versaloon_usb_setting_t usb_setting; +}; + +extern struct versaloon_interface_t versaloon_interface; +extern usb_dev_handle *versaloon_usb_device_handle; + +#endif /* __VERSALOON_H_INCLUDED__ */ + diff --git a/src/jtag/drivers/versaloon/versaloon_include.h b/src/jtag/drivers/versaloon/versaloon_include.h new file mode 100644 index 0000000000..eacb2e6495 --- /dev/null +++ b/src/jtag/drivers/versaloon/versaloon_include.h @@ -0,0 +1,100 @@ +/*************************************************************************** + * Copyright (C) 2009 by Simon Qian * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * 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, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +// This file is used to include different header and macros +// according to different platform +#include +#include +#include "usb_common.h" + +#define PARAM_CHECK 1 + +#define sleep_ms(ms) jtag_sleep((ms) * 1000) +#define dimof(arr) (sizeof(arr) / sizeof((arr)[0])) +#define TO_STR(name) #name + +#define RESULT int +#define LOG_BUG LOG_ERROR + +// Common error messages +#define ERRMSG_NOT_ENOUGH_MEMORY "Lack of memory." +#define ERRCODE_NOT_ENOUGH_MEMORY ERROR_FAIL + +#define ERRMSG_INVALID_VALUE "%d is invalid for %s." +#define ERRMSG_INVALID_INDEX "Index %d is invalid for %s." +#define ERRMSG_INVALID_USAGE "Invalid usage of %s" +#define ERRMSG_INVALID_TARGET "Invalid %s" +#define ERRMSG_INVALID_PARAMETER "Invalid parameter of %s." +#define ERRMSG_INVALID_INTERFACE_NUM "invalid inteface %d" +#define ERRMSG_INVALID_BUFFER "Buffer %s is not valid." +#define ERRCODE_INVALID_BUFFER ERROR_FAIL +#define ERRCODE_INVALID_PARAMETER ERROR_FAIL + +#define ERRMSG_NOT_SUPPORT_BY "%s is not supported by %s." + +#define ERRMSG_FAILURE_OPERATION "Fail to %s." +#define ERRMSG_FAILURE_OPERATION_ERRSTRING "Fail to %s, error string is %s." +#define ERRMSG_FAILURE_OPERATION_MESSAGE "Fail to %s, %s" +#define ERRCODE_FAILURE_OPERATION ERROR_FAIL + +#define GET_U16_MSBFIRST(p) ( ((*((uint8_t *)(p) + 0)) << 8) | \ + ((*((uint8_t *)(p) + 1)) << 0)) +#define GET_U32_MSBFIRST(p) ( ((*((uint8_t *)(p) + 0)) << 24) | \ + ((*((uint8_t *)(p) + 1)) << 16) | \ + ((*((uint8_t *)(p) + 2)) << 8) | \ + ((*((uint8_t *)(p) + 3)) << 0)) +#define GET_U16_LSBFIRST(p) ( ((*((uint8_t *)(p) + 0)) << 0) | \ + ((*((uint8_t *)(p) + 1)) << 8)) +#define GET_U32_LSBFIRST(p) ( ((*((uint8_t *)(p) + 0)) << 0) | \ + ((*((uint8_t *)(p) + 1)) << 8) | \ + ((*((uint8_t *)(p) + 2)) << 16) | \ + ((*((uint8_t *)(p) + 3)) << 24)) + +#define SET_U16_MSBFIRST(p, v) \ + do{\ + *((uint8_t *)(p) + 0) = (((uint16_t)(v)) >> 8) & 0xFF;\ + *((uint8_t *)(p) + 1) = (((uint16_t)(v)) >> 0) & 0xFF;\ + } while (0) +#define SET_U32_MSBFIRST(p, v) \ + do{\ + *((uint8_t *)(p) + 0) = (((uint32_t)(v)) >> 24) & 0xFF;\ + *((uint8_t *)(p) + 1) = (((uint32_t)(v)) >> 16) & 0xFF;\ + *((uint8_t *)(p) + 2) = (((uint32_t)(v)) >> 8) & 0xFF;\ + *((uint8_t *)(p) + 3) = (((uint32_t)(v)) >> 0) & 0xFF;\ + } while (0) +#define SET_U16_LSBFIRST(p, v) \ + do{\ + *((uint8_t *)(p) + 0) = (((uint16_t)(v)) >> 0) & 0xFF;\ + *((uint8_t *)(p) + 1) = (((uint16_t)(v)) >> 8) & 0xFF;\ + } while (0) +#define SET_U32_LSBFIRST(p, v) \ + do{\ + *((uint8_t *)(p) + 0) = (((uint32_t)(v)) >> 0) & 0xFF;\ + *((uint8_t *)(p) + 1) = (((uint32_t)(v)) >> 8) & 0xFF;\ + *((uint8_t *)(p) + 2) = (((uint32_t)(v)) >> 16) & 0xFF;\ + *((uint8_t *)(p) + 3) = (((uint32_t)(v)) >> 24) & 0xFF;\ + } while (0) + +#define GET_LE_U16(p) GET_U16_LSBFIRST(p) +#define GET_LE_U32(p) GET_U32_LSBFIRST(p) +#define GET_BE_U16(p) GET_U16_MSBFIRST(p) +#define GET_BE_U32(p) GET_U32_MSBFIRST(p) +#define SET_LE_U16(p, v) SET_U16_LSBFIRST(p, v) +#define SET_LE_U32(p, v) SET_U32_LSBFIRST(p, v) +#define SET_BE_U16(p, v) SET_U16_MSBFIRST(p, v) +#define SET_BE_U32(p, v) SET_U32_MSBFIRST(p, v) diff --git a/src/jtag/drivers/versaloon/versaloon_internal.h b/src/jtag/drivers/versaloon/versaloon_internal.h new file mode 100644 index 0000000000..c7c73b60ce --- /dev/null +++ b/src/jtag/drivers/versaloon/versaloon_internal.h @@ -0,0 +1,118 @@ +/*************************************************************************** + * Copyright (C) 2009 - 2010 by Simon Qian * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * 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, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef __VERSALOON_INTERNAL_H_INCLUDED__ +#define __VERSALOON_INTERNAL_H_INCLUDED__ + +#define VERSALOON_PRODUCTSTRING_INDEX 2 +#define VERSALOON_SERIALSTRING_INDEX 3 + +#define VERSALOON_PRODUCTSTRING "Versaloon" + +#define VERSALOON_VID 0x0483 +#define VERSALOON_PID 0xA038 +#define VERSALOON_INP 0x82 +#define VERSALOON_OUTP 0x03 +#define VERSALOON_IFACE 0x00 + +#define VERSALOON_FULL 1 +#define VERSALOON_MINI 2 +#define VERSALOON_NANO 3 + +#define VERSALOON_TIMEOUT 5000 +#define VERSALOON_TIMEOUT_LONG 60000 + +// USB Commands +// Common Commands +#define VERSALOON_COMMON_CMD_START 0x00 +#define VERSALOON_COMMON_CMD_END 0x0F + +#define VERSALOON_GET_INFO 0x00 +#define VERSALOON_GET_TVCC 0x01 +#define VERSALOON_GET_HARDWARE 0x02 +#define VERSALOON_GET_OFFLINE_SIZE 0x08 +#define VERSALOON_ERASE_OFFLINE_DATA 0x09 +#define VERSALOON_WRITE_OFFLINE_DATA 0x0A +#define VERSALOON_GET_OFFLINE_CHECKSUM 0x0B +#define VERSALOON_FW_UPDATE 0x0F +#define VERSALOON_FW_UPDATE_KEY 0xAA + +// MCU Command +#define VERSALOON_MCU_CMD_START 0x10 +#define VERSALOON_MCU_CMD_END 0x1F + +// USB_TO_XXX Command +#define VERSALOON_USB_TO_XXX_CMD_START 0x20 +#define VERSALOON_USB_TO_XXX_CMD_END 0x7F + +// VSLLink Command +#define VERSALOON_VSLLINK_CMD_START 0x80 +#define VERSALOON_VSLLINK_CMD_END 0xFF + + + +// Mass-product +#define MP_OK 0x00 +#define MP_FAIL 0x01 + +#define MP_ISSP 0x11 + + + +// pending struct +#define VERSALOON_MAX_PENDING_NUMBER 4096 +typedef RESULT (*versaloon_callback_t)(void *, uint8_t *, uint8_t *); +struct versaloon_want_pos_t +{ + uint16_t offset; + uint16_t size; + uint8_t *buff; + struct versaloon_want_pos_t *next; +}; +struct versaloon_pending_t +{ + uint8_t type; + uint8_t cmd; + uint16_t want_data_pos; + uint16_t want_data_size; + uint16_t actual_data_size; + uint8_t *data_buffer; + uint8_t collect; + uint32_t id; + struct versaloon_want_pos_t *pos; + void *extra_data; + versaloon_callback_t callback; +}; +extern struct versaloon_pending_t \ + versaloon_pending[VERSALOON_MAX_PENDING_NUMBER]; +extern uint16_t versaloon_pending_idx; +void versaloon_set_pending_id(uint32_t id); +void versaloon_set_callback(versaloon_callback_t callback); +void versaloon_set_extra_data(void * p); +RESULT versaloon_add_want_pos(uint16_t offset, uint16_t size, uint8_t *buff); +RESULT versaloon_add_pending(uint8_t type, uint8_t cmd, uint16_t actual_szie, + uint16_t want_pos, uint16_t want_size, uint8_t *buffer, uint8_t collect); +void versaloon_free_want_pos(void); + +RESULT versaloon_send_command(uint16_t out_len, uint16_t *inlen); +extern uint8_t *versaloon_buf; +extern uint8_t *versaloon_cmd_buf; +extern uint16_t versaloon_buf_size; + +#endif /* __VERSALOON_INTERNAL_H_INCLUDED__ */ + diff --git a/src/jtag/drivers/vsllink.c b/src/jtag/drivers/vsllink.c index 7533a090e3..2274be40d8 100644 --- a/src/jtag/drivers/vsllink.c +++ b/src/jtag/drivers/vsllink.c @@ -19,7 +19,7 @@ /* Versaloon is a programming tool for multiple MCUs. * It's distributed under GPLv3. - * You can find it at http://www.SimonQian.com/en/Versaloon. + * You can find it at http://www.Versaloon.com/. */ #ifdef HAVE_CONFIG_H @@ -30,59 +30,17 @@ #include #include "usb_common.h" -//#define _VSLLINK_IN_DEBUG_MODE_ - -static uint16_t vsllink_usb_vid; -static uint16_t vsllink_usb_pid; -static uint8_t vsllink_usb_bulkout; -static uint8_t vsllink_usb_bulkin; -static uint8_t vsllink_usb_interface; -static int VSLLINK_USB_TIMEOUT = 1000; +#include "versaloon/versaloon_include.h" +#include "versaloon/versaloon.h" static int vsllink_tms_offset; -/* Global USB buffers */ -static uint8_t *vsllink_usb_in_buffer; -static uint8_t *vsllink_usb_out_buffer; -static int vsllink_buffer_size = 128; - -/* Constants for Versaloon command */ -#define VERSALOON_GET_INFO 0x00 -#define VERSALOON_GET_TVCC 0x01 - -/* Constants for VSLLink command */ -#define VSLLINK_CMD_CONN 0x80 -#define VSLLINK_CMD_DISCONN 0x81 -#define VSLLINK_CMD_SET_SPEED 0x82 -#define VSLLINK_CMD_SET_PORT 0x90 -#define VSLLINK_CMD_GET_PORT 0x91 -#define VSLLINK_CMD_SET_PORTDIR 0x92 -#define VSLLINK_CMD_HW_JTAGSEQCMD 0xA0 -#define VSLLINK_CMD_HW_JTAGHLCMD 0xA1 -#define VSLLINK_CMD_HW_SWDCMD 0xA2 -#define VSLLINK_CMD_HW_JTAGRAWCMD 0xA3 - -#define VSLLINK_CMDJTAGSEQ_TMSBYTE 0x00 -#define VSLLINK_CMDJTAGSEQ_TMSCLOCK 0x40 -#define VSLLINK_CMDJTAGSEQ_SCAN 0x80 - -#define VSLLINK_CMDJTAGSEQ_CMDMSK 0xC0 -#define VSLLINK_CMDJTAGSEQ_LENMSK 0x3F - -#define JTAG_PINMSK_SRST (1 << 0) -#define JTAG_PINMSK_TRST (1 << 1) -#define JTAG_PINMSK_USR1 (1 << 2) -#define JTAG_PINMSK_USR2 (1 << 3) -#define JTAG_PINMSK_TCK (1 << 4) -#define JTAG_PINMSK_TMS (1 << 5) -#define JTAG_PINMSK_TDI (1 << 6) -#define JTAG_PINMSK_TDO (1 << 7) - struct pending_scan_result { int src_offset; int dest_offset; int length; /* Number of bits to read */ struct scan_command *command; /* Corresponding scan command */ + uint8_t *ack; uint8_t *buffer; bool last; /* indicate the last scan pending */ }; @@ -97,12 +55,12 @@ static struct pending_scan_result static void vsllink_end_state(tap_state_t state); static void vsllink_state_move(void); static void vsllink_path_move(int num_states, tap_state_t *path); +static void vsllink_tms(int num_bits, const uint8_t *bits); static void vsllink_runtest(int num_cycles); static void vsllink_stableclocks(int num_cycles, int tms); static void vsllink_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, struct scan_command *command); static void vsllink_reset(int trst, int srst); -static void vsllink_simple_command(uint8_t command); /* VSLLink tap buffer functions */ static void vsllink_tap_append_step(int tms, int tdi); @@ -119,10 +77,6 @@ struct vsllink { static struct vsllink *vsllink_usb_open(void); static void vsllink_usb_close(struct vsllink *vsllink); -static int vsllink_usb_message(struct vsllink *vsllink, int out_length, - int in_length); -static int vsllink_usb_write(struct vsllink *vsllink, int out_length); -static int vsllink_usb_read(struct vsllink *vsllink); #if defined _DEBUG_USB_COMMS_ || defined _DEBUG_JTAG_IO_ static void vsllink_debug_buffer(uint8_t *buffer, int length); @@ -134,12 +88,7 @@ static uint8_t *tms_buffer; static uint8_t *tdi_buffer; static uint8_t *tdo_buffer; -static struct vsllink *vsllink_handle; - -static void reset_command_pointer(void) -{ - tap_length = 0; -} +struct vsllink *vsllink_handle; static int vsllink_execute_queue(void) { @@ -152,7 +101,6 @@ static int vsllink_execute_queue(void) " vsllink " "-------------------------------------"); - reset_command_pointer(); while (cmd != NULL) { switch (cmd->type) { case JTAG_RUNTEST: @@ -188,6 +136,8 @@ static int vsllink_execute_queue(void) break; case JTAG_SCAN: + DEBUG_JTAG_IO("JTAG Scan..."); + vsllink_end_state(cmd->cmd.scan->end_state); scan_size = jtag_build_buffer( @@ -244,6 +194,7 @@ static int vsllink_execute_queue(void) case JTAG_STABLECLOCKS: DEBUG_JTAG_IO("add %d clocks", cmd->cmd.stableclocks->num_cycles); + switch (tap_get_state()) { case TAP_RESET: /* tms must be '1' to stay @@ -271,6 +222,13 @@ static int vsllink_execute_queue(void) ->num_cycles, scan_size); break; + case JTAG_TMS: + DEBUG_JTAG_IO("add %d jtag tms", + cmd->cmd.tms->num_bits); + + vsllink_tms(cmd->cmd.tms->num_bits, cmd->cmd.tms->bits); + break; + default: LOG_ERROR("BUG: unknown JTAG command type " "encountered: %d", cmd->type); @@ -284,22 +242,8 @@ static int vsllink_execute_queue(void) static int vsllink_speed(int speed) { - int result; - - vsllink_usb_out_buffer[0] = VSLLINK_CMD_SET_SPEED; - vsllink_usb_out_buffer[1] = (speed >> 0) & 0xff; - vsllink_usb_out_buffer[2] = (speed >> 8) & 0xFF; - - result = vsllink_usb_write(vsllink_handle, 3); - - if (result == 3) - return ERROR_OK; - else { - LOG_ERROR("VSLLink setting speed failed (%d)", result); - return ERROR_JTAG_DEVICE_ERROR; - } - - return ERROR_OK; + versaloon_interface.adaptors.jtag_raw.config(0, (uint16_t)speed); + return versaloon_interface.adaptors.peripheral_commit(); } static int vsllink_khz(int khz, int *jtag_speed) @@ -316,20 +260,42 @@ static int vsllink_speed_div(int jtag_speed, int *khz) return ERROR_OK; } -static int vsllink_init(void) +static void vsllink_free_buffer(void) { - int check_cnt, to_tmp; - int result; - char version_str[100]; - - vsllink_usb_in_buffer = malloc(vsllink_buffer_size); - vsllink_usb_out_buffer = malloc(vsllink_buffer_size); - if ((vsllink_usb_in_buffer == NULL) - || (vsllink_usb_out_buffer == NULL)) { - LOG_ERROR("Not enough memory"); - exit(-1); + if (tdi_buffer != NULL) + { + free(tdi_buffer); + tdi_buffer = NULL; + } + if (tdo_buffer != NULL) + { + free(tdo_buffer); + tdo_buffer = NULL; + } + if (tms_buffer != NULL) + { + free(tms_buffer); + tms_buffer = NULL; } +} + +static int vsllink_quit(void) +{ + versaloon_interface.adaptors.gpio.config(0, GPIO_SRST | GPIO_TRST, + 0, 0, GPIO_SRST | GPIO_TRST); + versaloon_interface.adaptors.gpio.fini(0); + versaloon_interface.adaptors.jtag_raw.fini(0); + versaloon_interface.adaptors.peripheral_commit(); + versaloon_interface.fini(); + + vsllink_free_buffer(); + vsllink_usb_close(vsllink_handle); + return ERROR_OK; +} + +static int vsllink_init(void) +{ vsllink_handle = vsllink_usb_open(); if (vsllink_handle == 0) { LOG_ERROR("Can't find USB JTAG Interface!"\ @@ -337,131 +303,44 @@ static int vsllink_init(void) return ERROR_JTAG_INIT_FAILED; } LOG_DEBUG("vsllink found on %04X:%04X", - vsllink_usb_vid, vsllink_usb_pid); - - to_tmp = VSLLINK_USB_TIMEOUT; - VSLLINK_USB_TIMEOUT = 100; - check_cnt = 0; - while (check_cnt < 5) { - vsllink_simple_command(VERSALOON_GET_INFO); - result = vsllink_usb_read(vsllink_handle); - - if (result > 2) { - vsllink_usb_in_buffer[result] = 0; - vsllink_buffer_size = vsllink_usb_in_buffer[0] - + (vsllink_usb_in_buffer[1] << 8); - strncpy(version_str, (char *)vsllink_usb_in_buffer + 2, - sizeof(version_str)); - LOG_INFO("%s", version_str); - - /* free the pre-allocated memory */ - free(vsllink_usb_in_buffer); - free(vsllink_usb_out_buffer); - vsllink_usb_in_buffer = NULL; - vsllink_usb_out_buffer = NULL; - - /* alloc new memory */ - vsllink_usb_in_buffer = malloc(vsllink_buffer_size); - vsllink_usb_out_buffer = malloc(vsllink_buffer_size); - if ((vsllink_usb_in_buffer == NULL) || - (vsllink_usb_out_buffer == NULL)) { - LOG_ERROR("Not enough memory"); - exit(-1); - } else - LOG_INFO("buffer size for USB is %d bytes", - vsllink_buffer_size); - - /* alloc tms/tdi/tdo buffer */ - tap_buffer_size = (vsllink_buffer_size - 3) / 2; - tms_buffer = (uint8_t *)malloc(tap_buffer_size); - tdi_buffer = (uint8_t *)malloc(tap_buffer_size); - tdo_buffer = (uint8_t *)malloc(tap_buffer_size); - if ((tms_buffer == NULL) || (tdi_buffer == NULL) || - (tdo_buffer == NULL)) { - LOG_ERROR("Not enough memory"); - exit(-1); - } - break; - } - vsllink_simple_command(VSLLINK_CMD_DISCONN); - check_cnt++; + versaloon_interface.usb_setting.vid, + versaloon_interface.usb_setting.pid); + versaloon_usb_device_handle = vsllink_handle->usb_handle; + + if (ERROR_OK != versaloon_interface.init()) + { + return ERROR_FAIL; } - if (check_cnt == 3) { - /* Fail to access Versaloon */ - LOG_ERROR("VSLLink initial failed"); - exit(-1); + if (versaloon_interface.usb_setting.buf_size < 32) + { + versaloon_interface.fini(); + return ERROR_FAIL; } - VSLLINK_USB_TIMEOUT = to_tmp; - - /* Some older firmware versions sometimes fail if the - * voltage isn't read first. - */ - vsllink_simple_command(VERSALOON_GET_TVCC); - result = vsllink_usb_read(vsllink_handle); - if (result != 2) - LOG_WARNING("Fail to get target voltage"); - else - LOG_INFO("Target runs at %d mV", vsllink_usb_in_buffer[0] + - (vsllink_usb_in_buffer[1] << 8)); - - /* connect to vsllink */ - vsllink_usb_out_buffer[0] = VSLLINK_CMD_CONN; - vsllink_usb_out_buffer[1] = 1; - vsllink_usb_message(vsllink_handle, 2, 0); - if (vsllink_usb_read(vsllink_handle) > 2) { - strncpy(version_str, (char *)vsllink_usb_in_buffer + 2, - sizeof(version_str)); - LOG_INFO("%s", version_str); + + // malloc buffer size for tap + tap_buffer_size = versaloon_interface.usb_setting.buf_size - 32; + vsllink_free_buffer(); + tdi_buffer = (uint8_t *)malloc(tap_buffer_size); + tdo_buffer = (uint8_t *)malloc(tap_buffer_size); + tms_buffer = (uint8_t *)malloc(tap_buffer_size); + if ((NULL == tdi_buffer) || (NULL == tdo_buffer) || (NULL == tms_buffer)) + { + vsllink_quit(); + return ERROR_FAIL; } - /* Set SRST and TRST to output, Set USR1 and USR2 to input */ - vsllink_usb_out_buffer[0] = VSLLINK_CMD_SET_PORTDIR; - vsllink_usb_out_buffer[1] = JTAG_PINMSK_SRST | JTAG_PINMSK_TRST - | JTAG_PINMSK_USR1 | JTAG_PINMSK_USR2; - vsllink_usb_out_buffer[2] = JTAG_PINMSK_SRST | JTAG_PINMSK_TRST; - if (vsllink_usb_write(vsllink_handle, 3) != 3) { - LOG_ERROR("VSLLink USB send data error"); - exit(-1); + versaloon_interface.adaptors.jtag_raw.init(0); + versaloon_interface.adaptors.jtag_raw.config(0, jtag_get_speed_khz()); + versaloon_interface.adaptors.gpio.init(0); + versaloon_interface.adaptors.gpio.config(0, GPIO_SRST | GPIO_TRST, + GPIO_TRST, GPIO_SRST, GPIO_SRST); + if (ERROR_OK != versaloon_interface.adaptors.peripheral_commit()) + { + return ERROR_FAIL; } vsllink_reset(0, 0); - - LOG_INFO("VSLLink Interface ready"); - vsllink_tap_init(); - - return ERROR_OK; -} - -static int vsllink_quit(void) -{ - if ((vsllink_usb_in_buffer != NULL) - && (vsllink_usb_out_buffer != NULL)) { - // Set all pins to input - vsllink_usb_out_buffer[0] = VSLLINK_CMD_SET_PORTDIR; - vsllink_usb_out_buffer[1] = JTAG_PINMSK_SRST | JTAG_PINMSK_TRST - | JTAG_PINMSK_USR1 | JTAG_PINMSK_USR2; - vsllink_usb_out_buffer[2] = 0; - if (vsllink_usb_write(vsllink_handle, 3) != 3) { - LOG_ERROR("VSLLink USB send data error"); - exit(-1); - } - - // disconnect - vsllink_simple_command(VSLLINK_CMD_DISCONN); - vsllink_usb_close(vsllink_handle); - vsllink_handle = NULL; - } - - if (vsllink_usb_in_buffer != NULL) { - free(vsllink_usb_in_buffer); - vsllink_usb_in_buffer = NULL; - } - if (vsllink_usb_out_buffer != NULL) { - free(vsllink_usb_out_buffer); - vsllink_usb_out_buffer = NULL; - } - return ERROR_OK; } @@ -513,6 +392,13 @@ static void vsllink_path_move(int num_states, tap_state_t *path) tap_set_end_state(tap_get_state()); } +static void vsllink_tms(int num_bits, const uint8_t *bits) +{ + for (int i = 0; i < num_bits; i++) { + vsllink_tap_append_step((bits[i / 8] >> (i % 8)) & 1, 0); + } +} + static void vsllink_stableclocks(int num_cycles, int tms) { while (num_cycles > 0) { @@ -569,48 +455,18 @@ static void vsllink_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, static void vsllink_reset(int trst, int srst) { - int result; - LOG_DEBUG("trst: %i, srst: %i", trst, srst); - /* Signals are active low */ - vsllink_usb_out_buffer[0] = VSLLINK_CMD_SET_PORT; - vsllink_usb_out_buffer[1] = JTAG_PINMSK_SRST | JTAG_PINMSK_TRST; - vsllink_usb_out_buffer[2] = 0; - if (srst == 0) - vsllink_usb_out_buffer[2] |= JTAG_PINMSK_SRST; - if (trst == 0) - vsllink_usb_out_buffer[2] |= JTAG_PINMSK_TRST; - - result = vsllink_usb_write(vsllink_handle, 3); - if (result != 3) - LOG_ERROR("VSLLink command VSLLINK_CMD_SET_PORT failed (%d)", - result); -} - -static void vsllink_simple_command(uint8_t command) -{ - int result; - - DEBUG_JTAG_IO("0x%02x", command); - - vsllink_usb_out_buffer[0] = command; - result = vsllink_usb_write(vsllink_handle, 1); - - if (result != 1) - LOG_ERROR("VSLLink command 0x%02x failed (%d)", - command, result); -} - -COMMAND_HANDLER(vsllink_handle_mode_command) -{ - if (CMD_ARGC != 1) { - LOG_ERROR("parameter error, " - "should be one parameter for mode"); - return ERROR_FAIL; - } + if (!srst) + versaloon_interface.adaptors.gpio.config(0, GPIO_SRST, 0, GPIO_SRST, GPIO_SRST); + else + versaloon_interface.adaptors.gpio.config(0, GPIO_SRST, GPIO_SRST, 0, 0); - return ERROR_OK; + if (!trst) + versaloon_interface.adaptors.gpio.out(0, GPIO_TRST, GPIO_TRST); + else + versaloon_interface.adaptors.gpio.out(0, GPIO_TRST, 0); + versaloon_interface.adaptors.peripheral_commit(); } COMMAND_HANDLER(vsllink_handle_usb_vid_command) @@ -621,7 +477,8 @@ COMMAND_HANDLER(vsllink_handle_usb_vid_command) return ERROR_OK; } - COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], vsllink_usb_vid); + COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], + versaloon_interface.usb_setting.vid); return ERROR_OK; } @@ -632,7 +489,8 @@ COMMAND_HANDLER(vsllink_handle_usb_pid_command) "should be one parameter for PID"); return ERROR_OK; } - COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], vsllink_usb_pid); + COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], + versaloon_interface.usb_setting.pid); return ERROR_OK; } @@ -644,9 +502,10 @@ COMMAND_HANDLER(vsllink_handle_usb_bulkin_command) return ERROR_OK; } - COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0], vsllink_usb_bulkin); + COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0], + versaloon_interface.usb_setting.ep_in); - vsllink_usb_bulkin |= 0x80; + versaloon_interface.usb_setting.ep_in |= 0x80; return ERROR_OK; } @@ -659,9 +518,10 @@ COMMAND_HANDLER(vsllink_handle_usb_bulkout_command) return ERROR_OK; } - COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0], vsllink_usb_bulkout); + COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0], + versaloon_interface.usb_setting.ep_out); - vsllink_usb_bulkout &= ~0x80; + versaloon_interface.usb_setting.ep_out &= ~0x80; return ERROR_OK; } @@ -674,7 +534,8 @@ COMMAND_HANDLER(vsllink_handle_usb_interface_command) return ERROR_OK; } - COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0], vsllink_usb_interface); + COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0], + versaloon_interface.usb_setting.interface); return ERROR_OK; } @@ -760,94 +621,20 @@ static void vsllink_tap_append_scan(int length, uint8_t *buffer, } } -static int vsllink_tap_execute(void) +static int vsllink_jtag_execute(void) { - int byte_length; int i; int result; if (tap_length <= 0) return ERROR_OK; - /* Pad data so that tap_length is divisible by 8 */ - if ((tap_length % 8) != 0) { - if (vsllink_tms_offset > 0) { - /* append tms:0 at vsllink_tms_offset, - * which is in Pause - */ - int start_pos = DIV_ROUND_UP(tap_length, 8) - 1; - int end_pos = DIV_ROUND_UP(vsllink_tms_offset, 8) - 1; - int shift_cnt = (start_pos + 1) * 8 - tap_length; - uint8_t last_mask = ~( - (1 << (vsllink_tms_offset % 8)) - 1); - - while (1) { - if (start_pos == end_pos) { - tms_buffer[start_pos] = - (tms_buffer[start_pos] - & ~last_mask) - | ((tms_buffer[start_pos] - & last_mask) - << shift_cnt); - tdi_buffer[start_pos] = - (tdi_buffer[start_pos] - & ~last_mask) - | - ((tdi_buffer[start_pos] - & last_mask) - << shift_cnt); - break; - } else if (start_pos == (end_pos + 1)) { - tms_buffer[start_pos] = - (tms_buffer[start_pos] - << shift_cnt) | - ((tms_buffer[start_pos - 1] - & last_mask) - >> (8 - shift_cnt)); - tdi_buffer[start_pos] = - (tdi_buffer[start_pos] - << shift_cnt) | - ((tdi_buffer[start_pos - 1] - & last_mask) - >> (8 - shift_cnt)); - } else { - tms_buffer[start_pos] = - (tms_buffer[start_pos] - << shift_cnt) | - (tms_buffer[start_pos - 1] - >> (8 - shift_cnt)); - tdi_buffer[start_pos] = - (tdi_buffer[start_pos] - << shift_cnt) | - (tdi_buffer[start_pos - 1] - >> (8 - shift_cnt)); - } - start_pos--; - } - tap_length = DIV_ROUND_UP(tap_length, 8) * 8; - } else { - /* append data at last */ - while ((tap_length % 8) != 0) { - vsllink_tap_append_step( - (tap_get_state() == TAP_RESET) - ? 1 : 0, 0); - } - } - } - byte_length = tap_length / 8; - - vsllink_usb_out_buffer[0] = VSLLINK_CMD_HW_JTAGRAWCMD; - vsllink_usb_out_buffer[1] = ((byte_length * 2 + 3) >> 0) & 0xff; - vsllink_usb_out_buffer[2] = ((byte_length * 2 + 3) >> 8) & 0xff; + versaloon_interface.adaptors.jtag_raw.execute(0, tdi_buffer, tms_buffer, + tdo_buffer, tap_length); - memcpy(&vsllink_usb_out_buffer[3], tdi_buffer, byte_length); - memcpy(&vsllink_usb_out_buffer[3 + byte_length], tms_buffer, - byte_length); + result = versaloon_interface.adaptors.peripheral_commit(); - result = vsllink_usb_message(vsllink_handle, 3 + 2 * byte_length, - byte_length); - - if (result == byte_length) { + if (result == ERROR_OK) { for (i = 0; i < pending_scan_results_length; i++) { struct pending_scan_result *pending_scan_result = &pending_scan_results_buffer[i]; @@ -860,12 +647,12 @@ static int vsllink_tap_execute(void) struct scan_command *command; command = pending_scan_result->command; - buf_set_buf(vsllink_usb_in_buffer, src_first, buffer, - dest_first, length); + buf_set_buf(tdo_buffer, src_first, buffer, dest_first, length); - DEBUG_JTAG_IO("JTAG scan read(%d bits, from %d bits):", - length, dest_first); #ifdef _DEBUG_JTAG_IO_ + DEBUG_JTAG_IO( + "JTAG scan read(%d bits, from src %d bits to dest %d bits):", + length, src_first, dest_first); vsllink_debug_buffer(buffer + dest_first / 8, DIV_ROUND_UP(length, 7)); #endif @@ -882,8 +669,7 @@ static int vsllink_tap_execute(void) } } } else { - LOG_ERROR("vsllink_tap_execute, wrong result %d, expected %d", - result, byte_length); + LOG_ERROR("vsllink_jtag_execute failure"); return ERROR_JTAG_QUEUE_FAILED; } @@ -892,42 +678,131 @@ static int vsllink_tap_execute(void) return ERROR_OK; } +static int vsllink_tap_execute(void) +{ + return vsllink_jtag_execute(); +} + /*****************************************************************************/ /* VSLLink USB low-level functions */ +static uint8_t usb_check_string(usb_dev_handle *usb, uint8_t stringidx, + char * string, char * buff, uint16_t buf_size) +{ + int len; + uint8_t alloced = 0; + uint8_t ret = 1; + + if (NULL == buff) + { + buf_size = 256; + buff = (char*)malloc(buf_size); + if (NULL == buff) + { + ret = 0; + goto free_and_return; + } + alloced = 1; + } + + strcpy(buff, ""); + len = usb_get_string_simple(usb, stringidx, (char *)buff, buf_size); + if ((len < 0) || (len != ((int)strlen((const char *)buff)))) + { + ret = 0; + goto free_and_return; + } + + buff[len] = '\0'; + if ((string != NULL) && strcmp((const char *)buff, string)) + { + ret = 0; + goto free_and_return; + } + +free_and_return: + if (alloced && (buff != NULL)) + { + free(buff); + buff = NULL; + } + return ret; +} + +static usb_dev_handle* find_usb_device(uint16_t VID, uint16_t PID, + uint8_t interface, int8_t serialindex, char *serialstring, + int8_t productindex, char *productstring) +{ + usb_dev_handle *dev_handle = NULL; + struct usb_bus *busses; + struct usb_bus *bus; + struct usb_device *dev; + + usb_init(); + usb_find_busses(); + usb_find_devices(); + busses = usb_get_busses(); + + for (bus = busses; bus; bus = bus->next) + { + for (dev = bus->devices; dev; dev = dev->next) + { + if ((dev->descriptor.idVendor == VID) + && (dev->descriptor.idProduct == PID)) + { + dev_handle = usb_open(dev); + if (NULL == dev_handle) + { + LOG_ERROR("failed to open %04X:%04X, %s", VID, PID, + usb_strerror()); + continue; + } + + // check description string + if (((productstring != NULL) && (productindex >= 0) + && !usb_check_string(dev_handle, productindex, + productstring, NULL, 0)) + || ((serialstring != NULL) && (serialindex >= 0) + && !usb_check_string(dev_handle, serialindex, + serialstring, NULL, 0))) + { + usb_close(dev_handle); + dev_handle = NULL; + continue; + } + + if (usb_claim_interface(dev_handle, interface) != 0) + { + LOG_ERROR(ERRMSG_FAILURE_OPERATION_MESSAGE, + "claim interface", usb_strerror()); + usb_close(dev_handle); + dev_handle = NULL; + continue; + } + + if (dev_handle != NULL) + { + return dev_handle; + } + } + } + } + + return dev_handle; +} + static struct vsllink *vsllink_usb_open(void) { usb_init(); - const uint16_t vids[] = { vsllink_usb_vid, 0 }; - const uint16_t pids[] = { vsllink_usb_pid, 0 }; struct usb_dev_handle *dev; - if (jtag_usb_open(vids, pids, &dev) != ERROR_OK) - return NULL; - /* usb_set_configuration required under win32 */ - struct usb_device *udev = usb_device(dev); - int ret = usb_set_configuration(dev, - udev->config[0].bConfigurationValue); - if (ret != 0) { - LOG_ERROR("fail to set configuration to %d (error %d)." - "Not enough permissions for the device?", - udev->config[0].bConfigurationValue, ret); - return NULL; - } - ret = usb_claim_interface(dev, vsllink_usb_interface); - if (ret != 0) { - LOG_ERROR("fail to claim interface %d, %d returned", - vsllink_usb_interface, ret); + dev = find_usb_device(versaloon_interface.usb_setting.vid, + versaloon_interface.usb_setting.pid, + versaloon_interface.usb_setting.interface, + 0, NULL, 2, "Versaloon"); + if (NULL == dev) return NULL; - } -#if 0 - /* - * This makes problems under Mac OS X. And is not needed - * under Windows. Hopefully this will not break a linux build - */ - usb_set_altinterface(dev, 0); -#endif struct vsllink *result = malloc(sizeof(struct vsllink)); result->usb_handle = dev; @@ -939,10 +814,10 @@ static void vsllink_usb_close(struct vsllink *vsllink) int ret; ret = usb_release_interface(vsllink->usb_handle, - vsllink_usb_interface); + versaloon_interface.usb_setting.interface); if (ret != 0) { LOG_ERROR("fail to release interface %d, %d returned", - vsllink_usb_interface, ret); + versaloon_interface.usb_setting.interface, ret); exit(-1); } @@ -955,79 +830,6 @@ static void vsllink_usb_close(struct vsllink *vsllink) free(vsllink); } -/* Send a message and receive the reply. */ -static int vsllink_usb_message(struct vsllink *vsllink, int out_length, - int in_length) -{ - int result; - - result = vsllink_usb_write(vsllink, out_length); - if (result == out_length) { - if (in_length > 0) { - result = vsllink_usb_read(vsllink); - if (result == in_length) - return result; - else { - LOG_ERROR("usb_bulk_read failed " - "(requested=%d, result=%d)", - in_length, result); - return -1; - } - } - return 0; - } else { - LOG_ERROR("usb_bulk_write failed (requested=%d, result=%d)", - out_length, result); - return -1; - } -} - -/* Write data from out_buffer to USB. */ -static int vsllink_usb_write(struct vsllink *vsllink, int out_length) -{ - int result; - - if (out_length > vsllink_buffer_size) { - LOG_ERROR("vsllink_write illegal out_length=%d (max=%d)", - out_length, vsllink_buffer_size); - return -1; - } - - result = usb_bulk_write(vsllink->usb_handle, vsllink_usb_bulkout, - (char *)vsllink_usb_out_buffer, out_length, - VSLLINK_USB_TIMEOUT); - - DEBUG_JTAG_IO("vsllink_usb_write, out_length = %d, result = %d", - out_length, result); - -#ifdef _DEBUG_USB_COMMS_ - LOG_DEBUG("USB out:"); - vsllink_debug_buffer(vsllink_usb_out_buffer, out_length); -#endif - -#ifdef _VSLLINK_IN_DEBUG_MODE_ - usleep(100000); -#endif - - return result; -} - -/* Read data from USB into in_buffer. */ -static int vsllink_usb_read(struct vsllink *vsllink) -{ - int result = usb_bulk_read(vsllink->usb_handle, vsllink_usb_bulkin, - (char *)vsllink_usb_in_buffer, vsllink_buffer_size, - VSLLINK_USB_TIMEOUT); - - DEBUG_JTAG_IO("vsllink_usb_read, result = %d", result); - -#ifdef _DEBUG_USB_COMMS_ - LOG_DEBUG("USB in:"); - vsllink_debug_buffer(vsllink_usb_in_buffer, result); -#endif - return result; -} - #define BYTES_PER_LINE 16 #if defined _DEBUG_USB_COMMS_ || defined _DEBUG_JTAG_IO_ @@ -1075,17 +877,16 @@ static const struct command_registration vsllink_command_handlers[] = { .handler = &vsllink_handle_usb_interface_command, .mode = COMMAND_CONFIG, }, - { - .name = "vsllink_mode", - .handler = &vsllink_handle_mode_command, - .mode = COMMAND_CONFIG, - }, COMMAND_REGISTRATION_DONE }; +static const char *vsllink_transports[] = {"jtag", "swd", NULL}; + struct jtag_interface vsllink_interface = { .name = "vsllink", + .supported = DEBUG_CAP_TMS_SEQ, .commands = vsllink_command_handlers, + .transports = vsllink_transports, .init = vsllink_init, .quit = vsllink_quit, diff --git a/tcl/interface/vsllink.cfg b/tcl/interface/vsllink.cfg index 07a5a0680e..fad7934904 100644 --- a/tcl/interface/vsllink.cfg +++ b/tcl/interface/vsllink.cfg @@ -1,25 +1,8 @@ # # Versaloon Link -- VSLLink # -# http://www.simonqian.com/en/Versaloon +# http://www.versaloon.com/ # interface vsllink -#vsllink_usb_vid 0x03EB -#vsllink_usb_pid 0x2103 -#vsllink_usb_bulkin 0x02 -#vsllink_usb_bulkout 0x02 -#vsllink_usb_interface 0 - -vsllink_usb_vid 0x0483 -vsllink_usb_pid 0x5740 -vsllink_usb_bulkin 0x02 -vsllink_usb_bulkout 0x03 -vsllink_usb_interface 1 - -# vsllink mode, dma or normal -# for low adapter_khz, use normal -# for high adapter_khz, use dma -#vsllink_mode dma -vsllink_mode normal