2 * avrdude - A Downloader/Uploader for AVR device programmers
3 * Copyright (C) 2003-2004 Theodore A. Roth <troth@openavr.org>
4 * Copyright (C) 2005 Johnathan Corgan <jcorgan@aeinet.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Boston, MA 02110-1301 USA
22 * avrdude interface for serial programming via FTDI bit bang mode operation.
40 #define RESET (1<<(pgm->pinno[PIN_AVR_RESET]-1))
41 #define SCK (1<<(pgm->pinno[PIN_AVR_SCK]-1))
42 #define MOSI (1<<(pgm->pinno[PIN_AVR_MOSI]-1))
43 #define MISO (1<<(pgm->pinno[PIN_AVR_MISO]-1))
44 #define FTDDR (MOSI|SCK|RESET)
47 static FT_STATUS status;
48 static FT_HANDLE handle;
50 static struct ftdi_context device;
54 static unsigned char txbits;
56 /* Send 8 bits over SPI bus with per-bit read back
59 static unsigned char ftbb_txrx(PROGRAMMER *pgm, unsigned char val)
67 #endif /* HAVE_LIBFTD2XX */
71 for (i = 0; i < 8; i++) { // For each bit
72 // Set up data on low phase of SCK
75 // Set MOSI to high bit of transmit data
82 FT_Write(handle, &txbits, 1, &written);
83 // Clock just fell, read previous input bit and shift in
84 FT_GetBitMode(handle, &bits);
86 ftdi_write_data(&device, &txbits, 1);
87 // Clock just fell, read previous input bit and shift in
88 ftdi_read_pins(&device, &bits);
89 #endif /* HAVE_LIBFTD2XX */
90 res = (res << 1) | (bits & MISO);
92 // Now raise SCK to latch data in AVR
96 FT_Write(handle, &txbits, 1, &written);
98 ftdi_write_data(&device, &txbits, 1);
99 #endif /* HAVE_LIBFTD2XX */
100 // Move on to next bit in transmit data
107 /* Generic programmer command function for pgm->cmd
109 * Sends four bytes of command in sequence and collects responses
112 static int ftbb_cmd(PROGRAMMER *pgm, unsigned char cmd[4], unsigned char res[4])
117 printf("CMD: %02X%02X%02X%02X ", cmd[0], cmd[1], cmd[2], cmd[3]);
120 for (i = 0; i < 4; i++) {
121 res[i] = ftbb_txrx(pgm, cmd[i]);
125 printf("RES: %02X%02X%02X%02X\n", res[0], res[1], res[2], res[3]);
131 /* Programmer initialization command for pgm->initialize
133 * Pulse RESET with SCK low, then send SPI start programming command
136 static int ftbb_initialize(PROGRAMMER *pgm, AVRPART *p)
140 #endif /* HAVE_LIBFTD2XX */
142 // Atmel documentation says to raise RESET for 2 cpu clocks while sclk is low
143 // then lower RESET and wait 20 ms.
147 FT_Write(handle, &txbits, 1, &written);
149 ftdi_write_data(&device, &txbits, 1);
150 #endif /* HAVE_LIBFTD2XX */
152 usleep(1000); // 2 AVR cpu clocks at any realistic clock rate
156 FT_Write(handle, &txbits, 1, &written);
158 ftdi_write_data(&device, &txbits, 1);
159 #endif /* HAVE_LIBFTD2XX */
163 pgm->program_enable(pgm, p);
167 /* Programmer status display for pgm->display
172 static void ftbb_display(PROGRAMMER *pgm, char *p)
175 printf("ftbb: display called with: %s\n", p);
178 printf("FTBB: RESET mapped to pinno %d\n", pgm->pinno[PIN_AVR_RESET]);
179 printf("FTBB: SCK mapped to pinno %d\n", pgm->pinno[PIN_AVR_SCK]);
180 printf("FTBB: MOSI mapped to pinno %d\n", pgm->pinno[PIN_AVR_MOSI]);
181 printf("FTBB: MISO mapped to pinno %d\n", pgm->pinno[PIN_AVR_MISO]);
184 /* Programmer enable command for pgm->enable
186 * Lowers SCK and RESET in preparation for serial programming
189 static void ftbb_enable(PROGRAMMER *pgm)
193 #endif /* HAVE_LIBFTD2XX */
200 FT_Write(handle, &txbits, 1, &written);
202 ftdi_write_data(&device, &txbits, 1);
203 #endif /* HAVE_LIBFTD2XX */
206 /* Programmer disable command for pgm->disable
208 * Raises RESET to return to normal chip operation
211 static void ftbb_disable(PROGRAMMER *pgm)
215 #endif /* HAVE_LIBFTD2XX */
216 // Raise RESET to return to normal mode
220 FT_Write(handle, &txbits, 1, &written);
222 ftdi_write_data(&device, &txbits, 1);
223 #endif /* HAVE_LIBFTD2XX */
226 /* Programmer programming mode enable function for pgm->program_enable
228 * Starts SPI programming mode
231 static int ftbb_program_enable(PROGRAMMER *pgm, AVRPART *p)
233 unsigned char cmd[4];
234 unsigned char res[4];
236 if (p->op[AVR_OP_PGM_ENABLE] == NULL) {
237 fprintf(stderr, "program enable instruction not defined for part \"%s\"\n", p->desc);
241 memset(cmd, 0, sizeof(cmd));
242 avr_set_bits(p->op[AVR_OP_PGM_ENABLE], cmd);
243 pgm->cmd(pgm, cmd, res);
248 /* Progammer erase function for pgm->erase
250 * Sends chip erase command and sleeps the chip erase delay
253 static int ftbb_chip_erase(PROGRAMMER *pgm, AVRPART *p)
255 unsigned char cmd[4];
256 unsigned char res[4];
258 if (p->op[AVR_OP_CHIP_ERASE] == NULL) {
259 fprintf(stderr, "chip erase instruction not defined for part \"%s\"\n", p->desc);
263 memset(cmd, 0, sizeof(cmd));
264 avr_set_bits(p->op[AVR_OP_CHIP_ERASE], cmd);
265 pgm->cmd(pgm, cmd, res);
266 usleep(p->chip_erase_delay);
272 /* Parse routine for device name
277 int ftbb_parse_name(char *name, int *vid, int *pid, int *ifc)
279 printf("name=%s\n", name);
283 /* Programmer open command for pgm->open
285 * Opens FTD2XX device specified by 'name', performs a chip reset, then
286 * sets the baudrate and bit bang mode
289 static int ftbb_open(PROGRAMMER *pgm, char *name)
292 ftbb_parse_name(name, &vid, &pid, &ifc);
296 if (strcmp(name, "ft0")) {
297 fprintf(stderr, "ERROR: FTD2XX device selection not yet implemented!\n");
301 // Call FTD2XX library to open device
302 if ((status = FT_Open(devnum, &handle)) != FT_OK) {
303 fprintf(stderr, "Failed to open FTD2XX device #%d.\n", devnum);
308 if ((status = FT_ResetDevice(handle)) != FT_OK) {
309 fprintf(stderr, "Failed to reset chipset for FTD2XX device #%d.\n", devnum);
313 // Set baud rate for bit bang interface
314 if ((status = FT_SetBaudRate(handle, pgm->baudrate)) != FT_OK) {
315 fprintf(stderr, "Failed to set baud rate for FTD2XX device #%d.\n", devnum);
319 // Set bit bang direction and mode
320 if ((status = FT_SetBitMode(handle, FTDDR, 1)) != FT_OK) {
321 fprintf(stderr, "Failed to set bit bang mode for FTD2XX device #%d.\n", devnum);
325 // Open device via FTDI library *** FIXME *** hardcoded VID and PID
326 if (ftdi_usb_open(&device, EZDOP_VENDORID, EZDOP_PRODUCTID)) {
327 fprintf(stderr, "ftdi_usb_open: %s", device.error_str);
331 // Reset FTDI chipset
332 if (ftdi_usb_reset(&device)) {
333 fprintf(stderr, "ftdi_usb_reset: %s", device.error_str);
337 // Set FTDI chipset baudrate for bitbang
338 if (ftdi_set_baudrate(&device, pgm->baudrate)) {
339 fprintf(stderr, "ftdi_set_baudrate: %s", device.error_str);
344 if (ftdi_enable_bitbang(&device, FTDDR)) {
345 fprintf(stderr, "ftdi_enable_bitbang: %s", device.error_str);
349 // Minimum chunk size for reads to reduce latency
350 if (ftdi_read_data_set_chunksize(&device, 256)) {
351 fprintf(stderr, "ftdi_read_data_set_chunksize: %s", device.error_str);
354 #endif /* HAVE_LIBFTD2XX */
359 /* Programmer close function for pgm->close
361 * Releases FTD2XX device
364 static void ftbb_close(PROGRAMMER *pgm)
369 ftdi_deinit(&device);
372 #endif /* FTDI_SUPPORT */
374 /* Programmer initialization command for startup.
376 * Sets appropriate function pointers in structure
377 * Tests FTD2XX interface by enumerating number of devices
380 void ftbb_initpgm (PROGRAMMER *pgm)
388 strcpy(pgm->type, "ftbb");
389 pgm->initialize = ftbb_initialize;
390 pgm->display = ftbb_display;
391 pgm->enable = ftbb_enable;
392 pgm->disable = ftbb_disable;
393 pgm->program_enable = ftbb_program_enable;
394 pgm->chip_erase = ftbb_chip_erase;
396 pgm->open = ftbb_open;
397 pgm->close = ftbb_close;
400 if ((status = FT_ListDevices(&num_devices, NULL, FT_LIST_NUMBER_ONLY)) != FT_OK)
401 fprintf(stderr, "Failed to initialize FTD2XX interface. (%li)\n", status);
403 printf("%lu FTD2XX device(s) found.\n", num_devices);
405 if ((status = ftdi_init(&device)) < 0)
406 fprintf(stderr, "Failed to initialize FTDI interface. (%i)\n", status);
410 #endif /* FTDI_SUPPORT */