diff --git a/ChangeLog b/ChangeLog index 591c74e2..5c411d1d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2009-10-10 Michal Ludvig + + Support for Arduino auto-reset: + * serial.h, ser_avrdoper.c, ser_posix.c, ser_win32.c: Added + serial_device.set_dtr_rts implementations. + * arduino.c, stk500.c, stk500.h: Call serial_set_dtr_rts() + to reset Arduino board before program upload. + Inspired by patch #6866, resolves bug #26703 + 2009-10-08 Michal Ludvig * buspirate.c: Optimised buspirate_cmd() - reading 1kB EEPROM now diff --git a/arduino.c b/arduino.c index 2f37c108..247f21a7 100644 --- a/arduino.c +++ b/arduino.c @@ -82,13 +82,40 @@ static int arduino_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m) return 3; } +static int arduino_open(PROGRAMMER * pgm, char * port) +{ + strcpy(pgm->port, port); + serial_open(port, pgm->baudrate? pgm->baudrate: 115200, &pgm->fd); + + /* Clear DTR and RTS to unload the RESET capacitor + * (for example in Arduino) */ + serial_set_dtr_rts(&pgm->fd, 0); + usleep(50*1000); + /* Set DTR and RTS back to high */ + serial_set_dtr_rts(&pgm->fd, 1); + usleep(50*1000); + + /* + * drain any extraneous input + */ + stk500_drain(pgm, 0); + + if (stk500_getsync(pgm) < 0) + return -1; + + return 0; +} + + void arduino_initpgm(PROGRAMMER * pgm) { /* This is mostly a STK500; just the signature is read - differently than on real STK500v1 */ + differently than on real STK500v1 + and the DTR signal is set when opening the serial port + for the Auto-Reset feature */ stk500_initpgm(pgm); strcpy(pgm->type, "Arduino"); pgm->read_sig_bytes = arduino_read_sig_bytes; - + pgm->open = arduino_open; } diff --git a/ser_avrdoper.c b/ser_avrdoper.c index ad3564ad..ed0af07a 100644 --- a/ser_avrdoper.c +++ b/ser_avrdoper.c @@ -634,6 +634,14 @@ static int avrdoper_drain(union filedescriptor *fdp, int display) /* ------------------------------------------------------------------------- */ +static int avrdoper_set_dtr_rts(union filedescriptor *fdp, int is_on) +{ + fprintf(stderr, "%s: AVR-Doper doesn't support DTR/RTS setting\n", progname); + return -1; +} + +/* ------------------------------------------------------------------------- */ + struct serial_device avrdoper_serdev = { .open = avrdoper_open, @@ -641,6 +649,7 @@ struct serial_device avrdoper_serdev = .send = avrdoper_send, .recv = avrdoper_recv, .drain = avrdoper_drain, + .set_dtr_rts = avrdoper_set_dtr_rts, .flags = SERDEV_FL_NONE, }; diff --git a/ser_posix.c b/ser_posix.c index 2408f9f0..751738eb 100644 --- a/ser_posix.c +++ b/ser_posix.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -210,6 +211,36 @@ net_open(const char *port, union filedescriptor *fdp) fdp->ifd = fd; } + +static int ser_set_dtr_rts(union filedescriptor *fdp, int is_on) +{ + unsigned int ctl; + int r; + + r = ioctl(fdp->ifd, TIOCMGET, &ctl); + if (r < 0) { + perror("ioctl(\"TIOCMGET\")"); + return -1; + } + + if (is_on) { + /* Clear DTR and RTS */ + ctl &= ~(TIOCM_DTR | TIOCM_RTS); + } + else { + /* Set DTR and RTS */ + ctl |= (TIOCM_DTR | TIOCM_RTS); + } + + r = ioctl(fdp->ifd, TIOCMSET, &ctl); + if (r < 0) { + perror("ioctl(\"TIOCMSET\")"); + return -1; + } + + return 0; +} + static void ser_open(char * port, long baud, union filedescriptor *fdp) { int rc; @@ -455,6 +486,7 @@ struct serial_device serial_serdev = .send = ser_send, .recv = ser_recv, .drain = ser_drain, + .set_dtr_rts = ser_set_dtr_rts, .flags = SERDEV_FL_CANSETSPEED, }; diff --git a/ser_win32.c b/ser_win32.c index ed8eb29d..bce99f50 100644 --- a/ser_win32.c +++ b/ser_win32.c @@ -203,6 +203,20 @@ static void ser_close(union filedescriptor *fd) hComPort = INVALID_HANDLE_VALUE; } +static int ser_set_dtr_rts(union filedescriptor *fdp, int is_on) +{ + HANDLE hComPort=(HANDLE)fd->pfd; + + if (is_on) { + EscapeCommFunction(hComPort, SETDTR); + EscapeCommFunction(hComPort, SETRTS); + } else { + EscapeCommFunction(hComPort, CLRDTR); + EscapeCommFunction(hComPort, CLRRTS); + } + return 0; +} + static int ser_send(union filedescriptor *fd, unsigned char * buf, size_t buflen) { @@ -378,6 +392,7 @@ struct serial_device serial_serdev = .send = ser_send, .recv = ser_recv, .drain = ser_drain, + .set_dtr_rts = ser_set_dtr_rts, .flags = SERDEV_FL_CANSETSPEED, }; diff --git a/serial.h b/serial.h index db9c1237..4a52f19b 100644 --- a/serial.h +++ b/serial.h @@ -52,6 +52,8 @@ struct serial_device int (*recv)(union filedescriptor *fd, unsigned char * buf, size_t buflen); int (*drain)(union filedescriptor *fd, int display); + int (*set_dtr_rts)(union filedescriptor *fd, int is_on); + int flags; #define SERDEV_FL_NONE 0x0000 /* no flags */ #define SERDEV_FL_CANSETSPEED 0x0001 /* device can change speed */ @@ -69,5 +71,6 @@ extern struct serial_device avrdoper_serdev; #define serial_send (serdev->send) #define serial_recv (serdev->recv) #define serial_drain (serdev->drain) +#define serial_set_dtr_rts (serdev->set_dtr_rts) #endif /* serial_h */ diff --git a/stk500.c b/stk500.c index fe8c9275..4e7c4fff 100644 --- a/stk500.c +++ b/stk500.c @@ -73,13 +73,13 @@ static int stk500_recv(PROGRAMMER * pgm, unsigned char * buf, size_t len) } -static int stk500_drain(PROGRAMMER * pgm, int display) +int stk500_drain(PROGRAMMER * pgm, int display) { return serial_drain(&pgm->fd, display); } -static int stk500_getsync(PROGRAMMER * pgm) +int stk500_getsync(PROGRAMMER * pgm) { unsigned char buf[32], resp[32]; diff --git a/stk500.h b/stk500.h index f6ed3f1b..4b22ee05 100644 --- a/stk500.h +++ b/stk500.h @@ -28,6 +28,10 @@ extern "C" { void stk500_initpgm (PROGRAMMER * pgm); +/* used by arduino.c to avoid duplicate code */ +int stk500_getsync(PROGRAMMER * pgm); +int stk500_drain(PROGRAMMER * pgm, int display); + #ifdef __cplusplus } #endif