As Brian Dean wrote:

> > As promised, i finished a new version of my patch. It can be found
> > at http://kju.de/misc/bitbang.diff.

First of all, again a big "Thanks!" to Michael for that contribution.
I think it's one of the more frequently requested items this code is
going to add now.  I guess if I eventually start to clone the JTAG ICE
mkII code for the mkI, we've covered any programmer on earth that is
in active use for the AVR.

> I'm curious - why did you remove the 'static' qualifier from all the
> par_xx() functions in 'par.c'?  Looks like the only functions that
> need to be external are par_setpin(), par_getpin(), and
> par_highpulsepin() (which looks like it was renamed from
> par_pulsepin()).

[I'll leave that question open here.]

> Otherwise, I think this looks good and should provide another useful
> programmer definition for folks.  You should add your name to the
> copyright in the files you have contributed.  See the copyright
> header for stk500v2.c for an example.

...as well as bumping the copyright year in any file that has been
touched, something that's quite often forgotten.

I've build the patched AVRDUDE on several systems, namely FreeBSD (4.x
and 5.x), Linux (2.6.x, AMD64 platform), and eventually also Win32
(see below).  It all works fine, though I've been pulling some of my
few hairs out until I noticed that a Linux-i386 binary simply didn't
work as expected on Linux-amd64, as apparently one of the ioctls (the
one to set/clear the break status) isn't implemented in the 32-bit
compat module.  Sigh.  A native rebuild on the amd64 system then
worked.  I've also verified the parport bit-banging adapter on my
"kitchentable" system (see below), and as Michael already noticed with
the STK200, that one continues to work fine.

Some random remarks and suggestions below.

Here are some timing values, taken for a full read of an ATmega128's
ROM on my kitchentable Toshiba Libretto 70ct (120 MHz Pentium):

Programmer  time [s]
ponyser          433
alf              182
stk500            41
jtag2fast         26

It appears the serial bit-banging is abysmally slow, in particular on
FreeBSD.  It's almost as slow on my 900 MHz Athlon desktop system, but
it seemed to be quite fast on the Linux system I've been testing (but
I've only got an ATmega16 there).

serbb_open() declares "int flags" inside function.  This breaks
compilation of a non-C99-aware compiler (as on my Libretto).  Better
declare that at the beginning of the function.

$Id$ lines are missing on newly added files.

Per the standard, C preprocessor command must start with the pound
sign in column 1 (but space might follow between the pound sign and
the command itself).

There's a lot of trailing white space in all the files.  I suggest
that new files should be stripped of it before entering the
repository.

All documentation updates are missing so far, even the basic comments
in avrdude.conf.in are a bit sparse.

The missing capitalization makes things hard to read.  I'd like to
avoid it for anything that is meant to be for public consumption
(avrdude.conf.in, documentation).

I've made a stab at implementing the meat of serbb_win32.c, basically
based on the documentation found on msdn.microsoft.com.  The result
has proven to work in a MinGW installation I've got access to at work.
The only point I don't understand, I didn't find any mention of the
DCD line in MSDN at all.  Does anybody know whether MS_RLSD_ON is the
Microsoft name for DCD, or is that something completely different?

Regarding the slowness of the serial bit-banging in FreeBSD, I think
the serbb_posix.c implementation could benefit from a locally cached
line status for all the output lines.  I've implemented it that way in
serbb_win32.c, but didn't touch serbb_posix.c yet.

The offset 7 for inverted IO lines in serbb was neither documented
nor very intuitive.  I thought a bit about it, and came to the
conclusion that a tilde before the pin number might be a more
comprehensible declaration.  The attached patch implements that.

-- 
cheers, J"org               .-.-.   --... ...--   -.. .  DL8DTL

http://www.sax.de/~joerg/                        NIC: JW11-RIPE
Never trust an operating system you don't have sources for. ;-)
/*
 * avrdude - A Downloader/Uploader for AVR device programmers
 * Copyright (C) 2003, 2004  Martin J. Thomas  <[EMAIL PROTECTED]>
 * Copyright (C) 2005 Michael Holzt <[EMAIL PROTECTED]>
 * Copyright (C) 2005 Joerg Wunsch <[EMAIL PROTECTED]>
 *
 * 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$ */

/*
 * Win32 serial bitbanging interface for avrdude.
 */

#if defined(WIN32NATIVE)


#include "ac_cfg.h"

#include <windows.h>
#include <stdio.h>

