- added jlink support, based on Jürgen Stuber patch

git-svn-id: svn://svn.berlios.de/openocd/trunk@658 b42882b7-edfa-0310-969c-e2dbd0fdcd60
This commit is contained in:
ntfreak 2008-05-14 14:13:38 +00:00
parent f1e72cf029
commit 548bb19aa2
8 changed files with 887 additions and 3 deletions

View File

@ -99,6 +99,10 @@ AC_ARG_ENABLE(oocd_trace,
AS_HELP_STRING([--enable-oocd_trace], [Enable building support for the OpenOCD+trace ETM capture device]), AS_HELP_STRING([--enable-oocd_trace], [Enable building support for the OpenOCD+trace ETM capture device]),
[build_oocd_trace=$enableval], [build_oocd_trace=no]) [build_oocd_trace=$enableval], [build_oocd_trace=no])
AC_ARG_ENABLE(jlink,
AS_HELP_STRING([--enable-jlink], [Enable building support for the Segger J-Link JTAG Programmer]),
[build_jlink=$enableval], [build_jlink=no])
AC_ARG_WITH(ftd2xx, AC_ARG_WITH(ftd2xx,
[AS_HELP_STRING(--with-ftd2xx, [AS_HELP_STRING(--with-ftd2xx,
[Where libftd2xx can be found <default=search>])], [Where libftd2xx can be found <default=search>])],
@ -251,6 +255,12 @@ else
AC_DEFINE(BUILD_OOCD_TRACE, 0, [0 if you don't want the OpenOCD+trace ETM capture driver.]) AC_DEFINE(BUILD_OOCD_TRACE, 0, [0 if you don't want the OpenOCD+trace ETM capture driver.])
fi fi
if test $build_jlink = yes; then
AC_DEFINE(BUILD_JLINK, 1, [1 if you want the J-Link JTAG driver.])
else
AC_DEFINE(BUILD_JLINK, 0, [0 if you don't want the J-Link JTAG driver.])
fi
AM_CONFIG_HEADER(config.h) AM_CONFIG_HEADER(config.h)
AM_INIT_AUTOMAKE(openocd, 1.0) AM_INIT_AUTOMAKE(openocd, 1.0)
@ -269,6 +279,7 @@ AM_CONDITIONAL(PRESTO_LIBFTDI, test $build_presto_libftdi = yes)
AM_CONDITIONAL(PRESTO_FTD2XX, test $build_presto_ftd2xx = yes) AM_CONDITIONAL(PRESTO_FTD2XX, test $build_presto_ftd2xx = yes)
AM_CONDITIONAL(USBPROG, test $build_usbprog = yes) AM_CONDITIONAL(USBPROG, test $build_usbprog = yes)
AM_CONDITIONAL(OOCD_TRACE, test $build_oocd_trace = yes) AM_CONDITIONAL(OOCD_TRACE, test $build_oocd_trace = yes)
AM_CONDITIONAL(JLINK, test $build_jlink = yes)
AM_CONDITIONAL(IS_CYGWIN, test $is_cygwin = yes) AM_CONDITIONAL(IS_CYGWIN, test $is_cygwin = yes)
AM_CONDITIONAL(IS_MINGW, test $is_mingw = yes) AM_CONDITIONAL(IS_MINGW, test $is_mingw = yes)
AM_CONDITIONAL(IS_WIN32, test $is_win32 = yes) AM_CONDITIONAL(IS_WIN32, test $is_win32 = yes)

View File

@ -176,6 +176,8 @@ build properly.}
@option{--enable-presto_libftdi} @option{--enable-presto_libftdi}
@item @item
@option{--enable-presto_ftd2xx} @option{--enable-presto_ftd2xx}
@item
@option{--enable-jlink}
@end itemize @end itemize
If you want to access the parallel port using the PPDEV interface you have to specify If you want to access the parallel port using the PPDEV interface you have to specify
@ -259,7 +261,7 @@ Set to <@var{enable}> to cause OpenOCD to send the memory configuration to gdb w
requested. gdb will then know when to set hardware breakpoints, and program flash requested. gdb will then know when to set hardware breakpoints, and program flash
using the gdb load command. @option{gdb_flash_program enable} will also need enabling using the gdb load command. @option{gdb_flash_program enable} will also need enabling
for flash programming to work. for flash programming to work.
Default behaviour is <@var{disable}> Default behaviour is <@var{enable}>
@item @b{gdb_flash_program} <@var{enable|disable}> @item @b{gdb_flash_program} <@var{enable|disable}>
@cindex gdb_flash_program @cindex gdb_flash_program
Set to <@var{enable}> to cause OpenOCD to program the flash memory when a Set to <@var{enable}> to cause OpenOCD to program the flash memory when a
@ -312,6 +314,10 @@ usbprog is a freely programmable USB adapter.
@item @b{gw16012} @item @b{gw16012}
Gateworks GW16012 JTAG programmer. Gateworks GW16012 JTAG programmer.
@end itemize @end itemize
@itemize @minus
@item @b{jlink}
Segger jlink usb adapter
@end itemize
@end itemize @end itemize
@itemize @bullet @itemize @bullet
@ -326,6 +332,7 @@ is optional, in which case the reset speed is used.
@item wiggler: maximum speed / @var{number} @item wiggler: maximum speed / @var{number}
@item ft2232: 6MHz / (@var{number}+1) @item ft2232: 6MHz / (@var{number}+1)
@item amt jtagaccel: 8 / 2**@var{number} @item amt jtagaccel: 8 / 2**@var{number}
@item jlink: maximum speed in kHz (0-12000), 0 will use RTCK
@end itemize @end itemize
Note: Make sure the jtag clock is no more than @math{1/6th × CPU-Clock}. This is Note: Make sure the jtag clock is no more than @math{1/6th × CPU-Clock}. This is

View File

@ -44,8 +44,12 @@ endif
if USBPROG if USBPROG
LIBUSB = -lusb LIBUSB = -lusb
else else
if JLINK
LIBUSB = -lusb
else
LIBUSB = LIBUSB =
endif endif
endif
if IS_WIN32 if IS_WIN32
if FTD2XXDIR if FTD2XXDIR

View File

@ -93,7 +93,13 @@ else
USBPROGFILES = USBPROGFILES =
endif endif
if JLINK
JLINKFILES = jlink.c
else
JLINKFILES =
endif
libjtag_a_SOURCES = jtag.c $(BITBANGFILES) $(PARPORTFILES) $(DUMMYFILES) $(FT2232FILES) $(AMTJTAGACCELFILES) $(EP93XXFILES) \ libjtag_a_SOURCES = jtag.c $(BITBANGFILES) $(PARPORTFILES) $(DUMMYFILES) $(FT2232FILES) $(AMTJTAGACCELFILES) $(EP93XXFILES) \
$(AT91RM9200FILES) $(GW16012FILES) $(BITQFILES) $(PRESTOFILES) $(USBPROGFILES) $(ECOSBOARDFILES) $(AT91RM9200FILES) $(GW16012FILES) $(BITQFILES) $(PRESTOFILES) $(USBPROGFILES) $(ECOSBOARDFILES) $(JLINKFILES)
noinst_HEADERS = bitbang.h jtag.h noinst_HEADERS = bitbang.h jtag.h

846
src/jtag/jlink.c Normal file
View File

@ -0,0 +1,846 @@
/***************************************************************************
* Copyright (C) 2007 by Juergen Stuber <juergen@jstuber.net> *
* based on Dominic Rath's and Benedikt Sauter's usbprog.c *
* *
* 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 *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "replacements.h"
#include "jtag.h"
#include <usb.h>
#include <string.h>
#include "log.h"
/* enable this to debug communication
*/
#if 0
#define _DEBUG_USB_COMMS_
#endif
#ifdef _DEBUG_JTAG_IO_
#define DEBUG_JTAG_IO(expr ...) LOG_DEBUG(expr)
#else
#define DEBUG_JTAG_IO(expr ...)
#endif
#define VID 0x1366
#define PID 0x0101
#define JLINK_WRITE_ENDPOINT 0x02
#define JLINK_READ_ENDPOINT 0x81
#define JLINK_USB_TIMEOUT 100
#define JLINK_IN_BUFFER_SIZE 2064
#define JLINK_OUT_BUFFER_SIZE 2064
/* Global USB buffers */
static u8 usb_in_buffer[JLINK_IN_BUFFER_SIZE];
static u8 usb_out_buffer[JLINK_OUT_BUFFER_SIZE];
/* Constants for JLink command */
#define JLINK_FIRMWARE_VERSION 0x01
#define JLINK_SPEED_COMMAND 0x05
#define JLINK_GET_STATUS_COMMAND 0x07
#define JLINK_TAP_SEQUENCE_COMMAND 0xcd
#define JLINK_GET_SERIAL 0xe6
#define JLINK_SET_SRST_LOW_COMMAND 0xdc
#define JLINK_SET_SRST_HIGH_COMMAND 0xdd
#define JLINK_SET_TRST_LOW_COMMAND 0xde
#define JLINK_SET_TRST_HIGH_COMMAND 0xdf
#define JLINK_HARDWARE_VERSION 0xe8
/* max speed 12MHz v5.0 jlink */
#define JLINK_MAX_SPEED 12000
/* External interface functions */
int jlink_execute_queue(void);
int jlink_speed(int speed);
int jlink_khz(int khz, int *jtag_speed);
int jlink_register_commands(struct command_context_s *cmd_ctx);
int jlink_init(void);
int jlink_quit(void);
/* CLI command handler functions */
int jlink_handle_jlink_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
/* Queue command functions */
void jlink_end_state(enum tap_state state);
void jlink_state_move(void);
void jlink_path_move(int num_states, enum tap_state *path);
void jlink_runtest(int num_cycles);
void jlink_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size, scan_command_t *command);
void jlink_reset(int trst, int srst);
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_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);
/* Jlink lowlevel functions */
typedef struct jlink_jtag
{
struct usb_dev_handle* usb_handle;
} jlink_jtag_t;
jlink_jtag_t *jlink_usb_open(void);
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);
#ifdef _DEBUG_USB_COMMS_
void jlink_debug_buffer(u8 *buffer, int length);
#endif
jlink_jtag_t* jlink_jtag_handle;
/***************************************************************************/
/* External interface implementation */
jtag_interface_t jlink_interface =
{
.name = "jlink",
.execute_queue = jlink_execute_queue,
.speed = jlink_speed,
.khz = jlink_khz,
.register_commands = jlink_register_commands,
.init = jlink_init,
.quit = jlink_quit
};
int jlink_execute_queue(void)
{
jtag_command_t *cmd = jtag_command_queue;
int scan_size;
enum scan_type type;
u8 *buffer;
while (cmd != NULL)
{
switch (cmd->type)
{
case JTAG_END_STATE:
DEBUG_JTAG_IO("end_state: %i", cmd->cmd.end_state->end_state);
if (cmd->cmd.end_state->end_state != -1)
{
jlink_end_state(cmd->cmd.end_state->end_state);
}
break;
case JTAG_RUNTEST:
DEBUG_JTAG_IO( "runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, \
cmd->cmd.runtest->end_state);
if (cmd->cmd.runtest->end_state != -1)
{
jlink_end_state(cmd->cmd.runtest->end_state);
}
jlink_runtest(cmd->cmd.runtest->num_cycles);
break;
case JTAG_STATEMOVE:
DEBUG_JTAG_IO("statemove end in %i",
cmd->cmd.statemove->end_state);
if (cmd->cmd.statemove->end_state != -1)
{
jlink_end_state(cmd->cmd.statemove->end_state);
}
jlink_state_move();
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]);
jlink_path_move(cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path);
break;
case JTAG_SCAN:
DEBUG_JTAG_IO("scan end in %i", cmd->cmd.scan->end_state);
if (cmd->cmd.scan->end_state != -1)
{
jlink_end_state(cmd->cmd.scan->end_state);
}
scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
DEBUG_JTAG_IO("scan input, length = %d", scan_size);
#ifdef _DEBUG_USB_COMMS_
jlink_debug_buffer(buffer, (scan_size + 7) / 8);
#endif
type = jtag_scan_type(cmd->cmd.scan);
jlink_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size, cmd->cmd.scan);
break;
case JTAG_RESET:
DEBUG_JTAG_IO("reset trst: %i srst %i",
cmd->cmd.reset->trst,
cmd->cmd.reset->srst);
jlink_tap_execute();
if (cmd->cmd.reset->trst == 1)
{
cur_state = TAP_TLR;
}
jlink_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
break;
case JTAG_SLEEP:
DEBUG_JTAG_IO("sleep %i", cmd->cmd.sleep->us);
jlink_tap_execute();
jtag_sleep(cmd->cmd.sleep->us);
break;
default:
LOG_ERROR("BUG: unknown JTAG command type encountered");
exit(-1);
}
cmd = cmd->next;
}
jlink_tap_execute();
return ERROR_OK;
}
/* Sets speed in kHz. */
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 */
if (speed == 0)
speed = -1;
usb_out_buffer[0] = JLINK_SPEED_COMMAND;
usb_out_buffer[1] = (speed >> 0) & 0xff;
usb_out_buffer[2] = (speed >> 8) & 0xff;
result = jlink_usb_write(jlink_jtag_handle, 3);
if (result == 3)
{
return ERROR_OK;
}
else
{
LOG_ERROR("J-Link setting speed failed (%d)", result);
return ERROR_JTAG_DEVICE_ERROR;
}
}
else
{
LOG_INFO("Requested speed %dkHz exceeds maximum of %dkHz, ignored", speed, JLINK_MAX_SPEED);
}
return ERROR_OK;
}
int jlink_khz(int khz, int *jtag_speed)
{
*jtag_speed = khz;
return ERROR_OK;
}
int jlink_register_commands(struct command_context_s *cmd_ctx)
{
register_command(cmd_ctx, NULL, "jlink_info", jlink_handle_jlink_info_command, COMMAND_EXEC,
"query jlink info");
return ERROR_OK;
}
int jlink_init(void)
{
int result;
jlink_jtag_handle = jlink_usb_open();
if (jlink_jtag_handle == 0)
{
LOG_ERROR("Can't find USB JTAG Interface! Please check connection and permissions.");
return ERROR_JTAG_INIT_FAILED;
}
result = jlink_usb_read(jlink_jtag_handle);
if (result != 2 || usb_in_buffer[0] != 0x07 || usb_in_buffer[1] != 0x00)
{
LOG_INFO("J-Link initial read failed, don't worry");
}
LOG_INFO("J-Link JTAG Interface ready");
jlink_reset(0, 0);
jlink_tap_init();
/* query jlink status */
jlink_get_status();
return ERROR_OK;
}
int jlink_quit(void)
{
jlink_usb_close(jlink_jtag_handle);
return ERROR_OK;
}
/***************************************************************************/
/* Queue command implementations */
void jlink_end_state(enum tap_state state)
{
if (tap_move_map[state] != -1)
{
end_state = state;
}
else
{
LOG_ERROR("BUG: %i is not a valid end state", state);
exit(-1);
}
}
/* Goes to the end state. */
void jlink_state_move(void)
{
int i;
int tms = 0;
u8 tms_scan = TAP_MOVE(cur_state, end_state);
for (i = 0; i < 7; i++)
{
tms = (tms_scan >> i) & 1;
jlink_tap_append_step(tms, 0);
}
cur_state = end_state;
}
void jlink_path_move(int num_states, enum tap_state *path)
{
int i;
for (i = 0; i < num_states; i++)
{
if (path[i] == tap_transitions[cur_state].low)
{
jlink_tap_append_step(0, 0);
}
else if (path[i] == tap_transitions[cur_state].high)
{
jlink_tap_append_step(1, 0);
}
else
{
LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_strings[cur_state], tap_state_strings[path[i]]);
exit(-1);
}
cur_state = path[i];
}
end_state = cur_state;
}
void jlink_runtest(int num_cycles)
{
int i;
enum tap_state saved_end_state = end_state;
/* only do a state_move when we're not already in RTI */
if (cur_state != TAP_RTI)
{
jlink_end_state(TAP_RTI);
jlink_state_move();
}
/* execute num_cycles */
for (i = 0; i < num_cycles; i++)
{
jlink_tap_append_step(0, 0);
}
/* finish in end_state */
jlink_end_state(saved_end_state);
if (cur_state != end_state)
{
jlink_state_move();
}
}
void jlink_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size, scan_command_t *command)
{
enum tap_state saved_end_state;
jlink_tap_ensure_space(1, scan_size + 8);
saved_end_state = end_state;
/* Move to appropriate scan state */
jlink_end_state(ir_scan ? TAP_SI : TAP_SD);
jlink_state_move();
jlink_end_state(saved_end_state);
/* Scan */
jlink_tap_append_scan(scan_size, buffer, command);
/* We are in Exit1, go to Pause */
jlink_tap_append_step(0, 0);
cur_state = ir_scan ? TAP_PI : TAP_PD;
if (cur_state != end_state)
{
jlink_state_move();
}
}
void jlink_reset(int trst, int srst)
{
LOG_DEBUG("trst: %i, srst: %i", trst, srst);
/* Signals are active low */
if (trst == 0)
{
jlink_simple_command(JLINK_SET_TRST_HIGH_COMMAND);
}
else if (trst == 1)
{
jlink_simple_command(JLINK_SET_TRST_LOW_COMMAND);
}
if (srst == 0)
{
jlink_simple_command(JLINK_SET_SRST_HIGH_COMMAND);
}
else if (srst == 1)
{
jlink_simple_command(JLINK_SET_SRST_LOW_COMMAND);
}
}
void jlink_simple_command(u8 command)
{
int result;
DEBUG_JTAG_IO("0x%02x", command);
usb_out_buffer[0] = command;
result = jlink_usb_write(jlink_jtag_handle, 1);
if (result != 1)
{
LOG_ERROR("J-Link command 0x%02x failed (%d)", command, result);
}
}
int jlink_get_status(void)
{
int result;
jlink_simple_command(JLINK_GET_STATUS_COMMAND);
result = jlink_usb_read(jlink_jtag_handle);
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", \
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)
{
LOG_ERROR("Vref too low. Eventually the target isn't powered or disconnected?\n");
}
}
else
{
LOG_ERROR("J-Link command JLINK_GET_STATUS_COMMAND failed (%d)\n", result);
}
return ERROR_OK;
}
int jlink_handle_jlink_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
int result;
int len = 0;
/* query hardware version */
jlink_simple_command(JLINK_FIRMWARE_VERSION);
result = jlink_usb_read(jlink_jtag_handle);
if (result == 2)
{
len = buf_get_u32(usb_in_buffer, 0, 16);
result = jlink_usb_read(jlink_jtag_handle);
if(result == len)
{
usb_in_buffer[result] = 0;
LOG_INFO(usb_in_buffer);
}
/* attempt to get status */
jlink_get_status();
}
else
{
LOG_ERROR("J-Link command JLINK_FIRMWARE_VERSION failed (%d)\n", result);
}
return ERROR_OK;
}
/***************************************************************************/
/* J-Link tap functions */
/* We use the maximal value observed */
#define JLINK_TAP_BUFFER_SIZE 390
static int tap_length;
static u8 tms_buffer[JLINK_TAP_BUFFER_SIZE];
static u8 tdi_buffer[JLINK_TAP_BUFFER_SIZE];
static u8 tdo_buffer[JLINK_TAP_BUFFER_SIZE];
typedef struct
{
int first; /* First bit position in tdo_buffer to read */
int length; /* Number of bits to read */
scan_command_t *command; /* Corresponding scan command */
u8 *buffer;
} pending_scan_result_t;
#define MAX_PENDING_SCAN_RESULTS 16
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()
{
tap_length = 0;
pending_scan_results_length = 0;
}
void jlink_tap_ensure_space(int scans, int bits)
{
int available_scans = MAX_PENDING_SCAN_RESULTS - pending_scan_results_length;
int available_bits = JLINK_TAP_BUFFER_SIZE * 8 - tap_length;
if (scans > available_scans || bits > available_bits)
{
jlink_tap_execute();
}
}
void jlink_tap_append_step(int tms, int tdi)
{
last_tms = tms;
int index = tap_length / 8;
if (index < JLINK_TAP_BUFFER_SIZE)
{
int bit_index = tap_length % 8;
u8 bit = 1 << bit_index;
if (tms)
{
tms_buffer[index] |= bit;
}
else
{
tms_buffer[index] &= ~bit;
}
if (tdi)
{
tdi_buffer[index] |= bit;
}
else
{
tdi_buffer[index] &= ~bit;
}
tap_length++;
}
else
{
LOG_ERROR("jlink_tap_append_step, overflow");
}
}
void jlink_tap_append_scan(int length, u8 *buffer, scan_command_t *command)
{
pending_scan_result_t *pending_scan_result = &pending_scan_results_buffer[pending_scan_results_length];
int i;
pending_scan_result->first = tap_length;
pending_scan_result->length = length;
pending_scan_result->command = command;
pending_scan_result->buffer = buffer;
for (i = 0; i < length; i++)
{
jlink_tap_append_step((i < length-1 ? 0 : 1), (buffer[i/8] >> (i%8)) & 1);
}
pending_scan_results_length++;
}
/* 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 byte_length;
int tms_offset;
int tdi_offset;
int i;
int result;
if (tap_length > 0)
{
/* Pad last byte so that tap_length is divisible by 8 */
while (tap_length % 8 != 0)
{
/* More of the last TMS value keeps us in the same state,
* analogous to free-running JTAG interfaces. */
jlink_tap_append_step(last_tms, 0);
}
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;
tms_offset = 3;
for (i = 0; i < byte_length; 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];
}
result = jlink_usb_message(jlink_jtag_handle, 3 + 2 * byte_length, byte_length);
if (result == byte_length)
{
for (i = 0; i < byte_length; i++)
{
tdo_buffer[i] = usb_in_buffer[i];
}
for (i = 0; i < pending_scan_results_length; i++)
{
pending_scan_result_t *pending_scan_result = &pending_scan_results_buffer[i];
u8 *buffer = pending_scan_result->buffer;
int length = pending_scan_result->length;
int first = pending_scan_result->first;
scan_command_t *command = pending_scan_result->command;
/* Copy to buffer */
buf_set_buf(tdo_buffer, first, buffer, 0, length);
DEBUG_JTAG_IO("pending scan result, length = %d", length);
#ifdef _DEBUG_USB_COMMS_
jlink_debug_buffer(buffer, byte_length);
#endif
if (jtag_read_buffer(buffer, command) != ERROR_OK)
{
jlink_tap_init();
return ERROR_JTAG_QUEUE_FAILED;
}
if (pending_scan_result->buffer != NULL)
{
free(pending_scan_result->buffer);
}
}
}
else
{
LOG_ERROR("jlink_tap_execute, wrong result %d, expected %d", result, byte_length);
return ERROR_JTAG_QUEUE_FAILED;
}
jlink_tap_init();
}
return ERROR_OK;
}
/*****************************************************************************/
/* JLink USB low-level functions */
jlink_jtag_t* jlink_usb_open()
{
struct usb_bus *busses;
struct usb_bus *bus;
struct usb_device *dev;
jlink_jtag_t *result;
result = (jlink_jtag_t*) malloc(sizeof(jlink_jtag_t));
usb_init();
usb_find_busses();
usb_find_devices();
busses = usb_get_busses();
/* find jlink_jtag device in usb bus */
for (bus = busses; bus; bus = bus->next)
{
for (dev = bus->devices; dev; dev = dev->next)
{
if ((dev->descriptor.idVendor == VID) && (dev->descriptor.idProduct == PID))
{
result->usb_handle = usb_open(dev);
/* usb_set_configuration required under win32 */
usb_set_configuration(result->usb_handle, dev->config[0].bConfigurationValue);
usb_claim_interface(result->usb_handle, 0);
usb_set_altinterface(result->usb_handle, 0);
return result;
}
}
}
free(result);
return NULL;
}
void jlink_usb_close(jlink_jtag_t *jlink_jtag)
{
usb_close(jlink_jtag->usb_handle);
free(jlink_jtag);
}
/* Send a message and receive the reply. */
int jlink_usb_message(jlink_jtag_t *jlink_jtag, int out_length, int in_length)
{
int result;
result = jlink_usb_write(jlink_jtag, out_length);
if (result == out_length)
{
result = jlink_usb_read(jlink_jtag);
if (result == in_length)
{
return result;
}
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;
}
}
/* Write data from out_buffer to USB. */
int jlink_usb_write(jlink_jtag_t *jlink_jtag, int out_length)
{
int result;
if (out_length > JLINK_OUT_BUFFER_SIZE)
{
LOG_ERROR("jlink_jtag_write illegal out_length=%d (max=%d)", out_length, JLINK_OUT_BUFFER_SIZE);
return -1;
}
result = usb_bulk_write(jlink_jtag->usb_handle, JLINK_WRITE_ENDPOINT, \
usb_out_buffer, out_length, JLINK_USB_TIMEOUT);
DEBUG_JTAG_IO("jlink_usb_write, out_length = %d, result = %d", out_length, result);
#ifdef _DEBUG_USB_COMMS_
jlink_debug_buffer(usb_out_buffer, out_length);
#endif
return result;
}
/* Read data from USB into in_buffer. */
int jlink_usb_read(jlink_jtag_t *jlink_jtag)
{
int result = usb_bulk_read(jlink_jtag->usb_handle, JLINK_READ_ENDPOINT, \
usb_in_buffer, JLINK_IN_BUFFER_SIZE, JLINK_USB_TIMEOUT);
DEBUG_JTAG_IO("jlink_usb_read, result = %d", result);
#ifdef _DEBUG_USB_COMMS_
jlink_debug_buffer(usb_in_buffer, result);
#endif
return result;
}
#ifdef _DEBUG_USB_COMMS_
#define BYTES_PER_LINE 16
void jlink_debug_buffer(u8 *buffer, int length)
{
char line[81];
char s[4];
int i;
int j;
for (i = 0; i < length; i += BYTES_PER_LINE)
{
snprintf(line, 5, "%04x", i);
for (j = i; j < i + BYTES_PER_LINE && j < length; j++)
{
snprintf(s, 4, " %02x", buffer[j]);
strcat(line, s);
}
LOG_DEBUG(line);
}
}
#endif

