From 854f42a09f39344af49f0572ac1a4298d2ad5754 Mon Sep 17 00:00:00 2001
From: Joerg Wunsch <j@uriah.heep.sax.de>
Date: Fri, 13 Jun 2008 21:19:46 +0000
Subject: [PATCH] Contributed by Janos Sallai <janos.sallai@vanderbilt.edu>:
 patch #6074: added support for crossbow's MIB510 programmer *
 avrdude.conf.in: Add entry for mib510. * stk500.c: Add special hooks to
 handle the MIB510 programmer. It mostly talks STK500v1 protocol but has a
 special hello and goodbye sequence, and uses a fixed block size of 256 bytes.
 * doc/avrdude.texi: Document support for mib510.

git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@773 81a1dc3b-b13d-400b-aceb-764788c761c2
---
 ChangeLog        |  10 +++++
 NEWS             |   2 +
 avrdude.conf.in  |   6 +++
 doc/avrdude.texi |   2 +
 stk500.c         | 106 ++++++++++++++++++++++++++++++++++++++++++++---
 5 files changed, 121 insertions(+), 5 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 94f18b7a..d177ff10 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2008-06-13  Joerg Wunsch <j.gnu@uriah.heep.sax.de>
+
+	Contributed by Janos Sallai <janos.sallai@vanderbilt.edu>:
+	patch #6074: added support for crossbow's MIB510 programmer
+	* avrdude.conf.in: Add entry for mib510.
+	* stk500.c: Add special hooks to handle the MIB510 programmer.
+	It mostly talks STK500v1 protocol but has a special hello and
+	goodbye sequence, and uses a fixed block size of 256 bytes.
+	* doc/avrdude.texi: Document support for mib510.
+
 2008-06-07  Joerg Wunsch <j.gnu@uriah.heep.sax.de>
 
 	Contributed by Klaus Leidinger <klaus@mikrocontroller-projekte.de>:
diff --git a/NEWS b/NEWS
index d30be3a5..c429bd89 100644
--- a/NEWS
+++ b/NEWS
@@ -20,6 +20,8 @@ Current:
     programmer, to allow overriding the device code sent to the
     programmer.
 