#include "avr.h"
#include "pindefs.h"
#include "pgm.h"
#include "bitbang.h"

extern char *progname;
extern int verbose;

/* cached status lines */
static int dtr, rts, txd;

#define W32SERBUFSIZE 1024

/*
  serial port/pin mapping

  1     cd      <-
  2     rxd     <-
  3     txd     ->
  4     dtr     ->
  5     dsr     <-
  6     rts     ->
  7     cts     <-

  Pin # above 7 means negated (pin - 7).
*/

void serbb_setpin(int fd, int pin, int value)
{
        HANDLE hComPort = (HANDLE)fd;
        LPVOID lpMsgBuf;
        DWORD dwFunc;
        const char *name;

        if (pin < 1 || pin > 14)
                return;

        if (pin > 7)
        {
                value = !value;
                pin -= 7;
        }

        pin--;

        switch (pin)
        {
        case 2:  /* txd */
                dwFunc = value? SETBREAK: CLRBREAK;
                name = value? "SETBREAK": "CLRBREAK";
                txd = value;
                break;

        case 3:  /* dtr */
                dwFunc = value? SETDTR: CLRDTR;
                name = value? "SETDTR": "CLRDTR";
                dtr = value;
                break;

        case 5:  /* rts */
                dwFunc = value? SETRTS: CLRRTS;
                name = value? "SETRTS": "CLRRTS";
                break;

        default:
                if (verbose)
                        fprintf(stderr,
                                "%s: serbb_setpin(): unknown pin %d\n",
                                progname, pin + 1);
                return;
        }
        if (verbose > 4)
                fprintf(stderr,
                        "%s: serbb_setpin(): EscapeCommFunction(%s)\n",
                        progname, name);
        if (!EscapeCommFunction(hComPort, dwFunc))
        {
                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: serbb_setpin(): SetCommState() failed: %s\n",
                        progname, (char *)lpMsgBuf);
                CloseHandle(hComPort);
                LocalFree(lpMsgBuf);
                exit(1);
        }
        return;
}

int serbb_getpin(int fd, int pin)
{
        HANDLE hComPort = (HANDLE)fd;
        LPVOID lpMsgBuf;
        int invert, rv;
        const char *name;
        DWORD modemstate;

        if (pin < 1 || pin > 14)
                return -1;

        if (pin > 7)
        {
                invert = 1;
                pin -= 7;
        } else
                invert = 0;

        pin --;

        if (pin == 0 /* cd */ || pin == 4 /* dsr */ || pin == 6 /* cts */)
        {
                if (!GetCommModemStatus(hComPort, &modemstate))
                {
                        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: serbb_setpin(): GetCommModemStatus() 
failed: %s\n",
                                progname, (char *)lpMsgBuf);
                        CloseHandle(hComPort);
                        LocalFree(lpMsgBuf);
                        exit(1);
                }
                if (verbose > 4)
                        fprintf(stderr,
                                "%s: serbb_getpin(): GetCommState() => 0x%lx\n",
                                progname, modemstate);
                switch (pin)
                {
                case 0:
                        modemstate &= MS_RLSD_ON;
                        break;
                case 4:
                        modemstate &= MS_DSR_ON;
                        break;
                case 6:
                        modemstate &= MS_CTS_ON;
                        break;
                }
                rv = modemstate != 0;
                if (invert)
                        rv = !rv;

                return rv;
        }

        switch (pin)
        {
        case 2: /* txd */
                rv = txd;
                name = "TXD";
                break;
        case 3: /* dtr */
                rv = dtr;
                name = "DTR";
                break;
        case 5: /* rts */
                rv = rts;
                name = "RTS";
                break;
        default:
                if (verbose)
                        fprintf(stderr,
                                "%s: serbb_getpin(): unknown pin %d\n",
                                progname, pin + 1);
                return -1;
        }
        if (verbose > 4)
                fprintf(stderr,
                        "%s: serbb_getpin(): return cached state for %s\n",
                        progname, name);
        if (invert)
                rv = !rv;

        return rv;
}

int serbb_highpulsepin(int fd, int pin)
{
        if (pin < 1 || pin > 13)
                return -1;

        serbb_setpin(fd, pin, 1);
#if SLOW_TOGGLE
        usleep(1000);
#endif
        serbb_setpin(fd, pin, 0);

#if SLOW_TOGGLE
        usleep(1000);
#endif

        return 0;
}


void serbb_display(PROGRAMMER *pgm, char *p)
{
  /* MAYBE */
}

