title: FTDI LibMPSSE SPI
body: <p>I recently purchased the FTDI C232HM-DDHSL-0 USB cable for use with SPI and I2C devices; my goal is to read the memory from an SPI memory chip that I removed from a router. However, I am having issues getting the libMPSSE library &amp; 2xx drivers to send signals to a connected device.<strong>I hooked the leads of the C232 up to a Saleae logic analyzer and saw that no signals were being output!</strong></p>
  
  <p>Useful links for this question:</p>
  
  <ul>
  <li>FTDI C232HM-DDHSL-0 (purchase):
  <a href="https://www.ftdichip.com/Products/Cables/USBMPSSE.htm" rel="nofollow noreferrer">https://www.ftdichip.com/Products/Cables/USBMPSSE.htm</a></li>
  <li>C232HM-DDHSL-0 data sheet:
  <a href="https://www.ftdichip.com/Support/Documents/DataSheets/Cables/DS_C232HM_MPSSE_CABLE.PDF" rel="nofollow noreferrer">https://www.ftdichip.com/Support/Documents/DataSheets/Cables/DS_C232HM_MPSSE_CABLE.PDF</a></li>
  <li>Memory Chip data sheet: <a href="https://www.macronix.com/Lists/Datasheet/Attachments/7370/MX25L6406E,%203V,%2064Mb,%20v1.9.pdf" rel="nofollow noreferrer">https://www.macronix.com/Lists/Datasheet/Attachments/7370/MX25L6406E,%203V,%2064Mb,%20v1.9.pdf</a></li>
  <li>2xx drivers: <a href="https://www.ftdichip.com/Drivers/D2XX.htm" rel="nofollow noreferrer">https://www.ftdichip.com/Drivers/D2XX.htm</a></li>
  <li>MPSSE SPI library:
  <a href="https://www.ftdichip.com/Support/SoftwareExamples/MPSSE/LibMPSSE-SPI.htm" rel="nofollow noreferrer">https://www.ftdichip.com/Support/SoftwareExamples/MPSSE/LibMPSSE-SPI.htm</a></li>
  </ul>
  
  <p>I am using a <strong>Debian x86_64</strong> machine. The MPSSE SPI download only had the i386 version of the library, so I downloaded the MPSSE SPI source (<a href="https://www.ftdichip.com/Support/SoftwareExamples/MPSSE/LibMPSSE-SPI.htm" rel="nofollow noreferrer">https://www.ftdichip.com/Support/SoftwareExamples/MPSSE/LibMPSSE-SPI.htm</a>) and built the x86_64 bit version. There were no build errors or warnings.</p>
  
  <p>I copied libftd2xx.so and libMPSSE.so to /usr/local/lib.</p>
  
  <p>I plugged the cable in, then removed the following kernel modules:</p>
  
  <ul>
  <li>ftdi_sio  &lt;-- Readme says to take take out</li>
  <li>usbserial  &lt;-- Readme says to take out </li>
  <li>usb_wann  &lt;-- Needed to remove to take out usbserial</li>
  <li>qcserial  &lt;-- Needed to remove to take out usbserial</li>
  </ul>
  
  <p>At this point I was hoping that my set up was done correctly.</p>
  
  <p>I connected 6x cables to the 8 pin memory chip:</p>
  
  <ul>
  <li>VCC &lt;--> red lead </li>
  <li>Ground &lt;--> black lead</li>
  <li>Chip select &lt;--> brown lead</li>
  <li>Data in &lt;--> green</li>
  <li>serial clock &lt;--> orange</li>
  <li>Data out &lt;--> yellow   </li>
  </ul>
  
  <p>I did not connect hold and write protect pins on the memory chip. Recall my goal is to read the memory out of the chip, and the waveform for the read did not show those pins were necessary.</p>
  
  <p>I am using this program:</p>
  
  <pre><code>/* Standard C libraries */
  #include&lt;stdio.h&gt;
  #include&lt;stdlib.h&gt;
  #include&lt;string.h&gt;
  
  #include "ftd2xx.h"
  #include "libMPSSE_spi.h"
  
  FT_HANDLE ftHandle;
  
  uint8 tx_buffer[4096] = {0};
  uint8 rx_buffer[4096] = {0};
  
  int main()
  {
      uint8 i = 0;
      int sizeToTransfer = 0;
      int sizeTransfered = 0;
      FT_STATUS status = FT_OK;
      FT_DEVICE_LIST_INFO_NODE devList = {0};
      ChannelConfig channelConf = {0};
  
      channelConf.ClockRate = 30000000; // 30Mhz
      channelConf.LatencyTimer = 75;
      channelConf.configOptions = SPI_CONFIG_OPTION_MODE0 | SPI_CONFIG_OPTION_CS_DBUS3 | SPI_CONFIG_OPTION_CS_ACTIVELOW;
      channelConf.Pin = 0x00000000;/*FinalVal-FinalDir-InitVal-InitDir (for dir 0=in, 1=out)*/
  
  
      //
      // Open the channel and dump some information
      //
      status = SPI_GetChannelInfo(0,&amp;devList);
      if (status != FT_OK)
      {
          printf("SPI_GetChannelInfo failed, status = %d\n", status);
          return -1;
      }
      printf("Flags=0x%x\n",devList.Flags);
      printf("Type=0x%x\n",devList.Type);
      printf("ID=0x%x\n",devList.ID);
      printf("LocId=0x%x\n",devList.LocId);
      printf("SerialNumber=%s\n",devList.SerialNumber); // TODO: Why blank?
      printf("Description=%s\n",devList.Description);
      printf("ftHandle=0x%p\n",devList.ftHandle);/*is 0 unless open*/
  
  
      //
      // Open channel 0 
      //
      status = SPI_OpenChannel(0,&amp;ftHandle);
      if (status != FT_OK)
      {
          printf("SPI_OpenChannel failed, status = %d\n", status);
          return -1;
      }
  
      //
      // Initialize the channel: See configuration structure at top of main()
      //
      status = SPI_InitChannel(ftHandle,&amp;channelConf);
      if (status != FT_OK)
      {
          printf("SPI_InitChannel failed, status = %d\n", status);
          return -1;
      }
  
      //
      // Send the read command (0x03), and read what we get in our receive buffer
      //
      sizeToTransfer=8;
      sizeTransfered=0;
      tx_buffer[0] = 0x03;
      status = SPI_ReadWrite(ftHandle, rx_buffer, tx_buffer, sizeToTransfer, &amp;sizeTransfered, 
              SPI_TRANSFER_OPTIONS_SIZE_IN_BYTES|SPI_TRANSFER_OPTIONS_CHIPSELECT_DISABLE|SPI_TRANSFER_OPTIONS_CHIPSELECT_ENABLE);
      if (status != FT_OK)
      {
          printf("SPI_ReadWrite failed, status = %d\n", status);
          return -1;
      }
  
      //
      // Dump the receive buffer to see if we got anything.
      //
      printf("Size transfered = %d\n", sizeTransfered);
      i = 0;
      while (i &lt; sizeTransfered)
      {
          printf("%02x",rx_buffer[i]);
          i++;
      }   
      printf("\n");
  
      //
      // Cleanup
      //
      status = SPI_CloseChannel(ftHandle);
      if (status != FT_OK)
      {   
          printf("SPI_CloseChannel failed, ret = %d\n", status);
      }
  
      return 0;
  }
  </code></pre>
  
  <p>To make and run the program:</p>
  
  <pre><code>To compile: gcc read_memory.c -lMPSSE -ldl
  To run: sudo ./a.out
  </code></pre>
  
  <p>My output is:</p>
  
  <pre><code>// The driver can at least detect the cable.
  Flags=0x2
  Type=0x8
  ID=0x4036001
  LocId=0x204
  SerialNumber=
  Description=USB &lt;-&gt; Serial
  ftHandle=0x(nil)
  Size transfered = 8
  
  // Junk in the receive buffer
  ff037fffffffffff
  </code></pre>
  
  <p>Whether I keep the memory chip connected or disconnected I get the same junk in the receive buffer. I see no LEDs light up on the cable or anything to indicate it is "working." I have tried SPI_Write() and SPI_Read() and get similar behavior. I tested on an Ubuntu VM (running on Windows host) and saw the exact same behavior.</p>
  
  <p>I am really excited to get this to work so if anyone can help me with what I am doing wrong it would be greatly appreciated! Thanks!</p>