Hello :-)

Sorry for my ignorance but Andreas could you please tell in one or two
words what is the main reason of creating "new" ft2232 driver and what
is new about that driver - the MPSSE is still the same instruction
set..?

Could you please tell what is the difference between new driver and
ft2232_bitbang and ft2232_transfer that I use for SWD as part of
LibSWD - maybe I could improve its speed too? :-)

http://repo.or.cz/w/openocd/libswd.git/blob/HEAD:/src/jtag/drivers/ft2232.c

 615 /** Generic IO BITBANG Port Manipulation Routine.
 616  * It can read and write port state using signal names. Each
interface have its
 617  * own specific signal names and fields. This function works on
those fields
 618  * and based on their values talks to the FT*232 chip on the
interface device.
 619  * ft2232 drivers use {low,high}_{output,direction} global
variables to remember
 620  * port direction and value, so we need to work on them as well
not to change
 621  * any other pin with our bit-baning performed only on selected pins.
 622  * The function name 'bitbang' reflects ability to change
selected pin states.
 623  *
 624  * @Note: FT2232 has special mechanism called MPSSE for serial
communications
 625  * that is far more efficient than pure 'bitbang' mode on this
device family.
 626  * Although our function is named 'bitbang' it does not use bitbang mode.
 627  * MPSSE command send value and port bytes on port write, but
does not on read.
 628  * This happens every time we want to change pin value, so we
need to use cache.
 629  * On write we want to OR direction mask already set by init() procedure
 630  * to mark bit-mask output. On read we want to clear bits given by mask
 631  * to mark them input. To read we need to write/update port state first.
 632  * Long story short: to read data we first need to set pins to input.
 633  *
 634  * @Warning: reading and writing will set pin direction input or output,
 635  * so it is possible to disable basic data output pins with bad masking,
 636  * but also gives chance to create and manage full TCL signal description,
 637  * that can be used to take advantage of some additional interface hardware
 638  * features installed on some devices (i.e. ADC, power supply, etc).
 639  * This gives new way of signal handling that is still backward-compatible.
 640  *
 641  * \param *device void pointer to pass additional driver
information to the routine.
 642  * \param signal is the string representation of the signal mask
stored in layout structure.
 643  * \param GETnSET if zero then perform read operation, write otherwise.
 644  * \param *value is the pointer that holds the value.
 645  * \return ERROR_OK on success, or ERROR_FAIL on failure.
 646  */
 647 int ft2232_bitbang(void *device, char *signal_name, int GETnSET,
int *value){
 648         uint8_t  buf[3];
 649         int retval, vall=0, valh=0;
 650         unsigned int sigmask;
 651         uint32_t bytes_written, bytes_read;
 652         oocd_interface_signal_t *sig;
 653
 654         //First get the signal mask, or return error if signal not defined.
 655         if (!(sig=oocd_interface_signal_find(signal_name))){
 656                 LOG_ERROR("Requested signal not found on this interface!");
 657                 return ERROR_FAIL;
 658         }
 659         // Pin mask is also related with port direction and
complicates it!!!
 660         sigmask=sig->mask;
 661
 662         // First check against restricted port pins defined by
the interface layout
 663         if (sigmask & layout->bitbang_deny){
 664                 LOG_ERROR("This interface does not allow to
bit-bang selected pins (0x%08X)!", layout->bitbang_deny);
 665                 return ERROR_FAIL;
 666         }
 667
 668         if (!GETnSET){
 669                 // We will SET port pins selected by sigmask.
 670                 // Modify our pins value, but remember about
other pins and their previous value
 671                 low_output  = (low_output & ~sigmask) | ((*value
& sigmask) & 0x0ff);
 672                 high_output = (high_output & ~(sigmask>>8)) |
(((*value & sigmask)>>8) & 0x0ff);
 673                 // Modify our pins direction, but remember about
other pins and their previous direction
 674                 low_direction  |= sigmask & 0x0ff;
 675                 high_direction |= (sigmask>>8) & 0x0ff;
 676                 // Now send those settings to the interface chip
 677                 buf[0] = 0x80;  //Set Data Bits LowByte
 678                 buf[1] = low_output;
 679                 buf[2] = low_direction;
 680                 if ((retval=ft2232_write(buf, 3, &bytes_written))
!= ERROR_OK) return retval;
 681                 buf[0] = 0x82;   //Set Data Bits HighByte
 682                 buf[1] = high_output;
 683                 buf[2] = high_direction;
 684                 if ((retval=ft2232_write(buf, 3, &bytes_written))
!= ERROR_OK) return retval;
 685                 sig->value = ((high_output<<8) | low_output) & sig->mask;
 686         } else {
 687                 // Modify our pins value, but remember about
other pins and their previous value
 688                 // DO WE REALLY NEED TO PULL-UP PINS TO READ
THEIR STATE OR SIMPLY LEAVE AS IS?
 689                 //low_output  = (low_output & ~sigmask) |
(sigmask & 0x0ff);
 690                 //high_output = (high_output & ~sigmask) |
(sigmask>>8) & 0x0ff);
 691                 // Modify our pins direction to input, but
remember about other pins and their previous direction
 692                 low_direction  &= ~(sigmask);
 693                 high_direction &= ~(sigmask>>8);
 694                 // Now send those settings to the interface chip
 695                 // First change desired pins to input
 696                 buf[0] = 0x80;  //Set Data Bits LowByte
 697                 buf[1] = low_output;
 698                 buf[2] = low_direction;
 699                 if ((retval=ft2232_write(buf, 3, &bytes_written))
!= ERROR_OK) return retval;
 700                 buf[0] = 0x82;   //Set Data Bits HighByte
 701                 buf[1] = high_output;
 702                 buf[2] = high_direction;
 703                 if ((retval=ft2232_write(buf, 3, &bytes_written))
!= ERROR_OK) return retval;
 704                 // Then read pins designated by a signal mask
 705                 buf[0]=0x81;    //Read Data Bits LowByte.
 706                 if ((retval=ft2232_write(buf, 1, &bytes_written))
!= ERROR_OK) return retval;
 707                 if ((retval=ft2232_read((uint8_t *)&vall, 1,
&bytes_read)) != ERROR_OK) return retval;
 708                 buf[0]=0x83;    //Read Data Bits HighByte.
 709                 if ((retval=ft2232_write(buf, 1, &bytes_written))
!= ERROR_OK) return retval;
 710                 if ((retval=ft2232_read((uint8_t *)&valh, 1,
&bytes_read)) != ERROR_OK) return retval;
 711                 sig->value = *value = ((valh<<8)|vall) &
sig->mask; //Join result bytes and apply signal bitmask
 712         }
 713         return ERROR_OK;
 714 }
 715
 716
 717 /** Transfer bits in/out stored in char array starting from LSB
first or MSB first,
 718  * alternatively if you want to make MSB-first shift on LSB-first
mode put data
 719  * in reverse order into input/output array.
 720  * \param *device void pointer to pass driver details to the function.
 721  * \param bits is the number of bits (char array elements) to transfer.
 722  * \param *mosidata pointer to char array with data to be send.
 723  * \param *misodata pointer to char array with data to be received.
 724  * \param nLSBfirst if zero shift data LSB-first, otherwise MSB-first.
 725  * \return number of bits sent on success, or ERROR_FAIL on failure.
 726  */
 727 int ft2232_transfer(void *device, int bits, char *mosidata, char
*misodata, int nLSBfirst){
 728         static uint8_t buf[65539], databuf;
 729         int i, retval, bit=0, byte=0, bytes=0;
 730         uint32_t bytes_written, bytes_read;
 731
 732         LOG_DEBUG("ft2232_transfer(device=@%p, bits=%d,
mosidata=@%p, misodata=@%p, nLSDfirst=%d) ",\
 733                 (void*)device, bits, (void*)mosidata,
(void*)misodata, nLSBfirst);
 734
 735         if (bits>65535){
 736                 LOG_ERROR("Cannot transfer more than 65536 bits at once!");
 737                 return ERROR_FAIL;
 738         }
 739
 740         if (bits>=8){
 741                 //Try to pack as many bits into bytes for better
performance.
 742                 bytes = bits/8;
 743                 bytes--;                      // MPSSE starts
counting bytes from 0.
 744                 buf[0]=(nLSBfirst)?0x31:0x39; // Clock Bytes In
and Out LSb or MSb first.
 745                 buf[1]=(char)bytes&0x0ff;
 746                 buf[2]=(char)((bytes>>8)&0x0ff);
 747                 bytes++;
 748                 for (byte=0;byte*8<bits;byte++){
 749                         databuf=0;
 750                         for (i=0;i<8;i++)
{databuf|=mosidata[byte*8+i]?(1<<i):0;}
 751                         buf[byte+3]=databuf;
 752                 }
 753                 retval=ft2232_write(buf, bytes+3, &bytes_written);
 754                 if (retval<0){
 755                         LOG_ERROR("ft2232_write() returns %d", retval);
 756                         return ERROR_FAIL;
 757                 }
 758                 retval=ft2232_read((uint8_t *)buf, bytes, &bytes_read);
 759                 if (retval<0){
 760                         LOG_ERROR("ft2232_read() returns %d", retval);
 761                         return ERROR_FAIL;
 762                 }
 763                 // Explode read bytes into bit array.
 764                 //for (bit=0;bit<bytes*8;bit++)
{misodata[bit]=(buf[bit/8]&(1<<bit))?1:0;}
 765                 for(byte=0;byte*8<bits;byte++)
for(bit=0;bit<8;bit++) misodata[byte*8+bit]=buf[byte]&(1<<bit)?1:0;
 766         }
 767
 768         // Now send remaining bits that cannot be packed as bytes.
 769         // Because "Clock Data Bits In and Out LSB/MSB" of FTDI
