diff --git a/ChangeLog b/ChangeLog index 91e783f4..37bf5101 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2013-05-15 Rene Liebscher + + * configure.ac: if both found libftdi and libftdi1 use only libftdi1 + * avrdude.conf.in: fixed buff pins of avrftdi programmers (low active buffer need now inverted numbers) + * avrftdi*.*: accept also old libftdi (0.20 still works with it), added powerup to initialize + * ft245r.c: accept libftdi1, code cleanup and make it more similar to avrfdti (os they might be merged someday) + 2013-05-08 Joerg Wunsch * configure.ac (AC_INIT): Bump version to 6.0rc1. diff --git a/Makefile.am b/Makefile.am index 930af58b..885636ec 100644 --- a/Makefile.am +++ b/Makefile.am @@ -63,7 +63,7 @@ avrdude_CFLAGS = @ENABLE_WARNINGS@ libavrdude_a_CFLAGS = @ENABLE_WARNINGS@ -avrdude_LDADD = $(top_builddir)/$(noinst_LIBRARIES) @LIBUSB@ @LIBUSB_1_0@ @LIBFTDI@ @LIBFTDI1@ @LIBHID@ @LIBELF@ @LIBPTHREAD@ -lm +avrdude_LDADD = $(top_builddir)/$(noinst_LIBRARIES) @LIBUSB_1_0@ @LIBUSB@ @LIBFTDI1@ @LIBFTDI@ @LIBHID@ @LIBELF@ @LIBPTHREAD@ -lm bin_PROGRAMS = avrdude diff --git a/avrdude.conf.in b/avrdude.conf.in index aae97dbe..2cc5d7b5 100644 --- a/avrdude.conf.in +++ b/avrdude.conf.in @@ -397,9 +397,7 @@ programmer # buff = 8; ; # This is an implementation of the above with a buffer IC (74AC244) and -# 4 LEDs directly attached, active low. The buff and reset pins are -# understood (by avrdude) to be active low, so there's no -# need to invert the bits. +# 4 LEDs directly attached, all active low. programmer id = "2232HIO"; desc = "FT2232H based generic programmer"; @@ -419,7 +417,7 @@ programmer sck = 0; mosi = 1; miso = 2; - buff = 4; + buff = ~4; #LED SIGNALs errled = ~ 11; rdyled = ~ 14; @@ -431,8 +429,8 @@ programmer #device ID of 0x6011. programmer parent "avrftdi" id = "4232h"; - desc = "FT4232H based generic programmer"; - usbpid = 0x6011; + desc = "FT4232H based generic programmer"; + usbpid = 0x6011; ; programmer @@ -452,7 +450,7 @@ programmer sck = 0; # TCK 9 white mosi = 1; # TDI 5 green miso = 2; # TDO 13 orange - buff = 4; + buff = ~4; # VTG VREF 1 brown with red tip # GND GND 20 black # The colors are on the 20 pin breakout cable @@ -517,7 +515,7 @@ programmer mosi = 1; miso = 2; # Enable correct buffers - buff = ~7; + buff = 7; ; programmer diff --git a/avrftdi_private.h b/avrftdi_private.h index f8fc92ff..141f7852 100644 --- a/avrftdi_private.h +++ b/avrftdi_private.h @@ -4,10 +4,14 @@ #include #ifdef HAVE_LIBUSB_1_0 -#ifdef HAVE_LIBFTDI1 +#if defined(HAVE_LIBFTDI1) || defined(HAVE_LIBFTDI) #include +#ifdef HAVE_LIBFTDI1 #include +#elif HAVE_LIBFTDI +#include +#endif #include "pgm.h" #include "pindefs.h" diff --git a/avrftdi_tpi.c b/avrftdi_tpi.c index c949f66e..9c5cde3b 100644 --- a/avrftdi_tpi.c +++ b/avrftdi_tpi.c @@ -16,10 +16,14 @@ #include "avrftdi_private.h" #ifdef HAVE_LIBUSB_1_0 -#ifdef HAVE_LIBFTDI1 +#if defined(HAVE_LIBFTDI1) || defined(HAVE_LIBFTDI) #include +#ifdef HAVE_LIBFTDI1 #include +#elif HAVE_LIBFTDI +#include +#endif static void avrftdi_tpi_disable(PROGRAMMER *); static int avrftdi_tpi_program_enable(PROGRAMMER * pgm, AVRPART * p); diff --git a/configure.ac b/configure.ac index ea3fab81..7c96181c 100644 --- a/configure.ac +++ b/configure.ac @@ -144,24 +144,25 @@ if test x$have_libusb_1_0 = xyes; then AC_CHECK_HEADERS([libusb.h]) fi AC_SUBST(LIBUSB_1_0, $LIBUSB_1_0) +AH_TEMPLATE([HAVE_LIBFTDI1], + [Define if FTDI support is enabled via libftdi1]) AH_TEMPLATE([HAVE_LIBFTDI], [Define if FTDI support is enabled via libftdi]) AH_TEMPLATE([HAVE_LIBFTDI_TYPE_232H], [Define if libftdi supports FT232H, libftdi version >= 0.20]) -AC_CHECK_LIB([ftdi], [ftdi_usb_get_strings], [have_libftdi=yes], [], [-lusb]) -if test x$have_libftdi = xyes; then - LIBFTDI="-lftdi -lusb" - AC_DEFINE([HAVE_LIBFTDI]) -fi -AC_SUBST(LIBFTDI, $LIBFTDI) -AH_TEMPLATE([HAVE_LIBFTDI1], - [Define if FTDI support is enabled via libftdi1]) AC_CHECK_LIB([ftdi1], [ftdi_new], [have_libftdi1=yes], [], [-lusb-1.0]) +AC_CHECK_LIB([ftdi], [ftdi_usb_get_strings], [have_libftdi=yes], [], [-lusb]) if test x$have_libftdi1 = xyes; then - LIBFTDI1="-lftdi1" - AC_DEFINE([HAVE_LIBFTDI1]) + LIBFTDI1="-lftdi1" + AC_DEFINE([HAVE_LIBFTDI1]) + AC_SUBST(LIBFTDI1, $LIBFTDI1) +else + if test x$have_libftdi = xyes; then + LIBFTDI="-lftdi -lusb" + AC_DEFINE([HAVE_LIBFTDI]) + AC_SUBST(LIBFTDI, $LIBFTDI) + fi fi -AC_SUBST(LIBFTDI1, $LIBFTDI1) AC_CHECK_HEADERS([pthread.h]) # as there exits header file only pthread implementations for Windows, check if we have a library AC_CHECK_LIB([pthread], [pthread_create], [have_pthread=yes]) @@ -486,18 +487,22 @@ else echo "DON'T HAVE libusb_1_0" fi -if test x$have_libftdi = xyes; then - echo "DO HAVE libftdi" -else - echo "DON'T HAVE libftdi" -fi - if test x$have_libftdi1 = xyes; then echo "DO HAVE libftdi1" else echo "DON'T HAVE libftdi1" fi +if test x$have_libftdi = xyes; then + if test x$have_libftdi1 = xyes; then + echo "DO HAVE libftdi (but prefer to use libftdi1)" + else + echo "DO HAVE libftdi" + fi +else + echo "DON'T HAVE libftdi" +fi + if test x$have_libhid = xyes; then echo "DO HAVE libhid" else diff --git a/ft245r.c b/ft245r.c index 00ec9f33..c51ee550 100644 --- a/ft245r.c +++ b/ft245r.c @@ -86,13 +86,17 @@ typedef dispatch_semaphore_t sem_t; #include #endif -#ifdef HAVE_LIBFTDI +#if defined(HAVE_LIBFTDI1) || defined(HAVE_LIBFTDI) #if defined(_WIN32) #include #endif +#ifdef HAVE_LIBFTDI1 +#include +#elif HAVE_LIBFTDI #include +#endif #define FT245R_CYCLES 2 @@ -107,7 +111,6 @@ static struct ftdi_context *handle; static unsigned char ft245r_ddr; static unsigned char ft245r_out; static unsigned char ft245r_in; -static unsigned char saved_signature[3]; #define BUFSIZE 0x2000 @@ -191,15 +194,9 @@ static int ft245r_drain(PROGRAMMER * pgm, int display) { return 0; } -static inline int ft245r_sync(PROGRAMMER * pgm) { - //printf ("sync.\n"); - // The old code did something that evaluated to a no-op. - - return 0; -} static int ft245r_chip_erase(PROGRAMMER * pgm, AVRPART * p) { - unsigned char cmd[4]; + unsigned char cmd[4] = {0,0,0,0}; unsigned char res[4]; if (p->op[AVR_OP_CHIP_ERASE] == NULL) { @@ -208,18 +205,14 @@ static int ft245r_chip_erase(PROGRAMMER * pgm, AVRPART * p) { return -1; } - memset(cmd, 0, sizeof(cmd)); - avr_set_bits(p->op[AVR_OP_CHIP_ERASE], cmd); pgm->cmd(pgm, cmd, res); usleep(p->chip_erase_delay); - pgm->initialize(pgm, p); - - return 0; + return pgm->initialize(pgm, p); } -static void ft245r_set_bitclock(PROGRAMMER * pgm) { +static int ft245r_set_bitclock(PROGRAMMER * pgm) { int r; int rate = 0; @@ -240,8 +233,9 @@ static void ft245r_set_bitclock(PROGRAMMER * pgm) { if (r) { fprintf(stderr, "Set baudrate (%d) failed with error '%s'.\n", rate, ftdi_get_error_string (handle)); - exit (1); + return -1; } + return 0; } static int set_pin(PROGRAMMER * pgm, int pinname, int val) { @@ -257,6 +251,8 @@ static int set_pin(PROGRAMMER * pgm, int pinname, int val) { ft245r_send (pgm, buf, 1); ft245r_recv (pgm, buf, 1); + + ft245r_in = buf[0]; return 0; } @@ -291,82 +287,12 @@ static int set_led_vfy(struct programmer_t * pgm, int value) { return set_pin(pgm, PIN_LED_VFY, value); } -static int ft245r_cmd(PROGRAMMER * pgm, unsigned char cmd[4], - unsigned char res[4]); -/* - * issue the 'program enable' command to the AVR device - */ -static int ft245r_program_enable(PROGRAMMER * pgm, AVRPART * p) { - int retry_count = 0; - unsigned char cmd[4]; - unsigned char res[4]; - int i,reset_ok; - - ft245r_set_bitclock(pgm); - -retry: - reset_ok = 0; - set_reset(pgm, 0); - usleep(5000); // 5ms - set_reset(pgm, 1); - usleep(5000); // 5ms - set_reset(pgm, 0); - usleep(5000); // 5ms - - cmd[0] = 0xAC; - cmd[1] = 0x53; - cmd[2] = 0; - cmd[3] = 0; - ft245r_cmd(pgm, cmd, res); - if (res[2] == 0x53 ) reset_ok = 1; - for (i=0; i<3; i++) { - cmd[0] = 0x30; - cmd[1] = 0; - cmd[2] = i; - cmd[3] = 0; - ft245r_cmd(pgm, cmd, res); - saved_signature[i] = res[3]; - } - if (reset_ok && (saved_signature[0] == 0x1e)) // success - return 0; - - if (retry_count < 5) { - if (retry_count == 3) { - ft245r_drain (pgm, 0); - tail = head; - } - retry_count++; - goto retry; - } - if ((verbose>=1) || FT245R_DEBUG) { - fprintf(stderr, - "%s: ft245r_program_enable: failed\n", progname); - fflush(stderr); - } - return -1; -} - -static int ft245r_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m) { - m->buf[0] = saved_signature[0]; - m->buf[1] = saved_signature[1]; - m->buf[2] = saved_signature[2]; - return 3; -} - -/* - * initialize the AVR device and prepare it to accept commands - */ -static int ft245r_initialize(PROGRAMMER * pgm, AVRPART * p) { - - return ft245r_program_enable(pgm, p); -} - /* * apply power to the AVR processor */ static void ft245r_powerup(PROGRAMMER * pgm) { - set_vcc(pgm,1); /* power up */ + set_vcc(pgm, ON); /* power up */ usleep(100); } @@ -376,12 +302,12 @@ static void ft245r_powerup(PROGRAMMER * pgm) */ static void ft245r_powerdown(PROGRAMMER * pgm) { - set_vcc(pgm,0); /* power down */ + set_vcc(pgm, OFF); /* power down */ } static void ft245r_disable(PROGRAMMER * pgm) { - set_buff(pgm,0); + set_buff(pgm, OFF); } @@ -396,9 +322,75 @@ static void ft245r_enable(PROGRAMMER * pgm) { * programmer needs to be directly connected to the AVR /RESET line * and not via the buffer chip. */ - set_reset(pgm,0); + set_reset(pgm, OFF); usleep(1); - set_buff(pgm,1); + set_buff(pgm, ON); +} + +static int ft245r_cmd(PROGRAMMER * pgm, unsigned char cmd[4], + unsigned char res[4]); +/* + * issue the 'program enable' command to the AVR device + */ +static int ft245r_program_enable(PROGRAMMER * pgm, AVRPART * p) { + unsigned char cmd[4] = {0,0,0,0}; + unsigned char res[4]; + int i; + + if (p->op[AVR_OP_PGM_ENABLE] == NULL) { + fprintf(stderr, + "%s: AVR_OP_PGM_ENABLE command not defined for %s\n", progname, p->desc); + fflush(stderr); + return -1; + } + + avr_set_bits(p->op[AVR_OP_PGM_ENABLE], cmd); + + for(i = 0; i < 4; i++) { + ft245r_cmd(pgm, cmd, res); + fprintf(stderr, + "%s: %02x %02x %02x %02x => %02x %02x %02x %02x \n", progname, cmd[0], cmd[1], cmd[2], cmd[3], res[0], res[1], res[2], res[3] ); + fflush(stderr); + + if (res[p->pollindex-1] == p->pollvalue) return 0; + + if ((verbose>=1) || FT245R_DEBUG) { + fprintf(stderr, + "%s: Program enable command not successful. Retrying.\n", progname); + fflush(stderr); + } + set_pin(pgm, PIN_AVR_RESET, ON); + usleep(20); + set_pin(pgm, PIN_AVR_RESET, OFF); + + if (i == 3) { + ft245r_drain(pgm, 0); + tail = head; + } + } + + fprintf(stderr, + "%s: Device is not responding to program enable. Check connection.\n", progname); + fflush(stderr); + + return -1; +} + +/* + * initialize the AVR device and prepare it to accept commands + */ +static int ft245r_initialize(PROGRAMMER * pgm, AVRPART * p) { + + ft245r_powerup(pgm); + + set_reset(pgm, OFF); + usleep(5000); // 5ms + set_reset(pgm, ON); + usleep(5000); // 5ms + set_reset(pgm, OFF); + usleep(5000); // 5ms + + return ft245r_program_enable(pgm, p); } static inline int set_data(PROGRAMMER * pgm, unsigned char *buf, unsigned char data) { @@ -520,7 +512,7 @@ static int ft245r_open(PROGRAMMER * pgm, char * port) { fprintf(stderr, "%s: invalid portname '%s': use 'ft[0-9]+'\n", progname,port); - exit(1); + return -1; } } else { devnum = 0; @@ -536,20 +528,9 @@ static int ft245r_open(PROGRAMMER * pgm, char * port) { devnum); if (rv) { fprintf (stderr, "can't open ftdi device %d. (%s)\n", devnum, ftdi_get_error_string(handle)); - ftdi_deinit (handle); - free(handle); - exit (1); + goto cleanup_no_usb; } - /* We start a new thread to read the output from the FTDI. This is - * necessary because otherwise we'll deadlock. We cannot finish - * writing because the ftdi cannot send the results because we - * haven't provided a read buffer yet. */ - - sem_init (&buf_data, 0, 0); - sem_init (&buf_space, 0, BUFSIZE); - pthread_create (&readerthread, NULL, reader, handle); - ft245r_ddr = pgm->pin[PIN_AVR_SCK].mask[0] | pgm->pin[PIN_AVR_MOSI].mask[0] @@ -575,16 +556,27 @@ static int ft245r_open(PROGRAMMER * pgm, char * port) { rv = ftdi_set_bitmode(handle, ft245r_ddr, BITMODE_SYNCBB); // set Synchronous BitBang - if (rv) { fprintf(stderr, "%s: Synchronous BitBangMode is not supported (%s)\n", progname, ftdi_get_error_string(handle)); - ftdi_usb_close(handle); - ftdi_deinit (handle); - free(handle); - exit(1); + goto cleanup; } + + rv = ft245r_set_bitclock(pgm); + if (rv) { + goto cleanup; + } + + /* We start a new thread to read the output from the FTDI. This is + * necessary because otherwise we'll deadlock. We cannot finish + * writing because the ftdi cannot send the results because we + * haven't provided a read buffer yet. */ + + sem_init (&buf_data, 0, 0); + sem_init (&buf_space, 0, BUFSIZE); + pthread_create (&readerthread, NULL, reader, handle); + /* * drain any extraneous input */ @@ -594,6 +586,13 @@ static int ft245r_open(PROGRAMMER * pgm, char * port) { ft245r_recv (pgm, &ft245r_in, 1); return 0; + +cleanup: + ftdi_usb_close(handle); +cleanup_no_usb: + ftdi_deinit (handle); + free(handle); + return -1; } @@ -605,7 +604,7 @@ static void ft245r_close(PROGRAMMER * pgm) { pthread_cancel(readerthread); pthread_join(readerthread, NULL); ftdi_usb_close(handle); - ftdi_deinit (handle); + ftdi_deinit (handle); // TODO this works with libftdi 0.20, but hangs with 1.0 free(handle); handle = NULL; } @@ -893,8 +892,6 @@ void ft245r_initpgm(PROGRAMMER * pgm) { pgm->paged_write = ft245r_paged_write; pgm->paged_load = ft245r_paged_load; - pgm->read_sig_bytes = ft245r_read_sig_bytes; - pgm->rdy_led = set_led_rdy; pgm->err_led = set_led_err; pgm->pgm_led = set_led_pgm;