X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fjtag%2Fjlink.c;h=c81e9a0291a9a61d7ce4d0aba639d906181b97a1;hb=68c598e88d5e09728ea845a81ab279c615bbaf0f;hp=16dac2a01b7f4f908bafb394963c27b7e8d194b3;hpb=f1e317e53441ce01cf559d553dccab0624d50329;p=openocd.git diff --git a/src/jtag/jlink.c b/src/jtag/jlink.c index 16dac2a01b..c81e9a0291 100644 --- a/src/jtag/jlink.c +++ b/src/jtag/jlink.c @@ -2,6 +2,9 @@ * 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 * @@ -51,23 +54,20 @@ #define JLINK_USB_TIMEOUT 100 -#define JLINK_IN_BUFFER_SIZE 2064 -#define JLINK_OUT_BUFFER_SIZE 2064 +#define JLINK_IN_BUFFER_SIZE 8192 +#define JLINK_OUT_BUFFER_SIZE 8192 +#define JLINK_EMU_RESULT_BUFFER_SIZE 64 /* Global USB buffers */ static u8 usb_in_buffer[JLINK_IN_BUFFER_SIZE]; static u8 usb_out_buffer[JLINK_OUT_BUFFER_SIZE]; +static u8 usb_emu_result_buffer[JLINK_EMU_RESULT_BUFFER_SIZE]; /* Constants for JLink command */ - -/* The JLINK_TAP_SEQUENCE_COMMAND is obsolete - * and we should use EMU_CMD_HW_JTAG instead */ -#define JLINK_TAP_SEQUENCE_COMMAND 0xcd - #define EMU_CMD_VERSION 0x01 #define EMU_CMD_SET_SPEED 0x05 #define EMU_CMD_GET_STATE 0x07 -#define EMU_CMD_HW_JTAG 0xcf +#define EMU_CMD_HW_JTAG3 0xcf #define EMU_CMD_HW_RESET0 0xdc #define EMU_CMD_HW_RESET1 0xdd #define EMU_CMD_HW_TRST0 0xde @@ -98,8 +98,8 @@ void jlink_simple_command(u8 command); int jlink_get_status(void); /* J-Link tap buffer functions */ -void jlink_tap_init(); -int jlink_tap_execute(); +void jlink_tap_init(void); +int jlink_tap_execute(void); void jlink_tap_ensure_space(int scans, int bits); void jlink_tap_append_step(int tms, int tdi); void jlink_tap_append_scan(int length, u8 *buffer, scan_command_t *command); @@ -115,6 +115,7 @@ void jlink_usb_close(jlink_jtag_t *jlink_jtag); int jlink_usb_message(jlink_jtag_t *jlink_jtag, int out_length, int in_length); int jlink_usb_write(jlink_jtag_t *jlink_jtag, int out_length); int jlink_usb_read(jlink_jtag_t *jlink_jtag); +int jlink_usb_read_emu_result(jlink_jtag_t *jlink_jtag); /* helper functions */ int jlink_get_version_info(void); @@ -171,8 +172,7 @@ int jlink_execute_queue(void) break; case JTAG_STATEMOVE: - DEBUG_JTAG_IO("statemove end in %i", - cmd->cmd.statemove->end_state); + DEBUG_JTAG_IO("statemove end in %i", cmd->cmd.statemove->end_state); if (cmd->cmd.statemove->end_state != -1) { @@ -182,9 +182,9 @@ int jlink_execute_queue(void) 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]); + DEBUG_JTAG_IO("pathmove: %i states, end in %i", \ + cmd->cmd.pathmove->num_states, \ + cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); jlink_path_move(cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path); break; @@ -208,9 +208,7 @@ int jlink_execute_queue(void) break; case JTAG_RESET: - DEBUG_JTAG_IO("reset trst: %i srst %i", - cmd->cmd.reset->trst, - cmd->cmd.reset->srst); + DEBUG_JTAG_IO("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); jlink_tap_execute(); @@ -294,7 +292,7 @@ int jlink_init(void) if (jlink_jtag_handle == 0) { - LOG_ERROR("Can't find USB JTAG Interface! Please check connection and permissions."); + LOG_ERROR("Cannot find jlink Interface! Please check connection and permissions."); return ERROR_JTAG_INIT_FAILED; } @@ -448,22 +446,22 @@ void jlink_reset(int trst, int srst) LOG_DEBUG("trst: %i, srst: %i", trst, srst); /* Signals are active low */ - if (trst == 0) + if (srst == 0) { - jlink_simple_command(EMU_CMD_HW_TRST1); + jlink_simple_command(EMU_CMD_HW_RESET1); } - else if (trst == 1) + else if (srst == 1) { - jlink_simple_command(EMU_CMD_HW_TRST0); + jlink_simple_command(EMU_CMD_HW_RESET0); } - if (srst == 0) + if (trst == 0) { - jlink_simple_command(EMU_CMD_HW_RESET1); + jlink_simple_command(EMU_CMD_HW_TRST1); } - else if (srst == 1) + else if (trst == 1) { - jlink_simple_command(EMU_CMD_HW_RESET0); + jlink_simple_command(EMU_CMD_HW_TRST0); } } @@ -489,17 +487,17 @@ int jlink_get_status(void) jlink_simple_command(EMU_CMD_GET_STATE); result = jlink_usb_read(jlink_jtag_handle); - if(result == 8) + 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", \ + 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) + if (vref < 1500) { - LOG_ERROR("Vref too low. Eventually the target isn't powered or disconnected?\n"); + LOG_ERROR("Vref too low. Check Target Power\n"); } } else @@ -524,7 +522,7 @@ int jlink_get_version_info(void) len = buf_get_u32(usb_in_buffer, 0, 16); result = jlink_usb_read(jlink_jtag_handle); - if(result == len) + if (result == len) { usb_in_buffer[result] = 0; LOG_INFO(usb_in_buffer); @@ -550,8 +548,8 @@ int jlink_handle_jlink_info_command(struct command_context_s *cmd_ctx, char *cmd /***************************************************************************/ /* J-Link tap functions */ -/* We use the maximal value observed */ -#define JLINK_TAP_BUFFER_SIZE 390 +/* 2048 is the max value we can use here */ +#define JLINK_TAP_BUFFER_SIZE 2048 static int tap_length; static u8 tms_buffer[JLINK_TAP_BUFFER_SIZE]; @@ -566,14 +564,14 @@ typedef struct u8 *buffer; } pending_scan_result_t; -#define MAX_PENDING_SCAN_RESULTS 16 +#define MAX_PENDING_SCAN_RESULTS 256 static int pending_scan_results_length; static pending_scan_result_t pending_scan_results_buffer[MAX_PENDING_SCAN_RESULTS]; static int last_tms; -void jlink_tap_init() +void jlink_tap_init(void) { tap_length = 0; pending_scan_results_length = 0; @@ -645,7 +643,7 @@ void jlink_tap_append_scan(int length, u8 *buffer, scan_command_t *command) /* 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 jlink_tap_execute() +int jlink_tap_execute(void) { int byte_length; int tms_offset; @@ -665,11 +663,12 @@ int jlink_tap_execute() byte_length = tap_length / 8; - usb_out_buffer[0] = JLINK_TAP_SEQUENCE_COMMAND; - usb_out_buffer[1] = (tap_length >> 0) & 0xff; - usb_out_buffer[2] = (tap_length >> 8) & 0xff; + usb_out_buffer[0] = EMU_CMD_HW_JTAG3; + usb_out_buffer[1] = 0; + usb_out_buffer[2] = (tap_length >> 0) & 0xff; + usb_out_buffer[3] = (tap_length >> 8) & 0xff; - tms_offset = 3; + tms_offset = 4; for (i = 0; i < byte_length; i++) { usb_out_buffer[tms_offset + i] = tms_buffer[i]; @@ -681,7 +680,7 @@ int jlink_tap_execute() usb_out_buffer[tdi_offset + i] = tdi_buffer[i]; } - result = jlink_usb_message(jlink_jtag_handle, 3 + 2 * byte_length, byte_length); + result = jlink_usb_message(jlink_jtag_handle, 4 + 2 * byte_length, byte_length); if (result == byte_length) { @@ -763,7 +762,14 @@ jlink_jtag_t* jlink_usb_open() /* 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; } } @@ -783,14 +789,50 @@ void jlink_usb_close(jlink_jtag_t *jlink_jtag) int jlink_usb_message(jlink_jtag_t *jlink_jtag, int out_length, int in_length) { int result; + int result2; result = jlink_usb_write(jlink_jtag, out_length); if (result == out_length) { result = jlink_usb_read(jlink_jtag); - if (result == in_length) + if (result == in_length || result == in_length+1) { - return result; + if (result == in_length) + { + /* Must read the result from the EMU too */ + result2 = jlink_usb_read_emu_result(jlink_jtag); + if (1 == result2) + { + /* Check the result itself */ + if (0 == usb_emu_result_buffer[0]) + { + return result; + } + else + { + LOG_ERROR("jlink_usb_read_emu_result (requested=0, result=%d)", usb_emu_result_buffer[0]); + return -1; + } + } + else + { + LOG_ERROR("jlink_usb_read_emu_result len (requested=1, result=%d)", result2); + return -1; + } + } + else + { + /* Check the result itself */ + if (0 == usb_in_buffer[result-1]) + { + return result-1; + } + else + { + LOG_ERROR("jlink_usb_read_emu_result (requested=0, result=%d)", usb_in_buffer[result]); + return -1; + } + } } else { @@ -841,6 +883,20 @@ int jlink_usb_read(jlink_jtag_t *jlink_jtag) return result; } +/* Read the result from the previous EMU cmd into result_buffer. */ +int jlink_usb_read_emu_result(jlink_jtag_t *jlink_jtag) +{ + int result = usb_bulk_read(jlink_jtag->usb_handle, JLINK_READ_ENDPOINT, \ + usb_emu_result_buffer, JLINK_EMU_RESULT_BUFFER_SIZE, JLINK_USB_TIMEOUT); + + DEBUG_JTAG_IO("jlink_usb_read_result, result = %d", result); + +#ifdef _DEBUG_USB_COMMS_ + jlink_debug_buffer(usb_emu_result_buffer, result); +#endif + return result; +} + #ifdef _DEBUG_USB_COMMS_ #define BYTES_PER_LINE 16