is a mess, pack single
 770         //  bit read/writes into buffer and then flush it using
single USB transfer.
 771         for (bit=bytes*8;bit<bits;bit++){
 772                 buf[3*bit+0]=(nLSBfirst)?0x33:0x3b;     // Clock
Bits In and Out LSb or MSb first.
 773                 buf[3*bit+1]=0;
// One bit per element.
 774                 buf[3*bit+2]=mosidata[bit]?0xff:0;      // Take
data from supplied array.
 775         }
 776         retval=ft2232_write(buf, 3*(bits-(bytes*8)), &bytes_written);
 777         if (retval<0){
 778                 LOG_ERROR("ft2232_write() returns %d", retval);
 779                 return ERROR_FAIL;
 780         }
 781         retval=ft2232_read((uint8_t *)misodata, bits-(bytes*8),
&bytes_read);
 782         if (retval<0){
 783                 LOG_ERROR("ft2232_read() returns %d", retval);
 784                 return ERROR_FAIL;
 785         }
 786         // FTDI MPSSE returns shift register value, our bit is MSb
 787         for (bit=bytes*8;bit<bits;bit++)
misodata[bit]=(misodata[bit]&(nLSBfirst?0x01:0x80))?1:0;
 788         //USE THIS FOR WIRE-LEVEL DEBUG
 789         //LOG_DEBUG("read 0x%02X written 0x%02X", misodata[bit],
mosidata[bit]);
 790
 791         return bit;
 792 }

Best regards! :-)

Tomek

-- 
CeDeROM, SQ7MHZ, http://www.tomek.cedro.info

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
OpenOCD-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openocd-devel

Reply via email to