X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fjtag%2Fdrivers%2Fjlink.c;h=728a05b87b4590c4df6beda9a633b46c73a86ccd;hb=0c7db47e58e5fe267219735630cd004b504e8535;hp=08df63bca7d7db3cf9dfebd31af096bd007c793b;hpb=b79f9ad1726778bdad2f89b9297a4acc6adb5b77;p=openocd.git diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c index 08df63bca7..728a05b87b 100644 --- a/src/jtag/drivers/jlink.c +++ b/src/jtag/drivers/jlink.c @@ -21,7 +21,7 @@ * 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. * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -64,33 +64,54 @@ static unsigned int jlink_hw_jtag_version = 2; /*#define JLINK_TAP_BUFFER_SIZE 256*/ /*#define JLINK_TAP_BUFFER_SIZE 384*/ -#define JLINK_IN_BUFFER_SIZE 2048 +#define JLINK_IN_BUFFER_SIZE (2048 + 1) #define JLINK_OUT_BUFFER_SIZE (2*2048 + 4) -#define JLINK_EMU_RESULT_BUFFER_SIZE 64 /* Global USB buffers */ static uint8_t usb_in_buffer[JLINK_IN_BUFFER_SIZE]; static uint8_t usb_out_buffer[JLINK_OUT_BUFFER_SIZE]; -static uint8_t usb_emu_result_buffer[JLINK_EMU_RESULT_BUFFER_SIZE]; /* Constants for JLink command */ #define EMU_CMD_VERSION 0x01 +#define EMU_CMD_RESET_TRST 0x02 +#define EMU_CMD_RESET_TARGET 0x03 #define EMU_CMD_SET_SPEED 0x05 #define EMU_CMD_GET_STATE 0x07 +#define EMU_CMD_SET_KS_POWER 0x08 +#define EMU_CMD_GET_SPEEDS 0xc0 +#define EMU_CMD_GET_HW_INFO 0xc1 +#define EMU_CMD_GET_COUNTERS 0xc2 +#define EMU_CMD_SELECT_IF 0xc7 #define EMU_CMD_HW_CLOCK 0xc8 #define EMU_CMD_HW_TMS0 0xc9 #define EMU_CMD_HW_TMS1 0xca +#define EMU_CMD_HW_DATA0 0xcb +#define EMU_CMD_HW_DATA1 0xcc +#define EMU_CMD_HW_JTAG 0xcd #define EMU_CMD_HW_JTAG2 0xce #define EMU_CMD_HW_JTAG3 0xcf +#define EMU_CMD_HW_RELEASE_RESET_STOP_EX 0xd0 +#define EMU_CMD_HW_RELEASE_RESET_STOP_TIMED 0xd1 #define EMU_CMD_GET_MAX_MEM_BLOCK 0xd4 +#define EMU_CMD_HW_JTAG_WRITE 0xd5 +#define EMU_CMD_HW_JTAG_GET_RESULT 0xd6 #define EMU_CMD_HW_RESET0 0xdc #define EMU_CMD_HW_RESET1 0xdd #define EMU_CMD_HW_TRST0 0xde #define EMU_CMD_HW_TRST1 0xdf #define EMU_CMD_GET_CAPS 0xe8 +#define EMU_CMD_GET_CPU_CAPS 0xe9 +#define EMU_CMD_EXEC_CPU_CMD 0xea +#define EMU_CMD_GET_CAPS_EX 0xed #define EMU_CMD_GET_HW_VERSION 0xf0 +#define EMU_CMD_WRITE_DCC 0xf1 #define EMU_CMD_READ_CONFIG 0xf2 #define EMU_CMD_WRITE_CONFIG 0xf3 +#define EMU_CMD_WRITE_MEM 0xf4 +#define EMU_CMD_READ_MEM 0xf5 +#define EMU_CMD_MEASURE_RTCK_REACT 0xf6 +#define EMU_CMD_WRITE_MEM_ARM79 0xf7 +#define EMU_CMD_READ_MEM_ARM79 0xf8 /* bits return from EMU_CMD_GET_CAPS */ #define EMU_CAP_RESERVED_1 0 @@ -205,9 +226,9 @@ struct jlink { static struct jlink *jlink_usb_open(void); static void jlink_usb_close(struct jlink *jlink); static int jlink_usb_message(struct jlink *jlink, int out_length, int in_length); +static int jlink_usb_io(struct jlink *jlink, int out_length, int in_length); static int jlink_usb_write(struct jlink *jlink, int out_length); static int jlink_usb_read(struct jlink *jlink, int expected_size); -static int jlink_usb_read_emu_result(struct jlink *jlink); /* helper functions */ static int jlink_get_version_info(void); @@ -399,6 +420,67 @@ static int jlink_khz(int khz, int *jtag_speed) return ERROR_OK; } +/* + * select transport interface + * + * @param iface [0..31] currently: 0=JTAG, 1=SWD + * @returns ERROR_OK or ERROR_ code + * + * @pre jlink_handle must be opened + * @pre function may be called only for devices, that have + * EMU_CAP_SELECT_IF capability enabled + */ +static int jlink_select_interface(int iface) +{ + /* According to Segger's document RM08001-R7 Date: October 8, 2010, + * http://www.segger.com/admin/uploads/productDocs/RM08001_JLinkUSBProtocol.pdf + * section 5.5.3 EMU_CMD_SELECT_IF + * > SubCmd 1..31 to select interface (0..31) + * + * The table below states: + * 0 TIF_JTAG + * 1 TIF_SWD + * + * This obviosly means that to select TIF_JTAG one should write SubCmd = 1. + * + * In fact, JTAG interface operates when SubCmd=0 + * + * It looks like a typo in documentation, because interfaces 0..31 could not + * be selected by 1..31 range command. + */ + assert(iface >= 0 && iface < 32); + int result; + + /* get available interfaces */ + usb_out_buffer[0] = EMU_CMD_SELECT_IF; + usb_out_buffer[1] = 0xff; + + result = jlink_usb_io(jlink_handle, 2, 4); + if (result != ERROR_OK) { + LOG_ERROR("J-Link query interface failed (%d)", result); + return ERROR_JTAG_DEVICE_ERROR; + } + + uint32_t iface_mask = buf_get_u32(usb_in_buffer, 0, 32); + + if (!(iface_mask & (1<kickstart_power_on_jtag_pin_19); } @@ -701,22 +794,15 @@ static int jlink_get_config(struct jlink_config *cfg) int result; int size = sizeof(struct jlink_config); - jlink_simple_command(EMU_CMD_READ_CONFIG); + usb_out_buffer[0] = EMU_CMD_READ_CONFIG; + result = jlink_usb_io(jlink_handle, 1, size); - result = jlink_usb_read(jlink_handle, size); - if (size != result) { + if (result != ERROR_OK) { LOG_ERROR("jlink_usb_read failed (requested=%d, result=%d)", size, result); return ERROR_FAIL; } memcpy(cfg, usb_in_buffer, size); - - /* - * Section 4.2.4 IN-transaction - * read dummy 0-byte packet - */ - jlink_usb_read(jlink_handle, 1); - return ERROR_OK; } @@ -755,8 +841,6 @@ static int jlink_set_config(struct jlink_config *cfg) static const char * const unsupported_versions[] = { "Jan 31 2011", "JAN 31 2011", - "Mar 19 2012", /* V4.44 */ - "May 3 2012", /* V4.46 "J-Link ARM V8 compiled May 3 2012 18:36:22" */ NULL /* End of list */ }; @@ -836,7 +920,7 @@ static int jlink_get_version_info(void) LOG_INFO("J-Link hw version %i", (int)jlink_hw_version); if (jlink_hw_type >= JLINK_HW_TYPE_MAX) - LOG_INFO("J-Link hw type uknown 0x%x", jlink_hw_type); + LOG_INFO("J-Link hw type uknown 0x%" PRIx32, jlink_hw_type); else LOG_INFO("J-Link hw type %s", jlink_hw_type_str[jlink_hw_type]); } @@ -1211,6 +1295,7 @@ static const struct command_registration jlink_command_handlers[] = { struct jtag_interface jlink_interface = { .name = "jlink", .commands = jlink_command_handlers, + .transports = jtag_only, .execute_queue = jlink_execute_queue, .speed = jlink_speed, @@ -1260,11 +1345,7 @@ static void jlink_tap_append_step(int tms, int tdi) { int index_var = tap_length / 8; - if (index_var >= JLINK_TAP_BUFFER_SIZE) { - LOG_ERROR("jlink_tap_append_step: overflow"); - *(uint32_t *)0xFFFFFFFF = 0; - exit(-1); - } + assert(index_var < JLINK_TAP_BUFFER_SIZE); int bit_index = tap_length % 8; uint8_t bit = 1 << bit_index; @@ -1337,10 +1418,17 @@ static int jlink_tap_execute(void) jlink_last_state = jtag_debug_state_machine(tms_buffer, tdi_buffer, tap_length, jlink_last_state); - result = jlink_usb_message(jlink_handle, 4 + 2 * byte_length, byte_length); - if (result != byte_length) { - LOG_ERROR("jlink_tap_execute, wrong result %d (expected %d)", - result, byte_length); + result = jlink_usb_message(jlink_handle, 4 + 2 * byte_length, + use_jtag3 ? byte_length + 1 : byte_length); + if (result != ERROR_OK) { + LOG_ERROR("jlink_tap_execute failed USB io (%d)", result); + jlink_tap_init(); + return ERROR_JTAG_QUEUE_FAILED; + } + + result = use_jtag3 ? usb_in_buffer[byte_length] : 0; + if (result != 0) { + LOG_ERROR("jlink_tap_execute failed, result %d", result); jlink_tap_init(); return ERROR_JTAG_QUEUE_FAILED; } @@ -1455,44 +1543,12 @@ static int jlink_usb_message(struct jlink *jlink, int out_length, int in_length) } result = jlink_usb_read(jlink, in_length); - if ((result != in_length) && (result != (in_length + 1))) { + if (result != in_length) { LOG_ERROR("usb_bulk_read failed (requested=%d, result=%d)", in_length, result); return ERROR_JTAG_DEVICE_ERROR; } - - if (jlink_hw_jtag_version < 3) - return result; - - int result2 = ERROR_OK; - if (result == in_length) { - /* Must read the result from the EMU too */ - result2 = jlink_usb_read_emu_result(jlink); - if (1 != result2) { - LOG_ERROR("jlink_usb_read_emu_result retried requested = 1, " - "result=%d, in_length=%i", result2, in_length); - /* Try again once, should only happen if (in_length%64 == 0) */ - result2 = jlink_usb_read_emu_result(jlink); - if (1 != result2) { - LOG_ERROR("jlink_usb_read_emu_result failed " - "(requested = 1, result=%d)", result2); - return ERROR_JTAG_DEVICE_ERROR; - } - } - - /* Check the result itself */ - result2 = usb_emu_result_buffer[0]; - } else { - /* Save the result, then remove it from return value */ - result2 = usb_in_buffer[result--]; - } - - if (result2) { - LOG_ERROR("jlink_usb_message failed with result=%d)", result2); - return ERROR_JTAG_DEVICE_ERROR; - } - - return result; + return ERROR_OK; } /* calls the given usb_bulk_* function, allowing for the data to @@ -1568,17 +1624,46 @@ static int jlink_usb_read(struct jlink *jlink, int expected_size) return result; } -/* Read the result from the previous EMU cmd into result_buffer. */ -static int jlink_usb_read_emu_result(struct jlink *jlink) +/* + * Send a message and receive the reply - simple messages. + * + * @param jlink pointer to driver data + * @param out_length data length in @c usb_out_buffer + * @param in_length data length to be read to @c usb_in_buffer + */ +static int jlink_usb_io(struct jlink *jlink, int out_length, int in_length) { - int result = usb_bulk_read_ex(jlink->usb_handle, jlink_read_ep, - (char *)usb_emu_result_buffer, 1 /* JLINK_EMU_RESULT_BUFFER_SIZE */, - JLINK_USB_TIMEOUT); + int result; + + result = jlink_usb_write(jlink, out_length); + if (result != out_length) { + LOG_ERROR("usb_bulk_write failed (requested=%d, result=%d)", + out_length, result); + return ERROR_JTAG_DEVICE_ERROR; + } - DEBUG_JTAG_IO("jlink_usb_read_result, result = %d", result); + result = jlink_usb_read(jlink, in_length); + if (result != in_length) { + LOG_ERROR("usb_bulk_read failed (requested=%d, result=%d)", + in_length, result); + return ERROR_JTAG_DEVICE_ERROR; + } - jlink_debug_buffer(usb_emu_result_buffer, result); - return result; + /* + * Section 4.2.4 IN-transaction: + * read dummy 0-byte packet if transaction size is + * multiple of 64 bytes but not max. size of 0x8000 + */ + if ((in_length % 64) == 0 && in_length != 0x8000) { + char dummy_buffer; + result = usb_bulk_read_ex(jlink->usb_handle, jlink_read_ep, + &dummy_buffer, 1, JLINK_USB_TIMEOUT); + if (result != 0) { + LOG_ERROR("dummy byte read failed"); + return ERROR_JTAG_DEVICE_ERROR; + } + } + return ERROR_OK; } #ifdef _DEBUG_USB_COMMS_