diff --git a/ChangeLog b/ChangeLog index 48cb86a3..f5bc20cb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2003-03-12 Theodore A. Roth + + * Makefile.am (avrdude_SOURCES): Add avr910.[ch], serial.h and + ser_posix.c files. + * avr910.c: New file (stubs for avr910 serial programmer). + * avr910.h: New file. + * ser_posix.c: New file. + * ser_win32.c: New file (just stubs for now). + * serial.h: New file. + * stk500.c: Move all the code for accessing the posix serial ports + into ser_posix. This will make a native win32 port easier and allows + the avr910 programmer to share the serial code. + 2003-03-12 Theodore A. Roth * configure.ac (AC_INIT): Set version to 4.0.0cvs since we're done diff --git a/Makefile.am b/Makefile.am index 0f3813e8..589d5359 100644 --- a/Makefile.am +++ b/Makefile.am @@ -48,6 +48,8 @@ avrdude_SOURCES = \ lexer.l \ avr.c \ avr.h \ + avr910.c \ + avr910.h \ avrpart.h \ config.c \ config.h \ @@ -67,6 +69,9 @@ avrdude_SOURCES = \ ppi.c \ ppi.h \ ppiwin.c \ + serial.h \ + ser_posix.c \ + ser_win32.c \ stk500.c \ stk500.h \ stk500_private.h \ diff --git a/avr910.c b/avr910.c new file mode 100644 index 00000000..72de6b22 --- /dev/null +++ b/avr910.c @@ -0,0 +1,216 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2003 Theodore A. Roth + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +/* + * avrdude interface for Atmel Low Cost Serial programmers which adher to the + * protocol described in application note avr910. + */ + +#include "ac_cfg.h" + +#include +#include +#include +#include + +#include "avr.h" +#include "pgm.h" +#include "avr910.h" +#include "serial.h" + +extern char * progname; +extern int do_cycles; + + +static int avr910_send(PROGRAMMER * pgm, char * buf, size_t len) +{ + return serial_send(pgm->fd, buf, len); +} + + +static int avr910_recv(PROGRAMMER * pgm, char * buf, size_t len) +{ + return serial_recv(pgm->fd, buf, len); +} + + +static int avr910_drain(PROGRAMMER * pgm, int display) +{ + return serial_drain(pgm->fd, display); +} + + +static int avr910_rdy_led(PROGRAMMER * pgm, int value) +{ + return 0; +} + + +static int avr910_err_led(PROGRAMMER * pgm, int value) +{ + return 0; +} + + +static int avr910_pgm_led(PROGRAMMER * pgm, int value) +{ + return 0; +} + + +static int avr910_vfy_led(PROGRAMMER * pgm, int value) +{ + return 0; +} + + +/* + * issue the 'chip erase' command to the AVR device + */ +static int avr910_chip_erase(PROGRAMMER * pgm, AVRPART * p) +{ + return 0; +} + +/* + * issue the 'program enable' command to the AVR device + */ +static int avr910_program_enable(PROGRAMMER * pgm, AVRPART * p) +{ + return -1; +} + + +/* + * apply power to the AVR processor + */ +static void avr910_powerup(PROGRAMMER * pgm) +{ + return; +} + + +/* + * remove power from the AVR processor + */ +static void avr910_powerdown(PROGRAMMER * pgm) +{ + return; +} + + +/* + * initialize the AVR device and prepare it to accept commands + */ +static int avr910_initialize(PROGRAMMER * pgm, AVRPART * p) +{ + return 0; +} + + +static int avr910_save(PROGRAMMER * pgm) +{ + return 0; +} + + +static void avr910_restore(PROGRAMMER * pgm) +{ + return; +} + + +static void avr910_disable(PROGRAMMER * pgm) +{ + return; +} + + +static void avr910_enable(PROGRAMMER * pgm) +{ + return; +} + + +/* + * transmit an AVR device command and return the results; 'cmd' and + * 'res' must point to at least a 4 byte data buffer + */ +static int avr910_cmd(PROGRAMMER * pgm, unsigned char cmd[4], + unsigned char res[4]) +{ + return 0; +} + + +static void avr910_open(PROGRAMMER * pgm, char * port) +{ + strcpy(pgm->port, port); + pgm->fd = serial_open(port, 19200); + + /* + * drain any extraneous input + */ + avr910_drain (pgm, 0); +} + +static void avr910_close(PROGRAMMER * pgm) +{ + serial_close(pgm->fd); + pgm->fd = -1; +} + + +static void avr910_display(PROGRAMMER * pgm, char * p) +{ + return; +} + + +void avr910_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "avr910"); + + /* + * mandatory functions + */ + pgm->rdy_led = avr910_rdy_led; + pgm->err_led = avr910_err_led; + pgm->pgm_led = avr910_pgm_led; + pgm->vfy_led = avr910_vfy_led; + pgm->initialize = avr910_initialize; + pgm->display = avr910_display; + pgm->save = avr910_save; + pgm->restore = avr910_restore; + pgm->enable = avr910_enable; + pgm->disable = avr910_disable; + pgm->powerup = avr910_powerup; + pgm->powerdown = avr910_powerdown; + pgm->program_enable = avr910_program_enable; + pgm->chip_erase = avr910_chip_erase; + pgm->cmd = avr910_cmd; + pgm->open = avr910_open; + pgm->close = avr910_close; + + /* + * optional functions + */ +} diff --git a/avr910.h b/avr910.h new file mode 100644 index 00000000..9ae392e1 --- /dev/null +++ b/avr910.h @@ -0,0 +1,29 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2003 Theodore A. Roth + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +#ifndef __avr910_h__ +#define __avr910_h__ + +#include "config.h" + +void avr910_initpgm (PROGRAMMER * pgm); + +#endif /* __avr910_h__ */ diff --git a/ser_posix.c b/ser_posix.c new file mode 100644 index 00000000..51719e2f --- /dev/null +++ b/ser_posix.c @@ -0,0 +1,298 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2003 Theodore A. Roth + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +/* + * Posix serial interface for avrdude. + */ + +#include +#include +#include + +#include +#include +#include + +extern char *progname; + +struct baud_mapping { + int baud; + speed_t speed; +}; + +/* There are a lot more baud rates we could handle, but what's the point? */ + +static struct baud_mapping baud_lookup_table [] = { + { 1200, B1200 }, + { 2400, B2400 }, + { 4800, B4800 }, + { 9600, B9600 }, + { 19200, B19200 }, + { 38400, B38400 }, + { 57600, B57600 }, + { 115200, B115200 }, + { 230400, B230400 }, + { 0, 0 } /* Terminator. */ +}; + +static speed_t serial_baud_lookup(int baud) +{ + struct baud_mapping *map = baud_lookup_table; + + while (map->baud) { + if (map->baud == baud) + return map->speed; + map++; + } + + fprintf(stderr, "%s: serial_baud_lookup(): unknown baud rate: %d", + progname, baud); + exit(1); +} + +static int serial_setattr(int fd, int baud) +{ + int rc; + struct termios termios; + speed_t speed = serial_baud_lookup (baud); + + if (!isatty(fd)) + return -1; + + /* + * initialize terminal modes + */ + rc = tcgetattr(fd, &termios); + if (rc < 0) { + fprintf(stderr, "%s: serial_setattr(): tcgetattr() failed, %s", + progname, strerror(errno)); + return -errno; + } + + termios.c_iflag = 0; + termios.c_oflag = 0; + termios.c_cflag = 0; + termios.c_cflag |= (CS8 | CREAD | CLOCAL); + termios.c_lflag = 0; + termios.c_cc[VMIN] = 1; + termios.c_cc[VTIME] = 0; + + cfsetospeed(&termios, speed); + cfsetispeed(&termios, speed); + + rc = tcsetattr(fd, TCSANOW, &termios); + if (rc < 0) { + fprintf(stderr, "%s: serial_setattr(): tcsetattr() failed, %s", + progname, strerror(errno)); + return -errno; + } + + return 0; +} + + +int serial_open(char * port, int baud) +{ + int rc; + int fd; + + /* + * open the serial port + */ + fd = open(port, O_RDWR | O_NOCTTY /*| O_NONBLOCK*/); + if (fd < 0) { + fprintf(stderr, "%s: serial_open(): can't open device \"%s\": %s\n", + progname, port, strerror(errno)); + exit(1); + } + + /* + * set serial line attributes + */ + rc = serial_setattr(fd, baud); + if (rc) { + fprintf(stderr, + "%s: serial_open(): can't set attributes for device \"%s\"\n", + progname, port); + exit(1); + } + + return fd; +} + + +void serial_close(int fd) +{ + /* FIXME: Should really restore the terminal to original state here. */ + + close(fd); +} + + +int serial_send(int fd, char * buf, size_t buflen) +{ + struct timeval timeout; + fd_set wfds; + int nfds; + int rc; + + if (!buflen) + return 0; + + timeout.tv_sec = 0; + timeout.tv_usec = 500000; + + while (buflen) { + FD_ZERO(&wfds); + FD_SET(fd, &wfds); + + reselect: + nfds = select(fd+1, NULL, &wfds, NULL, &timeout); + if (nfds == 0) { + fprintf(stderr, + "%s: serial_send(): programmer is not responding\n", + progname); + exit(1); + } + else if (nfds == -1) { + if (errno == EINTR) { + goto reselect; + } + else { + fprintf(stderr, "%s: serial_send(): select(): %s\n", + progname, strerror(errno)); + exit(1); + } + } + + rc = write(fd, buf, 1); + if (rc < 0) { + fprintf(stderr, "%s: serial_send(): write error: %s\n", + progname, strerror(errno)); + exit(1); + } + buf++; + buflen--; + } + + return 0; +} + + +int serial_recv(int fd, char * buf, size_t buflen) +{ + struct timeval timeout; + fd_set rfds; + int nfds; + int rc; + + timeout.tv_sec = 5; + timeout.tv_usec = 0; + + while (buflen) { + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + + reselect: + nfds = select(fd+1, &rfds, NULL, NULL, &timeout); + if (nfds == 0) { + fprintf(stderr, + "%s: serial_recv(): programmer is not responding\n", + progname); + exit(1); + } + else if (nfds == -1) { + if (errno == EINTR) { + goto reselect; + } + else { + fprintf(stderr, "%s: serial_recv(): select(): %s\n", + progname, strerror(errno)); + exit(1); + } + } + + rc = read(fd, buf, 1); + if (rc < 0) { + fprintf(stderr, "%s: serial_recv(): read error: %s\n", + progname, strerror(errno)); + exit(1); + } + buf++; + buflen--; + } + + return 0; +} + + +int serial_drain(int fd, int display) +{ + struct timeval timeout; + fd_set rfds; + int nfds; + int rc; + unsigned char buf; + + timeout.tv_sec = 0; + timeout.tv_usec = 250000; + + if (display) { + fprintf(stderr, "drain>"); + } + + while (1) { + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + + reselect: + nfds = select(fd+1, &rfds, NULL, NULL, &timeout); + if (nfds == 0) { + if (display) { + fprintf(stderr, " + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +/* + * Posix serial interface for avrdude. + */ + +extern char *progname; + +#if 0 + +int serial_open(char * port, int baud) +{ + return fd; +} + + +void serial_close(int fd) +{ +} + + +int serial_send(int fd, char * buf, size_t buflen) +{ + return 0; +} + + +int serial_recv(int fd, char * buf, size_t buflen) +{ + return 0; +} + + +int serial_drain(int fd, int display) +{ + return 0; +} + +#endif diff --git a/serial.h b/serial.h new file mode 100644 index 00000000..b8aaf3ff --- /dev/null +++ b/serial.h @@ -0,0 +1,42 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2003 Theodore A. Roth + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id$ */ + +/* This is the API for the generic serial interface. The implementations are + actually provided by the target dependant files: + + ser_posix.c : posix serial interface. + ser_win32.c : native win32 serial interface. + + The target file will be selected at configure time. */ + +#ifndef __serial_h__ +#define __serial_h__ + +#include "config.h" + +extern int serial_open(char * port, int baud); +extern void serial_close(int fd); + +extern int serial_send(int fd, char * buf, size_t buflen); +extern int serial_recv(int fd, char * buf, size_t buflen); +extern int serial_drain(int fd, int display); + +#endif /* __serial_h__ */ diff --git a/stk500.c b/stk500.c index 2442f37f..c570c8a5 100644 --- a/stk500.c +++ b/stk500.c @@ -33,15 +33,12 @@ #include #include #include -#include -#include #include -#include -#include #include "avr.h" #include "pgm.h" #include "stk500_private.h" +#include "serial.h" extern char * progname; @@ -51,153 +48,21 @@ extern int do_cycles; static int stk500_getparm(PROGRAMMER * pgm, unsigned parm, unsigned * value); -static int stk500_send(PROGRAMMER * pgm, char * buf, int buflen) +static int stk500_send(PROGRAMMER * pgm, char * buf, size_t len) { - struct timeval timeout; - fd_set wfds; - int nfds; - int rc; - - if (!buflen) - return 0; - - timeout.tv_sec = 0; - timeout.tv_usec = 500000; - - while (buflen) { - FD_ZERO(&wfds); - FD_SET(pgm->fd, &wfds); - - reselect: - nfds = select(pgm->fd+1, NULL, &wfds, NULL, &timeout); - if (nfds == 0) { - fprintf(stderr, - "%s: stk500_send(): programmer is not responding on %s\n", - progname, pgm->port); - exit(1); - } - else if (nfds == -1) { - if (errno == EINTR) { - goto reselect; - } - else { - fprintf(stderr, "%s: stk500_send(): select(): %s\n", - progname, strerror(errno)); - exit(1); - } - } - - rc = write(pgm->fd, buf, 1); - if (rc < 0) { - fprintf(stderr, "%s: stk500_send(): write error: %s\n", - progname, strerror(errno)); - exit(1); - } - buf++; - buflen--; - } - - return 0; + return serial_send(pgm->fd, buf, len); } - - -static int stk500_recv(PROGRAMMER * pgm, char * buf, int n) + +static int stk500_recv(PROGRAMMER * pgm, char * buf, size_t len) { - struct timeval timeout; - fd_set rfds; - int nfds; - int rc; - - timeout.tv_sec = 5; - timeout.tv_usec = 0; - - while (n) { - FD_ZERO(&rfds); - FD_SET(pgm->fd, &rfds); - - reselect: - nfds = select(pgm->fd+1, &rfds, NULL, NULL, &timeout); - if (nfds == 0) { - fprintf(stderr, - "%s: stk500_recv(): programmer is not responding on %s\n", - progname, pgm->port); - exit(1); - } - else if (nfds == -1) { - if (errno == EINTR) { - goto reselect; - } - else { - fprintf(stderr, "%s: stk500_recv(): select(): %s\n", - progname, strerror(errno)); - exit(1); - } - } - - rc = read(pgm->fd, buf, 1); - if (rc < 0) { - fprintf(stderr, "%s: stk500_recv(): read error: %s\n", - progname, strerror(errno)); - exit(1); - } - buf++; - n--; - } - - return 0; + return serial_recv(pgm->fd, buf, len); } - + static int stk500_drain(PROGRAMMER * pgm, int display) { - struct timeval timeout; - fd_set rfds; - int nfds; - int rc; - unsigned char buf; - - timeout.tv_sec = 0; - timeout.tv_usec = 250000; - - if (display) { - fprintf(stderr, "drain>"); - } - - while (1) { - FD_ZERO(&rfds); - FD_SET(pgm->fd, &rfds); - - reselect: - nfds = select(pgm->fd+1, &rfds, NULL, NULL, &timeout); - if (nfds == 0) { - if (display) { - fprintf(stderr, "fd, &buf, 1); - if (rc < 0) { - fprintf(stderr, "%s: stk500_drain(): read error: %s\n", - progname, strerror(errno)); - exit(1); - } - if (display) { - fprintf(stderr, "%02x ", buf); - } - } + return serial_drain(pgm->fd, display); } @@ -739,72 +604,10 @@ static void stk500_enable(PROGRAMMER * pgm) } -static int stk500_setattr(int fd) -{ - int rc; - struct termios termios; - - if (!isatty(fd)) - return -1; - - /* - * initialize terminal modes - */ - rc = tcgetattr(fd, &termios); - if (rc < 0) { - fprintf(stderr, "%s: stk500_setattr(): tcgetattr() failed, %s", - progname, strerror(errno)); - return -errno; - } - - termios.c_iflag = 0; - termios.c_oflag = 0; - termios.c_cflag = 0; - termios.c_cflag |= (CS8 | CREAD | CLOCAL); - termios.c_lflag = 0; - termios.c_cc[VMIN] = 1; - termios.c_cc[VTIME] = 0; - - cfsetospeed(&termios, B115200); - cfsetispeed(&termios, B115200); - - rc = tcsetattr(fd, TCSANOW, &termios); - if (rc < 0) { - fprintf(stderr, "%s: stk500_setattr(): tcsetattr() failed, %s", - progname, strerror(errno)); - return -errno; - } - - return 0; -} - - static void stk500_open(PROGRAMMER * pgm, char * port) { - int rc; - strcpy(pgm->port, port); - - /* - * open the serial port - */ - pgm->fd = open(port, O_RDWR | O_NOCTTY /*| O_NONBLOCK*/); - if (pgm->fd < 0) { - fprintf(stderr, "%s: stk500_open(): can't open device \"%s\": %s\n", - progname, port, strerror(errno)); - exit(1); - } - - /* - * set serial line attributes - */ - rc = stk500_setattr(pgm->fd); - if (rc) { - fprintf(stderr, - "%s: stk500_open(): can't set attributes for device \"%s\"\n", - progname, port); - exit(1); - } + pgm->fd = serial_open(port, 115200); /* * drain any extraneous input @@ -819,7 +622,7 @@ static void stk500_open(PROGRAMMER * pgm, char * port) static void stk500_close(PROGRAMMER * pgm) { - close(pgm->fd); + serial_close(pgm->fd); pgm->fd = -1; }