Hello, This patch replaces bit banging mode with faster byte shift mode. Tested so far with LPC2132 and Cypress EZ-USB FX2 controller (with Kolja Waschk's usb_jtag software).
All feedback much appreciated. -Juha
diff --git a/src/jtag/drivers/usb_blaster.c b/src/jtag/drivers/usb_blaster.c index 3703323..65d6bd4 100644 --- a/src/jtag/drivers/usb_blaster.c +++ b/src/jtag/drivers/usb_blaster.c @@ -4,6 +4,10 @@ * (http://www.ixo.de/info/usb_jtag/). * * Some updates by Anthony Liu (2006). * * Minor updates and cleanup by Catalin Patulea (2009). * + * Byte shift mode by Juha Karttunen (2010 * + * * + * Copyright (C) 2010 Juha Karttunen * + * [email protected] * * * * Copyright (C) 2009 Catalin Patulea * * [email protected] * @@ -62,6 +66,47 @@ * It is also possible to emulate this configuration using a single-chip USB * controller like the Cypress FX2 (again, see usb_jtag for details). */ + + +/* The following code fully utilizes the possibilities of the + * USB-Blaster. It buffers data up to the maximum packet size of 64 + * bytes. + * + * USB-Blaster offers a byte-shift mode to transmit up to 504 data + * bits (bidirectional) in a single USB packet. A header byte has to be sent as + * the first byte in a packet with the following meaning: + * + * Bit 7 (0x80): Must be set to indicate byte-shift mode. + * Bit 6 (0x40): If set, the USB-Blaster will also read data, not just write. + * Bit 5..0: Define the number N of following bytes + * + * All N following bytes will then be clocked out serially on TDI. If Bit 6 was + * set, it will afterwards return N bytes with TDO data read while clocking out + * the TDI data. LSB of the first byte after the header byte will appear first + * on TDI. + */ + +/* Simple bit banging mode: + * + * Bit 7 (0x80): Must be zero (see byte-shift mode above) + * Bit 6 (0x40): If set, you will receive a byte indicating the state of TDO + * in return. + * Bit 5 (0x20): Output Enable/LED. + * Bit 4 (0x10): TDI Output. + * Bit 3 (0x08): nCS Output (not used in JTAG mode). + * Bit 2 (0x04): nCE Output (not used in JTAG mode). + * Bit 1 (0x02): TMS Output. + * Bit 0 (0x01): TCK Output. + * + * For transmitting a single data bit, you need to write two bytes. Up to 64 + * bytes can be combined in a single USB packet (but this is not done in the + * code below). It isn't possible to read a data without transmitting data. + */ + + + + + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -81,7 +126,6 @@ #include <stdlib.h> #include <unistd.h> -#include "bitbang.h" #if (BUILD_USB_BLASTER_FTD2XX == 1 && BUILD_USB_BLASTER_LIBFTDI == 1) #error "BUILD_USB_BLASTER_FTD2XX && BUILD_USB_BLASTER_LIBFTDI " @@ -100,134 +144,6 @@ #include <sys/time.h> #include <time.h> -static char *usb_blaster_device_desc; -static uint16_t usb_blaster_vid = 0x09fb; /* Altera */ -static uint16_t usb_blaster_pid = 0x6001; /* USB-Blaster */ - -/* last output byte in simple bit banging mode */ -static uint8_t out_value; - -#if BUILD_USB_BLASTER_FTD2XX == 1 -static FT_HANDLE ftdih; -#elif BUILD_USB_BLASTER_LIBFTDI == 1 -static struct ftdi_context ftdic; -#endif - -static int usb_blaster_buf_write( - uint8_t *buf, int size, uint32_t *bytes_written) -{ -#if BUILD_USB_BLASTER_FTD2XX == 1 - FT_STATUS status; - DWORD dw_bytes_written; - -#ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG("usb_blaster_buf_write %02X (%d)\n", buf[0], size); -#endif - status = FT_Write(ftdih, buf, size, &dw_bytes_written); - if (status != FT_OK) - { - *bytes_written = dw_bytes_written; - LOG_ERROR("FT_Write returned: %lu", status); - return ERROR_JTAG_DEVICE_ERROR; - } - *bytes_written = dw_bytes_written; - return ERROR_OK; -#elif BUILD_USB_BLASTER_LIBFTDI == 1 - int retval; -#ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG("usb_blaster_buf_write %02X (%d)\n", buf[0], size); -#endif - retval = ftdi_write_data(&ftdic, buf, size); - if (retval < 0) - { - *bytes_written = 0; - LOG_ERROR("ftdi_write_data: %s", ftdi_get_error_string(&ftdic)); - return ERROR_JTAG_DEVICE_ERROR; - } - *bytes_written = retval; - return ERROR_OK; -#endif -} - -static int -usb_blaster_buf_read(uint8_t *buf, unsigned size, uint32_t *bytes_read) -{ -#if BUILD_USB_BLASTER_FTD2XX == 1 - DWORD dw_bytes_read; - FT_STATUS status; - - status = FT_Read(ftdih, buf, size, &dw_bytes_read); - if (status != FT_OK) - { - *bytes_read = dw_bytes_read; - LOG_ERROR("FT_Read returned: %lu", status); - return ERROR_JTAG_DEVICE_ERROR; - } -#ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG("usb_blaster_buf_read %02X (%lu)\n", buf[0], dw_bytes_read); -#endif - *bytes_read = dw_bytes_read; - return ERROR_OK; - -#elif BUILD_USB_BLASTER_LIBFTDI == 1 - int retval; - int timeout = 100; - - *bytes_read = 0; - while ((*bytes_read < size) && timeout--) - { - retval = ftdi_read_data(&ftdic, buf + *bytes_read, - size - *bytes_read); - if (retval < 0) - { - *bytes_read = 0; - LOG_ERROR("ftdi_read_data: %s", - ftdi_get_error_string(&ftdic)); - return ERROR_JTAG_DEVICE_ERROR; - } - *bytes_read += retval; - } -#ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG("usb_blaster_buf_read %02X (%d)\n", buf[0], *bytes_read); -#endif - return ERROR_OK; -#endif -} - -/* The following code doesn't fully utilize the possibilities of the - * USB-Blaster. It writes one byte per JTAG pin state change at a time; it - * doesn't even try to buffer data up to the maximum packet size of 64 bytes. - * - * Actually, the USB-Blaster offers a byte-shift mode to transmit up to 504 data - * bits (bidirectional) in a single USB packet. A header byte has to be sent as - * the first byte in a packet with the following meaning: - * - * Bit 7 (0x80): Must be set to indicate byte-shift mode. - * Bit 6 (0x40): If set, the USB-Blaster will also read data, not just write. - * Bit 5..0: Define the number N of following bytes - * - * All N following bytes will then be clocked out serially on TDI. If Bit 6 was - * set, it will afterwards return N bytes with TDO data read while clocking out - * the TDI data. LSB of the first byte after the header byte will appear first - * on TDI. - */ - -/* Simple bit banging mode: - * - * Bit 7 (0x80): Must be zero (see byte-shift mode above) - * Bit 6 (0x40): If set, you will receive a byte indicating the state of TDO - * in return. - * Bit 5 (0x20): Output Enable/LED. - * Bit 4 (0x10): TDI Output. - * Bit 3 (0x08): nCS Output (not used in JTAG mode). - * Bit 2 (0x04): nCE Output (not used in JTAG mode). - * Bit 1 (0x02): TMS Output. - * Bit 0 (0x01): TCK Output. - * - * For transmitting a single data bit, you need to write two bytes. Up to 64 - * bytes can be combined in a single USB packet (but this is not done in the - * code below). It isn't possible to read a data without transmitting data. - */ #define TCK (1 << 0) #define TMS (1 << 1) @@ -241,44 +157,42 @@ usb_blaster_buf_read(uint8_t *buf, unsigned size, uint32_t *bytes_read) #define READ_TDO (1 << 0) -static void usb_blaster_write_data(void) -{ - uint32_t bytes_written; - usb_blaster_buf_write(&out_value, 1, &bytes_written); -} -static int usb_blaster_read_data(void) -{ - int status; - uint8_t buf[1]; - uint32_t bytes_read; +static void usb_blaster_end_state(tap_state_t state); +static void usb_blaster_state_move(void); +static void usb_blaster_path_move(struct pathmove_command *cmd); +static void usb_blaster_runtest(int num_cycles); +static void usb_blaster_scan(bool ir_scan, + enum scan_type type, uint8_t *buffer, int scan_size); +static void usb_blaster_reset(int trst, int srst); +static void usb_blaster_write(int tck, int tms, int tdi); +static int usb_blaster_read(int tck, int tms, int tdi); +static int usb_blaster_buf_write( + uint8_t *buf, int size, uint32_t *bytes_written); +static int usb_blaster_buf_read(uint8_t *buf, + unsigned size, uint32_t *bytes_read); +static void usb_blaster_jtag_tms_send(void); +static void usb_blaster_jtag_write_and_read(char * buffer, int size); +static void usb_blaster_jtag_read_tdo(char *buffer, int size); +static void usb_blaster_jtag_write_tdi(char *buffer, int size); - out_value |= READ; - usb_blaster_write_data(); - out_value &= ~READ; - status = usb_blaster_buf_read(buf, 1, &bytes_read); - if (status < 0) - return 0; - return !!(buf[0] & READ_TDO); -} -static void usb_blaster_write(int tck, int tms, int tdi) -{ -#ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG("---- usb_blaster_write(%d,%d,%d)\n", tck, tms, tdi); +static char tms_chain[64]; +static int tms_chain_index; + +static char *usb_blaster_device_desc; +static uint16_t usb_blaster_vid = 0x09fb; /* Altera */ +static uint16_t usb_blaster_pid = 0x6001; /* USB-Blaster */ + + +#if BUILD_USB_BLASTER_FTD2XX == 1 +static FT_HANDLE ftdih; +#elif BUILD_USB_BLASTER_LIBFTDI == 1 +static struct ftdi_context ftdic; #endif - out_value &= ~(TCK | TMS | TDI); - if (tck) - out_value |= TCK; - if (tms) - out_value |= TMS; - if (tdi) - out_value |= TDI; - usb_blaster_write_data(); -} static int usb_blaster_speed(int speed) { @@ -301,17 +215,79 @@ static int usb_blaster_speed(int speed) return ERROR_OK; } -static void usb_blaster_reset(int trst, int srst) + + +static int usb_blaster_execute_queue(void) { - LOG_DEBUG("TODO: usb_blaster_reset(%d,%d) isn't implemented!", - trst, srst); -} + struct jtag_command *cmd = jtag_command_queue; /* currently processed command */ + int scan_size; + enum scan_type type; + uint8_t *buffer; -static struct bitbang_interface usb_blaster_bitbang = { - .read = usb_blaster_read_data, - .write = usb_blaster_write, - .reset = usb_blaster_reset, -}; + 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) || (cmd->cmd.reset->srst && (jtag_get_reset_config() & RESET_SRST_PULLS_TRST))) + { + tap_set_state(TAP_RESET); + } + usb_blaster_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 + usb_blaster_end_state(cmd->cmd.runtest->end_state); + usb_blaster_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 + usb_blaster_end_state(cmd->cmd.statemove->end_state); + usb_blaster_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 + usb_blaster_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 + usb_blaster_end_state(cmd->cmd.scan->end_state); + scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer); + type = jtag_scan_type(cmd->cmd.scan); + usb_blaster_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 usb_blaster_init(void) { @@ -440,7 +416,6 @@ static int usb_blaster_init(void) ftdi_disable_bitbang(&ftdic); #endif - bitbang_interface = &usb_blaster_bitbang; usb_blaster_speed(jtag_get_speed()); @@ -459,7 +434,6 @@ static int usb_blaster_init(void) } #endif #endif - return ERROR_OK; } @@ -477,6 +451,295 @@ static int usb_blaster_quit(void) return ERROR_OK; } + +static void usb_blaster_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 usb_blaster_state_move(void) +{ + int i = 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()); + + + for(i=0;i<tms_count;i++) + { + tms_chain[i+tms_chain_index] = (char) (tms_scan>>i) & 1; + } + + tms_chain_index += tms_count; + + + tap_set_state(tap_get_end_state()); +} + +static void usb_blaster_path_move(struct pathmove_command *cmd) +{ + int num_states = cmd->num_states; + int state_count, tms = 0; + + /* There may be queued transitions, and before following a specified + path, we must flush those queued transitions */ + usb_blaster_jtag_tms_send(); + + state_count = 0; + while (num_states) + { + if (tap_state_transition(tap_get_state(), false) == cmd->path[state_count]) + { + /* LOG_INFO("1"); */ + tms = 0; + } + else if (tap_state_transition(tap_get_state(), true) == cmd->path[state_count]) + { + /* LOG_INFO("2"); */ + tms = 1; + } + 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); + } + usb_blaster_write(0, tms, 0); + usb_blaster_write(1, tms, 0); + + tap_set_state(cmd->path[state_count]); + state_count++; + num_states--; + } + usb_blaster_write(0, tms, 0); + + tap_set_end_state(tap_get_state()); +} + + +static void usb_blaster_runtest(int num_cycles) +{ + int i; + + /* only do a state_move when we're not already in IDLE */ + if (tap_get_state() != TAP_IDLE) + { + usb_blaster_end_state(TAP_IDLE); + usb_blaster_state_move(); + } + + /* execute num_cycles */ + if (num_cycles > 0) + { + usb_blaster_jtag_tms_send(); + } + else + { + usb_blaster_jtag_tms_send(); + /* LOG_INFO("NUM CYCLES %i",num_cycles); */ + } + + for (i = 0; i < num_cycles; i++) + { + usb_blaster_write(0, 0, 0); + usb_blaster_write(1, 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 + + usb_blaster_write(0, 0, 0); + +} + +static void usb_blaster_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) + usb_blaster_end_state(TAP_IRSHIFT); + else + usb_blaster_end_state(TAP_DRSHIFT); + + /* Only move if we're not already there */ + if (tap_get_state() != tap_get_end_state()) + usb_blaster_state_move(); + + usb_blaster_end_state(saved_end_state); + + usb_blaster_jtag_tms_send(); + + void (*f)(char * buffer, int size); + switch (type) { + case SCAN_OUT: f = &usb_blaster_jtag_write_tdi; break; + case SCAN_IN: f = &usb_blaster_jtag_read_tdo; break; + case SCAN_IO: f = &usb_blaster_jtag_write_and_read; break; + default: + LOG_ERROR("unknown scan type: %i", type); + exit(-1); + } + f((char *)buffer, scan_size); + + /* Move from EXIT to PAUSE state */ + + usb_blaster_write(0,0,0); + usb_blaster_write(1,0,0); + usb_blaster_write(0,0,0); + + /* We know we are at PAUSE */ + if (ir_scan) + tap_set_state(TAP_IRPAUSE); + else + tap_set_state(TAP_DRPAUSE); + + + + if (tap_get_state() != tap_get_end_state()) + usb_blaster_state_move(); + + +} + +static void usb_blaster_write(int tck, int tms, int tdi) +{ + unsigned char output_value = 0x00; + uint32_t bytes_written; + + if (tms) + output_value |= (1<<1); + if (tdi) + output_value |= (1<<4); + if (tck) + output_value |= (1<<0); + + usb_blaster_buf_write(&output_value,1,&bytes_written); +} + +static int usb_blaster_read(int tck, int tms, int tdi) +{ + int status; + uint8_t ctrl_byte; + uint32_t bytes_read,bytes_written; + + ctrl_byte = READ; + + if (tms) + ctrl_byte |= TMS; + if (tdi) + ctrl_byte |= TDI; + if (tck) + ctrl_byte |= TCK; + + usb_blaster_buf_write(&ctrl_byte,1,&bytes_written); + + status = usb_blaster_buf_read(&ctrl_byte, 1, &bytes_read); + if (status < 0) + return 0; + + return (ctrl_byte & READ_TDO); + +} + +static int usb_blaster_buf_write( + uint8_t *buf, int size, uint32_t *bytes_written) +{ + +#if BUILD_USB_BLASTER_FTD2XX == 1 + FT_STATUS status; + DWORD dw_bytes_written; + +#ifdef _DEBUG_JTAG_IO_ + LOG_DEBUG("usb_blaster_buf_write %02X (%d)\n", buf[0], size); +#endif + status = FT_Write(ftdih, buf, size, &dw_bytes_written); + if (status != FT_OK) + { + *bytes_written = dw_bytes_written; + LOG_ERROR("FT_Write returned: %lu", status); + return ERROR_JTAG_DEVICE_ERROR; + } + *bytes_written = dw_bytes_written; + return ERROR_OK; +#elif BUILD_USB_BLASTER_LIBFTDI == 1 + int retval; +#ifdef _DEBUG_JTAG_IO_ + LOG_DEBUG("usb_blaster_buf_write %02X (%d)\n", buf[0], size); +#endif + retval = ftdi_write_data(&ftdic, buf, size); + if (retval < 0) + { + *bytes_written = 0; + LOG_ERROR("ftdi_write_data: %s", ftdi_get_error_string(&ftdic)); + return ERROR_JTAG_DEVICE_ERROR; + } + *bytes_written = retval; + return ERROR_OK; +#endif +} + +static int +usb_blaster_buf_read(uint8_t *buf, unsigned size, uint32_t *bytes_read) +{ + +#if BUILD_USB_BLASTER_FTD2XX == 1 + DWORD dw_bytes_read; + FT_STATUS status; + + status = FT_Read(ftdih, buf, size, &dw_bytes_read); + if (status != FT_OK) + { + *bytes_read = dw_bytes_read; + LOG_ERROR("FT_Read returned: %lu", status); + return ERROR_JTAG_DEVICE_ERROR; + } +#ifdef _DEBUG_JTAG_IO_ + LOG_DEBUG("usb_blaster_buf_read %02X (%lu)\n", buf[0], dw_bytes_read); + +#endif + *bytes_read = dw_bytes_read; + return ERROR_OK; + +#elif BUILD_USB_BLASTER_LIBFTDI == 1 + int retval; + int timeout = 100; + + *bytes_read = 0; + while ((*bytes_read < size) && timeout--) + { + retval = ftdi_read_data(&ftdic, buf + *bytes_read, + size - *bytes_read); + if (retval < 0) + { + *bytes_read = 0; + LOG_ERROR("ftdi_read_data: %s", + ftdi_get_error_string(&ftdic)); + return ERROR_JTAG_DEVICE_ERROR; + } + *bytes_read += retval; + } +#ifdef _DEBUG_JTAG_IO_ + LOG_DEBUG("usb_blaster_buf_read %02X (%d)\n", buf[0], *bytes_read); +#endif + return ERROR_OK; +#endif +} + + + +static void usb_blaster_reset(int trst, int srst) +{ + LOG_DEBUG("TODO: usb_blaster_reset(%d,%d) isn't implemented!", + trst, srst); + +} + + COMMAND_HANDLER(usb_blaster_handle_device_desc_command) { if (CMD_ARGC == 1) @@ -514,6 +777,8 @@ COMMAND_HANDLER(usb_blaster_handle_pin_command) const char * const pin_name = CMD_ARGV[0]; uint8_t mask; unsigned int state; + unsigned char out_value = 0x00; + uint32_t bytes_written; if (!strcmp(pin_name, "pin6")) mask = NCE; @@ -530,12 +795,12 @@ COMMAND_HANDLER(usb_blaster_handle_pin_command) if (state == 0) { out_value &= ~mask; - usb_blaster_write_data(); + usb_blaster_buf_write(&out_value,1,&bytes_written); } else if (state == 1) { out_value |= mask; - usb_blaster_write_data(); + usb_blaster_buf_write(&out_value,1,&bytes_written); } else { @@ -577,13 +842,260 @@ static const struct command_registration usb_blaster_command_handlers[] = { COMMAND_REGISTRATION_DONE }; + + + + +static void usb_blaster_jtag_write_and_read(char * buffer, int size) +{ + uint8_t tmp[64]; + int bufindex = 0, fillindex = 0; + int bit,extra = 0, tms; + uint32_t bytes_written, send_bits, bytes_read,loops,i, + remainder = 0; + char swap,rem_bits=0; + + /* 63 byte can be transfered (504 bit) */ + + + /* we must send last bit manually to be able to exit + from DRSHIFT state. Programmer won't do that for us. */ + + if ((size % 8) == 0) + { + size--; + extra = 1; + } + + while (size > 0) + { + if (size > 504) + { + send_bits = 504; + size = size - 504; + loops = 63; + } + else + { + loops = size / 8; + send_bits = loops * 8; + remainder = size - send_bits; + size = 0; + } + tmp[0] = SHMODE|READ; + tmp[0] |= (send_bits/8) & 0x3F; + + + for (i = 0; i < loops; i++) + { + tmp[1 + i] = buffer[bufindex]; + bufindex++; + } + if (remainder) rem_bits = buffer[bufindex]; + if (loops>0) + usb_blaster_buf_write(tmp,1+loops,&bytes_written); + + if (bytes_written == 1+loops && loops>0) + { + usleep(1); + int timeout = 0; + while (usb_blaster_buf_read(tmp, loops, &bytes_read) < 0) + { + timeout++; + if (timeout > 10) + break; + } + if (bytes_read != loops) + printf("%d bytes read of %d.\n",bytes_read,loops); + for (i = 0; i < loops; i++) + { + swap = tmp[i]; + buffer[fillindex] = swap; + fillindex++; + } + } + else if (loops){ + printf("write & read : buf_write failed! loops=%d bytes_written=%d\n",loops,bytes_written); + exit(1); + } + if (remainder) { + buffer[fillindex]=0; + if (extra) remainder++; + for (i=0,tms=0;i<remainder;i++) { + if (i == remainder-1) tms = 1; + bit = ((rem_bits & (1<<i)) >> i); + tmp[0]=usb_blaster_read(0,tms,bit); + usb_blaster_write(1,tms,bit); + buffer[fillindex] |= (tmp[0] << i); + } + fillindex++; + } + } +} + +static void usb_blaster_jtag_read_tdo(char * buffer, int size) +{ + uint8_t tmp[64]; + int fillindex = 0, extra = 0, tms; + uint32_t bytes_written, bytes_read, send_bits, + i, loops,remainder = 0; + char swap; + + /* 63 byte can be transfered (504 bit) */ + + if ((size % 8) == 0) + { + size--; + extra = 1; + } + + while (size > 0) + { + if (size > 504) + { + send_bits = 504; + size = size - 504; + loops = 63; + } + else + { + loops = size / 8; + send_bits = loops * 8; + remainder = size - send_bits; + size = 0; + } + tmp[0] = SHMODE | READ; + tmp[0] |= (send_bits/8) & 0x3F; + i = 0; + + for (i = 0; i < loops; i++) tmp[1 + i] = 0; + + if (loops) + usb_blaster_buf_write(tmp,1+loops,&bytes_written); + + if (bytes_written == 1+loops && loops) + { + usleep(1); + int timeout = 0; + while (usb_blaster_buf_read(tmp, loops, &bytes_read) < 0) + { + timeout++; + if (timeout > 10) + break; + } + if (bytes_read != loops) + printf("%d bytes read of %d.\n",bytes_read,loops); + + for (i = 0; i < loops; i++) + { + swap = tmp[i]; + buffer[fillindex++] = swap; + } + } + else if(loops){ + printf("read_tdo : needs to have check for sent data!\n"); + exit(1); + } + if (remainder) { + buffer[fillindex]=0; + if (extra) remainder++; + for (i=0,tms=0;i<remainder;i++) { + if (i == remainder-1) tms = 1; + tmp[0]=usb_blaster_read(0,tms,0); + usb_blaster_write(1,tms,0); + buffer[fillindex] |= (tmp[0] << i); + } + } + } +} + + +static void usb_blaster_jtag_write_tdi(char * buffer, int size) +{ + uint8_t tmp[64]; + int bufindex = 0; + int bit, extra = 0, tms; + uint32_t bytes_written, send_bits, i, + loops,remainder=0; + char rem_bits=0; + + /* 63 byte can be transfered (504 bit) */ + if ((size % 8) == 0) + { + size--; + extra = 1; + } + + while (size > 0) + { + if (size > 504) + { + send_bits = 504; + size = size - 504; + loops = 63; + } + else + { + loops = size / 8; + send_bits = loops * 8; + remainder = size - send_bits; + size = 0; + } + tmp[0] = SHMODE; + tmp[0] |= (send_bits/8) & 0x3F; + i = 0; + + for (i = 0; i < loops; i++) + { + tmp[1 + i] = buffer[bufindex]; + bufindex++; + } + if (remainder) rem_bits = buffer[bufindex]; + if (loops) + usb_blaster_buf_write(tmp,1+loops,&bytes_written); + if (bytes_written!=1+loops && loops>0) + printf("write_tdi : w/r mismatch loops=%d bytes written=%d\n", + loops,bytes_written); + if (remainder) { + if (extra) remainder++; + for (i=0,tms=0;i<remainder;i++) { + if (i == remainder-1) tms = 1; + bit = ((rem_bits & (1<<i)) >> i); + usb_blaster_write(0,tms,bit); + usb_blaster_write(1,tms,bit); + } + } + } +} + + + + +static void usb_blaster_jtag_tms_send(void) +{ + int i,tms = 0; + + if (tms_chain_index > 0) + { + for(i=0;i<tms_chain_index;i++) + { + tms = tms_chain[i]; + usb_blaster_write(0,tms,0); + usb_blaster_write(1,tms,0); + } + usb_blaster_write(0,tms,0); + tms_chain_index = 0; + } +} + struct jtag_interface usb_blaster_interface = { .name = "usb_blaster", - .commands = usb_blaster_command_handlers, - - .execute_queue = bitbang_execute_queue, + .commands = usb_blaster_command_handlers, + .execute_queue = usb_blaster_execute_queue, .speed = usb_blaster_speed, .init = usb_blaster_init, - .quit = usb_blaster_quit, + .quit = usb_blaster_quit }; + +
_______________________________________________ Openocd-development mailing list [email protected] https://lists.berlios.de/mailman/listinfo/openocd-development
