I've spent the day hacking together an experimental implementation of
serial programming via the FTDI FT232BM USB-to-serial converter bit bang
mode. Mostly a success, so far.
After familiarizing myself with the programmer_t abstraction and seeing
how it is implemented in par.c and other files, I was able to create a
new programmer type ('ftbb') and make a new programmer entry in
avrdude.conf that uses it. I did consider first trying to fit into
Michael Holtz' bit bang structure but there were more differences than
similarities, so I went the new interface route.
At the lowest level, there is a routine called ftbb_txrx() which sends
and receives 8 bits over the bit bang bus of the FTD2XX.
pgm->cmd builds on this and sends four bytes of a command and records
the four bytes of the response.
The other routines for open, close, enable, disable, initialize, erase,
etc., are straightforward, making the right calls to the FTDI DLL.
I am able to use the terminal mode successfully with an ATMega8 for
everything I've tried so far. All the memory space read commands from
the command line are working too.
There does seem to be a subtle timing bug as I can do a chip erase from
the terminal but not from the command line--the SPI bus falls out of
sync and doesn't respond any further. I do have the usleep() call with
the erase delay value in there, but maybe that's not where the problem lies.
However--this implementation is *extremely slow*. It accomplishes about
four commands per second, so reading 16 bytes of eeprom takes, for
example, 4 seconds. This is due ultimately to requiring a USB packet
per SCLK transition, with a 200ms or so fixed timeout inside the FTD2XX
device driver DLL. (I know, Joerg warned about this--but stay with me.)
As I outlined in a prior email, this situation happens because one has
to read back the status of the bit bang bus pins after SCLK goes low,
shifting the FTDI driver from transmitting to receiving for each bit.
This creates a ping-pong effect that kills the performance.
The much, much faster technique is to batch together bit bang bus sends
into a larger block (again, see previous email), and let the FTDI chip
clock these out over the bit bang bus at high speed. For a single
command, one would convert 32 bits into 64 bytes that would get sent as
a single USB packet.
This mode of operation, though, prevents any reads of the bit bang bus,
and thus the response from AVR is lost. There are many commands,
however, for which this should be ok. A stream of memory space writes
(flash or eeprom) could go quickly using this technique.
Unfortunately, avrdude does not internally distinguish between commands
which require a response and ones that don't, so I'm forced to do the
very slow method for everything. If there were a way in pgm->cmd() to
know that the response would be ignored, I could send the 32 bits all at
once in the fast way outlined above.
I can see that there is an opportunity to implement a paged write
routine that could batch these up and make it work that way, and other
batching techniques could be implemented in pgm->cmd() if I knew how to
figure out an appropriate time to stop batching and send out the buffer.
But again this would require knowing which commands need a response
and which don't.
Suggestions?
A patch is forthcoming, but I'm a little brain fried right now to do it.
The implementation is a quite fragile--Cygwin only, needs the FTDI
header file and .lib DLL import file in the current directory, and has
no conditionalization in the Makefile.am or source code files. It also
ignores the port specification (just uses FTD2XX device #0), ignores the
pin settings in avrdude.conf, and assumes things are wired exactly as I
have them on my board.
As is, I could use this for my AVR project, so my itch is mostly
scratched. But having gone this far, I'd sure like to see how it can be
integrated nicely and optimized for speed.
-Johnathan
_______________________________________________
avrdude-dev mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/avrdude-dev