smpinterface fix: missing rampZ-write for atmega1284p
[pub/USBaspLoader.git] / firmware / main.c
index 5e38af5..fd5dd48 100644 (file)
@@ -8,6 +8,8 @@
  * This Revision: $Id: main.c 786 2010-05-30 20:41:40Z cs $
  */
 
+#include "spminterface.h"  /* must be included as first! */
+
 #include <avr/io.h>
 #include <avr/interrupt.h>
 #include <avr/pgmspace.h>
@@ -18,6 +20,8 @@
 
 #include <avr/cpufunc.h>
 
+#include <avr/boot.h>
+
 #include <string.h>
 
 
@@ -44,6 +48,15 @@ static void leaveBootloader() __attribute__((__noreturn__));
 #define USBASP_FUNC_WRITEEEPROM     8
 #define USBASP_FUNC_SETLONGADDRESS  9
 
+// additional USBasp Commands
+#define USBASP_FUNC_SETISPSCK       10
+#define USBASP_FUNC_TPI_CONNECT      11
+#define USBASP_FUNC_TPI_DISCONNECT   12
+#define USBASP_FUNC_TPI_RAWREAD      13
+#define USBASP_FUNC_TPI_RAWWRITE     14
+#define USBASP_FUNC_TPI_READBLOCK    15
+#define USBASP_FUNC_TPI_WRITEBLOCK   16
+#define USBASP_FUNC_GETCAPABILITIES 127
 /* ------------------------------------------------------------------------ */
 
 #ifndef ulong
@@ -95,11 +108,10 @@ typedef union longConverter{
 }longConverter_t;
 
 
-
 #if BOOTLOADER_CAN_EXIT
 static uchar                   requestBootLoaderExit;
 #endif
-static volatile unsigned char  stayinloader = 1;
+static volatile unsigned char  stayinloader = 0xfe;
 
 static longConverter_t         currentAddress; /* in bytes */
 static uchar                   bytesRemaining;
@@ -123,6 +135,8 @@ static const uchar  signatureBytes[4] = {
     0x1e, 0x94, 0x06, 0
 #elif defined (__AVR_ATmega328P__)
     0x1e, 0x95, 0x0f, 0
+#elif defined (__AVR_ATmega1284P__)
+    0x1e, 0x97, 0x05, 0
 #else
 #   error "Device signature is not known, please edit main.c!"
 #endif
@@ -142,6 +156,7 @@ static void leaveBootloader()
     USB_INTR_CFG = 0;       /* also reset config bits */
     GICR = (1 << IVCE);     /* enable change of interrupt vectors */
     GICR = (0 << IVSEL);    /* move interrupts to application flash section */
+    
 /* We must go through a global function pointer variable instead of writing
  *  ((void (*)(void))0)();
  * because the compiler optimizes a constant 0 to "rcall 0" which is not
@@ -202,7 +217,7 @@ static uchar    replyBuffer[4];
         }
         replyBuffer[3] = rval;
         len = 4;
-    }else if(rq->bRequest == USBASP_FUNC_ENABLEPROG){
+    }else if((rq->bRequest == USBASP_FUNC_ENABLEPROG) || (rq->bRequest == USBASP_FUNC_SETISPSCK)){
         /* replyBuffer[0] = 0; is never touched and thus always 0 which means success */
         len = 1;
     }else if(rq->bRequest >= USBASP_FUNC_READFLASH && rq->bRequest <= USBASP_FUNC_SETLONGADDRESS){
@@ -222,14 +237,13 @@ static uchar    replyBuffer[4];
         }
 
     }else if(rq->bRequest == USBASP_FUNC_DISCONNECT){
-      stayinloader        &= (0x7f);
+      stayinloader        &= (0xfe);
 #if BOOTLOADER_CAN_EXIT
       requestBootLoaderExit = 1;      /* allow proper shutdown/close of connection */
 #endif
-    }else if(rq->bRequest == USBASP_FUNC_CONNECT){
-      stayinloader        |= (0x80);
     }else{
-        /* ignore: others */
+        /* ignore: others, but could be USBASP_FUNC_CONNECT */
+       stayinloader       |= (0x01);
     }
     return len;
 }
@@ -251,43 +265,31 @@ uchar   isLast;
     }else{
         uchar i;
         for(i = 0; i < len;){
-#if !HAVE_CHIP_ERASE
-            if((currentAddress.w[0] & (SPM_PAGESIZE - 1)) == 0){    /* if page start: erase */
-                DBG1(0x33, 0, 0);
-#   ifndef NO_FLASH_WRITE
-#      if HAVE_BLB11_SOFTW_LOCKBIT
-               if (CURRENT_ADDRESS < (addr_t)(BOOTLOADER_ADDRESS)) {
-#      endif
-                cli();
-                boot_page_erase(CURRENT_ADDRESS);   /* erase page */
-                sei();
-                boot_spm_busy_wait();               /* wait until page is erased */
-#      if HAVE_BLB11_SOFTW_LOCKBIT
-               }
-#      endif           
-#   endif
-            }
+#if HAVE_BLB11_SOFTW_LOCKBIT
+           if (CURRENT_ADDRESS >= (addr_t)(BOOTLOADER_ADDRESS)) {
+             return 1;
+           }
 #endif
             i += 2;
             DBG1(0x32, 0, 0);
-#      if HAVE_BLB11_SOFTW_LOCKBIT
-           if (CURRENT_ADDRESS < (addr_t)(BOOTLOADER_ADDRESS)) {
-#      endif
             cli();
             boot_page_fill(CURRENT_ADDRESS, *(short *)data);
             sei();
-#      if HAVE_BLB11_SOFTW_LOCKBIT
-           }
-#      endif
             CURRENT_ADDRESS += 2;
             data += 2;
             /* write page when we cross page boundary or we have the last partial page */
             if((currentAddress.w[0] & (SPM_PAGESIZE - 1)) == 0 || (isLast && i >= len && isLastPage)){
+#if !HAVE_CHIP_ERASE
+                DBG1(0x33, 0, 0);
+#   ifndef NO_FLASH_WRITE
+                cli();
+                boot_page_erase(CURRENT_ADDRESS - 2);   /* erase page */
+                sei();
+                boot_spm_busy_wait();                   /* wait until page is erased */
+#   endif
+#endif
                 DBG1(0x34, 0, 0);
 #ifndef NO_FLASH_WRITE
-#      if HAVE_BLB11_SOFTW_LOCKBIT
-               if ((CURRENT_ADDRESS - (addr_t)2) < (addr_t)(BOOTLOADER_ADDRESS)) {
-#      endif
                 cli();
                 boot_page_write(CURRENT_ADDRESS - 2);
                 sei();
@@ -295,9 +297,6 @@ uchar   isLast;
                 cli();
                 boot_rww_enable();
                 sei();
-#      if HAVE_BLB11_SOFTW_LOCKBIT
-               }
-#      endif
 #endif
             }
         }
@@ -335,7 +334,6 @@ uchar   i = 0;
     /* enforce USB re-enumerate: */
     usbDeviceDisconnect();  /* do this while interrupts are disabled */
     while(--i){         /* fake USB disconnect for > 250 ms */
-        wdt_reset();
         _delay_ms(1);
     }
     usbDeviceConnect();
@@ -345,7 +343,6 @@ uchar   i = 0;
 int __attribute__((noreturn)) main(void)
 {
     /* initialize  */
-    wdt_disable();      /* main app may have enabled watchdog */
     bootLoaderInit();
     odDebugInit();
     DBG1(0x00, 0, 0);
@@ -354,6 +351,7 @@ int __attribute__((noreturn)) main(void)
     GICR = (1 << IVSEL); /* move interrupts to boot flash section */
 #endif
     if(bootLoaderCondition()){
+       wdt_disable();    /* main app may have enabled watchdog */
 #if BOOTLOADER_CAN_EXIT
         uchar i = 0, j = 0;
 #endif
@@ -368,13 +366,13 @@ int __attribute__((noreturn)) main(void)
                 }
             }
 #endif
-       if (stayinloader & 0x1) {
+       if (stayinloader >= 0x10) {
          if (!bootLoaderCondition()) {
-           stayinloader = (stayinloader & 0xfc) | 0x2;
+           stayinloader-=0x10;
          } 
        } else {
          if (bootLoaderCondition()) {
-           stayinloader &= 0xfc;
+           if (stayinloader > 1) stayinloader-=2;
          }
        }