void serbb_enable(PROGRAMMER *pgm)
{
  /* nothing */
}

void serbb_disable(PROGRAMMER *pgm)
{
  /* nothing */
}

void serbb_powerup(PROGRAMMER *pgm)
{
  /* nothing */
}

void serbb_powerdown(PROGRAMMER *pgm)
{
  /* nothing */
}

int serbb_open(PROGRAMMER *pgm, char *port)
{
        DCB dcb;
        LPVOID lpMsgBuf;
        HANDLE hComPort = INVALID_HANDLE_VALUE;

        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: ser_open(): can't open device \"%s\": 
%s\n",
                        progname, port, (char*)lpMsgBuf);
                LocalFree(lpMsgBuf);
                return -1;
        }

        if (!SetupComm(hComPort, W32SERBUFSIZE, W32SERBUFSIZE))
        {
                CloseHandle(hComPort);
                fprintf(stderr, "%s: ser_open(): can't set buffers for 
\"%s\"\n",
                        progname, port);
                return -1;
        }


        ZeroMemory(&dcb, sizeof(DCB));
        dcb.DCBlength = sizeof(DCB);
        dcb.BaudRate = CBR_9600;
        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: ser_open(): can't set com-state for 
\"%s\"\n",
                        progname, port);
                return -1;
        }
        if (verbose > 2)
                fprintf(stderr,
                        "%s: ser_open(): opened comm port \"%s\", handle 
0x%x\n",
                        progname, port, (int)hComPort);

        pgm->fd = (int)hComPort;

        dtr = rts = txd = 0;

        return 0;
}

void serbb_close(PROGRAMMER *pgm)
{
        HANDLE hComPort=(HANDLE)pgm->fd;
        if (hComPort != INVALID_HANDLE_VALUE)
                CloseHandle (hComPort);
        if (verbose > 2)
                fprintf(stderr,
                        "%s: ser_close(): closed comm port handle 0x%x\n",
                        progname, (int)hComPort);

        hComPort = INVALID_HANDLE_VALUE;
}

void serbb_initpgm(PROGRAMMER *pgm)
{
  strcpy(pgm->type, "SERBB");

  pgm->rdy_led        = bitbang_rdy_led;
  pgm->err_led        = bitbang_err_led;
  pgm->pgm_led        = bitbang_pgm_led;
  pgm->vfy_led        = bitbang_vfy_led;
  pgm->initialize     = bitbang_initialize;
  pgm->display        = serbb_display;
  pgm->enable         = serbb_enable;
  pgm->disable        = serbb_disable;
  pgm->powerup        = serbb_powerup;
  pgm->powerdown      = serbb_powerdown;
  pgm->program_enable = bitbang_program_enable;
  pgm->chip_erase     = bitbang_chip_erase;
  pgm->cmd            = bitbang_cmd;
  pgm->open           = serbb_open;
  pgm->close          = serbb_close;

  /* this is a serial port bitbang device */
  pgm->flag           = 1;
}

#endif  /* WIN32NATIVE */
--- avrdude.conf.in.orig        Tue Aug  2 21:41:12 2005
+++ avrdude.conf.in     Tue Aug  2 22:13:58 2005
@@ -445,7 +445,7 @@
   id    = "ponyser";
   desc  = "serial port banging, design ponyprog serial";
   type  = serbb;
-  reset = 10;
+  reset = ~3;
   sck   = 6;
   mosi  = 4;
   miso  = 7;
@@ -471,7 +471,7 @@
   id    = "dasa3";
   desc  = "serial port banging, reset=!dtr sck=rts mosi=txd miso=cts";
   type  = serbb;
-  reset = 11;
+  reset = ~4;
   sck   = 6;
   mosi  = 3;
   miso  = 7;
--- config_gram.y.orig  Mon Aug  1 22:26:47 2005
+++ config_gram.y       Tue Aug  2 22:22:49 2005
@@ -50,7 +50,7 @@
 int yylex(void);
 int yyerror(char * errmsg);
 
-static int assign_pin(int pinno, TOKEN * v);
+static int assign_pin(int pinno, TOKEN * v, int invert);
 static int which_opcode(TOKEN * opcode);
 static int parse_cmdbits(OPCODE * op);
  
@@ -161,6 +161,7 @@
 %token TKN_COMMA
 %token TKN_EQUAL
 %token TKN_SEMI
+%token TKN_TILDE
 %token TKN_NUMBER
 %token TKN_STRING
 %token TKN_ID
