diff --git a/jtag/ChangeLog b/jtag/ChangeLog index 5f4fb0fd..73dd3cd1 100644 --- a/jtag/ChangeLog +++ b/jtag/ChangeLog @@ -1,3 +1,8 @@ +2008-02-25 Kolja Waschk + + * include/usbconn/libusb.h, src/tap/cable/jlink.c: J-Link driver + doesn't use global variables anymore + 2008-02-25 Jie Zhang * src/bus/buses.c (bus_drivers): bf548_ezkit_bus. diff --git a/jtag/include/usbconn/libusb.h b/jtag/include/usbconn/libusb.h index be2c87ba..4b1f95df 100644 --- a/jtag/include/usbconn/libusb.h +++ b/jtag/include/usbconn/libusb.h @@ -31,7 +31,8 @@ typedef struct { struct usb_device *dev; - struct usb_dev_handle *handle; + struct usb_dev_handle *handle; + void *data; } libusb_param_t; #endif diff --git a/jtag/src/tap/cable/jlink.c b/jtag/src/tap/cable/jlink.c index e50bb8e5..69ca9fb0 100644 --- a/jtag/src/tap/cable/jlink.c +++ b/jtag/src/tap/cable/jlink.c @@ -60,9 +60,22 @@ #define JLINK_IN_BUFFER_SIZE 2064 #define JLINK_OUT_BUFFER_SIZE 2064 -/* Global USB buffers */ -static char usb_in_buffer[JLINK_IN_BUFFER_SIZE]; -static char usb_out_buffer[JLINK_OUT_BUFFER_SIZE]; +/* We use the maximal value observed */ +#define JLINK_TAP_BUFFER_SIZE 390 + +typedef struct +{ + /* Global USB buffers */ + char usb_in_buffer[JLINK_IN_BUFFER_SIZE]; + char usb_out_buffer[JLINK_OUT_BUFFER_SIZE]; + + int tap_length; + uint8_t tms_buffer[JLINK_TAP_BUFFER_SIZE]; + uint8_t tdi_buffer[JLINK_TAP_BUFFER_SIZE]; + + int last_tdo; +} +jlink_usbconn_data_t; /* Constants for JLink command */ #define JLINK_SPEED_COMMAND 0x05 @@ -74,82 +87,64 @@ static char usb_out_buffer[JLINK_OUT_BUFFER_SIZE]; #define JLINK_MAX_SPEED 12000 - /* Queue command functions */ -static void jlink_reset( cable_t *cable, int trst, int srst); -static void jlink_simple_command( cable_t *cable, uint8_t command ); +static void jlink_reset( libusb_param_t *params, int trst, int srst); +static void jlink_simple_command( libusb_param_t *params, uint8_t command ); + /* J-Link tap buffer functions */ -static void jlink_tap_init(); -static int jlink_tap_execute(); -static void jlink_tap_append_step(int tms, int tdi); +static void jlink_tap_init( jlink_usbconn_data_t *data ); +static int jlink_tap_execute( libusb_param_t *params ); +static void jlink_tap_append_step( jlink_usbconn_data_t *data, int, int); /* Jlink lowlevel functions */ -static int jlink_usb_message( cable_t *cable, int out_length, int in_length); -static int jlink_usb_write( cable_t *cable, unsigned int out_length); -static int jlink_usb_read( cable_t *cable ); -static void jlink_debug_buffer(uint8_t *buffer, int length); - - +static int jlink_usb_message( libusb_param_t *params, int, int ); +static int jlink_usb_write( libusb_param_t *params, unsigned int ); +static int jlink_usb_read( libusb_param_t *params ); -void jlink_set_frequency( cable_t *cable, uint32_t frequency ) -{ - int result; - int speed = frequency / 1E3; +static void jlink_debug_buffer(uint8_t *buffer, int length); - if (1 <= speed && speed <= JLINK_MAX_SPEED) - { - usb_out_buffer[0] = JLINK_SPEED_COMMAND; - usb_out_buffer[1] = (speed >> 0) & 0xff; - usb_out_buffer[2] = (speed >> 8) & 0xff; +/* API functions */ - result = jlink_usb_write( cable, 3 ); +void jlink_set_frequency( cable_t *cable, uint32_t frequency ); - if (result != 3) - { - ERROR("J-Link setting speed failed (%d)\n", result); - } - } - else - { - INFO("Requested speed %dkHz exceeds maximum of %dkHz, ignored\n", - speed, JLINK_MAX_SPEED); - } -} +/***************************************************************************/ +/* J-Link tap functions */ -void jlink_reset( cable_t *cable, int trst, int srst) +void jlink_reset( libusb_param_t *params, int trst, int srst) { DEBUG("trst: %i, srst: %i\n", trst, srst); /* Signals are active low */ if (trst == 0) { - jlink_simple_command( cable, JLINK_SET_TRST_HIGH_COMMAND); + jlink_simple_command( params, JLINK_SET_TRST_HIGH_COMMAND); } else if (trst == 1) { - jlink_simple_command( cable, JLINK_SET_TRST_LOW_COMMAND); + jlink_simple_command( params, JLINK_SET_TRST_LOW_COMMAND); } if (srst == 0) { - jlink_simple_command( cable, JLINK_SET_SRST_HIGH_COMMAND); + jlink_simple_command( params, JLINK_SET_SRST_HIGH_COMMAND); } else if (srst == 1) { - jlink_simple_command( cable, JLINK_SET_SRST_LOW_COMMAND); + jlink_simple_command( params, JLINK_SET_SRST_LOW_COMMAND); } } -static void jlink_simple_command( cable_t *cable, uint8_t command) +static void jlink_simple_command( libusb_param_t *params, uint8_t command) { int result; + jlink_usbconn_data_t *data = params->data; DEBUG("simple_command: 0x%02x\n", command); - usb_out_buffer[0] = command; - result = jlink_usb_write( cable, 1 ); + data->usb_out_buffer[0] = command; + result = jlink_usb_write( params, 1 ); if (result != 1) { @@ -158,41 +153,31 @@ static void jlink_simple_command( cable_t *cable, uint8_t command) } /***************************************************************************/ -/* J-Link tap functions */ - -/* We use the maximal value observed */ -#define JLINK_TAP_BUFFER_SIZE 390 - -static int tap_length; -static uint8_t tms_buffer[JLINK_TAP_BUFFER_SIZE]; -static uint8_t tdi_buffer[JLINK_TAP_BUFFER_SIZE]; -static int last_tdo; - -static void jlink_tap_init() +static void jlink_tap_init( jlink_usbconn_data_t *data ) { - tap_length = 0; + data->tap_length = 0; } -static void jlink_tap_append_step(int tms, int tdi) +static void jlink_tap_append_step( jlink_usbconn_data_t *data, int tms, int tdi) { - int index = tap_length >> 3; + int index = data->tap_length >> 3; if (index < JLINK_TAP_BUFFER_SIZE) { - int bit_index = tap_length & 7; + int bit_index = data->tap_length & 7; uint8_t bit = 1 << bit_index; - if(bit_index == 0) - { - tms_buffer[index] = 0; - tdi_buffer[index] = 0; - }; + if(bit_index == 0) + { + data->tms_buffer[index] = 0; + data->tdi_buffer[index] = 0; + }; - if(tms) tms_buffer[index] |= bit; - if(tdi) tdi_buffer[index] |= bit; + if(tms) data->tms_buffer[index] |= bit; + if(tdi) data->tdi_buffer[index] |= bit; - tap_length++; + data->tap_length++; } else { @@ -200,46 +185,50 @@ static void jlink_tap_append_step(int tms, int tdi) } } -/* 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. */ -static int jlink_tap_execute( cable_t *cable ) +/* Send a tap sequence to the device, and receive the answer */ + +static int jlink_tap_execute( libusb_param_t *params ) { + jlink_usbconn_data_t *data = params->data; int byte_length; int tms_offset; int tdi_offset; int i; int result; - if (tap_length > 0) + if (data->tap_length > 0) { - byte_length = (tap_length + 7) >> 3; - usb_out_buffer[0] = JLINK_TAP_SEQUENCE_COMMAND; - usb_out_buffer[1] = (tap_length >> 0) & 0xff; - usb_out_buffer[2] = (tap_length >> 8) & 0xff; + byte_length = (data->tap_length + 7) >> 3; + data->usb_out_buffer[0] = JLINK_TAP_SEQUENCE_COMMAND; + data->usb_out_buffer[1] = (data->tap_length >> 0) & 0xff; + data->usb_out_buffer[2] = (data->tap_length >> 8) & 0xff; tms_offset = 3; for (i = 0; i < byte_length; i++) { - usb_out_buffer[tms_offset + i] = tms_buffer[i]; + data->usb_out_buffer[tms_offset + i] = + data->tms_buffer[i]; } tdi_offset = tms_offset + byte_length; for (i = 0; i < byte_length; i++) { - usb_out_buffer[tdi_offset + i] = tdi_buffer[i]; + data->usb_out_buffer[tdi_offset + i] = + data->tdi_buffer[i]; } result = jlink_usb_message( - cable, + params, 3 + 2 * byte_length, byte_length); if (result == byte_length) { - int bit_index = (tap_length - 1) & 7; + int bit_index = (data->tap_length - 1) & 7; uint8_t bit = 1 << bit_index; - last_tdo = ((usb_in_buffer[byte_length-1]) & bit ) ? 1 : 0; + data->last_tdo = + ((data->usb_in_buffer[byte_length-1]) & bit ) ? 1 : 0; } else { @@ -251,7 +240,7 @@ static int jlink_tap_execute( cable_t *cable ) return -2; } - jlink_tap_init(); + jlink_tap_init( data ); } return 0; } @@ -260,16 +249,16 @@ static int jlink_tap_execute( cable_t *cable ) /* Send a message and receive the reply. */ static int jlink_usb_message( - cable_t *cable, + libusb_param_t *params, int out_length, int in_length) { int result; - result = jlink_usb_write( cable, out_length ); + result = jlink_usb_write( params, out_length ); if (result == out_length) { - result = jlink_usb_read( cable ); + result = jlink_usb_read( params ); if (result == in_length) { return result; @@ -298,11 +287,12 @@ static int jlink_usb_message( /* ---------------------------------------------------------------------- */ /* Write data from out_buffer to USB. */ -static int jlink_usb_write( cable_t *cable, unsigned int out_length ) +static int jlink_usb_write( libusb_param_t *params, unsigned int out_length ) { int result; - struct usb_dev_handle *jlink; - jlink = ((libusb_param_t*)(cable->link.usb->params))->handle; + jlink_usbconn_data_t *data; + + data = params->data; if (out_length > JLINK_OUT_BUFFER_SIZE) { @@ -313,34 +303,33 @@ static int jlink_usb_write( cable_t *cable, unsigned int out_length ) } result = usb_bulk_write( - jlink, + params->handle, JLINK_WRITE_ENDPOINT, - usb_out_buffer, + data->usb_out_buffer, out_length, JLINK_USB_TIMEOUT); DEBUG("jlink_usb_write, out_length = %d, result = %d\n", out_length, result); - jlink_debug_buffer(usb_out_buffer, out_length); + jlink_debug_buffer(data->usb_out_buffer, out_length); return result; } /* ---------------------------------------------------------------------- */ /* Read data from USB into in_buffer. */ -static int jlink_usb_read( cable_t *cable ) +static int jlink_usb_read( libusb_param_t *params ) { - struct usb_dev_handle *jlink; - jlink = ((libusb_param_t*)(cable->link.usb->params))->handle; + jlink_usbconn_data_t *data = params->data; int result = usb_bulk_read( - jlink, + params->handle, JLINK_READ_ENDPOINT, - usb_in_buffer, + data->usb_in_buffer, JLINK_IN_BUFFER_SIZE, JLINK_USB_TIMEOUT); DEBUG("jlink_usb_read, result = %d\n", result); - jlink_debug_buffer(usb_in_buffer, result); + jlink_debug_buffer(data->usb_in_buffer, result); return result; } @@ -374,16 +363,25 @@ static int jlink_init( cable_t *cable ) { int result; - struct usb_dev_handle *jlink; + libusb_param_t *params; + jlink_usbconn_data_t *data; + + params = cable->link.usb->params; + params->data = malloc(sizeof(jlink_usbconn_data_t)); + if(params->data == NULL) + { + return -1; + } + data = params->data; if (usbconn_open( cable->link.usb )) return -1; - jlink = ((libusb_param_t*)(cable->link.usb->params))->handle; + jlink_tap_init( data ); - jlink_tap_init(); + result = jlink_usb_read( params ); - result = jlink_usb_read( cable ); - if (result != 2 || usb_in_buffer[0] != 0x07 || usb_in_buffer[1] != 0x00) + if (result != 2 || data->usb_in_buffer[0] != 0x07 + || data->usb_in_buffer[1] != 0x00) { INFO("J-Link initial read failed, don't worry (result=%d)\n", result); } @@ -391,28 +389,67 @@ jlink_init( cable_t *cable ) INFO("J-Link JTAG Interface ready\n"); jlink_set_frequency( cable, 4E6 ); - jlink_reset( cable, 0, 0); - jlink_tap_init(); - PARAM_TRST(cable) = 1; + jlink_reset( params, 0, 0); return 0; } /* ---------------------------------------------------------------------- */ -int tdo_cache; +static +void jlink_free( cable_t *cable ) +{ + jlink_usbconn_data_t *data; + data = ((libusb_param_t*)(cable->link.usb->params))->data; + free(data); + + generic_usbconn_free( cable ); +} + +/* ---------------------------------------------------------------------- */ + +void jlink_set_frequency( cable_t *cable, uint32_t frequency ) +{ + int result; + int speed = frequency / 1E3; + libusb_param_t *params = cable->link.usb->params; + jlink_usbconn_data_t *data = params->data; + + if (1 <= speed && speed <= JLINK_MAX_SPEED) + { + data->usb_out_buffer[0] = JLINK_SPEED_COMMAND; + data->usb_out_buffer[1] = (speed >> 0) & 0xff; + data->usb_out_buffer[2] = (speed >> 8) & 0xff; + + result = jlink_usb_write( params, 3 ); + + if (result != 3) + { + ERROR("J-Link setting speed failed (%d)\n", result); + } + } + else + { + INFO("Requested speed %dkHz exceeds maximum of %dkHz, ignored\n", + speed, JLINK_MAX_SPEED); + } +} + +/* ---------------------------------------------------------------------- */ static void jlink_clock( cable_t *cable, int tms, int tdi, int n ) { int i; + libusb_param_t *params = cable->link.usb->params; + jlink_usbconn_data_t *data = params->data; for (i = 0; i < n; i++) { - jlink_tap_append_step(tms, tdi); + jlink_tap_append_step( data, tms, tdi); } - jlink_tap_execute( cable ); + jlink_tap_execute( params ); } /* ---------------------------------------------------------------------- */ @@ -420,49 +457,54 @@ jlink_clock( cable_t *cable, int tms, int tdi, int n ) static int jlink_get_tdo( cable_t *cable ) { - // TODO: This is the TDO _before_ last clock occured - // ... Anyone knows how to get the current TDO state? + libusb_param_t *params = cable->link.usb->params; + jlink_usbconn_data_t *data = params->data; + + // TODO: This is the TDO _before_ last clock occured + // ... Anyone knows how to get the current TDO state? - return last_tdo; + return data->last_tdo; } /* ---------------------------------------------------------------------- */ void -jlink_copy_out_data( cable_t *cable, int len, int offset, char *buf ) +jlink_copy_out_data( jlink_usbconn_data_t *data, int len, int offset, char *buf ) { int i; for(i=0;i>3; - buf[offset+i] = (usb_in_buffer[byte] & bit) ? 1 : 0; + buf[offset+i] = (data->usb_in_buffer[byte] & bit) ? 1 : 0; } } int jlink_transfer( cable_t *cable, int len, char *in, char *out ) { - int i,j; + int i,j; + libusb_param_t *params = cable->link.usb->params; + jlink_usbconn_data_t *data = params->data; for(j=0, i=0; i= 8*JLINK_TAP_BUFFER_SIZE) + if(data->tap_length >= 8*JLINK_TAP_BUFFER_SIZE) { - jlink_tap_execute( cable ); - if(out) jlink_copy_out_data( cable, i-j, j, out); + jlink_tap_execute( params ); + if(out) jlink_copy_out_data( data, i-j, j, out); j = i; } }; - if(tap_length > 0) + if(data->tap_length > 0) { - jlink_tap_execute( cable ); - if(out) jlink_copy_out_data( cable, i-j, j, out); + jlink_tap_execute( params ); + if(out) jlink_copy_out_data( data, i-j, j, out); } - return i; + return i; } /* ---------------------------------------------------------------------- */ @@ -478,7 +520,7 @@ cable_driver_t jlink_cable_driver = { N_("Segger/IAR J-Link, Atmel SAM-ICE and others."), generic_usbconn_connect, generic_disconnect, - generic_usbconn_free, + jlink_free, jlink_init, generic_usbconn_done, jlink_set_frequency,