⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jlink.c

📁 UrJTAG package is free software, covered by the GNU General Public License, and you are welcome to
💻 C
字号:
/* * $Id: jlink.c,v 1.8 2003/08/19 08:42:20 telka Exp $ * * Segger J-Link cable driver * * Large portions of code were taken from the OpenOCD driver written by * Juergen Stuber, which in turn was based on Dominic Rath's and Benedikt * Sauter's usbprog.c. Therefore most of this code is actually * * Copyright (C) 2007 Juergen Stuber * * Modified to work in UrJTAG by K. Waschk in 2008. * * 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. * */#include "generic.h"#include "generic_usbconn.h"#include "usbconn.h"#include "usbconn/libusb.h"/* ---------------------------------------------------------------------- */#include "sysdep.h"#include "cable.h"#include "chain.h"#include "jtag.h"#include <usb.h>#include <string.h>#define INFO(...)   printf(__VA_ARGS__)#define ERROR(...)  printf(__VA_ARGS__)#define DEBUG(...)#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/* We use the maximal value observed */#define JLINK_TAP_BUFFER_SIZE 390typedef 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_DO_TRST_CYCLE                0x02#define JLINK_SPEED_COMMAND                0x05#define JLINK_GET_STATUS_COMMAND           0x07#define JLINK_GET_A                        0xc1#define JLINK_GET_B                        0xc2#define JLINK_SET_TMS_LOW_COMMAND          0xc9#define JLINK_SET_TMS_HIGH_COMMAND         0xca#define JLINK_SET_TDI_LOW_COMMAND          0xcb#define JLINK_SET_TDI_HIGH_COMMAND         0xcc#define JLINK_TAP_SEQUENCE_COMMAND         0xcd#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_MAX_SPEED 12000/* Queue command functions */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( 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( 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 );static void jlink_debug_buffer(char *buffer, int length);/* API functions */void jlink_set_frequency( cable_t *cable, uint32_t frequency );/***************************************************************************//* J-Link tap functions */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( params, JLINK_SET_TRST_HIGH_COMMAND);    }    else if (trst == 1)    {        jlink_simple_command( params, JLINK_SET_TRST_LOW_COMMAND);    }    if (srst == 0)    {        jlink_simple_command( params, JLINK_SET_SRST_HIGH_COMMAND);    }    else if (srst == 1)    {        jlink_simple_command( params, JLINK_SET_SRST_LOW_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);    data->usb_out_buffer[0] = command;    result = jlink_usb_write( params, 1 );    if (result != 1)    {        ERROR("J-Link command 0x%02x failed (%d)\n", command, result);    }}static int jlink_get_status( libusb_param_t *params ){    int result;    jlink_usbconn_data_t *data = params->data;		jlink_simple_command( params, 0x07 );    result = jlink_usb_read( params );	if(result == 8)	{		int vref = data->usb_in_buffer[0] + (data->usb_in_buffer[1]<<8);		INFO("Vref = %d.%d TCK=%d TDI=%d TDO=%d TMS=%d TRES=%d TRST=%d\n",			vref / 1000, vref % 1000,			data->usb_in_buffer[2],			data->usb_in_buffer[3],			data->usb_in_buffer[4],			data->usb_in_buffer[5],			data->usb_in_buffer[6],			data->usb_in_buffer[7]);		if(vref < 1500) 		{			ERROR("Vref too low. Eventually the target isn't powered or disconnected?\n");			result = -15;		};	}	else    {        ERROR("J-Link command 0x07 (get status) failed (%d)\n", result);    }	return result;}	/***************************************************************************/static void jlink_tap_init( jlink_usbconn_data_t *data ){    data->tap_length = 0;}static void jlink_tap_append_step( jlink_usbconn_data_t *data, int tms, int tdi){    int index = data->tap_length >> 3;    if (index < JLINK_TAP_BUFFER_SIZE)    {        int bit_index = data->tap_length & 7;        uint8_t bit = 1 << bit_index;        if(bit_index == 0)        {            data->tms_buffer[index] = 0;            data->tdi_buffer[index] = 0;        };        if(tms) data->tms_buffer[index] |= bit;        if(tdi) data->tdi_buffer[index] |= bit;        data->tap_length++;    }    else    {        ERROR("jlink_tap_append_step, overflow\n");    }}/* 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 (data->tap_length > 0)    {        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++)        {            data->usb_out_buffer[tms_offset + i] =                  data->tms_buffer[i];        }        tdi_offset = tms_offset + byte_length;        for (i = 0; i < byte_length; i++)        {            data->usb_out_buffer[tdi_offset + i] =                data->tdi_buffer[i];        }        result = jlink_usb_message(            params,             3 + 2 * byte_length,            byte_length);        if (result == byte_length)        {            int bit_index = (data->tap_length - 1) & 7;            uint8_t bit = 1 << bit_index;            data->last_tdo =                 ((data->usb_in_buffer[byte_length-1]) & bit ) ? 1 : 0;        }        else        {            ERROR(                "jlink_tap_execute, wrong result %d, expected %d\n",                result,                byte_length);            return -2;        }        jlink_tap_init( data );    }    return 0;}/* ---------------------------------------------------------------------- *//* Send a message and receive the reply. */static int jlink_usb_message(    libusb_param_t *params,    int out_length,    int in_length){    int result;    result = jlink_usb_write( params, out_length );    if (result == out_length)    {        result = jlink_usb_read( params );        if (result == in_length)        {            return result;        }        else        {            ERROR(                "usb_bulk_read failed (requested=%d, result=%d)\n",                in_length,                result);            return -1;        }    }    else    {        ERROR(            "usb_bulk_write failed (requested=%d, result=%d)\n",            out_length,            result);        return -1;    }}/* ---------------------------------------------------------------------- *//* Write data from out_buffer to USB. */static int jlink_usb_write( libusb_param_t *params, unsigned int out_length ){    int result;    jlink_usbconn_data_t *data;    data = params->data;    if (out_length > JLINK_OUT_BUFFER_SIZE)    {        ERROR("jlink_jtag_write illegal out_length=%d (max=%d)\n", out_length,         JLINK_OUT_BUFFER_SIZE);        return -1;    }    result = usb_bulk_write(        params->handle,         JLINK_WRITE_ENDPOINT,        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(data->usb_out_buffer, out_length);    return result;}/* ---------------------------------------------------------------------- *//* Read data from USB into in_buffer. */static int jlink_usb_read( libusb_param_t *params ){    jlink_usbconn_data_t *data = params->data;    int result = usb_bulk_read(        params->handle,        JLINK_READ_ENDPOINT,        data->usb_in_buffer,         JLINK_IN_BUFFER_SIZE,         JLINK_USB_TIMEOUT);    DEBUG("jlink_usb_read, result = %d\n", result);    jlink_debug_buffer(data->usb_in_buffer, result);    return result;}/* ---------------------------------------------------------------------- */#define BYTES_PER_LINE  16static void jlink_debug_buffer(char *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);        }        DEBUG(line);        DEBUG("\n");    }}/* ---------------------------------------------------------------------- */static int jlink_init( cable_t *cable ){    int result;    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_tap_init( data );    result = jlink_usb_read( params );    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);    }	result = jlink_get_status( params );	if (result < 0)	{		ERROR("Resetting J-Link. Please retry the cable command.\n");		usb_reset ( params->handle ); 		return -1;	}    INFO("J-Link JTAG Interface ready\n");    jlink_set_frequency( cable, 4E6 );    jlink_reset( params, 0, 0);    return 0;}/* ---------------------------------------------------------------------- */staticvoid 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;		/* speed = 0xFFFF for automatic (probably needs RTCK) */        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 voidjlink_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( data, tms, tdi);    }    jlink_tap_execute( params );}/* ---------------------------------------------------------------------- */static intjlink_get_tdo( cable_t *cable ){    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 data->last_tdo;}/* ---------------------------------------------------------------------- */voidjlink_copy_out_data( jlink_usbconn_data_t *data, int len, int offset, char *buf ){    int i;    for(i=0;i<len;i++)    {        int bit = (1<<(i&7));        int byte = i>>3;        buf[offset+i] = (data->usb_in_buffer[byte] & bit) ? 1 : 0;    }}intjlink_transfer( cable_t *cable, int len, char *in, char *out ){    int i,j;    libusb_param_t *params = cable->link.usb->params;    jlink_usbconn_data_t *data = params->data;    for(j=0, i=0; i<len; i++)    {        jlink_tap_append_step(data, 0, in[i]);        if(data->tap_length >= 8*JLINK_TAP_BUFFER_SIZE)        {            jlink_tap_execute( params );            if(out) jlink_copy_out_data( data, i-j, j, out);            j = i;        }    };    if(data->tap_length > 0)    {        jlink_tap_execute( params );        if(out) jlink_copy_out_data( data, i-j, j, out);    }        return i;}/* ---------------------------------------------------------------------- */static intjlink_set_trst( cable_t *cable, int trst ){    return 1;}cable_driver_t jlink_cable_driver = {    "jlink",    N_("Segger/IAR J-Link, Atmel SAM-ICE and others."),    generic_usbconn_connect,    generic_disconnect,    jlink_free,    jlink_init,    generic_usbconn_done,    jlink_set_frequency,    jlink_clock,    jlink_get_tdo,    jlink_transfer,    jlink_set_trst,    generic_get_trst,    generic_flush_using_transfer,    generic_usbconn_help};usbconn_cable_t usbconn_cable_jlink = {    "jlink",            /* cable name */    NULL,                /* string pattern, not used */    "libusb",            /* usbconn driver */     0x1366,                /* VID */    0x0101                /* PID */};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -