FTDI Device EEPROM Programming Using Vinculum VNC1L - AN 105
FTDI Device EEPROM Programming Using Vinculum VNC1L - AN 105
This document describes a C application that uses the VNC1L to program the EEPROM of an
FTDI peripheral device.
5 Contact Information............................................................................. 18
Appendix A - References .......................................................................... 19
Appendix B - Revision History.................................................................. 20
The VNC1L is a USB host controller IC which allows data to be transferred via USB to an FTDI peripheral
device (FTxxx). The FTDI devices may use an EEPROM to store USB device descriptors that can be
programmed over the USB. Programming is commonly done by connecting the FTDI device to a PC,
installing the required FTDI drivers and using the driver API functions to program the EEPROM of the
device. This application note describes how to configure the VNC1L to program the EEPROM of an FTDI
device.
Firmware available for the VNC1L allows the user to read, write and erase the EEPROM of an FTDI device.
These firmware commands can be used to reprogram the VID, PID, serial number, manufacturer string
and description string within the EEPROM of all existing FTDI peripheral devices connected to the VNC1L.
This can be achieved using a C application on a PC. The example code for Microsoft® Visual Studio® 2008
is available by request under NDA. Contact [email protected] .
Any software code examples given in this document are for information only. The examples are not
guaranteed and are not supported by FTDI.
1.1 Conventions
The following conventions are used in this document:
Convention Description
Monospaced type Indicates input or output from the monitor.
Terms Description
Command line interface which allows instructions to be given to the VNC1L and
Monitor
responses to be returned.
FTxxx Refers to the FT232R, FT245R, FT232B, FT245B and FT2232D/L/C chips.
The hardware required in this application is an FTDI VDIP1 development module and an FTDI TTL-232R-
3V3 cable. The VDIP1 module contains a VNC1L. A PC is used to communicate with the VNC1L on the
VDIP1 via the TTL-232-3V3 cable. The cable connects to the USB port of a PC and converts USB
signalling to a serial UART interface (at TTL levels). The serial UART signals connect to the VDIP1 module
via a six way header. The pin out for the six way header is described in Table 2.1 and Figure 2.1. The
monitor port of the VDIP1 must be configured in UART mode by setting the jumper links J3 and J4 on the
VDIP1 module as shown in Figure 2.1.
TTL Cable Header TTL Cable VDIP1 Pin Name VDIP1 Pin Number
Pin Number Header Pin Name
An alternative setup would be to attach a MCU or FPGA to the monitor port of the VDIP1 instead of the PC
and TTL-232R-3V3 cable.
To program the EEPROM of an FTxxx peripheral device, connect the USB socket of the FTxxx device into
the USB host port on the VDIP1 and then run the C application on the PC.
Note: An FTxxxB and FT2232D/C/L device must have an EEPROM connected to the IC. Ensure that when
using an FTxxxB or FT2232D/C/L device that there is an EEPROM connected to the device before
attempting to program the EEPROM using the VNC1L.
The TTL-232R-3V3 cable requires its own drivers. These drivers need to be installed on the PC. The
drivers for the cable are available from the Drivers section of the FTDI website. Ensure that the drivers
for the correct PC operating system are used.
Sending firmware commands to the VNC1L requires an application that transmits data down the TTL-
232R-3V3 cable. The FTDI D2XX Direct Driver allows the application software to interface with the
FT232R IC which is integrated within the TTL-232R-3V3 cable. The FTD2XX.DLL provides functions which
allow the firmware commands to communicate with the VNC1L from the PC. An explanation of the
application code that sends the firmware commands to the VNC1L is given in section 4.
There are a number of VNC1L firmware options. The VDIP1 module uses the VDAP firmware. The
firmware required for the EEPROM commands must be at least VDAP version 3.56 as the EEPROM
commands needed for this application were not available in earlier VDAP revisions.
If it is necessary to upgrade the VDAP software, please refer to the Vinculum Data Sheet for details of
how to do this.
An alternative could be to attach a MCU or FPGA to control the VNC1L. This would not require the TTL-
232R-3V3 cable or PC so there would be no need to install the drivers that are mentioned in Section
2.2.1. Instead the MCU or FPGA would require firmware programmed onto them that would send the
same firmware commands to the VNC1L as explained in the application code in Section 4. The main
advantage of this is that the device would not require a PC to program the EEPROM of the FTxxx devices
making the programmer application portable.
The VNC1L commands for reading, writing, and erasing the FTxxx chips EEPROM are referenced in Table
3.1. See the Vinculum Firmware Manual for the complete command set.
97 20 Address (1 byte),
FER <sp> Address (1 Byte) Read EEPROM
0D
Table 3.1 EEPROM access commands
Parameters: None.
Erase an external EEPROM (93C46, 93C56 or 93C66) attached to either an FT2xxB or FT2232D/C/L
device. This command has no effect on the inbuilt EEPROM of the FT2xxR.
Error Codes: None.
Parameters:
Address – 1 Byte: EEPROM address to be accessed.
Data – 2 Bytes: The data to be sent to the specified address, MSB first.
This command specifies an address and writes 2 bytes of data to that address. The access is word
aligned.
Error Codes: None.
Parameters:
Address - Byte: EEPROM address to be accessed.
This command reads back two bytes from the specified address. The data is returned MSB first.
Error Codes: None.
The following example details software which sets up a user interface to modify the VID, PID, serial
number, manufacturer string and description string of the FTxxx EEPROM. The firmware commands used
throughout this application note are documented in the Vinculum Firmware User Manual. The application
software code that this application note is based on is only available by request under NDA. Contact
[email protected] .
The code uses the D2XX DLL API functions to access the TTL-232R-3V3 cable. The full API function set is
documented in the D2XX programmer’s guide. The VNC1L UART monitor port has default interface
parameters that require to be configured in the TTL-232R-3V3 cable in order to access the VNC1L’s
monitor port. The FT_Open function opens the TTL-232R-3V3 cable for communication.
Parameters Values
Data Bits 8
Stop Bits 1
Parity None
To setup the parameters to match the VNC1L default parameters (see Table 4.1) the following subroutine
needs to be called.
{
//set baud rate
Status = FT_SetBaudRate(FtHandle,BaudRate);
//set serial parameters
Status = FT_SetDataCharacteristics(FtHandle, FT_BITS_8, FT_STOP_BITS_1,
FT_PARITY_NONE);
//set RTS line of TTL 232R
Status = FT_SetRts(FtHandle);
//set flow control to RTS/CTS
Status = FT_SetFlowControl(FtHandle, FT_FLOW_RTS_CTS, 0, 0);
}
Figure 4.1 Configure Port Code
This will establish a connection between the TTL-232R-3V3 cable and the VDIP1 module.
When the connection between the VDIP1 and TTL-232R-3V3 cable has been established, the VNC1L then
requires to be configured to establish a connection with the FTxxx device attached to the USB port 2 of
the VDIP1. The VNC1L operates by receiving firmware commands via the monitor port to perform a
certain function. When the VNC1L receives and processes a firmware command it returns a message to
the monitor port that lets the device connected to the monitor port know if the function was completed or
not. The subroutines described in 4.2.1 – 4.2.8 are required to make sure that the VNC1L is setup to
communicate with the FTxxx device and ready to start the EEPROM firmware commands.
Before sending firmware commands to the VCN1L a procedure needs to be able to read the responses
from the VNC1L. A subroutine is required to retrieve the amount of data in the TTL-232R-3V3 cable
receive buffer. This will calculate the number of bytes (RxBytes) that the VNC1L has returned to the TTL-
232R-3V3 cable.
{
DWORD TxBytes;
DWORD EventDword;
*RxBytes = 0;
The ReadByte() subroutine shown in Figure 4.3 uses the number of bytes in the receive buffer obtained
by calling the QueueStatus() subroutine and transfers this data into the DataIn buffer. The application
then checks this data to ensure that it is valid.
QueueStatus(&RxBytes);
ReadDataLength = RxBytes;
*DataRead = 0;
if (RxBytes == 0x00)
{
return;
}
else
{
Status = FT_Read(FtHandle, DataIn, ReadDataLength, DataRead);
if(Status != FT_OK)
{
printf("Read Failed\n");
ErrorStatus();
}
}
}
Figure 4.3 Read a Byte Routine
The code structure in Figure 4.4 is used to write firmware commands to the VNC1L. The variables
CmdSet and Len will change depending on the command that is sent. This fragment of code is referred to
throughout Section 4.2 using different variable values required for the appropiate firmware commands.
WriteDataLength = Len;
DataWritten = 0;
//Send command
Status = FT_Write(FtHandle, &CmdSet, WriteDataLength, &DataWritten);
if(Status != FT_OK)
{
printf("Write Failed\n");
ErrorStatus();
}
Sleep(30);
do
{
ReadByte(DataIn, &DataRead); //polling for prompt
}
while(DataRead = 0);
}
Figure 4.4 Write Routine
To ensure that the VNC1L is responding correctly to the data sent by the PC a carriage return is
transmitted to the VNC1L. A 0x0D is inserted into a data buffer and is written to the VNC1L. The VNC1L
should then respond with a prompt that is read in the ReadByte() subroutine. The carriage return is sent
to the VNC1L by using the write routine shown in Figure 4.4 with the variables CmdSet and Len set as
follows:
Len = 1;
UCHAR CmdSet[Len] = {0x0D}; //these hex values ac carriage return
The shortened command set reduces the number of characters required to be sent to the VNC1L. A
subroutine is set up in the application to switch from the monitors default extended command set (see
Table 4.1) to the shortened command set. In extended command set mode, printable characters are used
and commands are typically longer. In short command set mode, the commands are optimised for
program control and they have binary values representing the command. The shortened command set
mode is set in the VNC1L by using the write routine shown in Figure 4.4 with the variables CmdSet and
Len set as follows:
Len = 2;
UCHAR CmdSet[Len] = {0x10,0x0D}; //these hex values represent the shortened
//version of SCS
To check that an FTxxx device is attached to the VNC1L USB port 2 of the VDIP1 the Query Port 2 (QP2)
command is used. The QP2 command will return two bytes of information about the device that is
connected into USB port 2 of the VDIP1.
6 Unknown Device
1 Reserved (always 0)
Two bytes are returned by the VNC1L after a QP2 command is sent. The most significant byte (MSB) will
indicate the type of device that is attached to the VDIP1 and this byte is defined in Table 4.2. The QP()
subroutine is required to check if an FTxxx device is attached by sending the QP2 command to the VNC1L
and then reading the response. A check is done on the response data returned from the VNC1L to ensure
that bit 0 of the MSB is set to ‘1’ (this indicates an FTxxx Device) before the application continues. The
QP() subroutine calls the write routine shown in Figure 4.4 with the variables CmdSet and Len set as
follows:
Len = 2;
UCHAR CmdSet[Len] = {0x2C, 0x0D}; //these hex values represent the shortened
//version of QP2
To send data to an FTxxx device using the VNC1L it is necessary to select the correct endpoint of the
FTxxx device. The command SC 0 will select the correct endpoint for an FTxxx device. The SC()
subroutine calls the write routine shown in Figure 4.4 with the variables CmdSet and Len set as follows:
Len = 4;
UCHAR CmdSet[Len] = {0x86, 0x20, 0x00, 0x0D}; //these hex values represent the
//shortened version of SC 0
Before sending the EEPROM firmware commands, the application requires to determine the type of FTxxx
device connected to the VDIP1 before it can call the EEPROM subroutine for that particular chip. There
are three different chip types (FTxxxR, FTxxxB, and the FT2232D/C/L) which all have subtle differences
in their EEPROM structures and therefore require a specific subroutine when writing data to their
EEPROMs.
To determine which type of device is connected to the VDIP1 it is necessary to send the QD 0 command
to the VNC1L. The QD() subroutine calls the write routine shown in Figure 4.4 with the variables CmdSet
and Len set as follows:
Len = 4;
UCHAR CmdSet[Len] = {0x85, 0x20, 0x00, 0x0D}; //these hex values represent the
//shortened version of QD 0
The VNC1L returns 32 bytes of data after receiving a QD command. The FTxxx device type information is
indicated by the BCD bytes which are at an offset of 18, as shown in Table 4.3
0 1 USB Address
6 1 Data Toggles
8 1 Reserved
10 1 MI Index
11 1 Device Class
13 1 Device Protocol
14 2 VID
16 2 PID
18 2 BCD
21 - 31 11 Reserved
The BCD value returned from the QD command will be one of the following:
0x0600 – Represents an FTxxxR chip
0x0500 – Represents an FT2232D/C/L chip
0x0400 – Represents an FTxxxB chip
A comparison is done in the application code that determines what type of FTxxx chip is attached to the
VDIP1.
When the VNC1L has been configured (see section 4.2), the application software can begin programming
the EEPROM of the attached FTxxx device. Sections 4.3.1 – 4.3.4 describe the methods used to configure
the VID, PID, serial number, manufacturer string and description string of the FTxxx device.
There are three different EEPROM structures for the different device types. Writing data to the EEPROMs
of these three structures is very similar. Before the application overwrites any existing EEPROM
parameters it reads all the data currently in the EEPROM into a data buffer. The FER command defined in
section 3.3 can be used to returns 2 bytes of data from a location in the EEPROM. For simplicity it is
easier to read the data returned using the FER command in words rather than bytes. Figure 4.5
illustrates a subroutine for reading a word of data back from the VNC1L and Figure 4.6 shows a
subroutine for writing the FER command to the VCN1L. The FerWord() subroutine uses a variable called
AddrCount that can be changed to access the different locations in the EEPROM. To read the current
EEPROM data into the data buffer the AddrCount increments through every location in the EEPROM and
saves the data word returned into the data buffer. When complete, the data buffer will hold the values for
the entire EEPROM. The values of parameters such as the VID and PID can be replaced with new values
by editing the values in the data buffer. When the data buffer has been modified to the required custom
values, the entire data buffer is written back to the EEPROM in one routine.
{
DWORD RxBytes;
DWORD ReadDataLength;
memset(DataWordIn,0,5);
QueueStatus(&RxBytes);
ReadDataLength = RxBytes;
*DataRead = 0;
if (RxBytes == 0x00)
{
return;
}
else {
Status = FT_Read(FtHandle, DataWordIn, ReadDataLength, DataRead);
if(Status != FT_OK)
{
printf("Status not ok %d\n", Status);
ErrorStatus();
}
}
}
Figure 4.5 Read a Word Routine
{
DWORD WriteDataLength;
DWORD DataWritten;
//Send command
Status = FT_Write(FtHandle, &CmdSet, WriteDataLength, &DataWritten);
if(Status != FT_OK)
{
printf("Read Failed");
ErrorStatus();
}
Sleep(30);
do
{
ReadWord(DataWordIn, DataRead);
}
while(DataRead = 0);
}
Figure 4.6 Read a Word from an EEPROM
When the current data values of the EEPROM have been read into a data buffer, the next step is to create
a user interface that scans in the new parameters for the new VID, PID, serial number, manufacturer
string and description string. This would then replace the values currently in the data buffer with these
new required values. Each chip type has different locations for holding the parameters in the EEPROM.
The EEPROM structure document is only available on request under NDA. Contact [email protected]
When the user interface has completed editing the data in the data buffer, the checksum needs to be
recalculated and updated (see Section 4.3.4) before writing all the new data into the EEPROM. Figure 4.6
shows a subroutine that sends the FEW command (see Section 3.2) to the VNC1L to write data to the
EEPROM. A prompt is returned from the VNC1L if the command was executed successfully. The
ReadByte() subroutine function checks for the correct returned prompt. The AddrCount variable is
incremented to write the data that is held in the data buffer into every location of the EEPROM.
{
DWORD WriteDataLength;
DWORD DataWritten;
DWORD DataRead = 0;
UCHAR DataIn[512];
The FTxxxB and FT2232D/C/L chips have similar procedures for writing to their EEPROMs using the
VNC1L firmware commands. The EEPROM for the FTxxxR chip is integrated into the chip. Since the
EEPROM is internal you cannot erase the data using the FEE command (see Section 3.1). Also, the
latency time of the FTxxxR device needs to be set to 77ms (default latency time is 16ms) in order to
successfully write to the EEPROM of the device. Due to this latency, an additional subroutine is required
to set the latency time of an FTxxx device to 77ms using the VNC1L firmware command SSU. Since there
is no specific VNC1L firmware command to change the latency of an FTxxx chip the SSU command is
used to manually configure this latency in the FTxxxR device. The SSU command sends a packet of data
to a USB device control endpoint with a setup command. The subroutine for sending the SSU command is
shown in figure 4.7.
{
DWORD WriteDataLength;
DWORD DataWritten;
DWORD DataRead = 0;
UCHAR DataIn[512];
UCHAR CmdSet[11] = {0x9A, 0x20, 0x40, 0x09, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0D};
WriteDataLength = 11;
DataWritten = 0;
//Send command
Status = FT_Write(FtHandle, &CmdSet, WriteDataLength, &DataWritten);
if(Status != FT_OK)
{
printf("SC Command Failed\n");
ErrorStatus();
}
Sleep(30);
do
{
ReadByte(DataIn, &DataRead); //polling for prompt
}
while(DataRead = 0);
}
Figure 4.7 SSU Command to Change the Latency to 77ms
When the latency has been configured, the internal EEPROM can be accessed using the FEW command.
When writing to the EEPROM of FTxxxR devices, it is necessary to send data 2* 16 bit words (WORD1
and WORD2).
For example, Table 4.4 shows a segment of an example EEPROM map:
00 $0101 (WORD 1)
01 $0101 (WORD 2)
02 $0101 (WORD 1)
03 $0101 (WORD 2)
04 $0101 (WORD 1)
05 $0101 (WORD 2)
LOC = 05 (WORD 2)
FEW·$(LOC)0101 //current data in location 05
<prompt>
LOC = 01 (WORD 2)
FEW·$(LOC)FEFE
<prompt>
Table 4.5 shows the same EEPROM map after the FEW commands shown above are performed.
00 $0101 (WORD 1)
02 $0101 (WORD 1)
03 $0101 (WORD 2)
05 $0101 (WORD 2)
Writing data to the EEPROM starting at the first location and finishing at the last location, the conditions
for writing two words at a time in order are met.
4.3.4 Checksum
Before all the data in the data buffer is written to the EEPROM the checksum needs to be updated and
stored in the EEPROM at the correct location. This is done by using the values in the data buffer to
calculate and then store the checksum in the data buffer after the calculation is complete. This simplifies
the code by allowing the program to write all the data in the data buffer to the EEPROM in one routine
instead of writing to the EEPROM twice (once to write the data and twice to write the checksum into the
EEPROM).
The details of how to calculate the checksum of the EEPROM are in EEPROM documents that are only
available by request under NDA. Contact [email protected]
Vinculum is part of Future Technology Devices International Ltd. Neither the whole nor any part of the information contained in, or the
product described in this manual, may be adapted or reproduced in any material or electronic form without the prior written consent of
the copyright holder. This product and its documentation are supplied on an as-is basis and no warranty as to their suitability for any
particular purpose is either made or implied. Future Technology Devices International Ltd will not accept any claim for damages
howsoever arising as a result of use or failure of this product. Your statutory rights are not affected. This product or any variant of it is
not intended for use in any medical appliance, device or system in which the failure of the product might reasonably be expected to
result in personal injury. This document provides preliminary information that may be subject to change without notice. No freedom to
use patents or other intellectual property rights is implied by the publication of this document. Future Technology Devices International
Ltd, 373 Scotland Street, Glasgow G5 8QB United Kingdom. Scotland Registered Number: SC136640
Revision History
Version 1.00 Initial Release September, 2008