This is an automated email from Gerrit.

Tomasz CEDRO ([email protected]) just uploaded a new patch set to Gerrit, which 
you can find at http://openocd.zylin.com/1061

-- gerrit

commit 938eb7612b49fc07ff0f762710f87d2807472d5a
Author: Tomek CEDRO <[email protected]>
Date:   Tue Oct 30 16:59:20 2012 +0100

    Added ft2232_transfer() and ft2232_bitbang() implementation. New interface 
routines (interface signal handling) are now part of the build process 
(required by ft2232 transfer and bitbang functions). Extended ft2232 based jtag 
driver with existing ft2232_bitbang function.
    
    Change-Id: I2d1e68782f702d385a8a48964417b5046a88e7c4
    Signed-off-by: Tomek CEDRO <[email protected]>

diff --git a/configure.ac b/configure.ac
index 2f85f8e..0939b30 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1323,6 +1323,7 @@ AC_CONFIG_FILES([
   src/jtag/drivers/Makefile
   src/jtag/stlink/Makefile
   src/transport/Makefile
+  src/interface/Makefile
   src/xsvf/Makefile
   src/svf/Makefile
   src/target/Makefile
diff --git a/src/Makefile.am b/src/Makefile.am
index c78e81c..f449677 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -5,6 +5,7 @@ SUBDIRS = \
        helper \
        target \
        transport \
+       interface \
        flash \
        svf \
        xsvf \
@@ -92,6 +93,7 @@ libopenocd_la_LIBADD = \
        $(top_builddir)/src/pld/libpld.la \
        $(top_builddir)/src/jtag/libjtag.la \
        $(top_builddir)/src/transport/libtransport.la \
+       $(top_builddir)/src/interface/liboocdinterface.la \
        $(top_builddir)/src/flash/libflash.la \
        $(top_builddir)/src/target/libtarget.la \
        $(top_builddir)/src/server/libserver.la \
diff --git a/src/interface/Makefile.am b/src/interface/Makefile.am
index 8a7b301..cc74602 100644
--- a/src/interface/Makefile.am
+++ b/src/interface/Makefile.am
@@ -15,10 +15,11 @@ BUILT_SOURCES +=
 CLEANFILES +=
 
 liboocdinterface_la_SOURCES = \
-       interface.c
+       interface_signal.c
 
 noinst_HEADERS = \
-       interface.h
+       interface.h \
+       interface_signal.h
 
 EXTRA_DIST =
 
diff --git a/src/interface/interface_signal.c b/src/interface/interface_signal.c
index 5651447..7b4423c 100644
--- a/src/interface/interface_signal.c
+++ b/src/interface/interface_signal.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 Tomasz Boleslaw CEDRO
+ * Copyright (C) 2011-2012 Tomasz Boleslaw CEDRO
  * [email protected], http://www.tomek.cedro.info
  *
  * This program is free software; you can redistribute it and/or modify
diff --git a/src/jtag/drivers/ft2232.c b/src/jtag/drivers/ft2232.c
index 35df00a..864cc9e 100644
--- a/src/jtag/drivers/ft2232.c
+++ b/src/jtag/drivers/ft2232.c
@@ -86,6 +86,7 @@
 #include <jtag/interface.h>
 #include <transport/transport.h>
 #include <helper/time_support.h>
+#include <interface/interface.h>
 
 #if IS_CYGWIN == 1
 #include <windows.h>
@@ -623,6 +624,208 @@ static bool ft2232_device_is_highspeed(void)
 #endif
 }
 
+
+/** Generic IO BITBANG Port Manipulation Routine.
+ * It can read and write port state using signal names. Each interface have its
+ * own specific signal names and fields. This function works on those fields
+ * and based on their values talks to the FT*232 chip on the interface device.
+ * ft2232 drivers use {low,high}_{output,direction} global variables to 
remember
+ * port direction and value, so we need to work on them as well not to change
+ * any other pin with our bit-baning performed only on selected pins.
+ * The function name 'bitbang' reflects ability to change selected pin states.
+ *
+ * @Note: FT2232 has special mechanism called MPSSE for serial communications
+ * that is far more efficient than pure 'bitbang' mode on this device family.
+ * Although our function is named 'bitbang' it does not use bitbang mode.
+ * MPSSE command send value and port bytes on port write, but does not on read.
+ * This happens every time we want to change pin value, so we need to use 
cache.
+ * On write we want to OR direction mask already set by init() procedure
+ * to mark bit-mask output. On read we want to clear bits given by mask
+ * to mark them input. To read we need to write/update port state first.
+ * Long story short: to read data we first need to set pins to input.
+ *
+ * @Warning: reading and writing will set pin direction input or output,
+ * so it is possible to disable basic data output pins with bad masking,
+ * but also gives chance to create and manage full TCL signal description,
+ * that can be used to take advantage of some additional interface hardware
+ * features installed on some devices (i.e. ADC, power supply, etc).
+ * This gives new way of signal handling that is still backward-compatible.
+ *
+ * \param *device void pointer to pass additional driver information to the 
routine.
+ * \param signal is the string representation of the signal mask stored in 
layout structure.
+ * \param GETnSET if zero then perform read operation, write otherwise.
+ * \param *value is the pointer that holds the value.
+ * \return ERROR_OK on success, or ERROR_FAIL on failure.
+ */
+int ft2232_bitbang(void *device, char *signal_name, int GETnSET, int *value)
+{
+       uint8_t  buf[3];
+       int retval, vall = 0, valh = 0;
+       unsigned int sigmask;
+       uint32_t bytes_written, bytes_read;
+       oocd_interface_signal_t *sig = oocd_interface_signal_find(signal_name);
+
+       /* First get the signal mask, or return error if signal not defined. */
+       if (!sig) {
+               LOG_ERROR("Requested signal not found on this interface!");
+               return ERROR_FAIL;
+       }
+       /* Pin mask is also related with port direction and complicates it!!! */
+       sigmask = sig->mask;
+
+       /* First check against restricted port pins defined by the interface 
layout */
+       if (sigmask & layout->bitbang_deny) {
+               LOG_ERROR("This interface does not allow to bit-bang selected 
pins (0x%08X)!", layout->bitbang_deny);
+               return ERROR_FAIL;
+       }
+
+       if (!GETnSET) {
+               /* We will SET port pins selected by sigmask. */
+               /* Modify our pins value, but remember about other pins and 
their previous value */
+               low_output  = (low_output & ~sigmask) | ((*value & sigmask) & 
0x0ff);
+               high_output = (high_output & ~(sigmask >> 8)) | (((*value & 
sigmask) >> 8) & 0x0ff);
+               /* Modify our pins direction, but remember about other pins and 
their previous direction */
+               low_direction  |= sigmask & 0x0ff;
+               high_direction |= (sigmask >> 8) & 0x0ff;
+               /* Now send those settings to the interface chip */
+               buf[0] = 0x80;  /* Set Data Bits LowByte */
+               buf[1] = low_output;
+               buf[2] = low_direction;
+               retval = ft2232_write(buf, 3, &bytes_written);
+               if (retval != ERROR_OK)
+                       return retval;
+               buf[0] = 0x82;   /* Set Data Bits HighByte */
+               buf[1] = high_output;
+               buf[2] = high_direction;
+               retval = ft2232_write(buf, 3, &bytes_written);
+               if (retval != ERROR_OK)
+                       return retval;
+               sig->value = ((high_output << 8) | low_output) & sig->mask;
+       } else {
+               /* Modify our pins value, but remember about other pins and 
their previous value */
+               /* DO WE REALLY NEED TO PULL-UP PINS TO READ THEIR STATE OR 
SIMPLY LEAVE AS IS? */
+               /* low_output  = (low_output & ~sigmask) | (sigmask & 0x0ff); */
+               /* high_output = (high_output & ~sigmask) | (sigmask>>8) & 
0x0ff); */
+               /* Modify our pins direction to input, but remember about other 
pins and their previous direction */
+               low_direction  &= ~(sigmask);
+               high_direction &= ~(sigmask >> 8);
+               /* Now send those settings to the interface chip */
+               /* First change desired pins to input */
+               buf[0] = 0x80;  /* Set Data Bits LowByte */
+               buf[1] = low_output;
+               buf[2] = low_direction;
+               retval = ft2232_write(buf, 3, &bytes_written);
+               if (retval != ERROR_OK)
+                       return retval;
+               buf[0] = 0x82;   /* Set Data Bits HighByte */
+               buf[1] = high_output;
+               buf[2] = high_direction;
+               retval = ft2232_write(buf, 3, &bytes_written);
+               if (retval != ERROR_OK)
+                       return retval;
+               /* Then read pins designated by a signal mask */
+               buf[0] = 0x81;    /* Read Data Bits LowByte. */
+               retval = ft2232_write(buf, 1, &bytes_written);
+               if (retval != ERROR_OK)
+                       return retval;
+               retval = ft2232_read((uint8_t *)&vall, 1, &bytes_read);
+               if (retval != ERROR_OK)
+                       return retval;
+               buf[0] = 0x83;    /* Read Data Bits HighByte. */
+               retval = ft2232_write(buf, 1, &bytes_written);
+               if (retval != ERROR_OK)
+                       return retval;
+               retval = ft2232_read((uint8_t *)&valh, 1, &bytes_read);
+               if (retval != ERROR_OK)
+                       return retval;
+               sig->value = *value = ((valh << 8) | vall) & sig->mask; /* Join 
result bytes and apply signal bitmask */
+       }
+       return ERROR_OK;
+}
+
+
+/** Transfer bits in/out stored in char array starting from LSB first or MSB 
first,
+ * alternatively if you want to make MSB-first shift on LSB-first mode put data
+ * in reverse order into input/output array.
+ * \param *device void pointer to pass driver details to the function.
+ * \param bits is the number of bits (char array elements) to transfer.
+ * \param *mosidata pointer to char array with data to be send.
+ * \param *misodata pointer to char array with data to be received.
+ * \param nLSBfirst if zero shift data LSB-first, otherwise MSB-first.
+ * \return number of bits sent on success, or ERROR_FAIL on failure.
+ */
+int ft2232_transfer(void *device, int bits, char *mosidata, char *misodata, 
int nLSBfirst)
+{
+       static uint8_t buf[65539], databuf;
+       int i, retval, bit = 0, byte = 0, bytes = 0;
+       uint32_t bytes_written, bytes_read;
+
+       LOG_DEBUG("ft2232_transfer(device=@%p, bits=%d, mosidata=@%p, 
misodata=@%p, nLSDfirst=%d) ",\
+               (void *)device, bits, (void *)mosidata, (void *)misodata, 
nLSBfirst);
+
+       if (bits > 65535) {
+               LOG_ERROR("Cannot transfer more than 65536 bits at once!");
+               return ERROR_FAIL;
+       }
+
+       if (bits >= 8) {
+               /* Try to pack as many bits into bytes for better performance. 
*/
+               bytes = bits / 8;
+               bytes--;                      /* MPSSE starts counting bytes 
from 0. */
+               buf[0] = (nLSBfirst) ? 0x31 : 0x39; /* Clock Bytes In and Out 
LSb or MSb first. */
+               buf[1] = (char)bytes & 0x0ff;
+               buf[2] = (char)((bytes >> 8) & 0x0ff);
+               bytes++;
+               for (byte = 0; byte * 8 < bits; byte++) {
+                       databuf = 0;
+                       for (i = 0; i < 8; i++)
+                               databuf |= mosidata[byte * 8 + i] ? (1 << i) : 
0;
+                       buf[byte + 3] = databuf;
+               }
+               retval = ft2232_write(buf, bytes + 3, &bytes_written);
+               if (retval < 0) {
+                       LOG_ERROR("ft2232_write() returns %d", retval);
+                       return ERROR_FAIL;
+               }
+               retval = ft2232_read((uint8_t *)buf, bytes, &bytes_read);
+               if (retval < 0) {
+                       LOG_ERROR("ft2232_read() returns %d", retval);
+                       return ERROR_FAIL;
+               }
+               /* Explode read bytes into bit array. */
+               for (byte = 0; byte * 8 < bits; byte++)
+                       for (bit = 0; bit < 8; bit++)
+                               misodata[byte * 8 + bit] = buf[byte] & (1 << 
bit) ? 1 : 0;
+       }
+
+       /* Now send remaining bits that cannot be packed as bytes. */
+       /* Because "Clock Data Bits In and Out LSB/MSB" of FTDI is a mess, pack 
single */
+       /* bit read/writes into buffer and then flush it using single USB 
transfer. */
+       for (bit = bytes * 8; bit < bits; bit++) {
+               buf[3 * bit + 0] = (nLSBfirst) ? 0x33 : 0x3b;     /* Clock Bits 
In and Out LSb or MSb first. */
+               buf[3 * bit + 1] = 0;                            /* One bit per 
element. */
+               buf[3 * bit + 2] = mosidata[bit] ? 0xff : 0;      /* Take data 
from supplied array. */
+       }
+       retval = ft2232_write(buf, 3 * (bits - (bytes * 8)), &bytes_written);
+       if (retval < 0) {
+               LOG_ERROR("ft2232_write() returns %d", retval);
+               return ERROR_FAIL;
+       }
+       retval = ft2232_read((uint8_t *)misodata, bits - (bytes * 8), 
&bytes_read);
+       if (retval < 0) {
+               LOG_ERROR("ft2232_read() returns %d", retval);
+               return ERROR_FAIL;
+       }
+       /* FTDI MPSSE returns shift register value, our bit is MSb */
+       for (bit = bytes * 8; bit < bits; bit++)
+               misodata[bit] = (misodata[bit] & (nLSBfirst ? 0x01 : 0x80)) ? 1 
: 0;
+       /* USE THIS FOR WIRE-LEVEL DEBUG */
+       /* LOG_DEBUG("read 0x%02X written 0x%02X", misodata[bit], 
mosidata[bit]); */
+
+       return bit;
+}
+
+
 /*
  * Commands that only apply to the highspeed FTx232H devices (FT2232H, 
FT4232H, FT232H).
  * See chapter 6 in http://www.ftdichip.com/Documents/AppNotes/
@@ -4284,4 +4487,5 @@ struct jtag_interface ft2232_interface = {
        .speed_div = ft2232_speed_div,
        .khz = ft2232_khz,
        .execute_queue = ft2232_execute_queue,
+       .bitbang = ft2232_bitbang,
 };

-- 

------------------------------------------------------------------------------
LogMeIn Rescue: Anywhere, Anytime Remote support for IT. Free Trial
Remotely access PCs and mobile devices and provide instant support
Improve your efficiency, and focus on delivering more value-add services
Discover what IT Professionals Know. Rescue delivers
http://p.sf.net/sfu/logmein_12329d2d
_______________________________________________
OpenOCD-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openocd-devel

Reply via email to