From be4f46c49e855270719cceee194e2923a1e3f6a5 Mon Sep 17 00:00:00 2001 From: kiwi64ajs Date: Thu, 24 Jun 2004 11:05:07 +0000 Subject: [PATCH] merged in changes to allow native Win32 build with no cygwin DLL dependancy git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@419 81a1dc3b-b13d-400b-aceb-764788c761c2 --- avr910.c | 4 + butterfly.c | 75 ++++++++++++++ config_gram.y | 5 + configure.ac | 2 + confwin.c | 2 +- confwin.h | 2 +- fileio.c | 2 +- main.c | 25 ++++- pgm.h | 28 ++++++ ppi.h | 7 -- ppiwin.c | 126 ++++++++++------------- ser_posix.c | 5 + ser_win32.c | 274 +++++++++++++++++++++++++++++++++++++++++++++++++- term.c | 6 +- 14 files changed, 472 insertions(+), 91 deletions(-) diff --git a/avr910.c b/avr910.c index c54cd95f..bdac9a10 100644 --- a/avr910.c +++ b/avr910.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include "avr.h" #include "pgm.h" @@ -259,6 +261,8 @@ static int avr910_open(PROGRAMMER * pgm, char * port) * drain any extraneous input */ avr910_drain (pgm, 0); + + return 0; } static void avr910_close(PROGRAMMER * pgm) diff --git a/butterfly.c b/butterfly.c index ef893078..2c48bffb 100644 --- a/butterfly.c +++ b/butterfly.c @@ -93,6 +93,46 @@ static void butterfly_vfy_cmd_sent(PROGRAMMER * pgm, char * errmsg) } +static int butterfly_rdy_led(PROGRAMMER * pgm, int value) +{ + no_show_func_info(); + + /* Do nothing. */ + + return 0; +} + + +static int butterfly_err_led(PROGRAMMER * pgm, int value) +{ + no_show_func_info(); + + /* Do nothing. */ + + return 0; +} + + +static int butterfly_pgm_led(PROGRAMMER * pgm, int value) +{ + no_show_func_info(); + + /* Do nothing. */ + + return 0; +} + + +static int butterfly_vfy_led(PROGRAMMER * pgm, int value) +{ + no_show_func_info(); + + /* Do nothing. */ + + return 0; +} + + /* * issue the 'chip erase' command to the butterfly board */ @@ -132,6 +172,31 @@ static int butterfly_program_enable(PROGRAMMER * pgm, AVRPART * p) } +/* + * apply power to the AVR processor + */ +static void butterfly_powerup(PROGRAMMER * pgm) +{ + no_show_func_info(); + + /* Do nothing. */ + + return; +} + + +/* + * remove power from the AVR processor + */ +static void butterfly_powerdown(PROGRAMMER * pgm) +{ + no_show_func_info(); + + /* Do nothing. */ + + return; +} + /* * initialize the AVR device and prepare it to accept commands @@ -246,6 +311,7 @@ static int butterfly_initialize(PROGRAMMER * pgm, AVRPART * p) } + static void butterfly_disable(PROGRAMMER * pgm) { no_show_func_info(); @@ -288,6 +354,9 @@ static void butterfly_close(PROGRAMMER * pgm) butterfly_leave_prog_mode(pgm); + /* "exit programmer" added by Martin Thomas 2/2004 */ + butterfly_send(pgm, "E", 1); + serial_close(pgm->fd); pgm->fd = -1; } @@ -526,10 +595,16 @@ void butterfly_initpgm(PROGRAMMER * pgm) /* * mandatory functions */ + pgm->rdy_led = butterfly_rdy_led; + pgm->err_led = butterfly_err_led; + pgm->pgm_led = butterfly_pgm_led; + pgm->vfy_led = butterfly_vfy_led; pgm->initialize = butterfly_initialize; pgm->display = butterfly_display; pgm->enable = butterfly_enable; pgm->disable = butterfly_disable; + pgm->powerup = butterfly_powerup; + pgm->powerdown = butterfly_powerdown; pgm->program_enable = butterfly_program_enable; pgm->chip_erase = butterfly_chip_erase; /* pgm->cmd not supported, use default error message */ diff --git a/config_gram.y b/config_gram.y index 8624009a..0cd7ee82 100644 --- a/config_gram.y +++ b/config_gram.y @@ -37,6 +37,11 @@ #include "butterfly.h" #include "avr.h" +#if defined(WIN32NATIVE) +#define strtok_r( _s, _sep, _lasts ) \ + ( *(_lasts) = strtok( (_s), (_sep) ) ) +#endif + extern char * progname; int yylex(void); diff --git a/configure.ac b/configure.ac index 524cdf3c..46e88619 100644 --- a/configure.ac +++ b/configure.ac @@ -121,6 +121,8 @@ AC_SUBST(DEFAULT_SER_PORT, $DEFAULT_SER_PORT) case $target in *-*-mingw32* | *-*-cygwin* | *-*-windows*) WINDOWS_DIRS="windows" + CFLAGS="-mno-cygwin -DWIN32NATIVE" + LDFLAGS="-static" ;; esac AC_SUBST(WINDOWS_DIRS,$WINDOWS_DIRS) diff --git a/confwin.c b/confwin.c index 2d864c6b..06d8e01f 100644 --- a/confwin.c +++ b/confwin.c @@ -19,7 +19,7 @@ -#if defined(__CYGWIN__) +#if defined(WIN32NATIVE) #include #include diff --git a/confwin.h b/confwin.h index f57ae6e1..fd1c212d 100644 --- a/confwin.h +++ b/confwin.h @@ -19,7 +19,7 @@ -#if defined(__CYGWIN__) +#if defined(WIN32NATIVE) #ifndef __confwin_h__ #define __confwin_h__ diff --git a/fileio.c b/fileio.c index 5dd9f35e..7f2194ec 100644 --- a/fileio.c +++ b/fileio.c @@ -910,7 +910,7 @@ int fileio(int op, char * filename, FILEFMT format, if (rc < 0) return -1; - #if defined(__CYGWIN__) + #if defined(WIN32NATIVE) /* Open Raw Binary format in binary mode on Windows.*/ if(format == FMT_RBIN) { diff --git a/main.c b/main.c index 67d3263c..a0d435f3 100644 --- a/main.c +++ b/main.c @@ -700,11 +700,17 @@ int main(int argc, char * argv []) char * e; /* for strtol() error checking */ int quell_progress; int baudrate; /* override default programmer baud rate */ -#if !defined(__CYGWIN__) +#if !defined(WIN32NATIVE) char * homedir; #endif progname = rindex(argv[0],'/'); + + #if defined (WIN32NATIVE) + /* take care of backslash as dir sep in W32 */ + if (!progname) progname = rindex(argv[0],'\\'); + #endif /* WIN32NATIVE */ + if (progname) progname++; else @@ -742,7 +748,7 @@ int main(int argc, char * argv []) baudrate = 0; - #if defined(__CYGWIN__) + #if defined(WIN32NATIVE) win_sys_config_set(sys_config); win_usr_config_set(usr_config); @@ -897,8 +903,16 @@ int main(int argc, char * argv []) if (quell_progress == 0) { if (isatty (STDERR_FILENO)) update_progress = update_progress_tty; - else + else { update_progress = update_progress_no_tty; + #if defined(WIN32NATIVE) + /* disable all buffering of stderr for compatibility with + software that captures and redirects output to a GUI + i.e. Programmers Notepad */ + setvbuf( stderr, NULL, _IONBF, 0 ); + setvbuf( stdout, NULL, _IONBF, 0 ); + #endif /* WIN32NATIVE */ + } } if (verbose) { @@ -910,6 +924,11 @@ int main(int argc, char * argv []) "\n%s: Version %s\n" "%sCopyright (c) 2000-2003 Brian Dean, bsd@bsdhome.com\n\n", progname, version, progbuf); + #if defined(WIN32NATIVE) + #warning "Experimental Win32 Native Build" + fprintf(stderr,"%sExperimental Windows32 native build by Martin Thomas\n\n", + progbuf); + #endif } if (verbose) { diff --git a/pgm.h b/pgm.h index c1e71c5f..2654b304 100644 --- a/pgm.h +++ b/pgm.h @@ -83,4 +83,32 @@ typedef struct programmer_t { PROGRAMMER * pgm_new(void); +#if defined(WIN32NATIVE) + +#include + +/* usleep replacements */ +/* sleep Windows in ms, Unix usleep in us + #define usleep(us) Sleep((us)<20000?20:us/1000) + #define usleep(us) Sleep(us/1000) + #define ANTIWARP 3 + #define usleep(us) Sleep(us/1000*ANTIWARP) +*/ +void usleep(unsigned long us); + +void gettimeofday(struct timeval*, void*z); + +#define rindex strrchr + +#endif /* __win32native_h */ + + +#if !defined(ppi_claim) +# define ppi_claim(pgm) +#endif + +#if !defined(ppi_release) +# define ppi_release(pgm) +#endif + #endif diff --git a/ppi.h b/ppi.h index 487ddecb..7f817f9e 100644 --- a/ppi.h +++ b/ppi.h @@ -34,13 +34,6 @@ enum { }; -#if !defined(ppi_claim) -# define ppi_claim(pgm) -#endif - -#if !defined(ppi_release) -# define ppi_release(pgm) -#endif int ppi_get (int fd, int reg, int bit); diff --git a/ppiwin.c b/ppiwin.c index dccbfac6..e8a68fb6 100644 --- a/ppiwin.c +++ b/ppiwin.c @@ -30,7 +30,7 @@ reg = register as defined in an enum in ppi.h. This must be converted -#if defined(__CYGWIN__) +#if defined (WIN32NATIVE) #include #include @@ -40,11 +40,9 @@ reg = register as defined in an enum in ppi.h. This must be converted #include #include #include -#include +#include #include "ppi.h" - - extern char *progname; @@ -317,79 +315,61 @@ static void outb(unsigned char value, unsigned short port) return; } -/* These two functions usecPerfDelay and usleep are based on code from the - * uisp project and are a replacement for the cygwin usleep library - * function which seems to not delay for the correct time - */ +void gettimeofday(struct timeval*tv, void*z){ +// i've found only ms resolution, avrdude expects us -BOOL usecPerfDelay(long t) -{ - static BOOL perf_counter_checked = FALSE; - static BOOL use_perf_counter = FALSE; - static LARGE_INTEGER freq ; - - if (! perf_counter_checked) { - if (QueryPerformanceFrequency(&freq)){ - use_perf_counter = TRUE; - } - perf_counter_checked = TRUE; - } - - if (! use_perf_counter) - return FALSE; - - else { - LARGE_INTEGER now; - LARGE_INTEGER finish; - QueryPerformanceCounter(&now); - finish.QuadPart = now.QuadPart + (t * freq.QuadPart) / 1000000; - do { - QueryPerformanceCounter(&now); - } while (now.QuadPart < finish.QuadPart); - - return TRUE; - } -} - -/* -WARNING WARNING This function replaces the standard usleep() library function -because it doesn't appear to delay for the correct time. -*/ - -#ifndef MIN_SLEEP_USEC -#define MIN_SLEEP_USEC 20000 -#endif - -unsigned usleep( unsigned int uSeconds ) -{ - struct timeval t1, t2; - struct timespec nanoDelay ; - - if (usecPerfDelay(uSeconds)) - return(0); - - gettimeofday(&t1, NULL); - - if( uSeconds > MIN_SLEEP_USEC ) - { - nanoDelay.tv_sec = uSeconds / 1000000UL; - nanoDelay.tv_nsec = (uSeconds / 1000000UL) * 1000 ; - nanosleep( &nanoDelay, NULL ) ; - } - - /* loop for the remaining time */ - t2.tv_sec = uSeconds / 1000000UL; - t2.tv_usec = uSeconds % 1000000UL; - - timeradd(&t1, &t2, &t1); - - do { - gettimeofday(&t2, NULL); - } while (timercmp(&t2, &t1, <)); + SYSTEMTIME st; + GetSystemTime(&st); - return(0); + tv->tv_sec=(long)(st.wSecond+st.wMinute*60+st.wHour*3600); + tv->tv_usec=(long)(st.wMilliseconds*1000); } +// #define W32USLEEPDBG + +void usleep(unsigned long us) +{ + int has_highperf; + LARGE_INTEGER freq,start,stop,loopend; + #ifdef W32USLEEPDBG + unsigned long dt; + #endif + + // workaround: although usleep is very precise if using + // high-performance-timers there are sometimes problems with + // verify - increasing the delay helps sometimes but not + // realiably. There must be some other problem. Maybe just + // with my test-hardware maybe in the code-base. + //// us=(unsigned long) (us*1.5); + + has_highperf=QueryPerformanceFrequency(&freq); + + //has_highperf=0; // debug + + if (has_highperf) { + QueryPerformanceCounter(&start); + loopend.QuadPart=start.QuadPart+freq.QuadPart*us/(1000*1000); + do { + QueryPerformanceCounter(&stop); + } while (stop.QuadPart<=loopend.QuadPart); + } + else { + #ifdef W32USLEEPDBG + QueryPerformanceCounter(&start); + #endif + Sleep(1); + Sleep( (DWORD)((us+999)/1000) ); + #ifdef W32USLEEPDBG + QueryPerformanceCounter(&stop); + #endif + } + + #ifdef W32USLEEPDBG + dt=(unsigned long)((stop.QuadPart-start.QuadPart)*1000*1000/freq.QuadPart); + fprintf(stderr,"hpt:%i usleep usec:%lu sleep msec:%lu timed usec:%lu\n", + has_highperf,us,((us+999)/1000),dt); + #endif +} #endif diff --git a/ser_posix.c b/ser_posix.c index 59b3bd19..3cc48813 100644 --- a/ser_posix.c +++ b/ser_posix.c @@ -23,6 +23,9 @@ * Posix serial interface for avrdude. */ +#if !defined(WIN32NATIVE) + + #include #include #include @@ -350,3 +353,5 @@ int serial_drain(int fd, int display) return 0; } + +#endif /* WIN32NATIVE */ diff --git a/ser_win32.c b/ser_win32.c index 3b0555f2..bf978182 100644 --- a/ser_win32.c +++ b/ser_win32.c @@ -23,38 +23,306 @@ * Native Win32 serial interface for avrdude. */ +#if defined(WIN32NATIVE) + +#include +#include /* for isprint */ #include "serial.h" extern char *progname; +extern int verbose; -#if 0 +#define W32SERBUFSIZE 1024 + +struct baud_mapping { + long baud; + DWORD speed; +}; + +/* HANDLE hComPort=INVALID_HANDLE_VALUE; */ + +static struct baud_mapping baud_lookup_table [] = { + { 1200, CBR_1200 }, + { 2400, CBR_2400 }, + { 4800, CBR_4800 }, + { 9600, CBR_9600 }, + { 19200, CBR_19200 }, + { 38400, CBR_38400 }, + { 57600, CBR_57600 }, + { 115200, CBR_115200 }, + { 0, 0 } /* Terminator. */ +}; + +static DWORD serial_baud_lookup(long 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: %ld", + progname, baud); + exit(1); +} + + +BOOL serial_w32SetTimeOut(HANDLE hComPort, DWORD timeout) // in ms +{ + COMMTIMEOUTS ctmo; + ZeroMemory (&ctmo, sizeof(COMMTIMEOUTS)); + ctmo.ReadIntervalTimeout = timeout; + ctmo.ReadTotalTimeoutMultiplier = timeout; + ctmo.ReadTotalTimeoutConstant = timeout; + + return SetCommTimeouts(hComPort, &ctmo); +} int serial_open(char * port, long baud) { - return fd; + DCB dcb; + LPVOID lpMsgBuf; + HANDLE hComPort=INVALID_HANDLE_VALUE; + + /* if (hComPort!=INVALID_HANDLE_VALUE) + fprintf(stderr, "%s: serial_open(): \"%s\" is already open\n", + progname, port); + */ + + hComPort = CreateFile(port, GENERIC_READ | GENERIC_WRITE, 0, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + if (hComPort == INVALID_HANDLE_VALUE) { + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL); + fprintf(stderr, "%s: serial_open(): can't open device \"%s\": %s\n", + progname, port, (char*)lpMsgBuf); + LocalFree( lpMsgBuf ); + exit(1); + } + + if (!SetupComm(hComPort, W32SERBUFSIZE, W32SERBUFSIZE)) + { + CloseHandle(hComPort); + fprintf(stderr, "%s: serial_open(): can't set buffers for \"%s\"\n", + progname, port); + exit(1); + } + + ZeroMemory (&dcb, sizeof(DCB)); + dcb.DCBlength = sizeof(DCB); + dcb.BaudRate = serial_baud_lookup (baud); + dcb.fBinary = 1; + dcb.fDtrControl = DTR_CONTROL_DISABLE; + dcb.fRtsControl = RTS_CONTROL_DISABLE; + dcb.ByteSize = 8; + dcb.Parity = NOPARITY; + dcb.StopBits = ONESTOPBIT; + + if (!SetCommState(hComPort, &dcb)) + { + CloseHandle(hComPort); + fprintf(stderr, "%s: serial_open(): can't set com-state for \"%s\"\n", + progname, port); + exit(1); + } + + if (!serial_w32SetTimeOut(hComPort,0)) + { + CloseHandle(hComPort); + fprintf(stderr, "%s: serial_open(): can't set initial timeout for \"%s\"\n", + progname, port); + exit(1); + } + + return (int)hComPort; } void serial_close(int fd) { + HANDLE hComPort=(HANDLE)fd; + if (hComPort != INVALID_HANDLE_VALUE) + CloseHandle (hComPort); + + hComPort = INVALID_HANDLE_VALUE; } int serial_send(int fd, char * buf, size_t buflen) { + size_t len = buflen; + unsigned char c='\0'; + DWORD written; + + HANDLE hComPort=(HANDLE)fd; + + if (hComPort == INVALID_HANDLE_VALUE) { + fprintf(stderr, "%s: serial_send(): port not open\n", + progname); + exit(1); + } + + if (!len) return 0; + + if (verbose > 3) + { + fprintf(stderr, "%s: Send: ", progname); + + while (buflen) { + c = *buf; + if (isprint(c)) { + fprintf(stderr, "%c ", c); + } + else { + fprintf(stderr, ". "); + } + fprintf(stderr, "[%02x] ", c); + buf++; + buflen--; + } + fprintf(stderr, "\n"); + } + + serial_w32SetTimeOut(hComPort,500); + + if (!WriteFile (hComPort, buf, buflen, &written, NULL)) { + fprintf(stderr, "%s: serial_send(): write error: %s\n", + progname, "sorry no info avail"); // TODO + exit(1); + } + + if (written != buflen) { + fprintf(stderr, "%s: serial_send(): size/send mismatch\n", + progname); + exit(1); + } + + return 0; } int serial_recv(int fd, char * buf, size_t buflen) { + unsigned char c; + char * p = buf; + size_t len = 0; + DWORD read; + + HANDLE hComPort=(HANDLE)fd; + + if (hComPort == INVALID_HANDLE_VALUE) { + fprintf(stderr, "%s: serial_read(): port not open\n", + progname); + exit(1); + } + + serial_w32SetTimeOut(hComPort,5000); + + if (!ReadFile(hComPort, buf, buflen, &read, NULL)) { + LPVOID lpMsgBuf; + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL ); + fprintf(stderr, "%s: serial_recv(): read error: %s\n", + progname, (char*)lpMsgBuf); + LocalFree( lpMsgBuf ); + exit(1); + } + + p = buf; + + if (verbose > 3) + { + fprintf(stderr, "%s: Recv: ", progname); + + while (len) { + c = *p; + if (isprint(c)) { + fprintf(stderr, "%c ", c); + } + else { + fprintf(stderr, ". "); + } + fprintf(stderr, "[%02x] ", c); + + p++; + len--; + } + fprintf(stderr, "\n"); + } return 0; } int serial_drain(int fd, int display) { + // int rc; + unsigned char buf[10]; + BOOL readres; + DWORD read; + + HANDLE hComPort=(HANDLE)fd; + + if (hComPort == INVALID_HANDLE_VALUE) { + fprintf(stderr, "%s: serial_drain(): port not open\n", + progname); + exit(1); + } + + serial_w32SetTimeOut(hComPort,250); + + if (display) { + fprintf(stderr, "drain>"); + } + + while (1) { + readres=ReadFile(hComPort, buf, 1, &read, NULL); + if (!readres) { + LPVOID lpMsgBuf; + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL ); + fprintf(stderr, "%s: serial_drain(): read error: %s\n", + progname, (char*)lpMsgBuf); + LocalFree( lpMsgBuf ); + exit(1); + } + + if (read) { // data avail + if (display) fprintf(stderr, "%02x ", buf[0]); + } + else { // no more data + if (display) fprintf(stderr, " #if defined(HAVE_LIBREADLINE) +#if !defined(WIN32NATIVE) # include # include #endif +#endif #include "avr.h" #include "config.h" @@ -754,7 +756,7 @@ int do_cmd(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[]) char * terminal_get_input(const char *prompt) { -#if defined(HAVE_LIBREADLINE) +#if defined(HAVE_LIBREADLINE) && !defined(WIN32NATIVE) char *input; input = readline(prompt); if ((input != NULL) && (strlen(input) >= 1)) @@ -767,7 +769,7 @@ char * terminal_get_input(const char *prompt) if (fgets(input, sizeof(input), stdin)) { /* FIXME: readline strips the '\n', should this too? */ - strdup(input); + return strdup(input); } else return NULL;