avrdude-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avrdude-dev] Adding support for AVR Butterfly


From: Michael Mayer
Subject: Re: [avrdude-dev] Adding support for AVR Butterfly
Date: Thu, 23 Oct 2003 19:39:09 +0200
User-agent: KMail/1.5.3

I added support for the AVR Butterfly to the avr910 module. Using a RS232 
connection to the PC the Butterfly acts like a kind of avr910 programmer, but 
it uses something like a "extended subset" of the complete command set as 
specified in AVR109: Only the commands "aAeEPLptxyTSVs" are accepted, 'x' and 
'y' are replaced by dummy functions. To access the memory the "buffer load" 
mode using the commands 'b', 'B' and 'g' is used. This buffer mode speeds up 
the communication a lot: The complete 16kB flash is read or programmed in 10 
seconds.

To communicate with the butterfly you have to start the bootloader manually 
using the joystick-like switch as described in the documentation and then 
pressing down the button while invoking avrdude for the first time after 
entering the bootloader.

  Michael

>>>>>----snip------<<<<<
diff -u --recursive avrdude-4.2.0.orig/avr910.c avrdude-4.2.0/avr910.c
--- avrdude-4.2.0.orig/avr910.c 2003-09-06 19:20:39.000000000 +0200
+++ avrdude-4.2.0/avr910.c      2003-10-23 19:22:03.000000000 +0200
@@ -30,6 +30,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include <ctype.h>

 #include "avr.h"
 #include "pgm.h"
@@ -40,6 +41,7 @@
 extern int do_cycles;

 static char has_auto_incr_addr;
+static unsigned buffersize = 0;        /* default: buffered mode not 
supported */

 /* These two defines are only for debugging. Will remove them once it starts
    working. */
@@ -208,6 +210,10 @@

   no_show_func_info();

+  /* send some ESC to activate butterfly bootloader */
+  avr910_send(pgm, "\033\033\033\033", 4);
+  avr910_drain(pgm, 0);
+
   /* Get the programmer identifier. Programmer returns exactly 7 chars
      _without_ the null.*/

@@ -221,7 +227,10 @@
   avr910_recv(pgm, sw, sizeof(sw));

   avr910_send(pgm, "v", 1);
-  avr910_recv(pgm, hw, sizeof(hw));
+  avr910_recv(pgm, hw, 1);     /* first, read only _one_ byte */
+  if (hw[0]!='?') {
+    avr910_recv(pgm, &hw[1], 1);/* now, read second byte */
+  };

   /* Get the programmer type (serial or parallel). Expect serial. */

@@ -230,7 +239,11 @@

   fprintf(stderr, "Found programmer: Id = \"%s\"; type = %c\n", id, type);
   fprintf(stderr, "    Software Version = %c.%c; ", sw[0], sw[1]);
-  fprintf(stderr, "Hardware Version = %c.%c\n", hw[0], hw[1]);
+  if (hw[0]=='?') {
+    fprintf(stderr, "No Hardware Version given.\n");
+  } else {
+    fprintf(stderr, "Hardware Version = %c.%c\n", hw[0], hw[1]);
+  };

   /* See if programmer supports autoincrement of address. */

@@ -239,6 +252,20 @@
   if (has_auto_incr_addr == 'Y')
       fprintf(stderr, "Programmer supports auto addr increment.\n");

+  /* See if programmer supports buffered memory access. */
+
+  avr910_send(pgm, "b", 1);
+  avr910_recv(pgm, &c, 1);
+  if (c == 'Y') {
+      avr910_recv(pgm, &c, 1);
+      buffersize = c<<8;
+      avr910_recv(pgm, &c, 1);
+      buffersize += c;
+      fprintf(stderr,
+        "Programmer supports buffered memory access with buffersize=%i 
bytes.\n",
+        buffersize);
+  };
+
   /* Get list of devices that the programmer supports. */

   avr910_send(pgm, "t", 1);
@@ -410,32 +437,48 @@
 static int avr910_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
                              unsigned long addr, unsigned char value)
 {
-  unsigned char cmd[2];
+  unsigned char cmd[6];
+  int size;

   no_show_func_info();

-  if (strcmp(m->desc, "flash") == 0) {
-    if (addr & 0x01) {
-      cmd[0] = 'C';             /* Write Program Mem high byte */
-    }
+  if ((strcmp(m->desc, "flash") != 0) && (strcmp(m->desc, "eeprom") != 0))
+    return -1;
+
+  if (buffersize) {    /* use blockmode if avaliable */
+    cmd[0] = 'B';
+    cmd[1] = 0;
+    if ((cmd[3] = toupper(m->desc[0])) == 'E') {       /* write to eeprom */
+      cmd[2] = 1;
+      cmd[4] = value;
+      size = 5;
+    } else {                                           /* write to flash */
+      // @@@ not yet implemented
+      cmd[2] = 2;
+      size = 6;
+      return -1;
+    };
+  } else {             /* use traditional access */
+    if (m->desc[0] == 'E')
+      cmd[0] = 'D';
     else {
-      cmd[0] = 'c';
-    }
+      if (addr & 0x01) {
+        cmd[0] = 'C';             /* Write Program Mem high byte */
+      }
+      else {
+        cmd[0] = 'c';
+      }

-    addr >>= 1;
-  }
-  else if (strcmp(m->desc, "eeprom") == 0) {
-    cmd[0] = 'D';
-  }
-  else {
-    return -1;
-  }
+      addr >>= 1;
+    };

-  cmd[1] = value;
+    cmd[1] = value;
+    size = 2;
+  };

   avr910_set_addr(pgm, addr);

-  avr910_send(pgm, cmd, sizeof(cmd));
+  avr910_send(pgm, cmd, size);
   avr910_vfy_cmd_sent(pgm, "write byte");

   return 0;
@@ -458,7 +501,10 @@

     avr910_set_addr(pgm, addr >> 1);

-    avr910_send(pgm, "R", 1);
+    if (buffersize)
+      avr910_send(pgm, "g\000\002F", 4);
+    else
+      avr910_send(pgm, "R", 1);

     /* Read back the program mem word (MSB first) */
     avr910_recv(pgm, buf, sizeof(buf));
@@ -482,9 +528,12 @@
                                    unsigned long addr, unsigned char * value)
 {
   avr910_set_addr(pgm, addr);
-  avr910_send(pgm, "d", 1);
+  if (buffersize) {    /* prefer blockmode over traditional access */
+    avr910_send(pgm, "g\000\001E", 4);
+  } else {
+    avr910_send(pgm, "d", 1);
+  };
   avr910_recv(pgm, value, 1);
-
   return 0;
 }

@@ -593,71 +642,146 @@
 }


+static int avr910_paged_write_blockmode(PROGRAMMER * pgm, AVRPART * p, AVRMEM 
* m,
+                              int page_size, int n_bytes)
+{
+  unsigned int addr = 0;
+  unsigned int max_addr = n_bytes;
+  unsigned char *cmd;
+  unsigned int blocksize = buffersize;
+
+  if (m->desc[0] == 'e')
+    blocksize = 1;             /* Write to eeprom single bytes only */
+
+  avr910_set_addr(pgm, addr);
+
+  cmd = malloc(4+blocksize);
+  if (!cmd) return -1;
+  cmd[0] = 'B';
+  cmd[3] = toupper(m->desc[0]);
+
+  while (addr < max_addr) {
+    if ((max_addr - addr) < blocksize) {
+      blocksize = max_addr - addr;
+    };
+    memcpy(&cmd[4], &m->buf[addr], blocksize);
+    cmd[1] = (blocksize >> 8) & 0xff;
+    cmd[2] = blocksize & 0xff;
+
+    avr910_send(pgm, cmd, 4+blocksize);
+    avr910_vfy_cmd_sent(pgm, "write block");
+
+    addr += blocksize;
+
+    if (has_auto_incr_addr != 'Y') {
+      avr910_set_addr(pgm, addr>>1);
+    }
+
+    report_progress (addr, max_addr, NULL);
+  } /* while */
+  free(cmd);
+
+  return addr;
+}
+
+
 static int avr910_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
                               int page_size, int n_bytes)
 {
-  if (strcmp(m->desc, "flash") == 0) {
+  if (strcmp(m->desc, "flash") && strcmp(m->desc, "eeprom"))
+    return -2;
+
+  if (buffersize)      /* use blockmode if availiable */
+    return avr910_paged_write_blockmode(pgm, p, m, page_size, n_bytes);
+
+  if (m->desc[0] == 'f')
     return avr910_paged_write_flash(pgm, p, m, page_size, n_bytes);
-  }
-  else if (strcmp(m->desc, "eeprom") == 0) {
+  else
     return avr910_paged_write_eeprom(pgm, p, m, page_size, n_bytes);
-  }
-  else {
-    return -2;
-  }
 }


 static int avr910_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
                              int page_size, int n_bytes)
 {
-  unsigned char cmd;
-  int rd_size;
   unsigned int addr = 0;
-  unsigned int max_addr;
-  unsigned char buf[2];
+  unsigned int max_addr = n_bytes;
+  int rd_size = 1;

-  if (strcmp(m->desc, "flash") == 0) {
-    cmd = 'R';
-    rd_size = 2;                /* read two bytes per addr */
-  }
-  else if (strcmp(m->desc, "eeprom") == 0) {
-    cmd = 'd';
-    rd_size = 1;
-  }
-  else {
+  /* check parameter syntax: only "flash" or "eeprom" is allowed */
+  if (strcmp(m->desc, "flash") && strcmp(m->desc, "eeprom"))
     return -2;
-  }

-  max_addr = n_bytes/rd_size;
+  if (buffersize) {            /* use buffered mode if availiable */

-  avr910_set_addr(pgm, addr);
+    unsigned char cmd[4];
+    int blocksize = buffersize;

-  while (addr < max_addr) {
-    avr910_send(pgm, &cmd, 1);
-    if (cmd == 'R') {
-      /* The 'R' command returns two bytes, MSB first, we need to put the 
data
-         into the memory buffer LSB first. */
-      avr910_recv(pgm, buf, 2);
-      m->buf[addr*2]   = buf[1];  /* LSB */
-      m->buf[addr*2+1] = buf[0];  /* MSB */
-    }
-    else {
-      avr910_recv(pgm, &m->buf[addr], 1);
-    }
+    cmd[0] = 'g';
+    cmd[3] = toupper(m->desc[0]);

-    addr++;
+    avr910_set_addr(pgm, addr);
+    while (addr < max_addr) {
+      if ((max_addr - addr) < blocksize) {
+        blocksize = max_addr - addr;
+      };
+      cmd[1] = (blocksize >> 8) & 0xff;
+      cmd[2] = blocksize & 0xff;

-    if (has_auto_incr_addr != 'Y') {
-      avr910_set_addr(pgm, addr);
-    }
+      avr910_send(pgm, cmd, 4);
+      avr910_recv(pgm, &m->buf[addr], blocksize);

-    report_progress (addr, max_addr, NULL);
-  }
+      addr += blocksize;
+      if (has_auto_incr_addr != 'Y')
+        avr910_set_addr(pgm, addr);
+
+      report_progress (addr, max_addr, NULL);
+    } /* while */
+
+  } else {                     /* use traditional access */
+
+    unsigned char cmd;
+    unsigned char buf[2];
+
+    if (m->desc[0]=='f') {
+      cmd = 'R';
+      rd_size = 2;                /* read two bytes per addr */
+    } else {
+      cmd = 'd';
+    };
+
+    max_addr = n_bytes/rd_size;
+
+    avr910_set_addr(pgm, addr);
+
+    while (addr < max_addr) {
+      avr910_send(pgm, &cmd, 1);
+      if (cmd == 'R') {
+        /* The 'R' command returns two bytes, MSB first, we need to put the 
data
+           into the memory buffer LSB first. */
+        avr910_recv(pgm, buf, 2);
+        m->buf[addr*2]   = buf[1];  /* LSB */
+        m->buf[addr*2+1] = buf[0];  /* MSB */
+      }
+      else {
+        avr910_recv(pgm, &m->buf[addr], 1);
+      }
+
+      addr++;
+
+      if (has_auto_incr_addr != 'Y') {
+        avr910_set_addr(pgm, addr);
+      }
+
+      report_progress (addr, max_addr, NULL);
+    } /* while */
+
+  } /* else */

   return addr * rd_size;
 }

+
 /* Signature byte reads are always 3 bytes. */

 static int avr910_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m)





reply via email to

[Prev in Thread] Current Thread [Next in Thread]