View File

@ -193,6 +193,10 @@ static int hasKHz = 0;
extern jtag_interface_t usbprog_interface; extern jtag_interface_t usbprog_interface;
#endif #endif
#if BUILD_JLINK == 1
extern jtag_interface_t jlink_interface;
#endif
jtag_interface_t *jtag_interfaces[] = { jtag_interface_t *jtag_interfaces[] = {
#if BUILD_ECOSBOARD == 1 #if BUILD_ECOSBOARD == 1
&eCosBoard_interface, &eCosBoard_interface,
@ -226,6 +230,9 @@ jtag_interface_t *jtag_interfaces[] = {
#endif #endif
#if BUILD_USBPROG == 1 #if BUILD_USBPROG == 1
&usbprog_interface, &usbprog_interface,
#endif
#if BUILD_JLINK == 1
&jlink_interface,
#endif #endif
NULL, NULL,
}; };

View File

@ -32,5 +32,5 @@ nobase_dist_pkglib_DATA = xscale/debug_handler.bin event/at91eb40a_reset.script
target/lm3s811.cfg interface/luminary.cfg interface/luminary-lm3s811.cfg interface/stm32-stick.cfg \ target/lm3s811.cfg interface/luminary.cfg interface/luminary-lm3s811.cfg interface/stm32-stick.cfg \
interface/calao-usb-a9260-c01.cfg interface/calao-usb-a9260-c02.cfg \ interface/calao-usb-a9260-c01.cfg interface/calao-usb-a9260-c02.cfg \
interface/calao-usb-a9260.cfg target/at91sam9260minimal.cfg event/lpc2148_reset.script \ interface/calao-usb-a9260.cfg target/at91sam9260minimal.cfg event/lpc2148_reset.script \
interface/chameleon.cfg interface/at91rm9200.cfg interface/chameleon.cfg interface/at91rm9200.cfg interface/jlink.cfg

View File

@ -0,0 +1,3 @@
# jlink interface
interface jlink