@@ -426,15 +427,26 @@
   } |
 
   K_RESET  TKN_EQUAL TKN_NUMBER { free_token($1); 
-                                  assign_pin(PIN_AVR_RESET, $3); } |
+                                  assign_pin(PIN_AVR_RESET, $3, 0); } |
   K_SCK    TKN_EQUAL TKN_NUMBER { free_token($1); 
-                                  assign_pin(PIN_AVR_SCK, $3); } |
-  K_MOSI   TKN_EQUAL TKN_NUMBER { assign_pin(PIN_AVR_MOSI, $3); } |
-  K_MISO   TKN_EQUAL TKN_NUMBER { assign_pin(PIN_AVR_MISO, $3); } |
-  K_ERRLED TKN_EQUAL TKN_NUMBER { assign_pin(PIN_LED_ERR, $3); } |
-  K_RDYLED TKN_EQUAL TKN_NUMBER { assign_pin(PIN_LED_RDY, $3); } |
-  K_PGMLED TKN_EQUAL TKN_NUMBER { assign_pin(PIN_LED_PGM, $3); } |
-  K_VFYLED TKN_EQUAL TKN_NUMBER { assign_pin(PIN_LED_VFY, $3); }
+                                  assign_pin(PIN_AVR_SCK, $3, 0); } |
+  K_MOSI   TKN_EQUAL TKN_NUMBER { assign_pin(PIN_AVR_MOSI, $3, 0); } |
+  K_MISO   TKN_EQUAL TKN_NUMBER { assign_pin(PIN_AVR_MISO, $3, 0); } |
+  K_ERRLED TKN_EQUAL TKN_NUMBER { assign_pin(PIN_LED_ERR, $3, 0); } |
+  K_RDYLED TKN_EQUAL TKN_NUMBER { assign_pin(PIN_LED_RDY, $3, 0); } |
+  K_PGMLED TKN_EQUAL TKN_NUMBER { assign_pin(PIN_LED_PGM, $3, 0); } |
+  K_VFYLED TKN_EQUAL TKN_NUMBER { assign_pin(PIN_LED_VFY, $3, 0); } |
+
+  K_RESET  TKN_EQUAL TKN_TILDE TKN_NUMBER { free_token($1); 
+                                  assign_pin(PIN_AVR_RESET, $4, 1); } |
+  K_SCK    TKN_EQUAL TKN_TILDE TKN_NUMBER { free_token($1); 
+                                  assign_pin(PIN_AVR_SCK, $4, 1); } |
+  K_MOSI   TKN_EQUAL TKN_TILDE TKN_NUMBER { assign_pin(PIN_AVR_MOSI, $4, 1); } 
|
+  K_MISO   TKN_EQUAL TKN_TILDE TKN_NUMBER { assign_pin(PIN_AVR_MISO, $4, 1); } 
|
+  K_ERRLED TKN_EQUAL TKN_TILDE TKN_NUMBER { assign_pin(PIN_LED_ERR, $4, 1); } |
+  K_RDYLED TKN_EQUAL TKN_TILDE TKN_NUMBER { assign_pin(PIN_LED_RDY, $4, 1); } |
+  K_PGMLED TKN_EQUAL TKN_TILDE TKN_NUMBER { assign_pin(PIN_LED_PGM, $4, 1); } |
+  K_VFYLED TKN_EQUAL TKN_TILDE TKN_NUMBER { assign_pin(PIN_LED_VFY, $4, 1); }
 ;
 
 
@@ -862,7 +874,7 @@
 #endif
 
 
-static int assign_pin(int pinno, TOKEN * v)
+static int assign_pin(int pinno, TOKEN * v, int invert)
 {
   int value;
 
@@ -875,6 +887,8 @@
             progname, lineno, infile);
     exit(1);
   }
+  if (invert)
+    value |= PIN_INVERSE;
 
   current_prog->pinno[pinno] = value;
 
--- lexer.l.orig        Tue Aug  2 22:08:06 2005
+++ lexer.l     Tue Aug  2 22:08:23 2005
@@ -213,6 +213,7 @@
 ","       { yylval = NULL; pyytext(); return TKN_COMMA; }
 "="       { yylval = NULL; pyytext(); return TKN_EQUAL; }
 ";"       { yylval = NULL; pyytext(); return TKN_SEMI; }
