# HG changeset patch # User Mychaela Falconia # Date 1555982561 0 # Node ID ace3ed1d5ddf261992ec77f03553ebacd9a7463e # Parent 311c800268b820ed9da0b52bdbafea1e0206757f Unbuffered FT2232x JTAG article written diff -r 311c800268b8 -r ace3ed1d5ddf doc/Unbuffered-FT2232x-JTAG --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/Unbuffered-FT2232x-JTAG Tue Apr 23 01:22:41 2019 +0000 @@ -0,0 +1,155 @@ +How to make a safe JTAG adapter out of a generic unbuffered FT2232x board +========================================================================= + +Among the FOSS community of tinkerers who use OpenOCD to operate on the JTAG +interfaces of various hardware targets, one of the most common JTAG adapter +choices (if not the most common) is to use some adapter gadget based on an FTDI +chip, most commonly one of FT2232x variants. However, a major distinction needs +to be drawn between specialized purpose-made JTAG adapter products which just +happen to use an FT2232x chip internally, versus generic FT2232x breakout boards +which the user wires up for JTAG on his or her own. + +In an ideal world, using a purpose-made buffered JTAG adapter (one that has a +buffer inserted between FT2232x I/O pins and the target connection interface) +would be strongly preferable for a whole host of reasons. However, to this +author's disappointment, there are very few community vendors who make such +adapters, and I was NOT able to find any high-quality buffered JTAG adapter +which can be bought in the present and which comes with published schematics. +(There is one very well-known vendor of "community" JTAG adapters who refuses +to publish schematics for their current model; they have an older model for +which they did publish schematics, but it is discontinued and they are not +interested in bringing it back into production or handing the complete design +over to the community - probably because it would then compete with their +current sans-schematics product! Selling JTAG adapters to the community while +keeping their schematics secret is just assinine, and I refuse to give my +business to such vendors.) + +Given the current sorry state of availability of buffered JTAG adapters, I have +given more thought to the unbuffered option, and I found what appears to be a +way to make them safe - but my method requires programming the EEPROM on the +FT2232x board with a special custom configuration, and in this article I am +going to provide the full details and instructions. + +To begin with, an unbuffered JTAG adapter (one in which the target JTAG signals +are connected directly to FT2232x I/O pins without any buffer in between) can +work only with targets that operate their JTAG interface at 3.3 V, or perhaps +a slightly lower but still fully 3.3V-compatible logic voltage level like the +2.8 V I/O on Calypso GSM baseband processors. An unbuffered adapter CANNOT +work with, say, a 1.8 V JTAG interface - but as long as your target runs at +3.3 or 2.8 V, then we can continue. + +The next big problem with unbuffered FT2232x adapters is that if you don't put +a special configuration in the EEPROM (or if your FT2232x board omits the EEPROM +altogether), the channel which you are going to wire up for JTAG (can only be +Channel A on FT2232C/D, can be either channel on FT2232H) is going to come up +in FTDI's default UART mode on power-up, and it is going to stay in that mode +until and unless you run OpenOCD, which will then switch it into MPSSE mode for +JTAG. Why is it a problem? Answer: you need to connect the TDO line from the +target to the FT2232x chip's ADBUS2 pin for JTAG to work via MPSSE, but in the +power-up default UART mode this ADBUS2 pin is the RTS output. FT2232x RTS +output fighting with the target's TDO output - not good, and it could even fry +one or both of the chips. + +Unfortunately FTDI's stupid chip design does not allow the desired MPSSE mode +to be configured in the EEPROM so that it is there right from power-up. But +there is a workaround: if the EEPROM config is set up to put Channel A (the one +that will be wired for JTAG) into the rarely-used 245 FIFO mode instead of UART, +all 8 ADBUS pins (including ADBUS2 where TDO will be connected) will power up +as inputs with weak internal pull-ups (as long as the ACBUS2 control line is +left unconnected), which is much safer than what these pins do in the default +UART mode. + +And if we need to program the EEPROM with a special custom config to change +Channel A from 232 UART to 245 FIFO, we can also assign a different USB VID:PID +at the same time. FTDI's default FT2232x ID of 0403:6010 works great when both +channels of the FT2232x device are used as UARTs - the Linux kernel recognizes +this USB ID, creates a pair of ttyUSB devices (one for each channel), and +everything Just Works. But what if Channel A is used for JTAG and is therefore +not a valid UART channel? If the default USB ID is left unchanged, what happens +is that a pair of ttyUSB devices still gets created, with the first out of the +pair being completely bogus and non-functional. And when you run OpenOCD, that +bogus Channel A ttyUSB device disappears, while the Channel B ttyUSB device +(which will actually work if Channel B is wired as a UART) remains, creating a +gap in ttyUSB numbers. If you have a ton of ttyUSB devices on your system and +are struggling to keep track of which is which, this behaviour certainly does +not help. + +As it happens, our company Falconia Partners LLC has received a block of 8 PIDs +from FTDI, allocated out of FTDI's VID range - these PIDs have been officially +allocated by FTDI to our company for use in products based on FTDI chips. And +because we can spare one PID for a worthy cause, one of these PIDs (0403:7151) +is hereby being donated to the community for use on generic FT2232x boards in +the unbuffered JTAG adapter configuration. + +As of this writing, this 0403:7151 PID has not been submitted to Linux ftdi_sio +kernel maintainers yet, thus if you program it into your FT2232x EEPROM +following the instructions below, the kernel will leave that FT2232x device +completely alone. If you are interested only in JTAG and don't need an extra +UART on Channel B, this arrangement should be fully sufficient - you simply +configure your OpenOCD in userspace to find your unbuffered and ad-hoc-wired +JTAG adapter at that USB ID. And if you do need the UART on Channel B, you can +trivially patch your ftdi_sio.c kernel driver, adding the new ID to the table +with JTAG quirk (&ftdi_jtag_quirk) specified. + +Choice of FT2232x breakout board +================================ + +Here at FreeCalypso HQ we make very extensive use of FT2232C/D breakout boards +by PLDkit, and I officially recommend and endorse this vendor: + +http://pldkit.com/other/ft2232d-module + +These modules were originally made with FT2232D chips, then the vendor found a +stash of old but still good FT2232C chips, so apparently the current ones are +FT2232C, not D - but this distinction makes no difference for the present +purpose. + +These days FT2232H chips and FT2232H breakout boards are much more popular, but +I generally prefer FT2232C/D for classicness and simplicity. Additionally, +FTDI's AN_184 document lists I/O pin behaviour of various FTDI chips including +FT2232D and FT2232H; according to this document FT2232H I/O pins go through a +brief phase of acting as UART signals (including RTS output on ADBUS2) while +the EEPROM is being read, whereas FT2232D I/O pins are tristated during this +time. Thus I strongly recommend using an FT2232D breakout board. + +Programming the EEPROM +====================== + +The officially recommended FT2232D breakout boards from PLDkit have 93C46 +EEPROMs on them, and the boards are shipped with blank EEPROMs. The blank +EEPROM state is perfectly good for operating the board as a dual UART, but our +JTAG application calls for custom EEPROM programming. A number of people in +the FOSS community have produced several different tools for programming FTDI +EEPROMs, and you could even use FTDI's official Winblows tools if you like, but +I am going to describe how to program the EEPROM using the tools which I +developed and which are used in production here at Falconia Partners LLC. + +To compile my FTDI EEPROM tools, go into the fteeprom directory and run make +there; you will need to have libftdi (the classic one, not libftdi1) installed +on your system. If all you seek to do is to program this one EEPROM, you don't +need to install my tools system-wide - you can just run them from the directory +where they are compiled. + +If you have the FT2232D board in its initial blank-EEPROM state plugged into +your system and you don't have any other FT2232x devices with 0403:6010 IDs, +you can program the EEPROM for JTAG as follows - run this pipeline from the top +directory of this code repository: + +fteeprom/ftee-gen2232c eeproms/jtag-unbuf | fteeprom/fteeprom-prog i:0x0403:0x6010 + +Then unplug and replug the FT2232D board, and it should come back with the new +0403:7151 USD ID. If you wish to bring it back to its original blank-EEPROM +state, you can do so by erasing the EEPROM: + +fteeprom-erase i:0x0403:0x7151 + +Wire connections +================ + +The JTAG signal connections to ADBUS0 through ADBUS3 are fixed by FTDI, and if +you go against my advice and use FT2232H rather than FT2232C/D, then ADBUS7 is +also reserved for RTCK. The I/O pins available for reset and other sideband or +GPIO signals are ADBUS4 through ADBUS7 on FT2232C/D adapters, or ADBUS4 through +ADBUS6 and ACBUS5 through ACBUS7 on FT2232H. The other pins should be left +untouched to avoid problems with the 245 FIFO mode which is active in the time +window being power-up (USB plug-in) and running OpenOCD. diff -r 311c800268b8 -r ace3ed1d5ddf eeproms/jtag-unbuf --- a/eeproms/jtag-unbuf Mon Apr 22 23:28:27 2019 +0000 +++ b/eeproms/jtag-unbuf Tue Apr 23 01:22:41 2019 +0000 @@ -23,7 +23,7 @@ # 232 UART mode is NOT safe, as it will produce a fight on the ADBUS2 line # between the UART RTS output and the target's TDO output. 245 FIFO mode is # expected to be safer, as all 8 ADBUS lines will be inputs for as long as -# ACBUS2 and ACBUS2 are left unconnected and not driven by anything. +# the ACBUS2 line is left unconnected and not driven by anything. byte00 0x01 # Channel A: FIFO mode, D2XX driver byte01 0x08 # Channel B: UART mode, VCP driver