X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fjtag%2Fjlink.c;h=c81e9a0291a9a61d7ce4d0aba639d906181b97a1;hb=68c598e88d5e09728ea845a81ab279c615bbaf0f;hp=23125c3465ed39c81de12ec583450ada299fbd70;hpb=209112000bba84cfc024b35a0f851482f448c957;p=openocd.git diff --git a/src/jtag/jlink.c b/src/jtag/jlink.c index 23125c3465..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,10 @@ 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); #ifdef _DEBUG_USB_COMMS_ void jlink_debug_buffer(u8 *buffer, int length); @@ -168,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) { @@ -179,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; @@ -191,7 +194,7 @@ int jlink_execute_queue(void) if (cmd->cmd.scan->end_state != -1) { - jlink_end_state(cmd->cmd.scan->end_state); + jlink_end_state(cmd->cmd.scan->end_state); } scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer); @@ -205,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(); @@ -224,15 +225,14 @@ int jlink_execute_queue(void) jtag_sleep(cmd->cmd.sleep->us); break; - default: - LOG_ERROR("BUG: unknown JTAG command type encountered"); - exit(-1); + default: + LOG_ERROR("BUG: unknown JTAG command type encountered"); + exit(-1); } cmd = cmd->next; } - jlink_tap_execute(); - return ERROR_OK; + return jlink_tap_execute(); } /* Sets speed in kHz. */ @@ -240,7 +240,6 @@ int jlink_speed(int speed) { int result; -// if ((speed == -1) || ((1 <= speed) && (speed <= JLINK_MAX_SPEED))) if (speed <= JLINK_MAX_SPEED) { /* check for RTCK setting */ @@ -287,58 +286,39 @@ int jlink_register_commands(struct command_context_s *cmd_ctx) int jlink_init(void) { - int result; - int len; - int check_cnt; + int check_cnt; jlink_jtag_handle = jlink_usb_open(); 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; } - check_cnt = 0; - while (check_cnt < 3) - { - /* query hardware version */ - jlink_simple_command(EMU_CMD_VERSION); - result = jlink_usb_read(jlink_jtag_handle); - - if (result == 2) - { - /* Get length */ - len = buf_get_u32(usb_in_buffer, 0, 16); - - /* Get version */ - result = jlink_usb_read(jlink_jtag_handle); + check_cnt = 0; + while (check_cnt < 3) + { + if (jlink_get_version_info() == ERROR_OK) + { + /* attempt to get status */ + jlink_get_status(); + break; + } - if(result == len) - { - usb_in_buffer[result] = 0; - LOG_INFO(usb_in_buffer); - - /* attempt to get status */ - jlink_get_status(); - - break; - } - } - - check_cnt++; - } - - if (check_cnt == 3) - { - LOG_INFO("J-Link initial read failed, don't worry"); - } + check_cnt++; + } + + if (check_cnt == 3) + { + LOG_INFO("J-Link initial read failed, don't worry"); + } LOG_INFO("J-Link JTAG Interface ready"); jlink_reset(0, 0); jlink_tap_init(); - + return ERROR_OK; } @@ -466,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); } } @@ -507,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 @@ -528,7 +508,7 @@ int jlink_get_status(void) return ERROR_OK; } -int jlink_handle_jlink_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +int jlink_get_version_info(void) { int result; int len = 0; @@ -542,18 +522,24 @@ int jlink_handle_jlink_info_command(struct command_context_s *cmd_ctx, char *cmd 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); + return ERROR_OK; } - - /* attempt to get status */ - jlink_get_status(); } - else + + LOG_ERROR("J-Link command EMU_CMD_VERSION failed (%d)\n", result); + return ERROR_JTAG_DEVICE_ERROR; +} + +int jlink_handle_jlink_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + if (jlink_get_version_info() == ERROR_OK) { - LOG_ERROR("J-Link command EMU_CMD_VERSION failed (%d)\n", result); + /* attempt to get status */ + jlink_get_status(); } return ERROR_OK; @@ -562,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]; @@ -578,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; @@ -657,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; @@ -677,23 +663,24 @@ 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]; + usb_out_buffer[tms_offset + i] = 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]; + 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) { @@ -719,17 +706,17 @@ int jlink_tap_execute() jlink_debug_buffer(buffer, byte_length); #endif - if (jtag_read_buffer(buffer, command) != ERROR_OK) - { - jlink_tap_init(); + if (jtag_read_buffer(buffer, command) != ERROR_OK) + { + jlink_tap_init(); return ERROR_JTAG_QUEUE_FAILED; - } + } - if (pending_scan_result->buffer != NULL) - { + if (pending_scan_result->buffer != NULL) + { free(pending_scan_result->buffer); - } - } + } + } } else { @@ -775,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; } } @@ -795,25 +789,61 @@ 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 - { + 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; + return -1; } } @@ -850,7 +880,21 @@ int jlink_usb_read(jlink_jtag_t *jlink_jtag) #ifdef _DEBUG_USB_COMMS_ jlink_debug_buffer(usb_in_buffer, result); #endif - return result; + 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_