Index: openocd-0.4.0/tcl/interface/usbprog.cfg =================================================================== --- openocd-0.4.0/tcl/interface/usbprog.cfg (revision 12) +++ openocd-0.4.0/tcl/interface/usbprog.cfg (working copy) @@ -1,10 +1,7 @@ # -# Embedded Projects USBprog +# USB-JTAG adapter using USBProg # -# http://embedded-projects.net/index.php?page_id=135 +# http://code.google.com/p/usbprog-jtag/ # interface usbprog -# USBprog is broken w/short tms sequences, this is a workaround -# until the C code can be fixed. -tms_sequence long \ No newline at end of file Index: openocd-0.4.0/src/jtag/drivers/usbprog.c =================================================================== --- openocd-0.4.0/src/jtag/drivers/usbprog.c (revision 12) +++ openocd-0.4.0/src/jtag/drivers/usbprog.c (working copy) @@ -1,661 +1,880 @@ -/*************************************************************************** - * Copyright (C) 2007 by Benedikt Sauter * - * sauter@ixbat.de * - * * - * 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 based on Dominic Rath's amt_jtagaccel.c. - * - * usbprog is a free programming adapter. You can easily install - * different firmware versions from an "online pool" over USB. - * The adapter can be used for programming and debugging AVR and ARM - * processors, as USB to RS232 converter, as JTAG interface or as - * simple I/O interface (5 lines). - * - * http://www.embedded-projects.net/usbprog - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include "usb_common.h" - - -#define VID 0x1781 -#define PID 0x0c63 - -/* Pins at usbprog */ -#define TDO_BIT 0 -#define TDI_BIT 3 -#define TCK_BIT 2 -#define TMS_BIT 1 - -static void usbprog_end_state(tap_state_t state); -static void usbprog_state_move(void); -static void usbprog_path_move(struct pathmove_command *cmd); -static void usbprog_runtest(int num_cycles); -static void usbprog_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size); - -#define UNKOWN_COMMAND 0x00 -#define PORT_DIRECTION 0x01 -#define PORT_SET 0x02 -#define PORT_GET 0x03 -#define PORT_SETBIT 0x04 -#define PORT_GETBIT 0x05 -#define WRITE_TDI 0x06 -#define READ_TDO 0x07 -#define WRITE_AND_READ 0x08 -#define WRITE_TMS 0x09 -#define WRITE_TMS_CHAIN 0x0A - -struct usbprog_jtag -{ - struct usb_dev_handle* usb_handle; -}; - -static struct usbprog_jtag * usbprog_jtag_handle; - -static struct usbprog_jtag* usbprog_jtag_open(void); -//static void usbprog_jtag_close(struct usbprog_jtag *usbprog_jtag); -static void usbprog_jtag_init(struct usbprog_jtag *usbprog_jtag); -static unsigned char usbprog_jtag_message(struct usbprog_jtag *usbprog_jtag, char *msg, int msglen); - -static void usbprog_jtag_read_tdo(struct usbprog_jtag *usbprog_jtag, char * buffer, int size); -static void usbprog_jtag_write_tdi(struct usbprog_jtag *usbprog_jtag, char * buffer, int size); -static void usbprog_jtag_write_and_read(struct usbprog_jtag *usbprog_jtag, char * buffer, int size); -static void usbprog_jtag_write_tms(struct usbprog_jtag *usbprog_jtag, char tms_scan); - -static char tms_chain[64]; -static int tms_chain_index; - -static void usbprog_jtag_tms_collect(char tms_scan); -static void usbprog_jtag_tms_send(struct usbprog_jtag *usbprog_jtag); - -static void usbprog_write(int tck, int tms, int tdi); -static void usbprog_reset(int trst, int srst); - -static void usbprog_jtag_set_direction(struct usbprog_jtag *usbprog_jtag, unsigned char direction); -static void usbprog_jtag_write_slice(struct usbprog_jtag *usbprog_jtag,unsigned char value); -//static unsigned char usbprog_jtag_get_port(struct usbprog_jtag *usbprog_jtag); -static void usbprog_jtag_set_bit(struct usbprog_jtag *usbprog_jtag,int bit, int value); -//static int usbprog_jtag_get_bit(struct usbprog_jtag *usbprog_jtag, int bit); - -static int usbprog_speed(int speed) -{ - return ERROR_OK; -} - -static int usbprog_execute_queue(void) -{ - struct jtag_command *cmd = jtag_command_queue; /* currently processed command */ - int scan_size; - enum scan_type type; - uint8_t *buffer; - - while (cmd) - { - switch (cmd->type) - { - case JTAG_RESET: -#ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); -#endif - if (cmd->cmd.reset->trst == 1) - { - tap_set_state(TAP_RESET); - } - usbprog_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); - break; - case JTAG_RUNTEST: -#ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); -#endif - usbprog_end_state(cmd->cmd.runtest->end_state); - usbprog_runtest(cmd->cmd.runtest->num_cycles); - break; - case JTAG_STATEMOVE: -#ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state); -#endif - usbprog_end_state(cmd->cmd.statemove->end_state); - usbprog_state_move(); - break; - case JTAG_PATHMOVE: -#ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, - cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); -#endif - usbprog_path_move(cmd->cmd.pathmove); - break; - case JTAG_SCAN: -#ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG("scan end in %i", cmd->cmd.scan->end_state); -#endif - usbprog_end_state(cmd->cmd.scan->end_state); - scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer); - type = jtag_scan_type(cmd->cmd.scan); - usbprog_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size); - if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK) - return ERROR_JTAG_QUEUE_FAILED; - if (buffer) - free(buffer); - break; - case JTAG_SLEEP: -#ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG("sleep %i", cmd->cmd.sleep->us); -#endif - jtag_sleep(cmd->cmd.sleep->us); - break; - default: - LOG_ERROR("BUG: unknown JTAG command type encountered"); - exit(-1); - } - - cmd = cmd->next; - } - - return ERROR_OK; -} - -static int usbprog_init(void) -{ - usbprog_jtag_handle = usbprog_jtag_open(); - - tms_chain_index = 0; - if (usbprog_jtag_handle == 0) - { - LOG_ERROR("Can't find USB JTAG Interface! Please check connection and permissions."); - return ERROR_JTAG_INIT_FAILED; - } - - LOG_INFO("USB JTAG Interface ready!"); - - usbprog_jtag_init(usbprog_jtag_handle); - usbprog_reset(0, 0); - usbprog_write(0, 0, 0); - - return ERROR_OK; -} - -static int usbprog_quit(void) -{ - return ERROR_OK; -} - -/*************** jtag execute commands **********************/ -static void usbprog_end_state(tap_state_t state) -{ - if (tap_is_state_stable(state)) - tap_set_end_state(state); - else - { - LOG_ERROR("BUG: %i is not a valid end state", state); - exit(-1); - } -} - -static void usbprog_state_move(void) -{ - int i = 0, tms = 0; - uint8_t tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state()); - int tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state()); - - usbprog_jtag_write_tms(usbprog_jtag_handle, (char)tms_scan); - for (i = 0; i < tms_count; i++) - { - tms = (tms_scan >> i) & 1; - } - - tap_set_state(tap_get_end_state()); -} - -static void usbprog_path_move(struct pathmove_command *cmd) -{ - int num_states = cmd->num_states; - int state_count; - - /* There may be queued transitions, and before following a specified - path, we must flush those queued transitions */ - usbprog_jtag_tms_send(usbprog_jtag_handle); - - state_count = 0; - while (num_states) - { - if (tap_state_transition(tap_get_state(), false) == cmd->path[state_count]) - { - /* LOG_INFO("1"); */ - usbprog_write(0, 0, 0); - usbprog_write(1, 0, 0); - } - else if (tap_state_transition(tap_get_state(), true) == cmd->path[state_count]) - { - /* LOG_INFO("2"); */ - usbprog_write(0, 1, 0); - usbprog_write(1, 1, 0); - } - else - { - LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name(tap_get_state()), tap_state_name(cmd->path[state_count])); - exit(-1); - } - - tap_set_state(cmd->path[state_count]); - state_count++; - num_states--; - } - - tap_set_end_state(tap_get_state()); -} - -static void usbprog_runtest(int num_cycles) -{ - int i; - - /* only do a state_move when we're not already in IDLE */ - if (tap_get_state() != TAP_IDLE) - { - usbprog_end_state(TAP_IDLE); - usbprog_state_move(); - } - - /* execute num_cycles */ - if (num_cycles > 0) - { - usbprog_jtag_tms_send(usbprog_jtag_handle); - usbprog_write(0, 0, 0); - } - else - { - usbprog_jtag_tms_send(usbprog_jtag_handle); - /* LOG_INFO("NUM CYCLES %i",num_cycles); */ - } - - for (i = 0; i < num_cycles; i++) - { - usbprog_write(1, 0, 0); - usbprog_write(0, 0, 0); - } - -#ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG("runtest: cur_state %s end_state %s", tap_state_name(tap_get_state()), tap_state_name(tap_get_end_state())); -#endif - - /* finish in end_state */ - /* - usbprog_end_state(saved_end_state); - if (tap_get_state() != tap_get_end_state()) - usbprog_state_move(); - */ -} - -static void usbprog_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size) -{ - tap_state_t saved_end_state = tap_get_end_state(); - - if (ir_scan) - usbprog_end_state(TAP_IRSHIFT); - else - usbprog_end_state(TAP_DRSHIFT); - - /* Only move if we're not already there */ - if (tap_get_state() != tap_get_end_state()) - usbprog_state_move(); - - usbprog_end_state(saved_end_state); - - usbprog_jtag_tms_send(usbprog_jtag_handle); - - void (*f)(struct usbprog_jtag *usbprog_jtag, char * buffer, int size); - switch (type) { - case SCAN_OUT: f = &usbprog_jtag_write_tdi; break; - case SCAN_IN: f = &usbprog_jtag_read_tdo; break; - case SCAN_IO: f = &usbprog_jtag_write_and_read; break; - default: - LOG_ERROR("unknown scan type: %i", type); - exit(-1); - } - f(usbprog_jtag_handle, (char *)buffer, scan_size); - - /* The adapter does the transition to PAUSE internally */ - if (ir_scan) - tap_set_state(TAP_IRPAUSE); - else - tap_set_state(TAP_DRPAUSE); - - if (tap_get_state() != tap_get_end_state()) - usbprog_state_move(); -} - -/*************** jtag wrapper functions *********************/ - -static void usbprog_write(int tck, int tms, int tdi) -{ - unsigned char output_value = 0x00; - - if (tms) - output_value |= (1 << TMS_BIT); - if (tdi) - output_value |= (1 << TDI_BIT); - if (tck) - output_value |= (1 << TCK_BIT); - - usbprog_jtag_write_slice(usbprog_jtag_handle,output_value); -} - -/* (1) assert or (0) deassert reset lines */ -static void usbprog_reset(int trst, int srst) -{ - LOG_DEBUG("trst: %i, srst: %i", trst, srst); - - if (trst) - usbprog_jtag_set_bit(usbprog_jtag_handle, 5, 0); - else - usbprog_jtag_set_bit(usbprog_jtag_handle, 5, 1); - - if (srst) - usbprog_jtag_set_bit(usbprog_jtag_handle, 4, 0); - else - usbprog_jtag_set_bit(usbprog_jtag_handle, 4, 1); -} - -/*************** jtag lowlevel functions ********************/ - -struct usb_bus *busses; - -struct usbprog_jtag* usbprog_jtag_open(void) -{ - usb_set_debug(10); - usb_init(); - - const uint16_t vids[] = { VID, 0 }; - const uint16_t pids[] = { PID, 0 }; - struct usb_dev_handle *dev; - if (jtag_usb_open(vids, pids, &dev) != ERROR_OK) - return NULL; - - struct usbprog_jtag *tmp = malloc(sizeof(struct usbprog_jtag)); - tmp->usb_handle = dev; - - usb_set_configuration(dev, 1); - usb_claim_interface(dev, 0); - usb_set_altinterface(dev, 0); - - return tmp; -} - -#if 0 -static void usbprog_jtag_close(struct usbprog_jtag *usbprog_jtag) -{ - usb_close(usbprog_jtag->usb_handle); - free(usbprog_jtag); -} -#endif - -static unsigned char usbprog_jtag_message(struct usbprog_jtag *usbprog_jtag, char *msg, int msglen) -{ - int res = usb_bulk_write(usbprog_jtag->usb_handle, 3, msg,msglen, 100); - if ((msg[0] == 2) || (msg[0] == 1) || (msg[0] == 4) || (msg[0] == 0) || \ - (msg[0] == 6) || (msg[0] == 0x0A) || (msg[0] == 9)) - return 1; - if (res == msglen) - { - /* LOG_INFO("HALLLLOOO %i",(int)msg[0]); */ - res = usb_bulk_read(usbprog_jtag->usb_handle, 0x82, msg, 2, 100); - if (res > 0) - return (unsigned char)msg[1]; - else - return -1; - } - else - return -1; - return 0; -} - -static void usbprog_jtag_init(struct usbprog_jtag *usbprog_jtag) -{ - usbprog_jtag_set_direction(usbprog_jtag, 0xFE); -} - -static void usbprog_jtag_write_and_read(struct usbprog_jtag *usbprog_jtag, char * buffer, int size) -{ - char tmp[64]; /* fastes packet size for usb controller */ - int send_bits, bufindex = 0, fillindex = 0, i, loops; - - char swap; - /* 61 byte can be transfered (488 bit) */ - - while (size > 0) - { - if (size > 488) - { - send_bits = 488; - size = size - 488; - loops = 61; - } - else - { - send_bits = size; - loops = size / 8; - loops++; - size = 0; - } - tmp[0] = WRITE_AND_READ; - tmp[1] = (char)(send_bits >> 8); /* high */ - tmp[2] = (char)(send_bits); /* low */ - i = 0; - - for (i = 0; i < loops; i++) - { - tmp[3 + i] = buffer[bufindex]; - bufindex++; - } - - if (usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 64, 1000) == 64) - { - /* LOG_INFO("HALLLLOOO2 %i",(int)tmp[0]); */ - usleep(1); - int timeout = 0; - while (usb_bulk_read(usbprog_jtag->usb_handle, 0x82, tmp, 64, 1000) < 1) - { - timeout++; - if (timeout > 10) - break; - } - - for (i = 0; i < loops; i++) - { - swap = tmp[3 + i]; - buffer[fillindex++] = swap; - } - } - } -} - -static void usbprog_jtag_read_tdo(struct usbprog_jtag *usbprog_jtag, char * buffer, int size) -{ - char tmp[64]; /* fastes packet size for usb controller */ - int send_bits, fillindex = 0, i, loops; - - char swap; - /* 61 byte can be transfered (488 bit) */ - - while (size > 0) - { - if (size > 488) - { - send_bits = 488; - size = size - 488; - loops = 61; - } - else - { - send_bits = size; - loops = size / 8; - loops++; - size = 0; - } - tmp[0] = WRITE_AND_READ; - tmp[1] = (char)(send_bits >> 8); /* high */ - tmp[2] = (char)(send_bits); /* low */ - - usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 3, 1000); - - /* LOG_INFO("HALLLLOOO3 %i",(int)tmp[0]); */ - int timeout = 0; - usleep(1); - while (usb_bulk_read(usbprog_jtag->usb_handle, 0x82, tmp, 64, 10) < 1) - { - timeout++; - if (timeout > 10) - break; - } - - for (i = 0; i < loops; i++) - { - swap = tmp[3 + i]; - buffer[fillindex++] = swap; - } - } -} - -static void usbprog_jtag_write_tdi(struct usbprog_jtag *usbprog_jtag, char * buffer, int size) -{ - char tmp[64]; /* fastes packet size for usb controller */ - int send_bits, bufindex = 0, i, loops; - - /* 61 byte can be transfered (488 bit) */ - while (size > 0) - { - if (size > 488) - { - send_bits = 488; - size = size - 488; - loops = 61; - } - else - { - send_bits = size; - loops = size/8; - /* if (loops == 0) */ - loops++; - size = 0; - } - tmp[0] = WRITE_TDI; - tmp[1] = (char)(send_bits >> 8); /* high */ - tmp[2] = (char)(send_bits); /* low */ - i = 0; - - for (i = 0; i < loops; i++) - { - tmp[3 + i] = buffer[bufindex]; - bufindex++; - } - usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 64, 1000); - } -} - -static void usbprog_jtag_write_tms(struct usbprog_jtag *usbprog_jtag, char tms_scan) -{ - usbprog_jtag_tms_collect(tms_scan); -} - -static void usbprog_jtag_set_direction(struct usbprog_jtag *usbprog_jtag, unsigned char direction) -{ - char tmp[2]; - tmp[0] = PORT_DIRECTION; - tmp[1] = (char)direction; - usbprog_jtag_message(usbprog_jtag, tmp, 2); -} - -static void usbprog_jtag_write_slice(struct usbprog_jtag *usbprog_jtag,unsigned char value) -{ - char tmp[2]; - tmp[0] = PORT_SET; - tmp[1] = (char)value; - usbprog_jtag_message(usbprog_jtag, tmp, 2); -} - -#if 0 -static unsigned char usbprog_jtag_get_port(struct usbprog_jtag *usbprog_jtag) -{ - char tmp[2]; - tmp[0] = PORT_GET; - tmp[1] = 0x00; - return usbprog_jtag_message(usbprog_jtag, tmp, 2); -} -#endif - -static void usbprog_jtag_set_bit(struct usbprog_jtag *usbprog_jtag,int bit, int value) -{ - char tmp[3]; - tmp[0] = PORT_SETBIT; - tmp[1] = (char)bit; - if (value == 1) - tmp[2] = 0x01; - else - tmp[2] = 0x00; - usbprog_jtag_message(usbprog_jtag, tmp, 3); -} - -#if 0 -static int usbprog_jtag_get_bit(struct usbprog_jtag *usbprog_jtag, int bit) -{ - char tmp[2]; - tmp[0] = PORT_GETBIT; - tmp[1] = (char)bit; - - if (usbprog_jtag_message(usbprog_jtag, tmp, 2) > 0) - return 1; - else - return 0; -} -#endif - -static void usbprog_jtag_tms_collect(char tms_scan) -{ - tms_chain[tms_chain_index] = tms_scan; - tms_chain_index++; -} - -static void usbprog_jtag_tms_send(struct usbprog_jtag *usbprog_jtag) -{ - int i; - /* LOG_INFO("TMS SEND"); */ - if (tms_chain_index > 0) - { - char tmp[tms_chain_index + 2]; - tmp[0] = WRITE_TMS_CHAIN; - tmp[1] = (char)(tms_chain_index); - for (i = 0; i < tms_chain_index + 1; i++) - tmp[2 + i] = tms_chain[i]; - usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, tms_chain_index + 2, 1000); - tms_chain_index = 0; - } -} - -struct jtag_interface usbprog_interface = { - .name = "usbprog", - - .execute_queue = usbprog_execute_queue, - .speed = usbprog_speed, - .init = usbprog_init, - .quit = usbprog_quit -}; +/*************************************************************************** + * * + * Copyright (C) 2009 by Cahya Wirawan * + * Based on opendous driver by Vladimir Fonov * + * * + * Copyright (C) 2009 by Vladimir Fonov * + * Based on J-link driver by Juergen Stuber * + * * + * Copyright (C) 2007 by Juergen Stuber * + * based on Dominic Rath's and Benedikt Sauter's usbprog.c * + * * + * Copyright (C) 2008 by Spencer Oliver * + * spen@spen-soft.co.uk * + * * + * 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 "usb_common.h" +#include +#include +#include + +#define VID 0x1781 +#define PID 0x0c63 + +#define USBPROG_WRITE_ENDPOINT 0x02 +#define USBPROG_READ_ENDPOINT 0x82 + +static unsigned int usbprog_hw_jtag_version = 1; + +#define USBPROG_USB_TIMEOUT 1000 + +#define USBPROG_USB_BUFFER_SIZE 510 +#define USBPROG_IN_BUFFER_SIZE (USBPROG_USB_BUFFER_SIZE) +#define USBPROG_OUT_BUFFER_SIZE (USBPROG_USB_BUFFER_SIZE) + +/* Global USB buffers */ +static uint8_t usb_in_buffer[USBPROG_IN_BUFFER_SIZE]; +static uint8_t usb_out_buffer[USBPROG_OUT_BUFFER_SIZE]; + +/* Constants for USBPROG command */ + +#define USBPROG_MAX_SPEED 66 +#define USBPROG_MAX_TAP_TRANSMIT 500 //even number is easier to handle +#define USBPROG_MAX_INPUT_DATA (USBPROG_MAX_TAP_TRANSMIT*4) + +#define USBPROG_TAP_BUFFER_SIZE 65536 + +#define MAX_PENDING_SCAN_RESULTS (USBPROG_MAX_INPUT_DATA) + +//JTAG usb commans +#define JTAG_CMD_TAP_OUTPUT 0x0 +#define JTAG_CMD_SET_TRST 0x1 +#define JTAG_CMD_SET_SRST 0x2 +#define JTAG_CMD_READ_INPUT 0x3 +#define JTAG_CMD_TAP_OUTPUT_EMU 0x4 +#define JTAG_CMD_SET_DELAY 0x5 +#define JTAG_CMD_SET_SRST_TRST 0x6 + +/* External interface functions */ +static int usbprog_execute_queue(void); +static int usbprog_speed(int speed); +static int usbprog_speed_div(int speed, int *khz); +static int usbprog_khz(int khz, int *jtag_speed); +static int usbprog_init(void); +static int usbprog_quit(void); + +/* Queue command functions */ +static void usbprog_end_state(tap_state_t state); +static void usbprog_state_move(void); +static void usbprog_path_move(int num_states, tap_state_t *path); +static void usbprog_runtest(int num_cycles); +static void usbprog_scan(int ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, struct scan_command *command); +static void usbprog_reset(int trst, int srst); +static void usbprog_simple_command(uint8_t command,uint8_t _data); +static int usbprog_get_status(void); + +/* USBProg tap buffer functions */ +static void usbprog_tap_init(void); +static int usbprog_tap_execute(void); +static void usbprog_tap_ensure_space(int scans, int bits); +static void usbprog_tap_append_step(int tms, int tdi); +static void usbprog_tap_append_scan(int length, uint8_t *buffer, struct scan_command *command); + +/* usbprog lowlevel functions */ +struct usbprog_jtag +{ + struct usb_dev_handle* usb_handle; +}; + +static struct usbprog_jtag *usbprog_usb_open(void); +static void usbprog_usb_close(struct usbprog_jtag *usbprog_jtag); +static int usbprog_usb_message(struct usbprog_jtag *usbprog_jtag, int out_length, int in_length); +static int usbprog_usb_write(struct usbprog_jtag *usbprog_jtag, int out_length); +static int usbprog_usb_read(struct usbprog_jtag *usbprog_jtag); +//static int usbprog_usb_read_emu_result(struct usbprog_jtag *usbprog_jtag); + +/* helper functions */ +int usbprog_get_version_info(void); + +#ifdef _DEBUG_USB_COMMS_ +char time_str[50]; +static void usbprog_debug_buffer(uint8_t *buffer, int length); +char *usbprog_get_time(char *); +#endif + +static struct usbprog_jtag* usbprog_jtag_handle; + +/***************************************************************************/ +/* External interface implementation */ + +COMMAND_HANDLER(usbprog_handle_usbprog_info_command) +{ + if (usbprog_get_version_info() == ERROR_OK) + { + /* attempt to get status */ + usbprog_get_status(); + } + + return ERROR_OK; +} + +COMMAND_HANDLER(usbprog_handle_usbprog_hw_jtag_command) +{ + switch (CMD_ARGC) { + case 0: + command_print(CMD_CTX, "usbprog hw jtag %i", usbprog_hw_jtag_version); + break; + case 1: { + int request_version = atoi(CMD_ARGV[0]); + switch (request_version) { + case 2: case 3: + usbprog_hw_jtag_version = request_version; + break; + default: + return ERROR_COMMAND_SYNTAX_ERROR; + } + break; + } + default: + return ERROR_COMMAND_SYNTAX_ERROR; + } + + return ERROR_OK; +} + +static const struct command_registration usbprog_command_handlers[] = { + { + .name = "usbprog_info", + .handler = &usbprog_handle_usbprog_info_command, + .mode = COMMAND_EXEC, + .help = "show usbprog info", + }, + { + .name = "usbprog_hw_jtag", + .handler = &usbprog_handle_usbprog_hw_jtag_command, + .mode = COMMAND_EXEC, + .help = "access USBProg HW JTAG command version", + .usage = "[2|3]", + }, + COMMAND_REGISTRATION_DONE +}; + +struct jtag_interface usbprog_interface = +{ + .name = "usbprog", + .commands = usbprog_command_handlers, + .execute_queue = usbprog_execute_queue, + .speed = usbprog_speed, + .speed_div = usbprog_speed_div, + .khz = usbprog_khz, + .init = usbprog_init, + .quit = usbprog_quit, +}; + +static int usbprog_execute_queue(void) +{ + struct jtag_command *cmd = jtag_command_queue; + int scan_size; + enum scan_type type; + uint8_t *buffer; + + while (cmd != NULL) + { + switch (cmd->type) + { + case JTAG_RUNTEST: + DEBUG_JTAG_IO( "runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, \ + cmd->cmd.runtest->end_state); + + if (cmd->cmd.runtest->end_state != -1) + { + usbprog_end_state(cmd->cmd.runtest->end_state); + } + usbprog_runtest(cmd->cmd.runtest->num_cycles); + break; + + case JTAG_STATEMOVE: + DEBUG_JTAG_IO("statemove end in %i", cmd->cmd.statemove->end_state); + + if (cmd->cmd.statemove->end_state != -1) + { + usbprog_end_state(cmd->cmd.statemove->end_state); + } + usbprog_state_move(); + break; + + case JTAG_PATHMOVE: + DEBUG_JTAG_IO("pathmove: %i states, end in %i", \ + cmd->cmd.pathmove->num_states, \ + cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); + + usbprog_path_move(cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path); + break; + + case JTAG_SCAN: + DEBUG_JTAG_IO("scan end in %i", cmd->cmd.scan->end_state); + + if (cmd->cmd.scan->end_state != -1) + { + usbprog_end_state(cmd->cmd.scan->end_state); + } + + scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer); + DEBUG_JTAG_IO("scan input, length = %d", scan_size); + +#ifdef _DEBUG_USB_COMMS_ + usbprog_debug_buffer(buffer, (scan_size + 7) / 8); +#endif + type = jtag_scan_type(cmd->cmd.scan); + usbprog_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size, cmd->cmd.scan); + break; + + case JTAG_RESET: + DEBUG_JTAG_IO("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); + + usbprog_tap_execute(); + + if (cmd->cmd.reset->trst == 1) + { + tap_set_state(TAP_RESET); + } + usbprog_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); + break; + + case JTAG_SLEEP: + DEBUG_JTAG_IO("sleep %i", cmd->cmd.sleep->us); + usbprog_tap_execute(); + jtag_sleep(cmd->cmd.sleep->us); + break; + + default: + LOG_ERROR("BUG: unknown JTAG command type encountered"); + exit(-1); + } + cmd = cmd->next; + } + return usbprog_tap_execute(); +} + +/* Sets speed in kHz. */ +static int usbprog_speed(int speed) +{ + + if (speed <= USBPROG_MAX_SPEED) + { + //one day... + return ERROR_OK; + } + else + { + LOG_INFO("Requested speed %dkHz exceeds maximum of %dkHz, ignored", speed, USBPROG_MAX_SPEED); + } + + return ERROR_OK; +} + +static int usbprog_speed_div(int speed, int* khz) +{ + *khz = speed; + + return ERROR_OK; +} + +static int usbprog_khz(int khz, int *jtag_speed) +{ + *jtag_speed = khz; + //TODO: convert this into delay value for usbprog + + return ERROR_OK; +} + +static int usbprog_init(void) +{ + int check_cnt; + + usbprog_jtag_handle = usbprog_usb_open(); + + if (usbprog_jtag_handle == 0) + { + LOG_ERROR("Cannot find USBProg Interface! Please check connection and permissions."); + return ERROR_JTAG_INIT_FAILED; + } + + //reset the board + + //usb_control_msg(usbprog_jtag_handle, (REQDIR_DEVICETOHOST | REQTYPE_VENDOR | REQTYPE_STANDARD), 1, 0, 0, &dummy, 1, USBPROG_USB_TIMEOUT); + + check_cnt = 0; + while (check_cnt < 3) + { + if (usbprog_get_version_info() == ERROR_OK) + { + /* attempt to get status */ + usbprog_get_status(); + break; + } + + check_cnt++; + } + + LOG_INFO("USBProg JTAG Interface ready"); + + usbprog_reset(0, 0); + usbprog_tap_init(); + //usbprog_simple_command ( JTAG_CMD_SET_DELAY, 255); + + + return ERROR_OK; +} + +static int usbprog_quit(void) +{ + usbprog_usb_close(usbprog_jtag_handle); + return ERROR_OK; +} + +/***************************************************************************/ +/* Queue command implementations */ + +void usbprog_end_state(tap_state_t state) +{ + if (tap_is_state_stable(state)) + { + tap_set_end_state(state); + } + else + { + LOG_ERROR("BUG: %i is not a valid end state", state); + exit(-1); + } +} + +/* Goes to the end state. */ +void usbprog_state_move(void) +{ + int i; + int tms = 0; + uint8_t tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state()); + uint8_t tms_scan_bits = tap_get_tms_path_len(tap_get_state(), tap_get_end_state()); + + for (i = 0; i < tms_scan_bits; i++) + { + tms = (tms_scan >> i) & 1; + usbprog_tap_append_step(tms, 0); + } + + tap_set_state(tap_get_end_state()); +} + +void usbprog_path_move(int num_states, tap_state_t *path) +{ + int i; + + for (i = 0; i < num_states; i++) + { + if (path[i] == tap_state_transition(tap_get_state(), false)) + { + usbprog_tap_append_step(0, 0); + } + else if (path[i] == tap_state_transition(tap_get_state(), true)) + { + usbprog_tap_append_step(1, 0); + } + else + { + LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name(tap_get_state()), tap_state_name(path[i])); + exit(-1); + } + + tap_set_state(path[i]); + } + + tap_set_end_state(tap_get_state()); +} + +void usbprog_runtest(int num_cycles) +{ + int i; + + tap_state_t saved_end_state = tap_get_end_state(); + + /* only do a state_move when we're not already in IDLE */ + if (tap_get_state() != TAP_IDLE) + { + usbprog_end_state(TAP_IDLE); + usbprog_state_move(); + } + + /* execute num_cycles */ + for (i = 0; i < num_cycles; i++) + { + usbprog_tap_append_step(0, 0); + } + + /* finish in end_state */ + usbprog_end_state(saved_end_state); + if (tap_get_state() != tap_get_end_state()) + { + usbprog_state_move(); + } +} + +void usbprog_scan(int ir_scan, enum scan_type type, uint8_t *buffer, int scan_size, struct scan_command *command) +{ + tap_state_t saved_end_state; + + usbprog_tap_ensure_space(1, scan_size + 8); + + saved_end_state = tap_get_end_state(); + + /* Move to appropriate scan state */ + usbprog_end_state(ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT); + + usbprog_state_move(); + usbprog_end_state(saved_end_state); + + /* Scan */ + usbprog_tap_append_scan(scan_size, buffer, command); + + /* We are in Exit1, go to Pause */ + usbprog_tap_append_step(0, 0); + + tap_set_state(ir_scan ? TAP_IRPAUSE : TAP_DRPAUSE); + + if (tap_get_state() != tap_get_end_state()) + { + usbprog_state_move(); + } +} + +void usbprog_reset(int trst, int srst) +{ + LOG_DEBUG("trst: %i, srst: %i", trst, srst); + + /* Signals are active low */ +/* + if (srst == 0) + { + usbprog_simple_command ( JTAG_CMD_SET_SRST,1); + } + else if (srst == 1) + { + usbprog_simple_command ( JTAG_CMD_SET_SRST,0); + } + + if (trst == 0) + { + usbprog_simple_command ( JTAG_CMD_SET_TRST,1); + } + else if (trst == 1) + { + usbprog_simple_command ( JTAG_CMD_SET_TRST,0); + }*/ + + srst=srst?0:1; + trst=trst?0:2; + usbprog_simple_command ( JTAG_CMD_SET_SRST_TRST,srst|trst ); +} + +void usbprog_simple_command(uint8_t command,uint8_t _data) +{ + int result; + + DEBUG_JTAG_IO("0x%02x 0x%02x", command,_data); + + usb_out_buffer[0] = (uint16_t) 2; + usb_out_buffer[2] = command; + usb_out_buffer[3] = _data; + + result = usbprog_usb_message(usbprog_jtag_handle, 4, 1); + if (result != 1) + { + LOG_ERROR("USBProg command 0x%02x failed (%d)", command, result); + } +} + +int usbprog_get_status(void) +{ +/* + usbprog_simple_command(EMU_CMD_GET_STATE); + usbprog_simple_command(EMU_CMD_GET_STATE); + result = usbprog_usb_read(usbprog_jtag_handle); + + if (result == 8) + { + int vref = usb_in_buffer[0] + (usb_in_buffer[1] << 8); + LOG_INFO("Vref = %d.%d TCK = %d TDI = %d TDO = %d TMS = %d SRST = %d TRST = %d\n", \ + vref / 1000, vref % 1000, \ + usb_in_buffer[2], usb_in_buffer[3], usb_in_buffer[4], \ + usb_in_buffer[5], usb_in_buffer[6], usb_in_buffer[7]); + + if (vref < 1500) + { + LOG_ERROR("Vref too low. Check Target Power\n"); + } + } + else + { + LOG_ERROR("J-Link command EMU_CMD_GET_STATE failed (%d)\n", result); + } +*/ + return ERROR_OK; +} + +int usbprog_get_version_info(void) +{ + return ERROR_OK; +} + +/***************************************************************************/ +/* USBProg tap functions */ + + +static int tap_length; +static uint8_t tms_buffer[USBPROG_TAP_BUFFER_SIZE]; +static uint8_t tdo_buffer[USBPROG_TAP_BUFFER_SIZE]; + +struct pending_scan_result { + int first; /* First bit position in tdo_buffer to read */ + int length; /* Number of bits to read */ + struct scan_command *command; /* Corresponding scan command */ + uint8_t *buffer; +}; + +static int pending_scan_results_length; +static struct pending_scan_result pending_scan_results_buffer[MAX_PENDING_SCAN_RESULTS]; + +static int last_tms; + +void usbprog_tap_init(void) +{ + tap_length = 0; + pending_scan_results_length = 0; +} + +void usbprog_tap_ensure_space(int scans, int bits) +{ + int available_scans = MAX_PENDING_SCAN_RESULTS - pending_scan_results_length; + + if (scans > available_scans ) + { + usbprog_tap_execute(); + } +} + +void usbprog_tap_append_step(int tms, int tdi) +{ + last_tms = tms; + unsigned char _tms=tms?1:0; + unsigned char _tdi=tdi?1:0; + + int index = tap_length/4; + int bits = (tap_length%4)*2; + + if (tap_length < USBPROG_TAP_BUFFER_SIZE) + { + if(!bits) + tms_buffer[index]=0; + + tms_buffer[index] |= (_tdi<first = tap_length; + pending_scan_result->length = length; + pending_scan_result->command = command; + pending_scan_result->buffer = buffer; + + for (i = 0; i < length; i++) + { + usbprog_tap_append_step((i < length-1 ? 0 : 1), (buffer[i/8] >> (i%8)) & 1); + } + pending_scan_results_length++; +} + +/* Pad and send a tap sequence to the device, and receive the answer. + * For the purpose of padding we assume that we are in idle or pause state. */ +int usbprog_tap_execute(void) +{ + int byte_length,byte_length_out; + int i,j; + int result; + int output_counter; + + + if (tap_length > 0) + { + + //memset(tdo_buffer,0,USBPROG_TAP_BUFFER_SIZE); + //LOG_INFO("USBPROG tap execute %d",tap_length); + byte_length = (tap_length+3)/4; + byte_length_out = (tap_length+7)/8; + +#ifdef _DEBUG_USB_COMMS_ + LOG_DEBUG("USBProg is sending %d bytes", byte_length); +#endif + + output_counter=0; + for (j = 0, i = 0; j < byte_length;) + { + int recieve; + int transmit=byte_length-j; + if(transmit>USBPROG_MAX_TAP_TRANSMIT) + { + transmit=USBPROG_MAX_TAP_TRANSMIT; + recieve=(USBPROG_MAX_TAP_TRANSMIT)/2; + usb_out_buffer[2]=JTAG_CMD_TAP_OUTPUT; + + } else { + usb_out_buffer[2]=JTAG_CMD_TAP_OUTPUT | ((tap_length%4)<<4); + recieve=(transmit+1)/2; + } + *(uint16_t *)&usb_out_buffer[0]=transmit+1; + memmove(usb_out_buffer+3,tms_buffer+j,transmit); + result = usbprog_usb_message(usbprog_jtag_handle, 3 + transmit, recieve); + if(result!=recieve) + { + LOG_ERROR("usbprog_tap_execute, wrong result %d, expected %d", result, recieve); + return ERROR_JTAG_QUEUE_FAILED; + } + + memmove(tdo_buffer+i,usb_in_buffer,recieve); + i+=recieve; + j+=transmit; + } + + result=byte_length_out; +#ifdef _DEBUG_USB_COMMS_ + LOG_DEBUG("USBProg tap result %d",result); + usbprog_debug_buffer(tdo_buffer,result); +#endif + //LOG_INFO("USBProg tap execute %d",tap_length); + for (i = 0; i < pending_scan_results_length; i++) + { + struct pending_scan_result *pending_scan_result = &pending_scan_results_buffer[i]; + uint8_t *buffer = pending_scan_result->buffer; + int length = pending_scan_result->length; + int first = pending_scan_result->first; + struct scan_command *command = pending_scan_result->command; + + /* Copy to buffer */ + buf_set_buf(tdo_buffer, first, buffer, 0, length); + + DEBUG_JTAG_IO("pending scan result, length = %d", length); + +#ifdef _DEBUG_USB_COMMS_ + //usbprog_debug_buffer(buffer, byte_length_out); +#endif + + if (jtag_read_buffer(buffer, command) != ERROR_OK) + { + usbprog_tap_init(); + return ERROR_JTAG_QUEUE_FAILED; + } + + if (pending_scan_result->buffer != NULL) + { + free(pending_scan_result->buffer); + } + } + + usbprog_tap_init(); + } + + return ERROR_OK; +} + +/*****************************************************************************/ +/* USBProg USB low-level functions */ + +struct usbprog_jtag* usbprog_usb_open() +{ + struct usb_bus *busses; + struct usb_bus *bus; + struct usb_device *dev; + + struct usbprog_jtag *result; + + result = (struct usbprog_jtag*) malloc(sizeof(struct usbprog_jtag)); + + usb_init(); + usb_find_busses(); + usb_find_devices(); + + busses = usb_get_busses(); + + /* find usbprog_jtag device in usb bus */ + + for (bus = busses; bus; bus = bus->next) + { + for (dev = bus->devices; dev; dev = dev->next) + { + if ((dev->descriptor.idVendor == VID) && (dev->descriptor.idProduct == PID)) + { + result->usb_handle = usb_open(dev); + + /* usb_set_configuration required under win32 */ + usb_set_configuration(result->usb_handle, dev->config[0].bConfigurationValue); + usb_claim_interface(result->usb_handle, 0); + +#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(result->usb_handle, 0); +#endif + return result; + } + } + } + + free(result); + return NULL; +} + +void usbprog_usb_close(struct usbprog_jtag *usbprog_jtag) +{ + usb_close(usbprog_jtag->usb_handle); + free(usbprog_jtag); +} + +/* Send a message and receive the reply. */ +int usbprog_usb_message(struct usbprog_jtag *usbprog_jtag, int out_length, int in_length) +{ + int result; + + result = usbprog_usb_write(usbprog_jtag, out_length); + if (result == out_length) + { + result = usbprog_usb_read(usbprog_jtag); + if (result == in_length) + { + return result; + } + else + { + LOG_ERROR("usb_bulk_read failed (requested=%d, result=%d)", in_length, result); + return -1; + } + } + else + { + LOG_ERROR("usb_bulk_write failed (requested=%d, result=%d)", out_length, result); + return -1; + } +} + +/* Write data from out_buffer to USB. */ +int usbprog_usb_write(struct usbprog_jtag *usbprog_jtag, int out_length) +{ + int result; + + if (out_length > USBPROG_OUT_BUFFER_SIZE) + { + LOG_ERROR("usbprog_jtag_write illegal out_length=%d (max=%d)", out_length, USBPROG_OUT_BUFFER_SIZE); + return -1; + } + +#ifdef _DEBUG_USB_COMMS_ + LOG_DEBUG("%s: USB write begin", usbprog_get_time(time_str)); +#endif + result = usb_bulk_write(usbprog_jtag->usb_handle, USBPROG_WRITE_ENDPOINT, \ + (char *)usb_out_buffer, out_length, USBPROG_USB_TIMEOUT); +#ifdef _DEBUG_USB_COMMS_ + LOG_DEBUG("%s: USB write end: %d bytes", usbprog_get_time(time_str), result); +#endif + + DEBUG_JTAG_IO("usbprog_usb_write, out_length = %d, result = %d", out_length, result); + +#ifdef _DEBUG_USB_COMMS_ + //usbprog_debug_buffer(usb_out_buffer, out_length); +#endif + return result; +} + +/* Read data from USB into in_buffer. */ +int usbprog_usb_read(struct usbprog_jtag *usbprog_jtag) +{ +#ifdef _DEBUG_USB_COMMS_ + LOG_DEBUG("%s: USB read begin", usbprog_get_time(time_str)); +#endif + int result = usb_bulk_read(usbprog_jtag->usb_handle, USBPROG_READ_ENDPOINT, + (char *)usb_in_buffer, USBPROG_IN_BUFFER_SIZE, USBPROG_USB_TIMEOUT); +#ifdef _DEBUG_USB_COMMS_ + LOG_DEBUG("%s: USB read end: %d bytes", usbprog_get_time(time_str), result); +#endif + DEBUG_JTAG_IO("usbprog_usb_read, result = %d", result); + +#ifdef _DEBUG_USB_COMMS_ + //usbprog_debug_buffer(usb_in_buffer, result); +#endif + return result; +} + +//#ifdef _DEBUG_USB_COMMS_ +#define BYTES_PER_LINE 16 + +void usbprog_debug_buffer(uint8_t *buffer, int length) +{ + char line[81]; + char s[4]; + int i; + int j; + + for (i = 0; i < length; i += BYTES_PER_LINE) + { + snprintf(line, 5, "%04x", i); + for (j = i; j < i + BYTES_PER_LINE && j < length; j++) + { + snprintf(s, 4, " %02x", buffer[j]); + strcat(line, s); + } + LOG_DEBUG("%s", line); + } +} + +char *usbprog_get_time(char *str) +{ + struct timeb timebuffer; + char *timeline; + + ftime( &timebuffer ); + timeline = ctime( & ( timebuffer.time ) ); + snprintf(str, 49, "%.8s.%hu", &timeline[11], timebuffer.millitm); + return str; +} +//#endif