+  * Add support for the Crossbow MIB510 programmer (patch #6074).
+
 Version 5.5:
 
   * Add support for the USBtinyISP programmer (patch #6233)
diff --git a/avrdude.conf.in b/avrdude.conf.in
index 8e3dad3d..3f78008e 100644
--- a/avrdude.conf.in
+++ b/avrdude.conf.in
@@ -350,6 +350,12 @@ programmer
   type  = stk500;
 ;
 
+programmer
+  id    = "mib510";
+  desc  = "Crossbow MIB510 programming board";
+  type  = stk500;
+;
+
 programmer
   id    = "stk500v2";
   desc  = "Atmel STK500 Version 2.x firmware";
diff --git a/doc/avrdude.texi b/doc/avrdude.texi
index 064b61dd..22b8004e 100644
--- a/doc/avrdude.texi
+++ b/doc/avrdude.texi
@@ -441,6 +441,8 @@ Atmel JTAG ICE mkII in debugWire mode.
 Atmel JTAG ICE mkI, running at 115200 Bd
 @item @code{jtagmkII}    @tab
 Atmel JTAG ICE mkII (default speed 19200 Bd)
+@item @code{mib510}      @tab
+Crossbow MIB510 programming board
 @item @code{pavr}        @tab
 Jason Kyle's pAVR Serial Programmer
 @item @code{picoweb}     @tab
diff --git a/stk500.c b/stk500.c
index dfe04d7a..4481ce46 100644
--- a/stk500.c
+++ b/stk500.c
@@ -1,6 +1,7 @@
 /*
  * avrdude - A Downloader/Uploader for AVR device programmers
  * Copyright (C) 2002-2004 Brian S. Dean <bsd@bsdhome.com>
+ * Copyright (C) 2008 Joerg Wunsch
  *
  * 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
@@ -330,6 +331,77 @@ static int stk500_set_extended_parms(PROGRAMMER * pgm, int n,
   return -1;
 }
 
+/*
+ * Crossbow MIB510 initialization and shutdown.  Use cmd = 1 to
+ * initialize, cmd = 0 to close.
+ */
+static int mib510_isp(PROGRAMMER * pgm, unsigned char cmd)
+{
+  unsigned char buf[9];
+  int tries = 0;
+
+  buf[0] = 0xaa;
+  buf[1] = 0x55;
+  buf[2] = 0x55;
+  buf[3] = 0xaa;
+  buf[4] = 0x17;
+  buf[5] = 0x51;
+  buf[6] = 0x31;
+  buf[7] = 0x13;
+  buf[8] = cmd;
+
+
+ retry:
+
+  tries++;
+
+  stk500_send(pgm, buf, 9);
+  if (stk500_recv(pgm, buf, 1) < 0)
+    exit(1);
+  if (buf[0] == Resp_STK_NOSYNC) {
+    if (tries > 33) {
+      fprintf(stderr, "%s: mib510_isp(): can't get into sync\n",
+              progname);
+      return -1;
+    }
+    if (stk500_getsync(pgm) < 0)
+      return -1;
+    goto retry;
+  }
+  else if (buf[0] != Resp_STK_INSYNC) {
+    fprintf(stderr,
+            "%s: mib510_isp(): protocol error, "
+            "expect=0x%02x, resp=0x%02x\n",
+            progname, Resp_STK_INSYNC, buf[0]);
+    return -1;
+  }
+
+  if (stk500_recv(pgm, buf, 1) < 0)
+    exit(1);
+  if (buf[0] == Resp_STK_OK) {
+    return 0;
+  }
+  else if (buf[0] == Resp_STK_NODEVICE) {
+    fprintf(stderr, "%s: mib510_isp(): no device\n",
+            progname);
+    return -1;
+  }
+
+  if (buf[0] == Resp_STK_FAILED)
+  {
+      fprintf(stderr,
+          "%s: mib510_isp(): command %d failed\n",
+              progname, cmd);
+      return -1;
+  }
+
+
+  fprintf(stderr, "%s: mib510_isp(): unknown response=0x%02x\n",
+          progname, buf[0]);
+
+  return -1;
+}
+
 
 /*
  * initialize the AVR device and prepare it to accept commands
@@ -341,13 +413,18 @@ static int stk500_initialize(PROGRAMMER * pgm, AVRPART * p)
   int tries;
   unsigned maj, min;
   int rc;
-  int n_extparms = 3;
+  int n_extparms;
 
   stk500_getparm(pgm, Parm_STK_SW_MAJOR, &maj);
   stk500_getparm(pgm, Parm_STK_SW_MINOR, &min);
 
-  if ((maj > 1) || ((maj == 1) && (min > 10)))
+  // MIB510 does not need extparams
+  if (strcmp(ldata(lfirst(pgm->id)), "mib510") == 0)
+    n_extparms = 0;
+  else if ((maj > 1) || ((maj == 1) && (min > 10)))
     n_extparms = 4;
+  else
+    n_extparms = 3;
 
   tries = 0;
 
@@ -588,6 +665,11 @@ static int stk500_open(PROGRAMMER * pgm, char * port)
    */
   stk500_drain(pgm, 0);
 
+  // MIB510 init
+  if (strcmp(ldata(lfirst(pgm->id)), "mib510") == 0 &&
+      mib510_isp(pgm, 1) != 0)
+    return -1;
+
   if (stk500_getsync(pgm) < 0)
     return -1;
 
@@ -597,6 +679,10 @@ static int stk500_open(PROGRAMMER * pgm, char * port)
 
 static void stk500_close(PROGRAMMER * pgm)
 {
+  // MIB510 close
+  if (strcmp(ldata(lfirst(pgm->id)), "mib510") == 0)
+    (void)mib510_isp(pgm, 0);
+
   serial_close(&pgm->fd);
   pgm->fd.ifd = -1;
 }
@@ -666,7 +752,13 @@ static int stk500_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
   int flash;
 
   if (page_size == 0) {
-    page_size = 128;
+    // MIB510 uses page size of 256 bytes
+    if (strcmp(ldata(lfirst(pgm->id)), "mib510") == 0) {
+      page_size = 256;
+    }
+    else {
+      page_size = 128;
+    }
   }
 
   if (strcmp(m->desc, "flash") == 0) {
@@ -711,7 +803,9 @@ static int stk500_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
   for (addr = 0; addr < n; addr += page_size) {
     report_progress (addr, n_bytes, NULL);
     
-	if (addr + page_size > n_bytes) {
+    // MIB510 uses fixed blocks size of 256 bytes
+    if ((strcmp(ldata(lfirst(pgm->id)), "mib510") != 0) &&
+	(addr + page_size > n_bytes)) {
 	   block_size = n_bytes % page_size;
 	}
 	else {
@@ -832,7 +926,9 @@ static int stk500_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
   for (addr = 0; addr < n; addr += page_size) {
     report_progress (addr, n_bytes, NULL);
 
-	if (addr + page_size > n_bytes) {
+    // MIB510 uses fixed blocks size of 256 bytes
+    if ((strcmp(ldata(lfirst(pgm->id)), "mib510") != 0) &&
+	(addr + page_size > n_bytes)) {
 	   block_size = n_bytes % page_size;
 	}
 	else {