good morning,
I am new to ft2232H. I have tried to implement serial communication using MPSSE command in loop back mode. I tried to run code given for serial communication in AN_135
FTDI MPSSE Basics in loop back mode. But it gives
" Error - MPSSE receive buffer should have the looped-back data ".
I tried both the way 1. using command " byOutputBuffer[dwNumBytesToSend++] = 0x84; " to internally connect TDI/DO PIN and TDO/DI .
2. externally also connected both the pins.
i want the solution for this. Please correct me if I made any mistakes as soon as possible.
int main()
{
// -----------------------------------------------------------
// Variables
// -----------------------------------------------------------
FT_HANDLE ftHandle; // Handle of the FTDI device
FT_STATUS ftStatus; // Result of each D2XX call
DWORD dwNumDevs; // The number of devices
unsigned int uiDevIndex = 0xF; // The device in the list that we'll use
BYTE byOutputBuffer[8]; // Buffer to hold MPSSE commands and data
// to be sent to the FT2232H
BYTE byInputBuffer[8]; // Buffer to hold data read from the FT2232H
DWORD dwCount = 0; // General loop index
DWORD dwNumBytesToSend = 0; // Index to the output buffer
DWORD dwNumBytesSent = 0; // Count of actual bytes sent - used with FT_Write
DWORD dwNumBytesToRead = 0; // Number of bytes available to read
// in the driver's input buffer
DWORD dwNumBytesRead = 0; // Count of actual bytes read - used with FT_Read
DWORD dwClockDivisor = 0xFFFF; // Value of clock divisor, SCL Frequency =
// 60/((1+0x05DB)*2) (MHz) = 1Mhz
// -----------------------------------------------------------
// Does an FTDI device exist?
// -----------------------------------------------------------
printf("Checking for FTDI devices...\n");
ftStatus = FT_CreateDeviceInfoList(&dwNumDevs);
// Get the number of FTDI devices
if (ftStatus != FT_OK) // Did the command execute OK?
{
printf("Error in getting the number of devices\n");
return 1; // Exit with error
}
if (dwNumDevs < 1) // Exit if we don't see any
{
printf("There are no FTDI devices installed\n");
return 1; // Exit with error
}
printf("%lu FTDI devices found \
- the count includes individual ports on a single chip\n", dwNumDevs);
// -----------------------------------------------------------
// Open the port - For this application note, we'll assume the first device is a
// FT2232H or FT4232H. Further checks can be made against the device
// descriptions, locations, serial numbers, etc. before opening the port.
// -----------------------------------------------------------
printf("\nAssume first device has the MPSSE and open it...\n");
ftStatus = FT_Open(0, &ftHandle);
if (ftStatus != FT_OK)
{
printf("Open Failed with error %lu\n", ftStatus);
return 1; // Exit with error
}
// Configure port parameters
printf("\nConfiguring port for MPSSE use...\n");
ftStatus |= FT_ResetDevice(ftHandle);
//Reset USB device
//Purge USB receive buffer first by reading out all old data from FT2232H receive buffer
ftStatus |= FT_GetQueueStatus(ftHandle, &dwNumBytesToRead);
// Get the number of bytes in the FT2232H
// receive buffer
if ((ftStatus == FT_OK) && (dwNumBytesToRead > 0))
FT_Read(ftHandle, &byInputBuffer, dwNumBytesToRead, &dwNumBytesRead);
//Read out the data from FT2232H receive buffer
ftStatus |= FT_SetUSBParameters(ftHandle, 65536, 65535);
//Set USB request transfer sizes to 64K
ftStatus |= FT_SetChars(ftHandle, false, 0, false, 0);
//Disable event and error characters
ftStatus |= FT_SetTimeouts(ftHandle, 0, 5000);
//Sets the read and write timeouts in milliseconds
ftStatus |= FT_SetLatencyTimer(ftHandle, 1);
//Set the latency timer to 1mS (default is 16mS)
ftStatus |= FT_SetFlowControl(ftHandle, FT_FLOW_RTS_CTS, 0x00, 0x00);
//Turn on flow control to synchronize IN requests
ftStatus |= FT_SetBitMode(ftHandle, 0x0, 0x00);
//Reset controller
ftStatus |= FT_SetBitMode(ftHandle, 0x0, 0x02);
//Enable MPSSE mode
if (ftStatus != FT_OK)
{
printf("Error in initializing the MPSSE %lu\n", ftStatus);
FT_Close(ftHandle);
return 1; // Exit with error
}
Sleep(50); // Wait for all the USB stuff to complete and work
// Enable internal loop-back
byOutputBuffer[dwNumBytesToSend++] = 0x84;
// Enable loopback
ftStatus = FT_Write(ftHandle, byOutputBuffer, \
dwNumBytesToSend, &dwNumBytesSent);
// Send off the loopback command
dwNumBytesToSend = 0; // Reset output buffer pointer
// Check the receive buffer - it should be empty
ftStatus = FT_GetQueueStatus(ftHandle, &dwNumBytesToRead);
// the FT2232H receive buffer
if (dwNumBytesToRead != 0)
{
printf("Error - MPSSE receive buffer should be empty\n", ftStatus);
FT_SetBitMode(ftHandle, 0x0, 0x00);
// Reset the port to disable MPSSE
FT_Close(ftHandle); // Close the USB port
return 1; // Exit with error
}
// -----------------------------------------------------------
// Synchronize the MPSSE by sending a bogus opcode (0xAB),
// The MPSSE will respond with "Bad Command" (0xFA) followed by
// the bogus opcode itself.
// -----------------------------------------------------------
byOutputBuffer[dwNumBytesToSend++] = 0xAB;
//Add bogus command ‘0xAB’ to the queue
ftStatus = FT_Write(ftHandle, byOutputBuffer, dwNumBytesToSend, &dwNumBytesSent);
// Send off the BAD command
dwNumBytesToSend = 0; // Reset output buffer pointer
do
{
ftStatus = FT_GetQueueStatus(ftHandle, &dwNumBytesToRead);
// Get the number of bytes in the device input buffer
} while ((dwNumBytesToRead == 0) && (ftStatus == FT_OK));
//or Timeout
bool bCommandEchod = false;
ftStatus = FT_Read(ftHandle, &byInputBuffer, dwNumBytesToRead, &dwNumBytesRead);
//Read out the data from input buffer
for (dwCount = 0; dwCount < dwNumBytesRead - 1; dwCount++)
//Check if Bad command and echo command are received
{
if ((byInputBuffer[dwCount] == 0xFA) && (byInputBuffer[dwCount+1] == 0xAB))
{
bCommandEchod = true;
break;
}
}
if (bCommandEchod == false)
{
printf("Error in synchronizing the MPSSE\n");
FT_Close(ftHandle);
return 1; // Exit with error
}
dwNumBytesToSend = 0; // Reset output buffer pointer
// Check the receive buffer - it should be empty
ftStatus = FT_GetQueueStatus(ftHandle, &dwNumBytesToRead);
// Get the number of bytes in
// the FT2232H receive buffer
if (dwNumBytesToRead != 0)
{
printf("Error - MPSSE receive buffer should be empty\n", ftStatus);
FT_SetBitMode(ftHandle, 0x0, 0x00);
// Reset the port to disable MPSSE
FT_Close(ftHandle); // Close the USB port
return 1; // Exit with error
}
//MPSSE Setup
// -----------------------------------------------------------
// Configure the MPSSE settings for JTAG
// Multple commands can be sent to the MPSSE with one FT_Write
// -----------------------------------------------------------
dwNumBytesToSend = 0; // Start with a fresh index
// Set up the Hi-Speed specific commands for the FTx232H
byOutputBuffer[dwNumBytesToSend++] = 0x8A;
// Use 60MHz master clock (disable divide by 5)
byOutputBuffer[dwNumBytesToSend++] = 0x97;
// Turn off adaptive clocking (may be needed for ARM)
byOutputBuffer[dwNumBytesToSend++] = 0x8D;
// Disable three-phase clocking
ftStatus = FT_Write(ftHandle, byOutputBuffer, dwNumBytesToSend, &dwNumBytesSent);
// Send off the HS-specific commands
dwNumBytesToSend = 0; // Reset output buffer pointer
// Set TCK frequency
// TCK = 60MHz /((1 + [(1 +0xValueH*256) OR 0xValueL])*2)
byOutputBuffer[dwNumBytesToSend++] = '\x86';
// Command to set clock divisor
byOutputBuffer[dwNumBytesToSend++] = dwClockDivisor & 0xFF;
// Set 0xValueL of clock divisor
byOutputBuffer[dwNumBytesToSend++] = (dwClockDivisor >> 8) & 0xFF;
// Set 0xValueH of clock divisor
ftStatus = FT_Write(ftHandle, byOutputBuffer, dwNumBytesToSend, &dwNumBytesSent);
// Send off the clock divisor commands
dwNumBytesToSend = 0; // Reset output buffer pointer
// Set initial states of the MPSSE interface
// - low byte, both pin directions and output values
// Pin name Signal Direction Config Initial State Config
// ADBUS0 TCK/SK output 1 high 1
// ADBUS1 TDI/DO output 1 low 0
// ADBUS2 TDO/DI input 0 0
// ADBUS3 TMS/CS output 1 high 1
// ADBUS4 GPIOL0 output 1 low 0
// ADBUS5 GPIOL1 output 1 low 0
// ADBUS6 GPIOL2 output 1 high 1
// ADBUS7 GPIOL3 output 1 high 1
byOutputBuffer[dwNumBytesToSend++] = 0x80;
// Configure data bits low-byte of MPSSE port
byOutputBuffer[dwNumBytesToSend++] = 0xC9;
// Initial state config above
byOutputBuffer[dwNumBytesToSend++] = 0xFB;
// Direction config above
ftStatus = FT_Write(ftHandle, byOutputBuffer, dwNumBytesToSend, &dwNumBytesSent);
// Send off the low GPIO config commands
dwNumBytesToSend = 0; // Reset output buffer pointer
// Note that since the data in subsequent sections will be clocked on the rising edge, the
// inital clock state of high is selected. Clocks will be generated as high-low-high.
// For example, in this case, data changes on the rising edge to give it enough time
// to have it available at the device, which will accept data *into* the target device
// on the falling edge.
// Set initial states of the MPSSE interface
// - high byte, both pin directions and output values
// Pin name Signal Direction Config Initial State Config
// ACBUS0 GPIOH0 input 0 0
// ACBUS1 GPIOH1 input 0 0
// ACBUS2 GPIOH2 input 0 0
// ACBUS3 GPIOH3 input 0 0
// ACBUS4 GPIOH4 input 0 0
// ACBUS5 GPIOH5 input 0 0
// ACBUS6 GPIOH6 input 0 0
// ACBUS7 GPIOH7 input 0 0
byOutputBuffer[dwNumBytesToSend++] = 0x82;
// Configure data bits low-byte of MPSSE port
byOutputBuffer[dwNumBytesToSend++] = 0x00;
// Initial state config above
byOutputBuffer[dwNumBytesToSend++] = 0x00;
// Direction config above
ftStatus = FT_Write(ftHandle, byOutputBuffer, dwNumBytesToSend, &dwNumBytesSent);
// Send off the high GPIO config commands
dwNumBytesToSend = 0; // Reset output buffer pointer
for(dwCount = 0; dwCount < 8; dwCount++)
{ // Clear out the input and output buffers
byInputBuffer[dwCount] = 0x00;
byOutputBuffer[dwCount] = 0x00;
}
// Data Transmit, no receive
dwNumBytesToSend = 0;
byOutputBuffer[dwNumBytesToSend++] = 0x84;
// Enable loopback
ftStatus = FT_Write(ftHandle, byOutputBuffer, \
dwNumBytesToSend, &dwNumBytesSent);
//sleep(2);
dwNumBytesToSend = 0;
byOutputBuffer[dwNumBytesToSend++] = 0x10;
// Output on rising clock, no input
// MSB first, clock a number of bytes out
byOutputBuffer[dwNumBytesToSend++] = 0x01; // Length L
byOutputBuffer[dwNumBytesToSend++] = 0x00; // Length H
// Length = 0x0001 + 1
byOutputBuffer[dwNumBytesToSend++] = 0xA5;
byOutputBuffer[dwNumBytesToSend++] = 0x0F;
// Data = 0xA50F
ftStatus = FT_Write(ftHandle, byOutputBuffer, dwNumBytesToSend, &dwNumBytesSent);
// Send off the command
dwNumBytesToSend = 0; // Reset output buffer pointer
Sleep(2); // Wait for data to be transmitted and status
// to be returned by the device driver
// - see latency timer above
// Check the receive buffer - it should be empty
ftStatus = FT_GetQueueStatus(ftHandle, &dwNumBytesToRead);
// Get the number of bytes in
// the FT2232H receive buffer
// It should be zero since there was
// no data clocked *in*
FT_Read(ftHandle, &byInputBuffer, dwNumBytesToRead, &dwNumBytesRead);
if (dwNumBytesToRead != 0)
{
printf("Error - MPSSE receive buffer should be empty\n", ftStatus);
FT_SetBitMode(ftHandle, 0x0, 0x00);
// Reset the port to disable MPSSE
FT_Close(ftHandle); // Close the USB port
return 1; // Exit with error
}
printf("Press <Enter> to continue\n");
getchar(); // wait for a carriage return
// Now repeat the transmission with the send and receive op-code in place of transmit-only
// Data Transmit, with receive
byOutputBuffer[dwNumBytesToSend++] = 0x34;
// Output on rising clock, input on falling clock
// MSB first, clock a number of bytes out
byOutputBuffer[dwNumBytesToSend++] = 0x01; // Length L
byOutputBuffer[dwNumBytesToSend++] = 0x00; // Length H
// Length = 0x0001 + 1
byOutputBuffer[dwNumBytesToSend++] = 0xA5;
byOutputBuffer[dwNumBytesToSend++] = 0x0F;
// Data = 0xA50F
ftStatus = FT_Write(ftHandle, byOutputBuffer, dwNumBytesToSend, &dwNumBytesSent);
// Send off the command
dwNumBytesToSend = 0; // Reset output buffer pointer
Sleep(2); // Wait for data to be transmitted and status
// to be returned by the device driver
// - see latency timer above
// Check the receive buffer - it should contain the looped-back data
ftStatus = FT_GetQueueStatus(ftHandle, &dwNumBytesToRead);
// Get the number of bytes in
// the FT2232H receive buffer
// It should be zero since there was
// no data clocked *in*
FT_Read(ftHandle, &byInputBuffer, dwNumBytesToRead, &dwNumBytesRead);
// The input buffer should contain the same number of bytes as those output
printf("\n size:%d",dwNumBytesToRead);
if (dwNumBytesToRead != 2)
{
printf("Error - MPSSE receive buffer should have the looped-back data\n");
FT_SetBitMode(ftHandle, 0x0, 0x00);
// Reset the port to disable MPSSE
FT_Close(ftHandle); // Close the USB port
return 1; // Exit with error
}
printf("The correct number of bytes have been received\n");
// Check to be sure it's the same.
for(dwCount = 0; dwCount <= dwNumBytesRead - 1; dwCount++)
{
if (byInputBuffer[dwCount] != byOutputBuffer[dwCount + 3])
// Output data begins at location 3,
// after the opcode and length
{
printf("Error - Data received does not match data output\n");
FT_SetBitMode(ftHandle, 0x0, 0x00);
// Reset the port to disable MPSSE
FT_Close(ftHandle); // Close the USB port
return 1; // Exit with error
}
}
printf("The input data matches the output data\n");
printf("Press <Enter> to continue\n");
getchar(); // wait for a carriage return
// Clear the buffers
for(dwCount = 0; dwCount < 8; dwCount++)
{
byInputBuffer[dwCount] = 0x00;
byOutputBuffer[dwCount] = 0x00;
}
FT_Close(ftHandle);
return 0;
}