+"~"       { yylval = NULL; pyytext(); return TKN_TILDE; }
 
 "\n"      { lineno++; }
 [ \r\t]+  /* ignore whitespace */
--- par.c.orig  Mon Aug  1 22:26:48 2005
+++ par.c       Tue Aug  2 22:17:57 2005
@@ -79,6 +79,8 @@
 int par_setpin(int fd, int pin, int value)
 {
 
+  pin &= PIN_MASK;
+
   if (pin < 1 || pin > 17)
     return -1;
 
@@ -104,6 +106,8 @@
 {
   int value;
 
+  pin &= PIN_MASK;
+
   if (pin < 1 || pin > 17)
     return -1;
 
@@ -144,6 +148,8 @@
 
 int par_getpinmask(int pin)
 {
+  pin &= PIN_MASK;
+
   if (pin < 1 || pin > 17)
     return -1;
 
--- pindefs.h.orig      Tue May  3 14:21:32 2005
+++ pindefs.h   Tue Aug  2 22:12:06 2005
@@ -35,6 +35,8 @@
   PIN_LED_VFY,
   N_PINS
 };
+#define PIN_INVERSE 0x80       /* flag for inverted pin in serbb */
+#define PIN_MASK    0x7f
 
 #define LED_ON(fd,pin)  ppi_setpin(fd,pin,0)
 #define LED_OFF(fd,pin) ppi_setpin(fd,pin,1)
--- serbb_posix.c.orig  Tue Aug  2 21:36:21 2005
+++ serbb_posix.c       Tue Aug  2 22:16:25 2005
@@ -69,14 +69,14 @@
 {
   unsigned int ctl;
 
-  if ( pin < 1 || pin > 14 )
-    return;
-
-  if ( pin>7 )
+  if (pin & PIN_INVERSE)
   {
     value  = !value;
-    pin   -= 7;
-  } 
+    pin   &= PIN_MASK;
+  }
+
+  if ( pin < 1 || pin > 7 )
+    return;
 
   pin--;
   
@@ -109,16 +109,16 @@
   unsigned int ctl;
   unsigned char invert;
   
-  if ( pin < 1 || pin > 14 )
-    return(-1);
-  
-  if ( pin>7 )
+  if (pin & PIN_INVERSE)
   {
     invert = 1;
-    pin   -= 7;
+    pin   &= PIN_MASK;
   } else
     invert = 0;
 
+  if ( pin < 1 || pin > 7 )
+    return(-1);
+  
   pin --;
   
   switch ( pin )
@@ -153,7 +153,7 @@
 
 int serbb_highpulsepin(int fd, int pin)
 {
-  if (pin < 1 || pin > 13)
+  if (pin < 1 || pin > 7)
     return -1;
 
   serbb_setpin(fd, pin, 1);
--- serbb_win32.c.orig  Tue Aug  2 21:36:25 2005
+++ serbb_win32.c       Tue Aug  2 22:15:26 2005
@@ -56,7 +56,7 @@
   6    rts     ->
   7    cts     <-
 
-  Pin # above 7 means negated (pin - 7).
+  Negative pin # means negated value.
 */
 
 void serbb_setpin(int fd, int pin, int value)
@@ -66,15 +66,15 @@
         DWORD dwFunc;
         const char *name;
 
-        if (pin < 1 || pin > 14)
-                return;
-
-        if (pin > 7)
+        if (pin & PIN_INVERSE)
         {
                 value = !value;
-                pin -= 7;
+                pin &= PIN_MASK;
         }
 
+        if (pin < 1 || pin > 7)
+                return;
+
         pin--;
 
         switch (pin)
@@ -137,16 +137,16 @@
         const char *name;
         DWORD modemstate;
 
-        if (pin < 1 || pin > 14)
-                return -1;
-
-        if (pin > 7)
+        if (pin & PIN_INVERSE)
         {
                 invert = 1;
-                pin -= 7;
+                pin &= PIN_MASK;
         } else
                 invert = 0;
 
+        if (pin < 1 || pin > 7)
+                return -1;
+
         pin --;
 
         if (pin == 0 /* cd */ || pin == 4 /* dsr */ || pin == 6 /* cts */)
@@ -226,7 +226,7 @@
 
 int serbb_highpulsepin(int fd, int pin)
 {
-        if (pin < 1 || pin > 13)
+        if (pin < 1 || pin > 7)
                 return -1;
 
         serbb_setpin(fd, pin, 1);
_______________________________________________
avrdude-dev mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/avrdude-dev

Reply via email to