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 & 2xx drivers to send signals to a connected device.I hooked the leads of the C232 up to a Saleae logic analyzer and saw that no signals were being output!
Useful links for this question:
I am using a Debian x86_64 machine. The MPSSE SPI download only had the i386 version of the library, so I downloaded the MPSSE SPI source (https://www.ftdichip.com/Support/SoftwareExamples/MPSSE/LibMPSSE-SPI.htm) and built the x86_64 bit version. There were no build errors or warnings.
I copied libftd2xx.so and libMPSSE.so to /usr/local/lib.
I plugged the cable in, then removed the following kernel modules:
At this point I was hoping that my set up was done correctly.
I connected 6x cables to the 8 pin memory chip:
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.
I am using this program:
/* Standard C libraries */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#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,&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,&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,&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, &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 < 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;
}
To make and run the program:
To compile: gcc read_memory.c -lMPSSE -ldl
To run: sudo ./a.out
My output is:
// The driver can at least detect the cable.
Flags=0x2
Type=0x8
ID=0x4036001
LocId=0x204
SerialNumber=
Description=USB <-> Serial
ftHandle=0x(nil)
Size transfered = 8
// Junk in the receive buffer
ff037fffffffffff
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.
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!
Set device first to MPSSE mode, and it should work. See quite minimum (Python) example below based on FTD2XX library only (tested in Windows). LibMPSSE is not required to run simple SPI. Data can be read by s = dev.read(nbytes)
, where nbytes is byte count. Find more information in nice tutorial: Driving an SPI device using MPSSE
import ftd2xx
OPS = 0x03 # Bit mask for SPI clock and data out
OE = 0x08 # CS
dev = ftd2xx.open(0) # open first available device
if dev:
dev.setTimeouts(1000, 1000)
dev.setBitMode(OPS, 2) # bit mask, MPSSE mode
dev.write(bytes((0x86, 59, 0))) # set SCK to 100kHz
dev.write(bytes((0x80, 0, OE + OPS))) # CS low
data = 0x55,
n = len(data) - 1
dev.write(bytes(((0x11, n % 256, n // 256) + data))) # write SPI data
dev.write(bytes((0x80, OE, OE + OPS))) # CS high
dev.close()
User contributions licensed under CC BY-SA 3.0