Skip to content
Snippets Groups Projects
Commit 76b35638 authored by Ryan Corbin's avatar Ryan Corbin Committed by Spencer Oliver
Browse files

Added OpenJTAG Driver


Updated OpenJTAG driver from www.openjtag.org to work with latest version of OpenOCD.

Change-Id: I2917f4e5835fb9ca5265e81dc38515fa97ae9503
Signed-off-by: default avatarRyan Corbin <corbin.ryan@gmail.com>
Reviewed-on: http://openocd.zylin.com/1406


Tested-by: jenkins
Reviewed-by: default avatarSpencer Oliver <spen@spen-soft.co.uk>
parent cf8a3c3d
Branches
No related tags found
No related merge requests found
...@@ -446,6 +446,14 @@ AC_ARG_ENABLE([usbprog], ...@@ -446,6 +446,14 @@ AC_ARG_ENABLE([usbprog],
AS_HELP_STRING([--enable-usbprog], [Enable building support for the usbprog JTAG Programmer]), AS_HELP_STRING([--enable-usbprog], [Enable building support for the usbprog JTAG Programmer]),
[build_usbprog=$enableval], [build_usbprog=no]) [build_usbprog=$enableval], [build_usbprog=no])
AC_ARG_ENABLE([openjtag_ftd2xx],
AS_HELP_STRING([--enable-openjtag_ftd2xx], [Enable building support for the OpenJTAG Programmer with ftd2xx driver]),
[build_openjtag_ftd2xx=$enableval], [build_openjtag_ftd2xx=no])
AC_ARG_ENABLE([openjtag_ftdi],
AS_HELP_STRING([--enable-openjtag_ftdi], [Enable building support for the OpenJTAG Programmer with ftdi driver]),
[build_openjtag_ftdi=$enableval], [build_openjtag_ftdi=no])
AC_ARG_ENABLE([oocd_trace], AC_ARG_ENABLE([oocd_trace],
AS_HELP_STRING([--enable-oocd_trace], AS_HELP_STRING([--enable-oocd_trace],
[Enable building support for some prototype OpenOCD+trace ETM capture hardware]), [Enable building support for some prototype OpenOCD+trace ETM capture hardware]),
...@@ -754,6 +762,19 @@ else ...@@ -754,6 +762,19 @@ else
AC_DEFINE([BUILD_USBPROG], [0], [0 if you don't want the usbprog JTAG driver.]) AC_DEFINE([BUILD_USBPROG], [0], [0 if you don't want the usbprog JTAG driver.])
fi fi
AC_DEFINE([BUILD_OPENJTAG], [0], [0 if you don't want the OpenJTAG driver.])
AC_DEFINE([BUILD_OPENJTAG_FTD2XX], [0], [0 if you don't want the OpenJTAG driver with FTD2XX driver.])
AC_DEFINE([BUILD_OPENJTAG_LIBFTDI], [0], [0 if you don't want to build OpenJTAG driver with libftdi.])
if test $build_openjtag_ftd2xx = yes; then
AC_DEFINE([BUILD_OPENJTAG], [1], [1 if you want the OpenJTAG driver.])
AC_DEFINE([BUILD_OPENJTAG_FTD2XX], [1], [1 if you want the OpenJTAG driver with FTD2XX driver.])
fi
if test $build_openjtag_ftdi = yes; then
AC_DEFINE([BUILD_OPENJTAG], [1], [1 if you want the OpenJTAG drvier.])
AC_DEFINE([BUILD_OPENJTAG_LIBFTDI], [1], [1 if you want to build OpenJTAG with FTDI driver.])
fi
if test $build_oocd_trace = yes; then if test $build_oocd_trace = yes; then
AC_DEFINE([BUILD_OOCD_TRACE], [1], [1 if you want the OpenOCD+trace ETM capture driver.]) AC_DEFINE([BUILD_OOCD_TRACE], [1], [1 if you want the OpenOCD+trace ETM capture driver.])
else else
...@@ -849,7 +870,7 @@ then ...@@ -849,7 +870,7 @@ then
AC_MSG_ERROR([The option: with_ftd2xx_linux_tardir is for LINUX only.]) AC_MSG_ERROR([The option: with_ftd2xx_linux_tardir is for LINUX only.])
fi fi
if test $build_ft2232_ftd2xx = yes -o $build_presto_ftd2xx = yes -o $build_usb_blaster_ftd2xx = yes ; then if test $build_ft2232_ftd2xx = yes -o $build_presto_ftd2xx = yes -o $build_usb_blaster_ftd2xx = yes -o $build_openjtag_ftd2xx = yes; then
AC_MSG_CHECKING([for ftd2xx.lib exists (win32)]) AC_MSG_CHECKING([for ftd2xx.lib exists (win32)])
# if we are given a zipdir... # if we are given a zipdir...
...@@ -919,7 +940,7 @@ then ...@@ -919,7 +940,7 @@ then
AC_MSG_ERROR([The option: --with-ftd2xx-win32-zipdir is for win32 only]) AC_MSG_ERROR([The option: --with-ftd2xx-win32-zipdir is for win32 only])
fi fi
if test $build_ft2232_ftd2xx = yes -o $build_presto_ftd2xx = yes -o $build_usb_blaster_ftd2xx = yes ; then if test $build_ft2232_ftd2xx = yes -o $build_presto_ftd2xx = yes -o $build_usb_blaster_ftd2xx = yes -o $build_openjtag_ftd2xx = yes; then
# Must be linux # Must be linux
if test $host_os != linux-gnu && test $host_os != linux ; then if test $host_os != linux-gnu && test $host_os != linux ; then
AC_MSG_ERROR([The (linux) ftd2xx library from FTDICHIP.com is linux only. Try --enable-ft2232-libftdi instead]) AC_MSG_ERROR([The (linux) ftd2xx library from FTDICHIP.com is linux only. Try --enable-ft2232-libftdi instead])
...@@ -1066,7 +1087,8 @@ LDFLAGS=$LDFLAGS_SAVE ...@@ -1066,7 +1087,8 @@ LDFLAGS=$LDFLAGS_SAVE
CFLAGS=$CFLAGS_SAVE CFLAGS=$CFLAGS_SAVE
fi fi
if test $build_ft2232_libftdi = yes -o $build_usb_blaster_libftdi = yes; then if test $build_ft2232_libftdi = yes -o $build_usb_blaster_libftdi = yes -o \
$build_openjtag_ftdi = yes; then
# We assume: the package is preinstalled in the proper place # We assume: the package is preinstalled in the proper place
# these present as 2 libraries.. # these present as 2 libraries..
LIBS="$LIBS -lftdi -lusb" LIBS="$LIBS -lftdi -lusb"
...@@ -1198,6 +1220,7 @@ AM_CONDITIONAL([GW16012], [test $build_gw16012 = yes]) ...@@ -1198,6 +1220,7 @@ AM_CONDITIONAL([GW16012], [test $build_gw16012 = yes])
AM_CONDITIONAL([PRESTO_LIBFTDI], [test $build_presto_libftdi = yes]) AM_CONDITIONAL([PRESTO_LIBFTDI], [test $build_presto_libftdi = yes])
AM_CONDITIONAL([PRESTO_DRIVER], [test $build_presto_ftd2xx = yes -o $build_presto_libftdi = yes]) AM_CONDITIONAL([PRESTO_DRIVER], [test $build_presto_ftd2xx = yes -o $build_presto_libftdi = yes])
AM_CONDITIONAL([USBPROG], [test $build_usbprog = yes]) AM_CONDITIONAL([USBPROG], [test $build_usbprog = yes])
AM_CONDITIONAL([OPENJTAG], [test $build_openjtag_ftd2xx = yes -o $build_openjtag_ftdi = 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([JLINK], [test $build_jlink = yes])
AM_CONDITIONAL([AICE], [test $build_aice = yes]) AM_CONDITIONAL([AICE], [test $build_aice = yes])
......
...@@ -115,6 +115,10 @@ if SYSFSGPIO ...@@ -115,6 +115,10 @@ if SYSFSGPIO
DRIVERFILES += sysfsgpio.c DRIVERFILES += sysfsgpio.c
endif endif
if OPENJTAG
DRIVERFILES += openjtag.c
endif
noinst_HEADERS = \ noinst_HEADERS = \
bitbang.h \ bitbang.h \
bitq.h \ bitq.h \
......
/*******************************************************************************
* Driver for OpenJTAG Project (www.openjtag.org) *
* Compatible with libftdi and ftd2xx drivers. *
* *
* Copyright (C) 2010 by Ivan Meleca <mileca@gmail.com> *
* *
* Copyright (C) 2013 by Ryan Corbin, GlueLogix Inc. <corbin.ryan@gmail.com> *
* Updated to work with OpenOCD v0.7.0. Fixed libftdi read speed issue. *
* *
* Based on usb_blaster.c *
* Copyright (C) 2009 Catalin Patulea *
* Copyright (C) 2006 Kolja Waschk *
* *
* And jlink.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 *
* (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., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
***************************************************************************/
/***************************************************************************
* Version 1.0 Tested on a MCBSTM32 board using a Cortex M3 (stm32f103x), *
* GDB and Eclipse under Linux (Ubuntu 10.04) *
* *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <jtag/interface.h>
#include <jtag/commands.h>
#include "usb_common.h"
/*
* OpenJTAG-OpenOCD state conversion
*/
typedef enum openjtag_tap_state {
OPENJTAG_TAP_INVALID = -1,
OPENJTAG_TAP_RESET = 0,
OPENJTAG_TAP_IDLE = 1,
OPENJTAG_TAP_SELECT_DR = 2,
OPENJTAG_TAP_CAPTURE_DR = 3,
OPENJTAG_TAP_SHIFT_DR = 4,
OPENJTAG_TAP_EXIT1_DR = 5,
OPENJTAG_TAP_PAUSE_DR = 6,
OPENJTAG_TAP_EXIT2_DR = 7,
OPENJTAG_TAP_UPDATE_DR = 8,
OPENJTAG_TAP_SELECT_IR = 9,
OPENJTAG_TAP_CAPURE_IR = 10,
OPENJTAG_TAP_SHIFT_IR = 11,
OPENJTAG_TAP_EXIT1_IR = 12,
OPENJTAG_TAP_PAUSE_IR = 13,
OPENJTAG_TAP_EXIT2_IR = 14,
OPENJTAG_TAP_UPDATE_IR = 15,
} openjtag_tap_state_t;
#if (BUILD_OPENJTAG_FTD2XX == 1 && BUILD_OPENJTAG_LIBFTDI == 1)
#error "BUILD_OPENJTAG_FTD2XX && BUILD_OPENJTAG_LIBFTDI "
"are mutually exclusive"
#elif (BUILD_OPENJTAG_FTD2XX != 1 && BUILD_OPENJTAG_LIBFTDI != 1)
#error "BUILD_OPENJTAG_FTD2XX || BUILD_OPENJTAG_LIBFTDI must be chosen"
#endif
/* OPENJTAG access library includes */
#if BUILD_OPENJTAG_FTD2XX == 1
#include <ftd2xx.h>
#elif BUILD_OPENJTAG_LIBFTDI == 1
#include <ftdi.h>
#endif
/* OpenJTAG vid/pid */
static uint16_t openjtag_vid = 0x0403;
static uint16_t openjtag_pid = 0x6001;
static char *openjtag_device_desc;
#if BUILD_OPENJTAG_FTD2XX == 1
static FT_HANDLE ftdih;
#elif BUILD_OPENJTAG_LIBFTDI == 1
static struct ftdi_context ftdic;
#endif
#define OPENJTAG_BUFFER_SIZE 504
#define OPENJTAG_MAX_PENDING_RESULTS 256
struct openjtag_scan_result {
uint32_t bits; /* Length in bits*/
struct scan_command *command; /* Corresponding scan command */
uint8_t *buffer;
};
/* USB RX/TX buffers */
static int usb_tx_buf_offs;
static uint8_t usb_tx_buf[OPENJTAG_BUFFER_SIZE];
static uint32_t usb_rx_buf_len;
static uint8_t usb_rx_buf[OPENJTAG_BUFFER_SIZE];
/* Pending readings */
static struct openjtag_scan_result openjtag_scan_result_buffer[OPENJTAG_MAX_PENDING_RESULTS];
static int openjtag_scan_result_count;
/* Openocd usb handler */
struct openocd {
struct usb_dev_handle *usb_handle;
};
#ifdef _DEBUG_USB_COMMS_
#define DEBUG_TYPE_READ 0
#define DEBUG_TYPE_WRITE 1
#define DEBUG_TYPE_OCD_READ 2
#define DEBUG_TYPE_BUFFER 3
#define LINE_LEN 16
static void openjtag_debug_buffer(uint8_t *buffer, int length, uint8_t type)
{
char line[128];
char s[4];
int i;
int j;
switch (type) {
case DEBUG_TYPE_READ:
sprintf(line, "USB READ %d bytes", length);
break;
case DEBUG_TYPE_WRITE:
sprintf(line, "USB WRITE %d bytes", length);
break;
case DEBUG_TYPE_OCD_READ:
sprintf(line, "TO OpenOCD %d bytes", length);
break;
case DEBUG_TYPE_BUFFER:
sprintf(line, "Buffer %d bytes", length);
break;
}
LOG_DEBUG("%s", line);
for (i = 0; i < length; i += LINE_LEN) {
switch (type) {
case DEBUG_TYPE_READ:
sprintf(line, "USB READ: %04x", i);
break;
case DEBUG_TYPE_WRITE:
sprintf(line, "USB WRITE: %04x", i);
break;
case DEBUG_TYPE_OCD_READ:
sprintf(line, "TO OpenOCD: %04x", i);
break;
case DEBUG_TYPE_BUFFER:
sprintf(line, "BUFFER: %04x", i);
break;
}
for (j = i; j < i + LINE_LEN && j < length; j++) {
sprintf(s, " %02x", buffer[j]);
strcat(line, s);
}
LOG_DEBUG("%s", line);
}
}
#endif
static int8_t openjtag_get_tap_state(int8_t state)
{
switch (state) {
case TAP_DREXIT2: return OPENJTAG_TAP_EXIT2_DR;
case TAP_DREXIT1: return OPENJTAG_TAP_EXIT1_DR;
case TAP_DRSHIFT: return OPENJTAG_TAP_SHIFT_DR;
case TAP_DRPAUSE: return OPENJTAG_TAP_PAUSE_DR;
case TAP_IRSELECT: return OPENJTAG_TAP_SELECT_IR;
case TAP_DRUPDATE: return OPENJTAG_TAP_UPDATE_DR;
case TAP_DRCAPTURE: return OPENJTAG_TAP_CAPTURE_DR;
case TAP_DRSELECT: return OPENJTAG_TAP_SELECT_DR;
case TAP_IREXIT2: return OPENJTAG_TAP_EXIT2_IR;
case TAP_IREXIT1: return OPENJTAG_TAP_EXIT1_IR;
case TAP_IRSHIFT: return OPENJTAG_TAP_SHIFT_IR;
case TAP_IRPAUSE: return OPENJTAG_TAP_PAUSE_IR;
case TAP_IDLE: return OPENJTAG_TAP_IDLE;
case TAP_IRUPDATE: return OPENJTAG_TAP_UPDATE_IR;
case TAP_IRCAPTURE: return OPENJTAG_TAP_CAPURE_IR;
case TAP_RESET: return OPENJTAG_TAP_RESET;
case TAP_INVALID:
default: return OPENJTAG_TAP_INVALID;
}
}
static int openjtag_buf_write(
uint8_t *buf, int size, uint32_t *bytes_written)
{
#if BUILD_OPENJTAG_FTD2XX == 1
FT_STATUS status;
DWORD dw_bytes_written;
#ifdef _DEBUG_USB_COMMS_
openjtag_debug_buffer(buf, size, DEBUG_TYPE_WRITE);
#endif
status = FT_Write(ftdih, buf, size, &dw_bytes_written);
if (status != FT_OK) {
*bytes_written = dw_bytes_written;
LOG_ERROR("FT_Write returned: %u", status);
return ERROR_JTAG_DEVICE_ERROR;
}
*bytes_written = dw_bytes_written;
return ERROR_OK;
#elif BUILD_OPENJTAG_LIBFTDI == 1
int retval;
#ifdef _DEBUG_USB_COMMS_
openjtag_debug_buffer(buf, size, DEBUG_TYPE_WRITE);
#endif
retval = ftdi_write_data(&ftdic, buf, size);
if (retval < 0) {
*bytes_written = 0;
LOG_ERROR("ftdi_write_data: %s", ftdi_get_error_string(&ftdic));
return ERROR_JTAG_DEVICE_ERROR;
}
*bytes_written += retval;
return ERROR_OK;
#endif
}
static int openjtag_buf_read(uint8_t *buf, uint32_t qty, uint32_t *bytes_read)
{
#if BUILD_OPENJTAG_FTD2XX == 1
DWORD dw_bytes_read;
FT_STATUS status;
int timeout = 50;
*bytes_read = 0;
while (qty && (*bytes_read < qty) && timeout--) {
status = FT_Read(ftdih, buf + *bytes_read,
qty - *bytes_read, &dw_bytes_read);
if (status != FT_OK) {
*bytes_read = dw_bytes_read;
LOG_ERROR("FT_Read returned: %u", status);
return ERROR_JTAG_DEVICE_ERROR;
}
*bytes_read += dw_bytes_read;
}
#ifdef _DEBUG_USB_COMMS_
openjtag_debug_buffer(buf, *bytes_read, DEBUG_TYPE_READ);
#endif
return ERROR_OK;
#elif BUILD_OPENJTAG_LIBFTDI == 1
int retval;
int timeout = 5;
*bytes_read = 0;
while ((*bytes_read < qty) && timeout--) {
retval = ftdi_read_data(&ftdic, buf + *bytes_read,
qty - *bytes_read);
if (retval < 0) {
*bytes_read = 0;
DEBUG_JTAG_IO("ftdi_read_data: %s",
ftdi_get_error_string(&ftdic));
return ERROR_JTAG_DEVICE_ERROR;
}
*bytes_read += retval;
}
#ifdef _DEBUG_USB_COMMS_
openjtag_debug_buffer(buf, *bytes_read, DEBUG_TYPE_READ);
#endif
#endif
return ERROR_OK;
}
static int openjtag_sendcommand(uint8_t cmd)
{
uint32_t written;
return openjtag_buf_write(&cmd, 1, &written);
}
static int openjtag_speed(int speed)
{
int clockcmd;
switch (speed) {
case 48000:
clockcmd = 0x00;
break;
case 24000:
clockcmd = 0x20;
break;
case 12000:
clockcmd = 0x40;
break;
case 6000:
clockcmd = 0x60;
break;
case 3000:
clockcmd = 0x80;
break;
case 1500:
clockcmd = 0xA0;
break;
case 750:
clockcmd = 0xC0;
break;
case 375:
clockcmd = 0xE0;
break;
default:
clockcmd = 0xE0;
LOG_WARNING("adapter speed not recognized, reverting to 375 kHz");
break;
}
openjtag_sendcommand(clockcmd);
return ERROR_OK;
}
static int openjtag_init(void)
{
uint8_t latency_timer;
#if BUILD_OPENJTAG_FTD2XX == 1
FT_STATUS status;
#endif
usb_tx_buf_offs = 0;
usb_rx_buf_len = 0;
openjtag_scan_result_count = 0;
#if BUILD_OPENJTAG_FTD2XX == 1
LOG_DEBUG("'openjtag' interface using FTD2XX");
#elif BUILD_OPENJTAG_LIBFTDI == 1
LOG_DEBUG("'openjtag' interface using libftdi");
#endif
/* Open by device description */
if (openjtag_device_desc == NULL) {
LOG_WARNING("no openjtag device description specified, "
"using default 'Open JTAG Project'");
openjtag_device_desc = "Open JTAG Project";
}
#if BUILD_OPENJTAG_FTD2XX == 1
#if IS_WIN32 == 0
/* Add non-standard Vid/Pid to the linux driver */
status = FT_SetVIDPID(openjtag_vid, openjtag_pid);
if (status != FT_OK) {
LOG_WARNING("couldn't add %4.4x:%4.4x",
openjtag_vid, openjtag_pid);
}
#endif
status = FT_OpenEx(openjtag_device_desc, FT_OPEN_BY_DESCRIPTION,
&ftdih);
if (status != FT_OK) {
DWORD num_devices;
LOG_ERROR("unable to open ftdi device: %u", status);
status = FT_ListDevices(&num_devices, NULL,
FT_LIST_NUMBER_ONLY);
if (status == FT_OK) {
char **desc_array = malloc(sizeof(char *)
* (num_devices + 1));
unsigned int i;
for (i = 0; i < num_devices; i++)
desc_array[i] = malloc(64);
desc_array[num_devices] = NULL;
status = FT_ListDevices(desc_array, &num_devices,
FT_LIST_ALL | FT_OPEN_BY_DESCRIPTION);
if (status == FT_OK) {
LOG_ERROR("ListDevices: %u\n", num_devices);
for (i = 0; i < num_devices; i++)
LOG_ERROR("%i: %s", i, desc_array[i]);
}
for (i = 0; i < num_devices; i++)
free(desc_array[i]);
free(desc_array);
} else {
LOG_ERROR("ListDevices: NONE\n");
}
return ERROR_JTAG_INIT_FAILED;
}
status = FT_SetLatencyTimer(ftdih, 2);
if (status != FT_OK) {
LOG_ERROR("unable to set latency timer: %u", status);
return ERROR_JTAG_INIT_FAILED;
}
status = FT_GetLatencyTimer(ftdih, &latency_timer);
if (status != FT_OK) {
LOG_ERROR("unable to get latency timer: %u", status);
return ERROR_JTAG_INIT_FAILED;
}
LOG_DEBUG("current latency timer: %i", latency_timer);
status = FT_SetBitMode(ftdih, 0x00, 0x40);
if (status != FT_OK) {
LOG_ERROR("unable to disable bit i/o mode: %u", status);
return ERROR_JTAG_INIT_FAILED;
}
status = FT_SetTimeouts(ftdih, 50, 0);
if (status != FT_OK) {
LOG_ERROR("unable to set timeouts: %u", status);
return ERROR_JTAG_INIT_FAILED;
}
status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX);
if (status != FT_OK) {
LOG_ERROR("unable to FT_Purge() %u", status);
return ERROR_JTAG_INIT_FAILED;
}
#elif BUILD_OPENJTAG_LIBFTDI == 1
if (ftdi_init(&ftdic) < 0)
return ERROR_JTAG_INIT_FAILED;
/* context, vendor id, product id, description, serial id */
if (ftdi_usb_open_desc(&ftdic, openjtag_vid, openjtag_pid, openjtag_device_desc, NULL) < 0) {
LOG_ERROR("unable to open ftdi device: %s", ftdic.error_str);
return ERROR_JTAG_INIT_FAILED;
}
if (ftdi_usb_reset(&ftdic) < 0) {
LOG_ERROR("unable to reset ftdi device");
return ERROR_JTAG_INIT_FAILED;
}
if (ftdi_set_latency_timer(&ftdic, 2) < 0) {
LOG_ERROR("unable to set latency timer");
return ERROR_JTAG_INIT_FAILED;
}
if (ftdi_get_latency_timer(&ftdic, &latency_timer) < 0) {
LOG_ERROR("unable to get latency timer");
return ERROR_JTAG_INIT_FAILED;
}
LOG_DEBUG("current latency timer: %u", latency_timer);
ftdi_disable_bitbang(&ftdic);
/* was (3000000 / 4) with a comment about a bug in libftdi when using high baudrate */
if (ftdi_set_baudrate(&ftdic, 3000000) < 0) {
LOG_ERROR("Can't set baud rate to max: %s",
ftdi_get_error_string(&ftdic));
return ERROR_JTAG_DEVICE_ERROR;
};
#endif
#if BUILD_OPENJTAG_FTD2XX == 1
status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX);
if (status != FT_OK)
return ERROR_JTAG_INIT_FAILED;
#elif BUILD_OPENJTAG_LIBFTDI == 1
if (ftdi_usb_purge_buffers(&ftdic) < 0) {
LOG_ERROR("ftdi_purge_buffers: %s", ftdic.error_str);
return ERROR_JTAG_INIT_FAILED;
}
#endif
/* OpenJTAG speed */
openjtag_sendcommand(0xE0); /*Start at slowest adapter speed*/
/* MSB */
openjtag_sendcommand(0x75);
return ERROR_OK;
}
static int openjtag_quit(void)
{
#if BUILD_OPENJTAG_FTD2XX == 1
FT_Close(ftdih);
#elif BUILD_OPENJTAG_LIBFTDI == 1
ftdi_usb_close(&ftdic);
ftdi_deinit(&ftdic);
#endif
return ERROR_OK;
}
static void openjtag_write_tap_buffer(void)
{
uint32_t written;
openjtag_buf_write(usb_tx_buf, usb_tx_buf_offs, &written);
openjtag_buf_read(usb_rx_buf, usb_tx_buf_offs, &usb_rx_buf_len);
usb_tx_buf_offs = 0;
}
static int openjtag_execute_tap_queue(void)
{
openjtag_write_tap_buffer();
int res_count = 0;
if (openjtag_scan_result_count && usb_rx_buf_len) {
int count;
int rx_offs = 0;
int len;
/* for every pending result */
while (res_count < openjtag_scan_result_count) {
/* get sent bits */
len = openjtag_scan_result_buffer[res_count].bits;
count = 0;
uint8_t *buffer = openjtag_scan_result_buffer[res_count].buffer;
while (len) {
if (len <= 8) {
DEBUG_JTAG_IO("bits < 8 buf = 0x%X, will be 0x%X",
usb_rx_buf[rx_offs], usb_rx_buf[rx_offs] >> (8 - len));
buffer[count] = usb_rx_buf[rx_offs] >> (8 - len);
len = 0;
} else {
buffer[count] = usb_rx_buf[rx_offs];
len -= 8;
}
rx_offs++;
count++;
}
#ifdef _DEBUG_USB_COMMS_
openjtag_debug_buffer(buffer,
DIV_ROUND_UP(openjtag_scan_result_buffer[res_count].bits, 8), DEBUG_TYPE_OCD_READ);
#endif
jtag_read_buffer(buffer, openjtag_scan_result_buffer[res_count].command);
if (openjtag_scan_result_buffer[res_count].buffer)
free(openjtag_scan_result_buffer[res_count].buffer);
res_count++;
}
}
openjtag_scan_result_count = 0;
return ERROR_OK;
}
static void openjtag_add_byte(char buf)
{
if (usb_tx_buf_offs == OPENJTAG_BUFFER_SIZE) {
DEBUG_JTAG_IO("Forcing execute_tap_queue");
DEBUG_JTAG_IO("TX Buff offs=%d", usb_tx_buf_offs);
openjtag_execute_tap_queue();
}
usb_tx_buf[usb_tx_buf_offs] = buf;
usb_tx_buf_offs++;
}
static void openjtag_add_scan(uint8_t *buffer, int length, struct scan_command *scan_cmd)
{
/* Ensure space to send long chains */
/* We add two byte for each eight (or less) bits, one for command, one for data */
if (usb_tx_buf_offs + (DIV_ROUND_UP(length, 8) * 2) >= OPENJTAG_BUFFER_SIZE) {
DEBUG_JTAG_IO("Forcing execute_tap_queue from scan");
DEBUG_JTAG_IO("TX Buff offs=%d len=%d", usb_tx_buf_offs, DIV_ROUND_UP(length, 8) * 2);
openjtag_execute_tap_queue();
}
openjtag_scan_result_buffer[openjtag_scan_result_count].bits = length;
openjtag_scan_result_buffer[openjtag_scan_result_count].command = scan_cmd;
openjtag_scan_result_buffer[openjtag_scan_result_count].buffer = buffer;
uint8_t command;
uint8_t bits;
int count = 0;
while (length) {
/* write command */
command = 6;
/* last bits? */
if (length <= 8) {
/* tms high */
command |= (1 << 4);
/* bits to transfer */
bits = (length - 1);
command |= bits << 5;
length = 0;
} else {
/* whole byte */
/* bits to transfer */
bits = 7;
command |= (7 << 5);
length -= 8;
}
openjtag_add_byte(command);
openjtag_add_byte(buffer[count]);
count++;
}
openjtag_scan_result_count++;
}
static void openjtag_execute_reset(struct jtag_command *cmd)
{
DEBUG_JTAG_IO("reset trst: %i srst %i",
cmd->cmd.reset->trst, cmd->cmd.reset->srst);
uint8_t buf = 0x00;
if (cmd->cmd.reset->trst) {
buf = 0x03;
} else {
buf |= 0x04;
buf |= 0x05 << 4;
}
openjtag_add_byte(buf);
}
static void openjtag_execute_sleep(struct jtag_command *cmd)
{
jtag_sleep(cmd->cmd.sleep->us);
}
static void openjtag_set_state(uint8_t openocd_state)
{
int8_t state = openjtag_get_tap_state(openocd_state);
uint8_t buf = 0;
buf = 0x01;
buf |= state << 4;
openjtag_add_byte(buf);
}
static void openjtag_execute_statemove(struct jtag_command *cmd)
{
DEBUG_JTAG_IO("state move to %i", cmd->cmd.statemove->end_state);
tap_set_end_state(cmd->cmd.statemove->end_state);
openjtag_set_state(cmd->cmd.statemove->end_state);
tap_set_state(tap_get_end_state());
}
static void openjtag_execute_scan(struct jtag_command *cmd)
{
int scan_size, old_state;
uint8_t *buffer;
DEBUG_JTAG_IO("scan ends in %s", tap_state_name(cmd->cmd.scan->end_state));
/* get scan info */
tap_set_end_state(cmd->cmd.scan->end_state);
scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
#ifdef _DEBUG_USB_COMMS_
openjtag_debug_buffer(buffer, (scan_size + 7) / 8, DEBUG_TYPE_BUFFER);
#endif
/* set state */
old_state = tap_get_end_state();
openjtag_set_state(cmd->cmd.scan->ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT);
tap_set_state(cmd->cmd.scan->ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT);
tap_set_end_state(old_state);
openjtag_add_scan(buffer, scan_size, cmd->cmd.scan);
openjtag_set_state(cmd->cmd.scan->ir_scan ? TAP_IRPAUSE : TAP_DRPAUSE);
tap_set_state(cmd->cmd.scan->ir_scan ? TAP_IRPAUSE : TAP_DRPAUSE);
if (tap_get_state() != tap_get_end_state()) {
openjtag_set_state(tap_get_end_state());
tap_set_state(tap_get_end_state());
}
}
static void openjtag_execute_runtest(struct jtag_command *cmd)
{
tap_state_t end_state = cmd->cmd.runtest->end_state;
tap_set_end_state(end_state);
/* only do a state_move when we're not already in IDLE */
if (tap_get_state() != TAP_IDLE) {
openjtag_set_state(TAP_IDLE);
tap_set_state(TAP_IDLE);
}
if (cmd->cmd.runtest->num_cycles > 16)
LOG_WARNING("num_cycles > 16 on run test");
uint8_t command;
command = 7;
command |= ((cmd->cmd.runtest->num_cycles - 1) & 0x0F) << 4;
openjtag_add_byte(command);
tap_set_end_state(end_state);
if (tap_get_end_state() != tap_get_state()) {
openjtag_set_state(end_state);
tap_set_state(end_state);
}
}
static void openjtag_execute_command(struct jtag_command *cmd)
{
DEBUG_JTAG_IO("openjtag_execute_command %i", cmd->type);
switch (cmd->type) {
case JTAG_RESET:
openjtag_execute_reset(cmd);
break;
case JTAG_SLEEP:
openjtag_execute_sleep(cmd);
break;
case JTAG_TLR_RESET:
openjtag_execute_statemove(cmd);
break;
case JTAG_SCAN:
openjtag_execute_scan(cmd);
break;
case JTAG_RUNTEST:
openjtag_execute_runtest(cmd);
break;
case JTAG_PATHMOVE:
/* jlink_execute_pathmove(cmd); break; */
default:
LOG_ERROR("BUG: unknown Open JTAG command type encountered");
exit(-1);
}
}
static int openjtag_execute_queue(void)
{
struct jtag_command *cmd = jtag_command_queue;
while (cmd != NULL) {
openjtag_execute_command(cmd);
cmd = cmd->next;
}
return openjtag_execute_tap_queue();
}
static int openjtag_speed_div(int speed, int *khz)
{
*khz = speed;
return ERROR_OK;
}
static int openjtag_khz(int khz, int *jtag_speed)
{
if (khz >= 48000)
*jtag_speed = 48000;
else if (khz >= 24000)
*jtag_speed = 24000;
else if (khz >= 12000)
*jtag_speed = 12000;
else if (khz >= 6000)
*jtag_speed = 6000;
else if (khz >= 3000)
*jtag_speed = 3000;
else if (khz >= 1500)
*jtag_speed = 1500;
else if (khz >= 750)
*jtag_speed = 750;
else
*jtag_speed = 375;
return ERROR_OK;
}
COMMAND_HANDLER(openjtag_handle_device_desc_command)
{
if (CMD_ARGC == 1)
openjtag_device_desc = strdup(CMD_ARGV[0]);
else
LOG_ERROR("require exactly one argument to "
"openjtag_device_desc <description>");
return ERROR_OK;
}
static const struct command_registration openjtag_command_handlers[] = {
{
.name = "openjtag_device_desc",
.handler = openjtag_handle_device_desc_command,
.mode = COMMAND_CONFIG,
.help = "set the USB device description of the OpenJTAG",
.usage = "description-string",
},
COMMAND_REGISTRATION_DONE
};
struct jtag_interface openjtag_interface = {
.name = "openjtag",
.commands = openjtag_command_handlers,
.execute_queue = openjtag_execute_queue,
.speed = openjtag_speed,
.speed_div = openjtag_speed_div,
.khz = openjtag_khz,
.init = openjtag_init,
.quit = openjtag_quit,
};
...@@ -83,6 +83,9 @@ extern struct jtag_interface presto_interface; ...@@ -83,6 +83,9 @@ extern struct jtag_interface presto_interface;
#if BUILD_USBPROG == 1 #if BUILD_USBPROG == 1
extern struct jtag_interface usbprog_interface; extern struct jtag_interface usbprog_interface;
#endif #endif
#if BUILD_OPENJTAG == 1
extern struct jtag_interface openjtag_interface;
#endif
#if BUILD_JLINK == 1 #if BUILD_JLINK == 1
extern struct jtag_interface jlink_interface; extern struct jtag_interface jlink_interface;
#endif #endif
...@@ -170,6 +173,9 @@ struct jtag_interface *jtag_interfaces[] = { ...@@ -170,6 +173,9 @@ struct jtag_interface *jtag_interfaces[] = {
#if BUILD_USBPROG == 1 #if BUILD_USBPROG == 1
&usbprog_interface, &usbprog_interface,
#endif #endif
#if BUILD_OPENJTAG == 1
&openjtag_interface,
#endif
#if BUILD_JLINK == 1 #if BUILD_JLINK == 1
&jlink_interface, &jlink_interface,
#endif #endif
......
#
# OpenJTAG
#
# www.openjtag.org
#
interface openjtag
openjtag_device_desc "Open JTAG Project"
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment