Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[patch #9573] patch to add atmelice avr32 programming support to avrdude #735

Closed
avrs-admin opened this issue Dec 13, 2021 · 9 comments
Closed
Labels
enhancement New feature or request

Comments

@avrs-admin
Copy link

Thu 22 Feb 2018 10:16:28 AM UTC

This patch adds support for programming avr32 devices via the atmelice jtag programmer using the jtag3 driver. The update add a new programmer atmelice_avr32 which is used to access the new feature

file #43383: avr32-jtag3.patch
file #51797: avr32-jtag3.patch

This issue was migrated from https://savannah.nongnu.org/patch/?9573

@avrs-admin
Copy link
Author

Bradley Jarvis <bradley_jarvis>
Thu 22 Feb 2018 10:26:54 AM UTC

This patch is in relation to bug #43178, I have had a few people ask me for the patch lately so want to add it back into avrdude. I just re-applied my patch made on 6.1 which was the original code base I worked with to the latest svn trunk version.

@avrs-admin
Copy link
Author

Joerg Wunsch <joerg_wunsch>
Sun 20 Sep 2020 08:43:22 PM UTC

Thanks for submitting the patch!

First thing that springs to mind after applying it:

gmake[2]: Entering directory '/home/joerg/src/avrdude'
CC       libavrdude_a-jtag3.o
jtag3.c:1031:12: warning: 'jtag3_edbg_recv_frame' defined but not used [-Wunused-function]
static int jtag3_edbg_recv_frame(PROGRAMMER * pgm, unsigned char **msg) {
^~~~~~~~~~~~~~~~~~~~~

So why is this function no longer going to be used?

After some closer inspection, I have a number of stylistic issues with the patch before I'd like to apply it.

programmer
+  id    = "atmelice_avr32";
+  desc  = "Atmel-ICE (ARM/AVR) in ISP mode";

Really in ISP mode?

+        if (data[0]==SCOPE_AVR32)
+        {
+            char *str=0;
...
+              case AVR32_FAILURE_RECEIVE_LENGTH: str="Incorrect packet length"; break;
...
+  if (len > (((USBDEV_MAX_XFER_3-4)*16)-4))

I would appreciate if the patch keeps the existing style rule of having white space around operators (=, == etc.).

-         avrdude_message(MSG_INFO, "\\%03o", data[i]);
+          //avrdude_message(MSG_INFO, "\\%03o", data[i]);
+          avrdude_message(MSG_INFO, "\\%02x", data[i]);
...
+#if 0
/* 4 bytes overhead for CMD, fragment #, and length info */
int max_xfer = pgm->fd.usb.max_xfer;
int nfragments = (len + max_xfer - 1) / max_xfer;
@@ -507,6 +647,7 @@
}
data += this_len;
len -= this_len;
+#endif
}

Source code comments and conditional compilation is not the way to keep track of history. This is what SVN (or whatever VCS is used) is for.

Also, as you can see in the first snippet, make sure to not artificially alter the indentation style. Unfortunately, AVRDUDE's code base was never very consistent on whether to use TAB or spaces, but if you change a single existing line, do not convert a TAB to spaces or vice versa.

+  //if ((buf = malloc(USBDEV_MAX_XFER_3)) == NULL) {
+  //  avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): out of memory\n",
+       //    progname);
+  //  return -1;
+  //}

See above. If some piece of code isn't needed anymore, remove it, rather than commenting it out.

if ((c == RSP3_FAILED) && ((*resp)[3] == RSP3_FAIL_OCD_LOCKED)) {
avrdude_message(MSG_INFO,
-                     "%s: Device is locked! Chip erase required to unlock.\n",
-                     progname);
+          "%s: Device is locked! Chip erase required to unlock.\n",
+          progname);
} else {
avrdude_message(MSG_INFO, "%s: bad response to %s command: 0x%02x\n",
-                     progname, descr, c);
+          progname, descr, c);

Again, random indentation changes, please avoid this. Tell you editor to not touch anything else but what you're actually editing.

-  free(resp);
+  if (resp) free(resp);

Unneeded. The C standard guarantees free(0) does nothing.

The entire patch looks quite intrusive to the existing jtag3.c file. Thus, it imposes quite a bit of risk of breaking things that are unrelated to the AVR32 addition (see the first warning about a now unused function).

For that reason, I'd like to defer inclusion of the patch until after the next AVRDUDE release. Sorry, I don't have the time and energy of maintaining a separate -stable branch.

However, even though I'm setting it to "postponed" now, please feel encouraged to re-submit the patch with the above things fixed.

@avrs-admin
Copy link
Author

Bradley Jarvis <bradley_jarvis>
Mon 21 Sep 2020 02:09:36 AM UTC

No problem, I will update the patch following the formatting guides mentioned.

The function jtag3_edbg_recv_frame was only being called from jtag3_recv_frame and it had to be fixed so it was integrated into this function, from memory it was how it was handling fragmented frames. I initially implemented this patch on avrdude 6.1 back in 2015 and I believe in that version the jtag3.c module could not receive fragmented frames(besides I think my version is much clearer/cleaner ;).

I think the ISP comment is a copy/paste error, it should have been JTAG, thanks for picking that up.

I have made the changes and once I get a chance to test it on some hardware and then I will update the patch.

@avrs-admin
Copy link
Author

Bradley Jarvis <bradley_jarvis>
Wed 18 Aug 2021 12:50:56 PM UTC

Hi Joerg, I have attached a new patch with updated style changes and have also now tested on the AVR32 platform via jtag and also the AVR8 via ISP and XMEGA via PDI and all appears to work fine. There were some things that I needed to fix to get AVR8/XMEGA working.

I did find a potential memory leak in the current jtag3 driver in the function jtag3_command(), at the end of the function on error the the memort allocated to resp is freed and then resp=0, it should have beenresp=0. However looking through the rest of the code it only ever called free on resp if the jtag3_command failed so really no problem there.

Please let me know if I need to do anything else testing wise etc. Also not sure how to remove the old patch

@mcuee
Copy link
Collaborator

mcuee commented May 24, 2022

Can this patch be adapted for Atmel JTAG ICE mkII (as well as AVR Dragon) for the AVR32 support? They do support AVR32.

Ref:
https://www.microchip.com/en-us/development-tool/ATAVRDRAGON
https://www.microchip.com/en-us/development-tool/ATJTAGICE2

@mcuee
Copy link
Collaborator

mcuee commented May 24, 2022

Can this patch be adapted for Atmel JTAG ICE mkII (as well as AVR Dragon) for the AVR32 support? They do support AVR32.

Ref: https://www.microchip.com/en-us/development-tool/ATAVRDRAGON https://www.microchip.com/en-us/development-tool/ATJTAGICE2

The patch is here.

@mcuee
Copy link
Collaborator

mcuee commented May 24, 2022

The other thing is that this support can probably extended to other UC3 parts.
Ref: https://www.avrfreaks.net/forum/at32uc3c0512-avrdude-part-definition

@mcuee mcuee added the enhancement New feature or request label Jun 19, 2022
@mcuee
Copy link
Collaborator

mcuee commented Jun 23, 2022

AVR32 has been de-focused by Microchip/Atmel long ago. So we will close this issue.

@mcuee mcuee closed this as not planned Won't fix, can't repro, duplicate, stale Jun 23, 2022
@mcuee
Copy link
Collaborator

mcuee commented Jun 11, 2023

Patch:

Index: avrdude.conf.in
===================================================================
--- avrdude.conf.in	(revision 1453)
+++ avrdude.conf.in	(working copy)
@@ -1230,6 +1230,15 @@
 ;
 
 programmer
+  id    = "atmelice_avr32";
+  desc  = "Atmel-ICE (ARM/AVR) in JTAG mode";
+  type  = "jtagice3_avr32";
+  connection_type = usb;
+  usbpid = 0x2141;
+;
+
+
+programmer
   id    = "pavr";
   desc  = "Jason Kyle's pAVR Serial Programmer";
   type  = "avr910";
Index: jtag3.c
===================================================================
--- jtag3.c	(revision 1453)
+++ jtag3.c	(working copy)
@@ -70,6 +70,9 @@
   /* Start address of Xmega boot area */
   unsigned long boot_start;
 
+  /* AVR32 flashc address */
+  unsigned long flashc_start;
+
   /* Function to set the appropriate clock parameter */
   int (*set_sck)(PROGRAMMER *, unsigned char *);
 };
@@ -85,13 +88,18 @@
 #define PGM_FL_IS_JTAG          (0x0004)
 #define PGM_FL_IS_EDBG          (0x0008)
 #define PGM_FL_IS_UPDI          (0x0010)
+#define PGM_FL_IS_AVR32         (0x0020)
 
 static int jtag3_open(PROGRAMMER * pgm, char * port);
 static int jtag3_edbg_prepare(PROGRAMMER * pgm);
 static int jtag3_edbg_signoff(PROGRAMMER * pgm);
 static int jtag3_edbg_send(PROGRAMMER * pgm, unsigned char * data, size_t len);
-static int jtag3_edbg_recv_frame(PROGRAMMER * pgm, unsigned char **msg);
 
+static int jtag3_avr32_busy(PROGRAMMER * pgm);
+static int jtag3_avr32_read_register(PROGRAMMER * pgm, Avr32SABAddressMap, unsigned int, unsigned int *);
+static int jtag3_avr32_write_register(PROGRAMMER * pgm, Avr32SABAddressMap, unsigned int, unsigned int);
+static int jtag3_avr32_status_message(unsigned char code, short len, char *msg);
+
 static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p);
 static int jtag3_chip_erase(PROGRAMMER * pgm, AVRPART * p);
 static int jtag3_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
@@ -215,6 +223,10 @@
       avrdude_message(MSG_INFO, "[AVR] ");
       break;
 
+    case SCOPE_AVR32:
+      avrdude_message(MSG_INFO, "[AVR32] ");
+      break;
+
     default:
       avrdude_message(MSG_INFO, "[scope 0x%02x] ", data[0]);
       break;
@@ -231,6 +243,12 @@
       {
 	char reason[50];
 	sprintf(reason, "0x%02x", data[3]);
+        
+        if (data[0] == SCOPE_AVR32)
+        {
+          if (data[3] != AVR32_FAILURE_OK)
+            jtag3_avr32_status_message(data[3], sizeof(reason), reason);
+        } else {
 	switch (data[3])
 	{
 	  case RSP3_FAIL_NO_ANSWER:
@@ -265,6 +283,7 @@
 	    strcpy(reason, "debugWIRE communication failed");
 	    break;
 	}
+        }
 	avrdude_message(MSG_INFO, ", reason: %s\n", reason);
       }
       else
@@ -302,6 +321,16 @@
       }
       break;
 
+    case AVR32_RSP_ID:
+      if (data[0] == SCOPE_AVR32)
+      {
+        avrdude_message(MSG_INFO, "Device ID returned:\n");
+        for (i = 3; i < len; i++)
+          avrdude_message(MSG_INFO, "\\%02x", data[i]);
+        putc('\n', stderr);
+        break;
+      }
+    
   default:
     avrdude_message(MSG_INFO, "unknown message 0x%02x\n", data[1]);
   }
@@ -434,7 +463,7 @@
 
 static int jtag3_edbg_send(PROGRAMMER * pgm, unsigned char * data, size_t len)
 {
-  unsigned char buf[USBDEV_MAX_XFER_3];
+  unsigned char buf[USBDEV_MAX_XFER_3], i, c;
   unsigned char status[USBDEV_MAX_XFER_3];
   int rv;
 
@@ -447,67 +476,63 @@
   avrdude_message(MSG_DEBUG, "\n%s: jtag3_edbg_send(): sending %lu bytes\n",
 	    progname, (unsigned long)len);
 
-  /* 4 bytes overhead for CMD, fragment #, and length info */
-  int max_xfer = pgm->fd.usb.max_xfer;
-  int nfragments = (len + max_xfer - 1) / max_xfer;
-  if (nfragments > 1)
+  if (len > (((USBDEV_MAX_XFER_3-4)*16)-4))
+  {
+    avrdude_message(MSG_INFO, "%s: jtag3_edbg_send(): data too long(%lubytes), cannot send!\n",
+                    progname, ((USBDEV_MAX_XFER_3-4)*16)-4);
+    return -1;
+  }
+  
+  for (i = 0, c = ((len+4+(USBDEV_MAX_XFER_3-5))/(USBDEV_MAX_XFER_3-4)); i < c; i++)
+  {
+    unsigned short l;
+    
+    l = USBDEV_MAX_XFER_3-(i?4:8);
+    if (l > len) l = len;
+    
+    avrdude_message(MSG_DEBUG, "%s: jtag3_edbg_send(): packet %d of %d, length %dbytes\n",
+                    progname, i+1, c, l);
+    
+    memset(buf, 0, sizeof(buf));
+    buf[0] = EDBG_VENDOR_AVR_CMD;
+    buf[1] = ((i+1) << 4) | c;	/* first out of a total of 1 fragments */
+    buf[2] = (l+(i?0:4)) >> 8;
+    buf[3] = (l+(i?0:4)) & 0xff;
+    
+    if (!i)
     {
-      avrdude_message(MSG_DEBUG, "%s: jtag3_edbg_send(): fragmenting into %d packets\n",
-                      progname, nfragments);
+      /* this is only sent in the first fragment */
+      buf[4] = TOKEN;
+      buf[5] = 0;                   /* dummy */
+      u16_to_b2(buf + 6, PDATA(pgm)->command_sequence);
     }
-  int frag;
-  for (frag = 0; frag < nfragments; frag++)
+    
+    memcpy(buf + (i?4:8), data, l);
+    data += l;
+    len -= l;
+
+    if (serial_send(&pgm->fd, buf, USBDEV_MAX_XFER_3) != 0)
     {
-      int this_len;
-
-      /* All fragments have the (CMSIS-DAP layer) CMD, the fragment
-       * identifier, and the length field. */
-      buf[0] = EDBG_VENDOR_AVR_CMD;
-      buf[1] = ((frag + 1) << 4) | nfragments;
-
-      if (frag == 0)
-        {
-          /* Only first fragment has TOKEN and seq#, thus four bytes
-           * less payload than subsequent fragments. */
-          this_len = len < max_xfer - 8? len: max_xfer - 8;
-          buf[2] = (this_len + 4) >> 8;
-          buf[3] = (this_len + 4) & 0xff;
-          buf[4] = TOKEN;
-          buf[5] = 0;                   /* dummy */
-          u16_to_b2(buf + 6, PDATA(pgm)->command_sequence);
-          memcpy(buf + 8, data, this_len);
-        }
-      else
-        {
-          this_len = len < max_xfer - 4? len: max_xfer - 4;
-          buf[2] = (this_len) >> 8;
-          buf[3] = (this_len) & 0xff;
-          memcpy(buf + 4, data, this_len);
-        }
-
-      if (serial_send(&pgm->fd, buf, max_xfer) != 0) {
-        avrdude_message(MSG_INFO, "%s: jtag3_edbg_send(): failed to send command to serial port\n",
+      avrdude_message(MSG_INFO, "%s: jtag3_edbg_send(): failed to send command to serial port\n",
+                       progname);
+      return -1;
+    }
+    rv = serial_recv(&pgm->fd, status, USBDEV_MAX_XFER_3);
+ 
+    if (rv < 0)
+     {
+      /* timeout in receive */
+      avrdude_message(MSG_NOTICE2, "%s: jtag3_edbg_send(): Timeout receiving packet\n",
                         progname);
-        return -1;
-      }
-      rv = serial_recv(&pgm->fd, status, max_xfer);
-
-      if (rv < 0) {
-        /* timeout in receive */
-        avrdude_message(MSG_NOTICE2, "%s: jtag3_edbg_send(): Timeout receiving packet\n",
-                        progname);
-        return -1;
-      }
-      if (status[0] != EDBG_VENDOR_AVR_CMD ||
-          (frag == nfragments - 1 && status[1] != 0x01))
-        {
-          /* what to do in this case? */
-          avrdude_message(MSG_INFO, "%s: jtag3_edbg_send(): Unexpected response 0x%02x, 0x%02x\n",
-                          progname, status[0], status[1]);
-        }
-      data += this_len;
-      len -= this_len;
+      return -1;
     }
+    if (status[0] != EDBG_VENDOR_AVR_CMD || status[1] != ((i+1==c)?0x01:0x00))
+    {
+       /* what to do in this case? */
+       avrdude_message(MSG_INFO, "%s: jtag3_edbg_send(): Unexpected response 0x%02x, 0x%02x\n",
+                       progname, status[0], status[1]);
+     }
+  }
 
   return 0;
 }
@@ -640,135 +665,72 @@
  * Caller must eventually free the buffer.
  */
 static int jtag3_recv_frame(PROGRAMMER * pgm, unsigned char **msg) {
-  int rv;
-  unsigned char *buf = NULL;
-
-  if (pgm->flag & PGM_FL_IS_EDBG)
-    return jtag3_edbg_recv_frame(pgm, msg);
-
-  avrdude_message(MSG_TRACE, "%s: jtag3_recv():\n", progname);
-
-  if ((buf = malloc(pgm->fd.usb.max_xfer)) == NULL) {
-    avrdude_message(MSG_INFO, "%s: jtag3_recv(): out of memory\n",
-	    progname);
-    return -1;
-  }
-  if (verbose >= 4)
-    memset(buf, 0, pgm->fd.usb.max_xfer);
-
-  rv = serial_recv(&pgm->fd, buf, pgm->fd.usb.max_xfer);
-
-  if (rv < 0) {
-    /* timeout in receive */
-    avrdude_message(MSG_NOTICE2, "%s: jtag3_recv(): Timeout receiving packet\n",
-                      progname);
-    free(buf);
-    return -1;
-  }
-
-  *msg = buf;
-
-  return rv;
-}
-
-static int jtag3_edbg_recv_frame(PROGRAMMER * pgm, unsigned char **msg) {
-  int rv, len = 0;
-  unsigned char *buf = NULL;
-  unsigned char *request;
-
-  avrdude_message(MSG_TRACE, "%s: jtag3_edbg_recv():\n", progname);
-
-  if ((buf = malloc(USBDEV_MAX_XFER_3)) == NULL) {
-    avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): out of memory\n",
-	    progname);
-    return -1;
-  }
-  if ((request = malloc(pgm->fd.usb.max_xfer)) == NULL) {
-    avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): out of memory\n",
-	    progname);
-    free(buf);
-    return -1;
-  }
-
-  *msg = buf;
-
-  int nfrags = 0;
-  int thisfrag = 0;
-
-  do {
-    request[0] = EDBG_VENDOR_AVR_RSP;
-
-    if (serial_send(&pgm->fd, request, pgm->fd.usb.max_xfer) != 0) {
+  int rv, len, i, c, l;
+  unsigned char buf[USBDEV_MAX_XFER_3];
+  
+   avrdude_message(MSG_TRACE, "%s: jtag3_edbg_recv():\n", progname);
+  
+  if (msg) *msg=0;
+  
+  for (i = 0, c = 1, len = 0; i < c; i++)
+  {
+    unsigned char seq;
+    
+    memset(buf, 0, sizeof(buf));
+    buf[0] = EDBG_VENDOR_AVR_RSP;
+    
+    if (serial_send(&pgm->fd, buf, sizeof(buf)) != 0) {
       avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): error sending CMSIS-DAP vendor command\n",
                       progname);
-      free(request);
-      free(*msg);
       return -1;
     }
-
-    rv = serial_recv(&pgm->fd, buf, pgm->fd.usb.max_xfer);
-
+ 
+    rv = serial_recv(&pgm->fd, buf, sizeof(buf));
+    c = buf[1]&0x0f;
+    seq = buf[1]>>4;
+ 
     if (rv < 0) {
       /* timeout in receive */
       avrdude_message(MSG_NOTICE2, "%s: jtag3_edbg_recv(): Timeout receiving packet\n",
-                      progname);
-      free(*msg);
-      free(request);
-      return -1;
+                        progname);
+      len = -1;
+      break;
     }
-
+    
     if (buf[0] != EDBG_VENDOR_AVR_RSP) {
-      avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): Unexpected response 0x%02x\n",
-                      progname, buf[0]);
-      free(*msg);
-      free(request);
-      return -1;
+      avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): Unexpected response 0x%02x, 0x%02x\n",
+                      progname, buf[0], buf[1]);
+      len = -1;
+      break;
     }
-
-    /* calculate fragment information */
-    if (thisfrag == 0) {
-      /* first fragment */
-      nfrags = buf[1] & 0x0F;
-      thisfrag = 1;
-    } else {
-      if (nfrags != (buf[1] & 0x0F)) {
-        avrdude_message(MSG_INFO,
-                        "%s: jtag3_edbg_recv(): "
-                        "Inconsistent # of fragments; had %d, now %d\n",
-                        progname, nfrags, (buf[1] & 0x0F));
-        free(*msg);
-        free(request);
-        return -1;
-      }
+    
+    if (seq != (i+1))
+    {
+      avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): fragment out of sequence got %d, expecting %d of %d\n",
+                      progname, seq, i+1, c);
+      len = -1;
+      break;
     }
-    if (thisfrag != ((buf[1] >> 4) & 0x0F)) {
-      avrdude_message(MSG_INFO,
-                      "%s: jtag3_edbg_recv(): "
-                      "Inconsistent fragment number; expect %d, got %d\n",
-                      progname, thisfrag, ((buf[1] >> 4) & 0x0F));
-      free(*msg);
-      free(request);
-      return -1;
+    
+    /* allocate memory for large buffer once first packet is received */
+    if (msg && !*msg)
+    {
+      *msg = malloc(USBDEV_MAX_XFER_3*c);
+      memset(*msg, 0, USBDEV_MAX_XFER_3*c);
     }
-
-    int thislen = (buf[2] << 8) | buf[3];
-    if (thislen > rv + 4) {
-      avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): Unexpected length value (%d > %d)\n",
-                      progname, thislen, rv + 4);
-      thislen = rv + 4;
-    }
-    if (len + thislen > USBDEV_MAX_XFER_3) {
-      avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): Length exceeds max size (%d > %d)\n",
-                      progname, len + thislen, USBDEV_MAX_XFER_3);
-      thislen = USBDEV_MAX_XFER_3 - len;
-    }
-    memmove(buf, buf + 4, thislen);
-    thisfrag++;
-    len += thislen;
-    buf += thislen;
-  } while (thisfrag <= nfrags);
-
-  free(request);
+    
+    /* copy packet buffer to larger buffer and update length */
+    l = (buf[2] << 8) | buf[3];
+    memcpy((*msg)+len, buf+4, l);
+    len += l;
+  }
+  
+  if (len < 0 && msg && *msg)
+  {
+    free(*msg);
+    *msg=0;
+  }
+  
   return len;
 }
 
@@ -791,8 +753,8 @@
     rv &= USB_RECV_LENGTH_MASK;
     r_seqno = ((*msg)[2] << 8) | (*msg)[1];
     avrdude_message(MSG_DEBUG, "%s: jtag3_recv(): "
-	      "Got message seqno %d (command_sequence == %d)\n",
-	      progname, r_seqno, PDATA(pgm)->command_sequence);
+	      "Got message seqno %d (command_sequence == %d, size == %d)\n",
+	      progname, r_seqno, PDATA(pgm)->command_sequence, rv);
     if (r_seqno == PDATA(pgm)->command_sequence) {
       if (++(PDATA(pgm)->command_sequence) == 0xffff)
 	PDATA(pgm)->command_sequence = 0;
@@ -820,8 +782,8 @@
   int status;
   unsigned char c;
 
-  avrdude_message(MSG_NOTICE2, "%s: Sending %s command: ",
-	    progname, descr);
+  avrdude_message(MSG_NOTICE2, "%s: Sending %s command(%d bytes): ",
+	    progname, descr, cmdlen);
   jtag3_send(pgm, cmd, cmdlen);
 
   status = jtag3_recv(pgm, resp);
@@ -835,11 +797,34 @@
     putc('\n', stderr);
     jtag3_prmsg(pgm, *resp, status);
   } else {
-    avrdude_message(MSG_NOTICE2, "0x%02x (%d bytes msg)\n", (*resp)[1], status);
+    avrdude_message(MSG_NOTICE2, "0x%02x (%d bytes msg:", (*resp)[1], status);
+    if ((*resp)[1]==0x84 && status>3 )//&& status<32)
+    {
+      int i;
+      
+      avrdude_message(MSG_NOTICE2, " - ");
+      for (i=0; i<status; i++) 
+        avrdude_message(MSG_NOTICE2, "%02x ", (*resp)[i]);
+    }
+    avrdude_message(MSG_NOTICE2, ")\n");
   }
 
   c = (*resp)[1];
-  if ((c & RSP3_STATUS_MASK) != RSP3_OK) {
+  if ((c & RSP3_STATUS_MASK) == RSP3_OK) {
+    if (status > 3 && pgm->flag & PGM_FL_IS_AVR32 && 
+        (*resp)[0] == SCOPE_AVR32 && (*resp)[2] == 1) {
+      char reason[50];
+      
+      if (jtag3_avr32_status_message((*resp)[status-1], sizeof(reason), reason) < 0) {
+        avrdude_message(MSG_INFO, 
+          "%s: bad response to %s command: 0x%02x (%s, 0x%02x, %i)\n",
+          progname, descr, c, reason, (*resp)[status-1], status);
+      } else {
+        avrdude_message(MSG_NOTICE2, "%s: AVR32 %s command ok(received %d bytes)\n",
+            progname, descr, status);
+      }
+    }
+  } else {
     if ((c == RSP3_FAILED) && ((*resp)[3] == RSP3_FAIL_OCD_LOCKED)) {
       avrdude_message(MSG_INFO,
 		      "%s: Device is locked! Chip erase required to unlock.\n",
@@ -850,7 +835,7 @@
     }
     status = (*resp)[3];
     free(*resp);
-    resp = 0;
+    *resp = 0;
     return -status;
   }
 
@@ -892,15 +877,39 @@
  */
 static int jtag3_chip_erase(PROGRAMMER * pgm, AVRPART * p)
 {
-  unsigned char buf[8], *resp;
+  unsigned char buf[8], *resp, size;
 
-  buf[0] = SCOPE_AVR;
-  buf[1] = CMD3_ERASE_MEMORY;
-  buf[2] = 0;
-  buf[3] = XMEGA_ERASE_CHIP;
-  buf[4] = buf[5] = buf[6] = buf[7] = 0; /* page address */
+  size=0;
+  if (pgm->flag & PGM_FL_IS_AVR32)
+  {
+#if 0
+    return 0;
+#else
+    unsigned int value;
+    
+    do
+    {
+      if (jtag3_avr32_read_register(pgm, AVR32_SAB_HSB,
+        PDATA(pgm)->flashc_start + 0x08, &value)<0) return -1;
+    } while (!(value & 1));
 
-  if (jtag3_command(pgm, buf, 8, &resp, "chip erase") < 0)
+    buf[size++] = SCOPE_AVR32;
+    buf[size++] = AVR32_CMD_ERASE;
+    buf[size++] = 0;
+#endif
+  } else
+  {
+    buf[size++] = SCOPE_AVR;
+    buf[size++] = CMD3_ERASE_MEMORY;
+    buf[size++] = 0;
+    buf[size++] = XMEGA_ERASE_CHIP;
+    buf[size++] = 0; /* page address */
+    buf[size++] = 0;
+    buf[size++] = 0;
+    buf[size++] = 0;
+  }
+  
+  if (jtag3_command(pgm, buf, size, &resp, "chip erase") < 0)
     return -1;
 
   free(resp);
@@ -954,45 +963,90 @@
 
 static int jtag3_program_enable(PROGRAMMER * pgm)
 {
-  unsigned char buf[3], *resp;
+  unsigned char buf[64], *resp, size;
   int status;
 
   if (PDATA(pgm)->prog_enabled)
     return 0;
 
-  buf[0] = SCOPE_AVR;
-  buf[1] = CMD3_ENTER_PROGMODE;
-  buf[2] = 0;
-
-  if ((status = jtag3_command(pgm, buf, 3, &resp, "enter progmode")) >= 0) {
+  size=0;
+  if (pgm->flag & PGM_FL_IS_AVR32)
+  {
+    buf[size++] = SCOPE_AVR32;
+    buf[size++] = AVR32_CMD_SET;
+    buf[size++] = 0;
+    buf[size++] = AVR32_CTXT_SESSION;
+    buf[size++] = 0;
+    buf[size++] = 1;
+    buf[size++] = 1;
+    status = jtag3_command(pgm, buf, size, &resp, "Activate session");
     free(resp);
-    PDATA(pgm)->prog_enabled = 1;
-
-    return 0;
+    if (status < 0) return status;
+    
+    size=0;
+    buf[size++] = SCOPE_AVR32;
+    buf[size++] = AVR32_CMD_RESET;
+    buf[size++] = 0;
+    buf[size++] = 0x07;
+    status = jtag3_command(pgm, buf, size, &resp, "Set avr32 CPU reset");
+  } else
+  {
+    buf[size++] = SCOPE_AVR;
+    buf[size++] = CMD3_ENTER_PROGMODE;
+    buf[size++] = 0;
+    status = jtag3_command(pgm, buf, 3, &resp, "enter progmode");
   }
 
+  free(resp);
+  if (status >= 0) PDATA(pgm)->prog_enabled = 1;
+  
   return status;
 }
 
 static int jtag3_program_disable(PROGRAMMER * pgm)
 {
-  unsigned char buf[3], *resp;
+  unsigned char buf[8], *resp=0, size;
+  int status;
 
   if (!PDATA(pgm)->prog_enabled)
     return 0;
 
-  buf[0] = SCOPE_AVR;
-  buf[1] = CMD3_LEAVE_PROGMODE;
-  buf[2] = 0;
+  size=0;
+  if (pgm->flag & PGM_FL_IS_AVR32)
+  {
+    buf[size++] = SCOPE_AVR32;
+    buf[size++] = AVR32_CMD_HALT;
+    buf[size++] = 0;
+    buf[size++] = 0;
+    jtag3_command(pgm, buf, size, &resp, "un-halt");
+    free(resp);
+    
+    size=0;
+    buf[size++] = SCOPE_AVR32;
+    buf[size++] = AVR32_CMD_RESET;
+    buf[size++] = 0;
+    buf[size++] = 0x1F;
+    jtag3_command(pgm, buf, size, &resp, "Full reset avr32");
+    free(resp);
+    
+    size=0;
+    buf[size++] = SCOPE_AVR32;
+    buf[size++] = AVR32_CMD_RESET;
+    buf[size++] = 0;
+    buf[size++] = 0x00;
+    status = jtag3_command(pgm, buf, size, &resp, "Clear avr32 CPU reset");
+  } else {
+    buf[size++] = SCOPE_AVR;
+    buf[size++] = CMD3_LEAVE_PROGMODE;
+    buf[size++] = 0;
+    status = jtag3_command(pgm, buf, size, &resp, "leave progmode");
+  }
 
-  if (jtag3_command(pgm, buf, 3, &resp, "leave progmode") < 0)
-    return -1;
-
   free(resp);
 
-  PDATA(pgm)->prog_enabled = 0;
+  if (status >= 0) PDATA(pgm)->prog_enabled = 0;
 
-  return 0;
+  return status;
 }
 
 static int jtag3_set_sck_xmega_pdi(PROGRAMMER *pgm, unsigned char *clk)
@@ -1018,7 +1072,7 @@
 {
   unsigned char conn = 0, parm[4];
   const char *ifname;
-  unsigned char cmd[4], *resp;
+  unsigned char cmd[32], *resp;
   int status;
 
   /*
@@ -1061,7 +1115,7 @@
     if (p->flags & AVRPART_HAS_UPDI)
       conn = PARM3_CONN_UPDI;
   } else {
-    ifname = "JTAG";
+    ifname = (pgm->flag & PGM_FL_IS_AVR32) ? "JTAGavr32" : "JTAG";
     if (p->flags & AVRPART_HAS_JTAG)
       conn = PARM3_CONN_JTAG;
   }
@@ -1273,15 +1327,98 @@
   }
 
   int use_ext_reset;
+	unsigned char size;
+  
+  if (pgm->flag & PGM_FL_IS_AVR32)
+  {
+    unsigned int speed=4000;
+    
+    size = 0;
+    cmd[size++] = SCOPE_AVR32;
+    cmd[size++] = AVR32_CMD_SET;
+    cmd[size++] = 0;
+    cmd[size++] = AVR32_CTXT_PHYSICAL;
+    cmd[size++] = AVR32_PHY_JTAG_CLOCK;
+    cmd[size++] = 2;
+    cmd[size++] = speed&0xff;
+    cmd[size++] = (speed>>8)&0xff;
+    jtag3_command(pgm, cmd, size, &resp, "Set avr32 JTAG clock");
+    free(resp);
+    
+    size = 0;
+    cmd[size++] = SCOPE_AVR32;
+    cmd[size++] = AVR32_CMD_SET;
+    cmd[size++] = 0;
+    cmd[size++] = AVR32_CTXT_PHYSICAL;
+    cmd[size++] = AVR32_PHY_DAISY;
+    cmd[size++] = 4;
+    cmd[size++] = 0;
+    cmd[size++] = 0;
+    cmd[size++] = 0;
+    cmd[size++] = 0;
+    jtag3_command(pgm, cmd, size, &resp, "Clear avr32 JTAG daisy chain");
+    free(resp);
+    
+    size = 0;
+    cmd[size++] = SCOPE_AVR32;
+    cmd[size++] = AVR32_CMD_SET;
+    cmd[size++] = 0;
+    cmd[size++] = AVR32_CTXT_PHYSICAL;
+    cmd[size++] = AVR32_PHY_PHYSICAL;
+    cmd[size++] = 1;
+    cmd[size++] = AVR32_PHYSICAL_INTERFACE_JTAG;
+    jtag3_command(pgm, cmd, size, &resp, "Set avr32 interface to JTAG");
+    free(resp);
+    
+    size = 0;
+    cmd[size++] = SCOPE_AVR32;
+    cmd[size++] = AVR32_CMD_SET;
+    cmd[size++] = 0;
+    cmd[size++] = AVR32_CTXT_DEVICE;
+    cmd[size++] = 0;
+    cmd[size++] = 0x14;
+    cmd[size++] = 0x00;
+    cmd[size++] = 0x00;
+    cmd[size++] = 0x00;
+    cmd[size++] = 0x14;
+    cmd[size++] = 0xfe;
+    cmd[size++] = 0xff;
+    cmd[size++] = 0x00;
+    cmd[size++] = 0x02;
+    cmd[size++] = 0x01;
+    cmd[size++] = 0x01;
+    cmd[size++] = 0x05;
+    cmd[size++] = 0x00;
+    cmd[size++] = 0x04;
+    cmd[size++] = 0x00;
+    cmd[size++] = 0x00;
+    cmd[size++] = 0x00;
+    cmd[size++] = 0x00;
+    cmd[size++] = 0x00;
+    cmd[size++] = 0x00;
+    cmd[size++] = 0x00;
+    jtag3_command(pgm, cmd, size, &resp, "Set avr32 device context");
+    free(resp);
+  }
 
   for (use_ext_reset = 0; use_ext_reset <= 1; use_ext_reset++) {
-    cmd[0] = SCOPE_AVR;
-    cmd[1] = CMD3_SIGN_ON;
-    cmd[2] = 0;
-    cmd[3] = use_ext_reset;			/* external reset */
+    size = 0;
+    if (pgm->flag & PGM_FL_IS_AVR32)
+    {
+      cmd[size++] = SCOPE_AVR32;
+      cmd[size++] = AVR32_CMD_ACTIVATE_PHYSICAL;
+    } else {
+      cmd[size++] = SCOPE_AVR;
+      cmd[size++] = CMD3_SIGN_ON;
+    }
+    cmd[size++] = 0;
+    cmd[size++] = use_ext_reset;			/* external reset */
 
-    if ((status = jtag3_command(pgm, cmd, 4, &resp, "AVR sign-on")) >= 0)
+
+    if ((status = jtag3_command(pgm, cmd, size, &resp, "AVR sign-on")) >= 0)
+    {
       break;
+    }
 
     avrdude_message(MSG_INFO, "%s: retrying with external reset applied\n",
 		    progname);
@@ -1308,12 +1445,148 @@
     if (p->flags & AVRPART_HAS_UPDI) {
       /* Partial Family_ID has been returned */
       avrdude_message(MSG_NOTICE, "%s: Partial Family_ID returned: \"%c%c%c%c\"\n",
-	      progname, resp[3], resp[4], resp[5], resp[6]);
-    }
-    else
+        progname, resp[3], resp[4], resp[5], resp[6]);
+    } else if (pgm->flag & PGM_FL_IS_AVR32) {
+      unsigned int value;
+      
+      // on the AVR32 use the JTAG ID to determine the FLASHC module address
+      if (((resp[3] | (resp[4]<<8))&0x0fff)>>1 == 0x01f) // identifies ATMEL
+      {
+        // check 16bit part number and assign address location
+        switch (((unsigned long)(resp[4] | (resp[5]<<8) | (resp[6]<<16))>>4)&0xFFFF)
+        {
+          // assume 0xfffe1400 address, there doesn't seem to be a pattern to
+          // the part numbering, it might be worth adding the address to the
+          // avrdude.conf processor config as a part argument
+          default:
+          
+          // a0 a1 a3 a4 b0 b1
+          // d3 d4 - flashcdw
+          case 0x1EDC: // AT32UC3A0512
+          case 0x1EDF: // AT32UC3A0256
+          case 0x1EE2: // AT32UC3A0128
+          case 0x1EDD: // AT32UC3A1512
+          case 0x1EE0: // AT32UC3A1256
+          case 0x1EE3: // AT32UC3A1128
+          
+          case 0x2050: // AT32UC3B0512
+          case 0x2052: // AT32UC3B1512
+          case 0x1EE4: // AT32UC3B0256
+          case 0x1EE5: // AT32UC3B1256
+          case 0x1EE6: // AT32UC3B0128
+          case 0x1EE9: // AT32UC3B1128
+          case 0x1EEA: // AT32UC3B064
+          case 0x1EEB: // AT32UC3B164
+
+          case 0x2020: // AT32UC3A3256S
+          case 0x2021: // AT32UC3A3128S
+          case 0x2022: // AT32UC3A364S
+          case 0x2026: // AT32UC3A3256
+          case 0x2027: // AT32UC3A3128
+          case 0x2028: // AT32UC3A364
+          case 0x2029: // AT32UC3A4256S
+          case 0x202a: // AT32UC3A4128S
+          case 0x202b: // AT32UC3A464S
+          case 0x202c: // AT32UC3A4256
+          case 0x202d: // AT32UC3A128
+          case 0x202e: // AT32UC3A64
+          
+          case 0x2123: // ATUC256D3
+          case 0x2120: // ATUC128D3
+          case 0x2121: // ATUC64D3
+          case 0x2133: // ATUC256D4
+          case 0x2130: // ATUC128D4
+          case 0x2131: // ATUC64D4
+            
+            PDATA(pgm)->flashc_start = 0xfffe1400;
+            break;
+          
+          
+          // c0 c1 c2
+          // l0 l1 l2 l3 l4 - flashcdw
+          case 0x2000: // AT32UC3C0512C
+          case 0x2001: // AT32UC3C0256C
+          case 0x2002: // AT32UC3C0128C
+          case 0x2003: // AT32UC3C064C
+          case 0x2004: // AT32UC3C1512C
+          case 0x2005: // AT32UC3C1256C
+          case 0x2006: // AT32UC3C1128C
+          case 0x2007: // AT32UC3C164C
+          case 0x2008: // AT32UC3C2512C
+          case 0x2009: // AT32UC3C2256C
+          case 0x200A: // AT32UC3C2128C
+          case 0x200B: // AT32UC3C264C
+          
+          case 0x21C9: // AT32UC3L0256
+          case 0x21CA: // AT32UC3L0128
+          
+          case 0x21C3: // ATUC256L3U
+          case 0x21C4: // ATUC128L3U
+          case 0x21C5: // ATUC64L3U
+          case 0x21C6: // ATUC256L4U
+          case 0x21C7: // ATUC128L4U
+          case 0x21C8: // ATUC64L4U
+          
+            PDATA(pgm)->flashc_start = 0xfffe0000;
+            break;
+        }
+      }
+      
+      free(resp);
+      
+      do
+      {
+        if (jtag3_avr32_read_register(pgm, AVR32_SAB_HSB, 
+          PDATA(pgm)->flashc_start + 0x08, &value)<0) return -1;
+      } while (!(value&1));
+      
+      size = 0;
+      cmd[size++] = SCOPE_AVR32;
+      cmd[size++] = AVR32_CMD_IS_PROTECTED;
+      cmd[size++] = 0;
+      jtag3_command(pgm, cmd, size, &resp, "Check avr32 is protected");
+      free(resp);
+      
+      size = 0;
+      cmd[size++] = SCOPE_AVR32;
+      cmd[size++] = AVR32_CMD_RESET;
+      cmd[size++] = 0;
+      cmd[size++] = 0x07;
+      jtag3_command(pgm, cmd, size, &resp, "Full reset avr32");
+      free(resp);
+      
+      jtag3_avr32_write_register(pgm, AVR32_SAB_OCD, 0x00000008, 0x00003000);
+      
+      size = 0;
+      cmd[size++] = SCOPE_AVR32;
+      cmd[size++] = AVR32_CMD_GET_ID;
+      cmd[size++] = 0;
+      jtag3_command(pgm, cmd, size, &resp, "Get ID");
+      free(resp);
+      
+      do
+      {
+        if (jtag3_avr32_read_register(pgm, AVR32_SAB_HSB,
+          PDATA(pgm)->flashc_start + 0x08, &value)<0) return -1;
+      } while (!(value&1));
+      
+      size = 0;
+      cmd[size++] = SCOPE_AVR32;
+      cmd[size++] = AVR32_CMD_HALT;
+      cmd[size++] = 0;
+      cmd[size++] = 1;
+      jtag3_command(pgm, cmd, size, &resp, "Halt avr32");
+      
+      do
+      {
+        if (jtag3_avr32_read_register(pgm, AVR32_SAB_HSB,
+          PDATA(pgm)->flashc_start + 0x08, &value)<0) return -1;
+      } while (!(value & 1));
+    } else {
       /* JTAG ID has been returned */
       avrdude_message(MSG_NOTICE, "%s: JTAG ID returned: 0x%02x 0x%02x 0x%02x 0x%02x\n",
 	      progname, resp[3], resp[4], resp[5], resp[6]);
+    }
   }
 
   free(resp);
@@ -1561,15 +1834,23 @@
 
 void jtag3_close(PROGRAMMER * pgm)
 {
-  unsigned char buf[4], *resp;
+  unsigned char buf[4], *resp, size;
 
   avrdude_message(MSG_NOTICE2, "%s: jtag3_close()\n", progname);
 
-  buf[0] = SCOPE_AVR;
-  buf[1] = CMD3_SIGN_OFF;
-  buf[2] = buf[3] = 0;
-
-  if (jtag3_command(pgm, buf, 3, &resp, "AVR sign-off") >= 0)
+  size=0;
+  if (pgm->flag & PGM_FL_IS_AVR32)
+  {
+    buf[size++] = SCOPE_AVR32;
+    buf[size++] = AVR32_CMD_DEACTIVATE_PHYSICAL;
+  } else
+  {
+    buf[size++] = SCOPE_AVR;
+    buf[size++] = CMD3_SIGN_OFF;
+    buf[size++] = 0;
+  }
+ 
+  if (jtag3_command(pgm, buf, size, &resp, "AVR sign-off") >= 0)
     free(resp);
 
   buf[0] = SCOPE_GENERAL;
@@ -1639,11 +1920,11 @@
                                 unsigned int page_size,
                                 unsigned int addr, unsigned int n_bytes)
 {
-  unsigned int block_size;
+  unsigned int block_size, size;
   unsigned int maxaddr = addr + n_bytes;
   unsigned char *cmd;
   unsigned char *resp;
-  int status, dynamic_memtype = 0;
+  int status;
   long otimeout = serial_recv_timeout;
 
   avrdude_message(MSG_NOTICE2, "%s: jtag3_paged_write(.., %s, %d, 0x%lx, %d)\n",
@@ -1659,48 +1940,12 @@
 
   if (page_size == 0) page_size = 256;
 
-  if ((cmd = malloc(page_size + 13)) == NULL) {
+  if ((cmd = malloc(page_size + 32)) == NULL) {
     avrdude_message(MSG_INFO, "%s: jtag3_paged_write(): Out of memory\n",
 	    progname);
     return -1;
   }
 
-  cmd[0] = SCOPE_AVR;
-  cmd[1] = CMD3_WRITE_MEMORY;
-  cmd[2] = 0;
-  if (strcmp(m->desc, "flash") == 0) {
-    PDATA(pgm)->flash_pageaddr = (unsigned long)-1L;
-    cmd[3] = jtag3_memtype(pgm, p, addr);
-    if (p->flags & AVRPART_HAS_PDI)
-      /* dynamically decide between flash/boot memtype */
-      dynamic_memtype = 1;
-  } else if (strcmp(m->desc, "eeprom") == 0) {
-    if (pgm->flag & PGM_FL_IS_DW) {
-      /*
-       * jtag3_paged_write() to EEPROM attempted while in
-       * DW mode.  Use jtag3_write_byte() instead.
-       */
-      for (; addr < maxaddr; addr++) {
-	status = jtag3_write_byte(pgm, p, m, addr, m->buf[addr]);
-	if (status < 0) {
-	  free(cmd);
-	  return -1;
-	}
-      }
-      free(cmd);
-      return n_bytes;
-    }
-    cmd[3] = ( p->flags & AVRPART_HAS_PDI ) ? MTYPE_EEPROM_XMEGA : MTYPE_EEPROM_PAGE;
-    PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L;
-  } else if ( ( strcmp(m->desc, "usersig") == 0 ) ) {
-    cmd[3] = MTYPE_USERSIG;
-  } else if ( ( strcmp(m->desc, "boot") == 0 ) ) {
-    cmd[3] = MTYPE_BOOT_FLASH;
-  } else if ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) {
-    cmd[3] = MTYPE_FLASH;
-  } else {
-    cmd[3] = MTYPE_SPM;
-  }
   serial_recv_timeout = 100;
   for (; addr < maxaddr; addr += page_size) {
     if ((maxaddr - addr) < page_size)
@@ -1711,31 +1956,170 @@
 	      "block_size at addr %d is %d\n",
 	      progname, addr, block_size);
 
-    if (dynamic_memtype)
-      cmd[3] = jtag3_memtype(pgm, p, addr);
+    if (pgm->flag & PGM_FL_IS_AVR32) {
+      int erase,write,blank;
+      unsigned int i;
+      
+      if (jtag3_avr32_busy(pgm)<0) return -1;
+      
+      size = 0;
+      cmd[size++] = SCOPE_AVR32;
+      cmd[size++] = AVR32_CMD_READ;
+      cmd[size++] = 1;
+      cmd[size++] = AVR32_MEMTYPE_BLOCK;
+      u32_to_b4(&cmd[size], jtag3_memaddr(pgm, p, m, 0x80000000|addr));
+      size += 4;
+      cmd[size++] = AVR32_SAB_HSB;
+      u32_to_b4(&cmd[size], page_size);
+      size += 4;
+      
+      erase = page_size;
+      write = page_size;
+      blank = 0;
+      
+      status = jtag3_command(pgm, cmd, size, &resp, "read memory");
+      if (status < 0) return status;
+      
+      if (resp[0] == SCOPE_AVR32 && resp[1] == AVR32_RSP_DATA &&
+        resp[2] == cmd[2] && status == 4+page_size && resp[status-1] == 0x00) {
+        for (i = 0; i < page_size; i++) {
+          unsigned char want,diff;
+          
+          /* if blank counts to zero then the page is blank and does
+           not need to be written after an erase */
+          want = m->buf[addr+(i&0xfffffffc)+(3-(i&0x3))];
+          
+          if (want == 0xff) blank++;
+          
+          /* get the difference between what we want and what we have */
+          diff = want ^ resp[3 + i];
+          
+          /* match, so decrement write, otherwise check if we need to erase */
+          if (!diff) write--;
+          if (!(diff & want)) erase--;
+        }
+      }
+      free(resp);
+      
+      /* only write page if there is a difference */
+      if (write || erase)
+        avrdude_message(MSG_NOTICE2, "%s: jtag3_paged_write(): "
+            "address:0x%08x size:%d write:%d erase:%d\n",
+            progname, addr, page_size, write, erase);
+      
+      if (erase)
+      {
+        /* erase page if required */
+        if (jtag3_avr32_write_register(pgm, AVR32_SAB_HSB, 
+          PDATA(pgm)->flashc_start + 0x04, 0xa5000002|(((addr/page_size)&0xffff)<<8)) < 0)
+          return -1;
+        
+        if (jtag3_avr32_busy(pgm)<0) return -1;
+      }
+      
+      if (blank != page_size && write)
+      {
+        /* clear page buffer */
+        if (jtag3_avr32_write_register(pgm, AVR32_SAB_HSB, 
+          PDATA(pgm)->flashc_start + 0x04, 0xa5000003) < 0) return -1;
+        
+        /* wait until flash controller is ready */
+        if (jtag3_avr32_busy(pgm) < 0) return -1;
+        
+        /* create write command */
+        size = 0;
+        cmd[size++] = SCOPE_AVR32;
+        cmd[size++] = AVR32_CMD_WRITE;
+        cmd[size++] = 0;
+        cmd[size++] = AVR32_MEMTYPE_BLOCK;
+        
+        u32_to_b4(&cmd[size], jtag3_memaddr(pgm, p, m, 0x80000000|addr));
+        size += 4;
+        cmd[size++] = AVR32_SAB_HSB;
+        u32_to_b4(&cmd[size], page_size);
+        size += 4;
+        
+        for (i = 0; i < page_size; i++)
+          cmd[size++]=m->buf[addr+(i&0xfffffffc)+(3-(i&0x3))];
+        
+        avrdude_message(MSG_NOTICE2, "%s: jtag3_paged_write(): "
+          "write %lubytes to address:0x%08x\n",
+          progname, size, addr);
+        
+        /* write block to flash page buffer */
+        if (jtag3_command(pgm, cmd, size, &resp, "write memory") < 0)
+          return -1;
+        
+        /* wait until flash controller is ready */
+        if (jtag3_avr32_busy(pgm)<0) return -1;
+        
+        /* write page buffer to flash */
+        if (jtag3_avr32_write_register(pgm, AVR32_SAB_HSB, 
+          PDATA(pgm)->flashc_start + 0x04, 0xa5000001|(((addr/page_size)&0xffff)<<8)) < 0)
+          return -1;
+        
+        if (jtag3_avr32_busy(pgm)<0) return -1;
+      }
+    } else {
+      size=0;
+      cmd[size++] = SCOPE_AVR;
+      cmd[size++] = CMD3_WRITE_MEMORY;
+      cmd[size++] = 0;
+      if (strcmp(m->desc, "flash") == 0) {
+        PDATA(pgm)->flash_pageaddr = (unsigned long)-1L;
+        cmd[size++] = jtag3_memtype(pgm, p, addr);
+      } else if (strcmp(m->desc, "eeprom") == 0) {
+        if (pgm->flag & PGM_FL_IS_DW) {
+          /*
+           * jtag3_paged_write() to EEPROM attempted while in
+           * DW mode.  Use jtag3_write_byte() instead.
+           */
+          for (; addr < maxaddr; addr++) {
+            status = jtag3_write_byte(pgm, p, m, addr, m->buf[addr]);
+            if (status < 0) {
+              free(cmd);
+              return -1;
+            }
+          }
+          free(cmd);
+          return n_bytes;
+        }
+        cmd[size++] = ( p->flags & AVRPART_HAS_PDI ) ? MTYPE_EEPROM_XMEGA : MTYPE_EEPROM_PAGE;
+        PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L;
+      } else if ( ( strcmp(m->desc, "usersig") == 0 ) ) {
+        cmd[size++] = MTYPE_USERSIG;
+      } else if ( ( strcmp(m->desc, "boot") == 0 ) ) {
+        cmd[size++] = MTYPE_BOOT_FLASH;
+      } else if ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) {
+        cmd[size++] = MTYPE_FLASH;
+      } else {
+        cmd[size++] = MTYPE_SPM;
+      }
+      u32_to_b4(&cmd[size], jtag3_memaddr(pgm, p, m, addr));
+      size+=4;
+      u32_to_b4(&cmd[size], page_size);
+      size+=4;
+      cmd[size++] = 0;
 
-    u32_to_b4(cmd + 8, page_size);
-    u32_to_b4(cmd + 4, jtag3_memaddr(pgm, p, m, addr));
-    cmd[12] = 0;
+      /*
+       * The JTAG ICE will refuse to write anything but a full page, at
+       * least for the flash ROM.  If a partial page has been requested,
+       * set the remainder to 0xff.  (Maybe we should rather read back
+       * the existing contents instead before?  Doesn't matter much, as
+       * bits cannot be written to 1 anyway.)
+       */
+      memset(cmd + size, 0xff, page_size);
+      memcpy(cmd + size, m->buf + addr, block_size);
 
-    /*
-     * The JTAG ICE will refuse to write anything but a full page, at
-     * least for the flash ROM.  If a partial page has been requested,
-     * set the remainder to 0xff.  (Maybe we should rather read back
-     * the existing contents instead before?  Doesn't matter much, as
-     * bits cannot be written to 1 anyway.)
-     */
-    memset(cmd + 13, 0xff, page_size);
-    memcpy(cmd + 13, m->buf + addr, block_size);
+      if ((status = jtag3_command(pgm, cmd, page_size + size,
+        &resp, "write memory")) < 0) {
+        free(resp);
+        serial_recv_timeout = otimeout;
+        return -1;
+      }
 
-    if ((status = jtag3_command(pgm, cmd, page_size + 13,
-				&resp, "write memory")) < 0) {
-      free(cmd);
-      serial_recv_timeout = otimeout;
-      return -1;
+      free(resp);
     }
-
-    free(resp);
   }
 
   free(cmd);
@@ -1750,7 +2134,7 @@
 {
   unsigned int block_size;
   unsigned int maxaddr = addr + n_bytes;
-  unsigned char cmd[12];
+  unsigned char cmd[16], size;
   unsigned char *resp;
   int status, dynamic_memtype = 0;
   long otimeout = serial_recv_timeout;
@@ -1768,30 +2152,43 @@
 
   page_size = m->readsize;
 
-  cmd[0] = SCOPE_AVR;
-  cmd[1] = CMD3_READ_MEMORY;
-  cmd[2] = 0;
-
-  if (strcmp(m->desc, "flash") == 0) {
-    cmd[3] = jtag3_memtype(pgm, p, addr);
-    if (p->flags & AVRPART_HAS_PDI)
-      /* dynamically decide between flash/boot memtype */
-      dynamic_memtype = 1;
-  } else if (strcmp(m->desc, "eeprom") == 0) {
-    cmd[3] = ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) ? MTYPE_EEPROM : MTYPE_EEPROM_PAGE;
-    if (pgm->flag & PGM_FL_IS_DW)
-      return -1;
-  } else if ( ( strcmp(m->desc, "prodsig") == 0 ) ) {
-    cmd[3] = MTYPE_PRODSIG;
-  } else if ( ( strcmp(m->desc, "usersig") == 0 ) ) {
-    cmd[3] = MTYPE_USERSIG;
-  } else if ( ( strcmp(m->desc, "boot") == 0 ) ) {
-    cmd[3] = MTYPE_BOOT_FLASH;
-  } else if ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) {
-    cmd[3] = MTYPE_FLASH;
-  } else {
-    cmd[3] = MTYPE_SPM;
+  size=0;
+ 
+  if (pgm->flag & PGM_FL_IS_AVR32)
+  {
+    cmd[size++] = SCOPE_AVR32;
+    cmd[size++] = AVR32_CMD_READ;
+    cmd[size++] = 1;
+    
+    cmd[size++] = AVR32_MEMTYPE_BLOCK;
+  } else
+  {
+    cmd[size++] = SCOPE_AVR;
+    cmd[size++] = CMD3_READ_MEMORY;
+    cmd[size++] = 0;
+    
+    if (strcmp(m->desc, "flash") == 0) {
+      cmd[size++] = jtag3_memtype(pgm, p, addr);
+      if (p->flags & AVRPART_HAS_PDI)
+        /* dynamically decide between flash/boot memtype */
+        dynamic_memtype = 1;
+    } else if (strcmp(m->desc, "eeprom") == 0) {
+      cmd[size++] = ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) ? MTYPE_EEPROM : MTYPE_EEPROM_PAGE;
+      if (pgm->flag & PGM_FL_IS_DW)
+        return -1;
+    } else if ( ( strcmp(m->desc, "prodsig") == 0 ) ) {
+      cmd[size++] = MTYPE_PRODSIG;
+    } else if ( ( strcmp(m->desc, "usersig") == 0 ) ) {
+      cmd[size++] = MTYPE_USERSIG;
+    } else if ( ( strcmp(m->desc, "boot") == 0 ) ) {
+      cmd[size++] = MTYPE_BOOT_FLASH;
+    } else if ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) {
+      cmd[size++] = MTYPE_FLASH;
+    } else {
+      cmd[size++] = MTYPE_SPM;
+    }
   }
+  
   serial_recv_timeout = 100;
   for (; addr < maxaddr; addr += page_size) {
     if ((maxaddr - addr) < page_size)
@@ -1803,22 +2200,45 @@
 	      progname, addr, block_size);
 
     if (dynamic_memtype)
-      cmd[3] = jtag3_memtype(pgm, p, addr);
+      cmd[size-1] = jtag3_memtype(pgm, p, addr);
 
-    u32_to_b4(cmd + 8, block_size);
-    u32_to_b4(cmd + 4, jtag3_memaddr(pgm, p, m, addr));
+    /* set the address and size of buffer to read */
+    if (pgm->flag & PGM_FL_IS_AVR32)
+    {
+      u32_to_b4(&cmd[size], jtag3_memaddr(pgm, p, m, 0x80000000|addr));
+      size+=4;
+      cmd[size++]=AVR32_SAB_HSB;
+      u32_to_b4(&cmd[size], block_size);
+      size+=4;
+    } else
+    {
+      u32_to_b4(&cmd[size], jtag3_memaddr(pgm, p, m, addr));
+      size+=4;
+      u32_to_b4(&cmd[size], block_size);
+      size+=4;
+    }
 
-    if ((status = jtag3_command(pgm, cmd, 12, &resp, "read memory")) < 0)
-      return -1;
+    while ((status = jtag3_command(pgm, cmd, size, &resp, "read memory")) < 0)
+      avrdude_message(MSG_INFO, "%s: error status %d)\n",
+	      progname, status);
 
+    /* reset header size */
+    size -= (pgm->flag & PGM_FL_IS_AVR32) ? 9 : 8;
+    
     if (resp[1] != RSP3_DATA ||
 	status < block_size + 4) {
-      avrdude_message(MSG_INFO, "%s: wrong/short reply to read memory command\n",
-	      progname);
+      avrdude_message(MSG_INFO, "%s: wrong/short reply to read memory command (read %dbytes, expected %dbytes)\n",
+	      progname, status, block_size+4);
       serial_recv_timeout = otimeout;
       free(resp);
       return -1;
     }
+    if (pgm->flag & PGM_FL_IS_AVR32)
+    {
+      unsigned int i;
+      for (i=0; i<status - 4; i++)
+        m->buf[addr+i]=resp[3+(i&0xfffffffc)+(3-(i&3))];
+    } else
     memcpy(m->buf + addr, resp + 3, status - 4);
     free(resp);
   }
@@ -2497,3 +2917,249 @@
   pgm->read_sib       = jtag3_read_sib;
 }
 
+
+const char jtag3_avr32_desc[] = "Atmel JTAGICE3 in AVR32 JTAG mode";
+
+void jtag3_avr32_initpgm(PROGRAMMER * pgm)
+{
+  strcpy(pgm->type, "JTAGICE3_AVR32");
+
+  /*
+   * mandatory functions
+   */
+  pgm->initialize     = jtag3_initialize;
+  pgm->display        = jtag3_display;
+  pgm->enable         = jtag3_enable;
+  pgm->disable        = jtag3_disable;
+  pgm->program_enable = jtag3_program_enable_dummy;
+  pgm->chip_erase     = jtag3_chip_erase;
+  pgm->open           = jtag3_open;
+  pgm->close          = jtag3_close;
+  pgm->read_byte      = 0;
+  pgm->write_byte     = 0;
+
+  /*
+   * optional functions
+   */
+  pgm->paged_write    = jtag3_paged_write;
+  pgm->paged_load     = jtag3_paged_load;
+  pgm->page_erase     = jtag3_page_erase;
+  pgm->print_parms    = jtag3_print_parms;
+  pgm->setup          = jtag3_setup;
+  pgm->teardown       = jtag3_teardown;
+  pgm->page_size      = 256;
+  pgm->flag           = PGM_FL_IS_AVR32;
+}
+
+int jtag3_avr32_busy(PROGRAMMER * pgm)
+{
+  unsigned int count;
+  
+  /* wait until flash controller is ready */
+  count = 3;
+  do
+  {
+    int status;
+    unsigned int value;
+    
+    status = jtag3_avr32_read_register(pgm, AVR32_SAB_HSB, PDATA(pgm)->flashc_start + 0x08, &value);
+    
+    if (status >= 0)
+    {
+      if (value&4) avrdude_message(MSG_INFO, "%s: failed operation on locked region\n", progname);
+      if (value&8) avrdude_message(MSG_INFO, "%s: pragram error, invalid command/bad keyword\n", progname);
+      if (value&1) count--;
+    }
+  } while (count);
+  
+  if (count) avrdude_message(MSG_INFO, "%s: failed to wait\n", progname);
+  
+  return count ? -1 : 0;
+}
+
+
+int jtag3_avr32_read_register(PROGRAMMER * pgm, Avr32SABAddressMap region,
+  unsigned int addr, unsigned int *data)
+{
+  unsigned char i, buf[32], size, *resp, msg[64];
+  int rv, len;
+  
+  rv = -1;
+  size = 0;
+  
+  buf[size++] = SCOPE_AVR32;
+  buf[size++] = AVR32_CMD_READ;
+  buf[size++] = 1;
+  buf[size++] = AVR32_MEMTYPE_BLOCK;
+  
+  for (i = 0; i < sizeof(addr); i++)
+    buf[size++] = (addr>>(i<<3))&0xff;
+  
+  buf[size++] = region;
+  
+  for (i = 0; i < sizeof(*data); i++)
+    buf[size++] = sizeof(*data)>>(i<<3);
+  
+  snprintf(msg, sizeof(msg), "read avr32 register %02x:0x%08x", region, addr);
+  len=jtag3_command(pgm, buf, size, &resp, msg);
+  if (len >= 4)
+  {
+    if (jtag3_avr32_status_message(resp[len-1], sizeof(msg), msg) < 0)
+    {
+      avrdude_message(MSG_INFO, "%s: %s: error reading register 0x%08x: %s\n", 
+        progname, __func__, addr, msg);
+    } else
+    {
+      if (resp[0] == buf[0] && resp[1] == AVR32_RSP_DATA && resp[2] == buf[2])
+      {
+        /* response correct */
+        for (i = 0, *data = 0; i < sizeof(*data); i++)
+          if (data) *data |= resp[3+i]<<(i<<3);
+
+        avrdude_message(MSG_DEBUG, "%s: %s: register:0x%08x = 0x%08x\n",
+          progname, __func__, addr, *data);
+        rv = 0;
+      } else 
+        avrdude_message(MSG_INFO, "%s: %s: invalid response reading register:0x%08x, %02x %02x %02x\n",
+          progname, __func__, addr, resp[0], resp[1], resp[2]);
+    }
+  } else
+    avrdude_message(MSG_INFO, "%s: %s: invalid length %dbytes\n",
+      progname, __func__, len);
+  
+  free(resp);
+  
+  avrdude_message(MSG_DEBUG, "%s: %s: return %d\n", progname, __func__, rv);
+  return rv;
+}
+
+
+int jtag3_avr32_write_register(PROGRAMMER * pgm, Avr32SABAddressMap region,
+  unsigned int addr, unsigned int data)
+{
+  unsigned char i, buf[32], size, *resp, msg[64];
+  int rv, len;
+  
+  rv=-1;
+  size=0;
+  
+  avrdude_message(MSG_DEBUG, "%s: %s: register:0x%08x = 0x%08x\n",
+                  progname, __func__, addr, data);
+  
+  buf[size++] = SCOPE_AVR32;
+  buf[size++] = AVR32_CMD_WRITE;
+  buf[size++] = 0;
+  buf[size++] = AVR32_MEMTYPE_BLOCK;
+  
+  snprintf(msg, sizeof(msg), "write avr32 register %02x:0x%08x = 0x%08x", region, addr, data);
+  
+  for (i = 0; i < sizeof(addr); i++)
+    buf[size++] = (addr>>(i<<3))&0xff;
+  
+  buf[size++] = region;
+  
+  for (i = 0; i < sizeof(data); i++)
+    buf[size++] = sizeof(data)>>(i<<3);
+  
+  for (i = 0; i < sizeof(data); i++, data>>=8)
+    buf[size++] = data&0xff;;
+  
+  len = jtag3_command(pgm, buf, size, &resp, msg);
+  if (len == 3)
+  {
+    char reason[50];
+    
+    if (jtag3_avr32_status_message(buf[2], sizeof(reason), reason) < 0)
+    {
+      avrdude_message(MSG_INFO, "%s: %s: error writing register:0x%08x, %s\n", 
+        progname, __func__, addr, reason);
+    } else
+    {
+      if (resp[0] == buf[0] && resp[1] == AVR32_RSP_OK)
+      {
+        /* response correct */
+        rv = 0;
+      } else
+      {
+        avrdude_message(MSG_INFO, "%s: %s: "
+          "OK response incorrect writing to register 0x%08x, "
+          "expected 0x%02x 0x%02, got 0x%02x 0x%02\n",
+          progname, __func__, addr, buf[0], AVR32_RSP_OK, resp[0], resp[1]);
+      }
+    }
+  } else
+    avrdude_message(MSG_INFO, "%s: %s: invalid response length %dbytes writing register:0x%08x\n", 
+      progname, __func__, len, addr);
+  
+  free(resp);
+  
+  avrdude_message(MSG_DEBUG, "%s: %s: return %d\n", progname, __func__, rv);
+  return rv;
+}
+
+
+int jtag3_avr32_status_message(unsigned char code, short len, char *msg)
+{
+  const char *str=0;
+  
+  switch (code)
+  {
+    case AVR32_FAILURE_OK: break;
+    case AVR32_FAILURE_NACK: str = "NACK received from target"; break;
+    case AVR32_FAILURE_LENGTH: str = "Incorrect packet length"; break;
+    case AVR32_FAILURE_RECEIVE_TIMEOUT: str = "Receive function timeout"; break;
+    case AVR32_FAILURE_RECEIVE_SYNC: str = "Receive did not sync"; break;
+    case AVR32_FAILURE_RECEIVE_LENGTH: str = "Incorrect packet length"; break;
+    case AVR32_FAILURE_TRANSMIT_OVERFLOW: str = "Transmit buffer overflow"; break;
+    case AVR32_FAILURE_INVALID_MEMTYPE: str = "Invalid memtype given"; break;
+    case AVR32_FAILURE_WRITE_ERROR: str = "A write error occurred"; break;
+    case AVR32_FAILURE_WRITE_BUSY: str = "Busy signal received"; break;
+    case AVR32_FAILURE_READ_SHORT: str = "Short-packet received"; break;
+    case AVR32_FAILURE_ERASE_TIMEOUT: str = "Erase command timeout"; break;
+    case AVR32_FAILURE_FLASHREADY_TIMEOUT: str = "Flash controller busy"; break;
+    case AVR32_FAILURE_ILLEGAL_STATE: str = "Illegal state specified"; break;
+    case AVR32_FAILURE_NOT_SUPPORTED: str = "Feature not supported"; break;
+    case AVR32_FAILURE_PROGE: str = "Programming error"; break;
+    case AVR32_FAILURE_LOCKE: str = "Lock error"; break;
+    case AVR32_FAILURE_STEP_TIMEOUT: str = "Single stepping timeout"; break;
+    case AVR32_FAILURE_READ_BUSY: str = "Busy bit was set"; break;
+    case AVR32_FAILURE_READ_ERROR: str = "Error bit was set"; break;
+    case AVR32_FAILURE_HARDWARE_ERROR: str = "aWire hardware init error"; break;
+    case AVR32_FAILURE_NO_CONTACT: str = "No response from aWire"; break;
+    case AVR32_FAILURE_NO_TARGET_POWER: str = "No target power"; break;
+    case AVR32_FAILURE_NOT_IMPLEMENTED: str = "Command not implemented"; break;
+    case AVR32_FAILURE_UNSUPPORTED_HARDWARE: str = "Hardware not supported"; break;
+    case AVR32_FAILURE_JTAGM_INIT_ERROR: str = "JTAG master init error"; break;
+    case AVR32_FAILURE_NO_DEVICE_FOUND: str = "devices  =  =  0!"; break;
+    case AVR32_FAILURE_JTAGM_ERROR: str = "JTAG master error"; break;
+    case AVR32_FAILURE_INVALID_SIZE: str = "Too many or too few bytes"; break;
+    case AVR32_FAILURE_INVALID_ADDRESS: str = "Bad address requested"; break;
+    case AVR32_FAILURE_AWIRE_SET_BAUD_ERROR: str = "Failure setting baud"; break;
+    case AVR32_FAILURE_INVALID_DATA: str = "Data invalid, discard it"; break;
+    case AVR32_FAILURE_INVALID_PHYSICAL_MODE: str = "Physical mode not valid"; break;
+    case AVR32_FAILURE_INVALID_CLOCK_SPEED: str = "The clock is not valid"; break;
+    case AVR32_FAILURE_AWIRE_ERROR_RESPONSE: str = "Error response received"; break;
+    case AVR32_FAILURE_AWIRE_OVERFLOW: str = "Overflow data RX overflow/aWire master error"; break;
+    case AVR32_FAILURE_AWIRE_CRC: str = "aWire CRC error"; break;
+    case AVR32_FAILURE_AWIRE_TUNE: str = "aWire TUNE error"; break;
+    case AVR32_FAILURE_JTAGM_WAS_BUSY: str = "JTAG master busy"; break;
+    case AVR32_FAILURE_JTAGM_TIMEOUT: str = "JTAG master timeout"; break;
+    case AVR32_FAILURE_BAD_VALUE: str = "Invalid parameter value"; break;
+    case AVR32_FAILURE_ERASE_ERROR: str = "Erase error"; break;
+    case AVR32_FAILURE_CONFIG_ERROR: str = "Insufficient config info"; break;
+    case AVR32_FAILURE_INVALID_EMULATOR_MODE: str = "Mode is not valid"; break;
+    case AVR32_FAILURE_CPU_DIRTY_TIMEOUT: str = "CPU wait timeout"; break;
+    case AVR32_FAILURE_CPU_MODE: str = "CPU not in debug mode"; break;
+    case AVR32_FAILURE_CPU_DEBUG_MODE_TIMEOUT: str = "CPU debug mode timeout"; break;
+    case AVR32_FAILURE_AWIRE_RW_STATUS: str = "Unexpected status"; break;
+    case AVR32_FAILURE_TRANSMIT_TIMEOUT: str = "Data TX timeout"; break;
+    case AVR32_FAILURE_INTERNAL_RESPONSE_ERROR: str = "Near disaster"; break;
+    default:
+      if (msg && len) snprintf(msg, len, "Unknown response code %02x\n", code);
+      break;
+  }
+  
+  if (msg && len && str) strncpy(msg, str, len);
+  
+  return code == AVR32_FAILURE_OK ? 0 : -1;
+}
Index: jtag3.h
===================================================================
--- jtag3.h	(revision 1453)
+++ jtag3.h	(working copy)
@@ -42,10 +42,12 @@
 extern const char jtag3_dw_desc[];
 extern const char jtag3_pdi_desc[];
 extern const char jtag3_updi_desc[];
+extern const char jtag3_avr32_desc[];
 void jtag3_initpgm (PROGRAMMER * pgm);
 void jtag3_dw_initpgm (PROGRAMMER * pgm);
 void jtag3_pdi_initpgm (PROGRAMMER * pgm);
 void jtag3_updi_initpgm (PROGRAMMER * pgm);
+void jtag3_avr32_initpgm (PROGRAMMER * pgm);
 
 /*
  * These functions are referenced from stk500v2.c for JTAGICE3 in
Index: jtag3_private.h
===================================================================
--- jtag3_private.h	(revision 1453)
+++ jtag3_private.h	(working copy)
@@ -96,6 +96,9 @@
 #define SCOPE_GENERAL              0x01
 #define SCOPE_AVR_ISP              0x11
 #define SCOPE_AVR                  0x12
+#define SCOPE_AVR32                0x13
+#define SCOPE_TPI                  0x14
+#define SCOPE_EDBG                 0x20
 
 /* Info scope */
 #define CMD3_GET_INFO              0x00
@@ -347,3 +350,292 @@
     unsigned char ocd_base_addr[2];
 };
 #endif /* JTAG3_PRIVATE_EXPORTED */
+
+
+
+/* avr32 programming interface, this overlays edbg interface */
+enum Avr32GenericCommands {
+    AVR32_CMD_QUERY                 = 0x00, //! Capability discovery 
+    AVR32_CMD_SET                   = 0x01, //! Set parameters
+    AVR32_CMD_GET                   = 0x02, //! Get parameters
+    AVR32_CMD_ACTIVATE_PHYSICAL     = 0x03, //! Connect physically
+    AVR32_CMD_DEACTIVATE_PHYSICAL   = 0x04, //! Disconnect physically
+    AVR32_CMD_GET_ID                = 0x10, //! Read the ID
+    AVR32_CMD_ERASE                 = 0x11, //! Erase the device
+    AVR32_CMD_HALT                  = 0x12, //! Stop or start execution
+    AVR32_CMD_RESET                 = 0x13, //! Apply or release reset
+    AVR32_CMD_STEP                  = 0x14, //! Single step
+    AVR32_CMD_READ                  = 0x15, //! Read memory
+    AVR32_CMD_WRITE                 = 0x16, //! Write memory
+    AVR32_CMD_TAP                   = 0x17, //! Low-level JTAG commands
+    AVR32_CMD_IS_PROTECTED          = 0x18, //! Check protected bit
+    AVR32_CMD_ERASE_SECTION         = 0x19  //! Partial erase
+};
+
+enum Avr32GenericResponses {
+    AVR32_RSP_FAILED                = 0xA0, //! Execution failed
+    AVR32_RSP_OK                    = 0x80, //! All OK
+    AVR32_RSP_LIST                  = 0x81, //! List of items returned
+    AVR32_RSP_ID                    = 0x82, //! ID value returned
+    AVR32_RSP_PC                    = 0x83, //! PC value returned
+    AVR32_RSP_DATA                  = 0x84  //! Data returned
+};
+
+enum Avr32GenericQueryContexts {
+    AVR32_QUERY_COMMANDS             = 0x00, //! Supported command list
+    AVR32_QUERY_CONFIGURATION        = 0x05, //! Supported configuration list
+    AVR32_QUERY_READ_MEMTYPES        = 0x06, //! Supported read memtypes list
+    AVR32_QUERY_WRITE_MEMTYPES       = 0x07, //! Supported write memtypes list
+    AVR32_QUERY_COMMAND_VERSIONS     = 0x08  //! Version map of command list
+};
+ 
+enum Avr32GenericSetGetContexts {
+    AVR32_CTXT_USB                  = 0x03, //! Transport-related settings
+    AVR32_CTXT_SESSION              = 0x04, //! Session-related settings
+    AVR32_CTXT_PHYSICAL             = 0x80, //! Physical interface related
+    AVR32_CTXT_DEVICE                = 0x82, //! Device specific settings
+};
+
+enum Avr32GenericSessionContextParameters {
+    AVR32_SESS_RUN_LED              = 0x00, //! Control the LED
+};
+
+enum Avr32GenericUsbContextParameters {
+    AVR32_USB_MAX_READ              = 0x00, //! Read payload size
+    AVR32_USB_MAX_WRITE             = 0x01  //! Write payload size
+};
+
+enum Avr32GenericPhysicalContextParameters {
+    AVR32_PHY_PHYSICAL              = 0x00, //! Physical interface selector
+    AVR32_PHY_JTAG_CLOCK            = 0x01, //! JTAG clock value
+    AVR32_PHY_AW_MAXBAUD            = 0x02, //! Maximum aWire baud
+    AVR32_PHY_DAISY                 = 0x03, //! JTAG daisy chain settings
+    AVR32_PHY_AWIRE_BAUD            = 0x04, //! Current aWire baud
+    AVR32_PHY_AWIRE_VERSION         = 0x05, //! aWire slave version
+    AVR32_PHY_EXT_RESET             = 0x0C, //! External reset control
+};
+
+enum Avr32GenericDeviceContext {
+    AVR32_FLASH_CTRL_BASE           = 0x02, //! Flash controller base address
+    AVR32_FLASH_PAGEBYTES           = 0x06, //! Number of bytes in one flash page
+    AVR32_RESET_DOMAINS         = 0x0A, //! Number of reset domains
+    AVR32_FLASH_PAGES               = 0x0B, //! Number of pages in the flash block
+    AVR32_AWIRE_BASE                = 0x10  //! Base address for aWire module
+};
+
+enum Avr32GenericMemoryTypes {
+    AVR32_MEMTYPE_SAB               = 0x80, //! Service Access Bus (SAB) word access
+    AVR32_MEMTYPE_NEXUS             = 0x81, //! Nexus mode access to SAB
+    AVR32_MEMTYPE_MEMORY_SERVICE    = 0x82, //! Memory Service mode access to SAB
+    AVR32_MEMTYPE_BLOCK             = 0x83, //! Block access to SAB
+    AVR32_MEMTYPE_BYTE              = 0x84, //! 8-bit access to SAB
+    AVR32_MEMTYPE_HALF_WORD         = 0x85, //! 16-bit access to SAB
+    AVR32_MEMTYPE_INTERNAL_FLASH    = 0x90, //! Write access to internal FLASH
+    AVR32_MEMTYPE_SYSREG            = 0x91, //! Access to system registers
+    AVR32_MEMTYPE_REGFILE           = 0x92, //! Access to register file
+    AVR32_MEMTYPE_USER_PAGE         = 0x93  //! Access to User Page in flash
+};
+
+enum Avr32GenericPhysicalInterfaces {
+    AVR32_PHYSICAL_INTERFACE_NONE   = 0x00, //! No physical
+    AVR32_PHYSICAL_INTERFACE_JTAG   = 0x04, //! JTAG physical
+    AVR32_PHYSICAL_INTERFACE_AWIRE  = 0x07  //! aWire physical
+};
+
+enum Avr32TapCommands {
+    AVR32_TAP_IR                    = 0x00, //! JTAG Instruction Register access
+    AVR32_TAP_DR                    = 0x01  //! JTAG Data Register access
+};
+
+typedef enum Avr32SABAddressMap {
+	AVR32_SAB_OCD					= 0x01,
+	AVR32_SAB_HSB_CPU				= 0x04,
+	AVR32_SAB_HSB					= 0x05,
+	AVR32_SAB_MSU					= 0x06
+} Avr32SABAddressMap;
+
+enum Avr32GenericFailureCodes {
+    AVR32_FAILURE_OK                        = 0x00, //! All OK
+    AVR32_FAILURE_NACK                      = 0x01, //! NACK received from target
+    AVR32_FAILURE_LENGTH                    = 0x02, //! Incorrect packet length
+    AVR32_FAILURE_RECEIVE_TIMEOUT           = 0x03, //! Receive function timeout
+    AVR32_FAILURE_RECEIVE_SYNC              = 0x04, //! Receive did not sync
+    AVR32_FAILURE_RECEIVE_LENGTH            = 0x05, //! Incorrect packet length
+    AVR32_FAILURE_TRANSMIT_OVERFLOW         = 0x06, //! Transmit buffer overflow
+    AVR32_FAILURE_INVALID_MEMTYPE           = 0x07, //! Invalid memtype given
+    AVR32_FAILURE_WRITE_ERROR               = 0x08, //! A write error occurred 
+    AVR32_FAILURE_WRITE_BUSY                = 0x09, //! Busy signal received
+    AVR32_FAILURE_READ_SHORT                = 0x0A, //! Short-packet received
+    AVR32_FAILURE_ERASE_TIMEOUT             = 0x0B, //! Erase command timeout 
+    AVR32_FAILURE_FLASHREADY_TIMEOUT        = 0x0C, //! Flash controller busy
+    AVR32_FAILURE_ILLEGAL_STATE             = 0x0D, //! Illegal state specified
+    AVR32_FAILURE_NOT_SUPPORTED             = 0x0E, //! Feature not supported
+    AVR32_FAILURE_PROGE                     = 0x0F, //! Programming error
+    AVR32_FAILURE_LOCKE                     = 0x10, //! Lock error
+    AVR32_FAILURE_STEP_TIMEOUT              = 0x11, //! Single stepping timeout
+    AVR32_FAILURE_READ_BUSY                 = 0x12, //! Busy bit was set
+    AVR32_FAILURE_READ_ERROR                = 0x13, //! Error bit was set
+    AVR32_FAILURE_HARDWARE_ERROR            = 0x14, //! aWire hardware init error
+    AVR32_FAILURE_NO_CONTACT                = 0x15, //! No response from aWire 
+    AVR32_FAILURE_NO_TARGET_POWER           = 0x16, //! No target power 
+    AVR32_FAILURE_NOT_IMPLEMENTED           = 0x17, //! Command not implemented
+    AVR32_FAILURE_UNSUPPORTED_HARDWARE      = 0x18, //! Hardware not supported
+    AVR32_FAILURE_JTAGM_INIT_ERROR          = 0x19, //! JTAG master init error
+    AVR32_FAILURE_NO_DEVICE_FOUND           = 0x1A, //! devices == 0!    
+    AVR32_FAILURE_JTAGM_ERROR               = 0x1B, //! JTAG master error
+    AVR32_FAILURE_INVALID_SIZE              = 0x1D, //! Too many or too few bytes
+    AVR32_FAILURE_INVALID_ADDRESS           = 0x1E, //! Bad address requested
+    AVR32_FAILURE_AWIRE_SET_BAUD_ERROR      = 0x1F, //! Failure setting baud   
+    AVR32_FAILURE_INVALID_DATA              = 0x20, //! Data invalid, discard it
+    AVR32_FAILURE_INVALID_PHYSICAL_MODE     = 0x21, //! Physical mode not valid  
+    AVR32_FAILURE_INVALID_CLOCK_SPEED       = 0x22, //! The clock is not valid
+    AVR32_FAILURE_AWIRE_ERROR_RESPONSE      = 0x23, //! Error response received
+    AVR32_FAILURE_AWIRE_OVERFLOW            = 0x24, //! Overflow data RX overflow
+    AVR32_FAILURE_AWM_ERROR                 = 0x24, //! aWire master error
+    AVR32_FAILURE_AWIRE_CRC                 = 0x25, //! aWire CRC error
+    AVR32_FAILURE_AWIRE_TUNE                = 0x26, //! aWire TUNE error
+    AVR32_FAILURE_JTAGM_WAS_BUSY            = 0x29, //! JTAG master busy 
+    AVR32_FAILURE_JTAGM_TIMEOUT             = 0x2A, //! JTAG master timeout
+    AVR32_FAILURE_BAD_VALUE                 = 0x2B, //! Invalid parameter value
+    AVR32_FAILURE_ERASE_ERROR               = 0x2C, //! Erase error
+    AVR32_FAILURE_CONFIG_ERROR              = 0x2D, //! Insufficient config info
+    AVR32_FAILURE_INVALID_EMULATOR_MODE     = 0x2E, //! Mode is not valid 
+    AVR32_FAILURE_CPU_DIRTY_TIMEOUT         = 0x2F, //! CPU wait timeout
+    AVR32_FAILURE_CPU_MODE                  = 0x30, //! CPU not in debug mode 
+    AVR32_FAILURE_CPU_DEBUG_MODE_TIMEOUT    = 0x31, //! CPU debug mode timeout
+    AVR32_FAILURE_AWIRE_RW_STATUS           = 0x32, //! Unexpected status
+    AVR32_FAILURE_TRANSMIT_TIMEOUT          = 0x33, //! Data TX timeout
+    AVR32_FAILURE_INTERNAL_RESPONSE_ERROR   = 0xFE, //! Near disaster
+    AVR32_FAILURE_UNKNOWN                   = 0xFF, //! Disaster
+};
+
+
+
+
+enum EdbgCommands {
+    //**********************************************************
+    // Protocol commands
+    //**********************************************************
+
+    // Basics
+    EDBG_CMD_QUERY                                      = 0x00,
+    EDBG_CMD_SET                                        = 0x01,
+    EDBG_CMD_GET                                        = 0x02,
+};
+
+enum EdbgResponses {
+    //**********************************************************
+    // Protocol responses
+    //**********************************************************
+
+    EDBG_RSP_OK                                         = 0x80,
+    EDBG_RSP_LIST                                       = 0x81,
+    EDBG_RSP_DATA                                       = 0x84,
+    EDBG_RSP_FAILED                                     = 0xA0
+};
+
+
+enum EdbgFailureCodes {
+    //**********************************************************
+    // Failure response codes (RSP_FAILED)
+    //**********************************************************
+
+    EDBG_FAILED_OK                                      = 0x00,
+    EDBG_FAILED_NOT_SUPPORTED                           = 0x01,
+    EDBG_FAILED_ILLEGAL_GPIO_PIN                        = 0x10,
+    EDBG_FAILED_ILLEGAL_GPIO_MODE                       = 0x11,
+    EDBG_FAILED_ILLEGAL_VOLTAGE_RANGE                   = 0x12,
+    EDBG_FAILED_ILLEGAL_INTERVAL                        = 0x13,
+    EDBG_FAILED_ILLEGAL_MAX_THRESHOLD                   = 0x14,
+    EDBG_FAILED_ILLEGAL_MIN_THRESHOLD                   = 0x15,
+    EDBG_FAILED_ILLEGAL_ACTION                          = 0x16,
+    EDBG_FAILED_ILLEGAL_FREQUENCY                       = 0x17,
+    EDBG_FAILED_ILLEGAL_MODE                            = 0x18,
+    EDBG_FAILED_ILLEGAL_FLAGS                           = 0x19,
+    EDBG_FAILED_FLASH_WRITE                             = 0x20,
+    EDBG_FAILED_OVERFLOW                                = 0x30,
+    EDBG_FAILED_UNKNOWN                                 = 0xFF
+};
+
+enum EdbgConfigTypes {
+    EDBG_CONFIGTYPE_CHAR                                = 0x00,
+    EDBG_CONFIGTYPE_SHORT                               = 0x01,
+    EDBG_CONFIGTYPE_WORD                                = 0x02,
+    EDBG_CONFIGTYPE_BIT                                 = 0x03,
+    EDBG_CONFIGTYPE_STRING                              = 0x10,
+    EDBG_CONFIGTYPE_ARRAY                               = 0x20,
+};
+
+enum EdbgConfigTags {
+    //**********************************************************
+    // EDBG Configuration Tags
+    //**********************************************************
+
+    EDBG_CONFIG_VERSION                                 = 0x00,
+    EDBG_CONFIG_SERIAL_NUMBER                           = 0x01,
+    EDBG_CONFIG_BOARD_NAME                              = 0x02,
+    EDBG_CONFIG_MANUFACTURER_NAME                       = 0x03,
+    EDBG_CONFIG_TARGET_NAME                             = 0x04,
+    EDBG_CONFIG_TARGET_SIGNATURE                        = 0x05,
+    EDBG_CONFIG_TARGET_JTAGID                           = 0x06,
+    EDBG_CONFIG_TARGET_CHIPID                           = 0x07,
+    EDBG_CONFIG_INTERFACES                              = 0x08,
+    EDBG_CONFIG_DGI_GPIO_MAP                            = 0x09,
+    EDBG_CONFIG_EXTENSION_MAP                           = 0x0A,
+    EDBG_CONFIG_EXTENSION_STATUS                        = 0x0B,
+    EDBG_CONFIG_EXTENSION_MANUFACTURER                  = 0x0C,
+    EDBG_CONFIG_EXTENSION_PRODUCT                       = 0x0D,
+    EDBG_CONFIG_EXTENSION_REVISION                      = 0x0E,
+    EDBG_CONFIG_EXTENSION_SERIAL                        = 0x0F,
+    EDBG_CONFIG_EXTENSION_MIN_VOLTAGE                   = 0x10,
+    EDBG_CONFIG_EXTENSION_MAX_VOLTAGE                   = 0x11,
+    EDBG_CONFIG_EXTENSION_CURRENT                       = 0x12,
+    EDBG_CONFIG_BOARD_TYPE                              = 0x13,
+    EDBG_CONFIG_FAMILY_NAME                             = 0x14,
+    EDBG_CONFIG_TVS                                     = 0x15,
+    EDBG_CONFIG_VERSION_MINOR                           = 0x16,
+    EDBG_CONFIG_USB_ID                                  = 0x17,
+    EDBG_CONFIG_KIT_DATA                                = 0x20,
+};
+
+enum EdbgInterfaces {
+    //**********************************************************
+    // EDBG Configuration Tags
+    //********************************************************** 
+    // GPIO, USART, UART, TWI, SPI, CDC
+    // SWD, ARMJTAG, AVRJTAG, aW, dW, PDI, ISP, DBG_EN
+
+    EDBG_IF_DBG_EN                                      = 15,
+    EDBG_IF_DBG_ISP                                     = 14,
+    EDBG_IF_DBG_PDI                                     = 13,
+    EDBG_IF_DBG_DW                                      = 12,
+    EDBG_IF_DBG_AW                                      = 11,
+    EDBG_IF_DBG_AVRJTAG                                 = 10,
+    EDBG_IF_DBG_ARMJTAG                                 = 9,
+    EDBG_IF_DBG_SWD                                     = 8,
+    
+    EDBG_IF_DGI_SPI                                     = 0,
+    EDBG_IF_DGI_TWI                                     = 1,
+    EDBG_IF_DGI_UART                                    = 2,
+    EDBG_IF_DGI_USART                                   = 3,
+    EDBG_IF_DGI_GPIO                                    = 4,
+    EDBG_IF_CDC                                         = 5,
+    
+    EDBG_IF_ERASE_PIN                                   = 7,
+};
+enum EDBGQueryContexts {
+    // QUERY types on this protocol
+    EDBG_QUERY_COMMANDS                                 = 0x00
+};
+    
+enum EDBGSetGetContexts {
+    EDBG_CONTEXT_CONTROL                                = 0x00,
+    EDBG_CONTEXT_CONFIG0                                = 0x10,
+    EDBG_CONTEXT_CONFIG1                                = 0x11,
+}; 
+
+enum EDBGControlContextParameters {
+    EDBG_CONTROL_LED_USAGE                              = 0x00,
+    EDBG_CONTROL_EXT_PROG                               = 0x01,
+    EDBG_CONTROL_TARGET_POWER                           = 0x10
+};
Index: pgm_type.c
===================================================================
--- pgm_type.c	(revision 1453)
+++ pgm_type.c	(working copy)
@@ -81,6 +81,7 @@
         {"jtagice3_updi", jtag3_updi_initpgm, jtag3_updi_desc},
         {"jtagice3_dw", jtag3_dw_initpgm, jtag3_dw_desc},
         {"jtagice3_isp", stk500v2_jtag3_initpgm, stk500v2_jtag3_desc},
+        {"jtagice3_avr32", jtag3_avr32_initpgm, jtag3_avr32_desc},
         {"linuxgpio", linuxgpio_initpgm, linuxgpio_desc},
         {"linuxspi", linuxspi_initpgm, linuxspi_desc},
         {"par", par_initpgm, par_desc},

@avrdudes avrdudes locked and limited conversation to collaborators Jun 24, 2023
@mcuee mcuee converted this issue into discussion #1435 Jun 24, 2023

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants