ATmega2560 passed extensive testing (20MHz)
[pub/USBaspLoader.git] / firmware / main.c
index 91127ef..e40c0b5 100644 (file)
@@ -3,11 +3,10 @@
  * Author: Christian Starkjohann
  * Author: Stephan Baerwolf
  * Creation Date: 2007-12-08
- * Modification Date: 2012-11-10
+ * Modification Date: 2013-03-31
  * Tabsize: 4
  * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
  * License: GNU GPL v2 (see License.txt)
- * This Revision: $Id: main.c 786 2010-05-30 20:41:40Z cs $
  */
 
 #include "spminterface.h"  /* must be included as first! */
@@ -131,6 +130,8 @@ static const uchar  signatureBytes[4] = {
     SIGNATURE_BYTES
 #elif defined (__AVR_ATmega8__) || defined (__AVR_ATmega8A__) || defined (__AVR_ATmega8HVA__)
     0x1e, 0x93, 0x07, 0
+#elif defined (__AVR_ATmega16__)
+    0x1e, 0x94, 0x03, 0
 #elif defined (__AVR_ATmega32__)
     0x1e, 0x95, 0x02, 0
 #elif defined (__AVR_ATmega48__) || defined (__AVR_ATmega48A__) || defined (__AVR_ATmega48P__)
@@ -161,18 +162,33 @@ static const uchar  signatureBytes[4] = {
     0x1e, 0x95, 0x14, 0
 #elif defined (__AVR_ATmega328P__)
     0x1e, 0x95, 0x0f, 0
+#elif defined (__AVR_ATmega640__)
+    0x1e, 0x96, 0x08, 0
 #elif defined (__AVR_ATmega644__) || defined (__AVR_ATmega644A__)
     0x1e, 0x96, 0x09, 0
 #elif defined (__AVR_ATmega644P__) || defined (__AVR_ATmega644PA__)
     0x1e, 0x96, 0x0a, 0
 #elif defined (__AVR_ATmega128__)
     0x1e, 0x97, 0x02, 0
+#elif defined (__AVR_ATmega1280__)
+    0x1e, 0x97, 0x03, 0
+#elif defined (__AVR_ATmega1281__)
+    0x1e, 0x97, 0x04, 0
 #elif defined (__AVR_ATmega1284__)
     0x1e, 0x97, 0x06, 0
 #elif defined (__AVR_ATmega1284P__)
     0x1e, 0x97, 0x05, 0
+#elif defined (__AVR_ATmega2560__)
+    0x1e, 0x98, 0x01, 0
+#elif defined (__AVR_ATmega2561__)
+    0x1e, 0x98, 0x02, 0
 #else
-#   error "Device signature is not known, please edit main.c!"
+#   if (defined(SIGNATURE_0) && defined(SIGNATURE_1) && defined(SIGNATURE_2))
+#     warning "Device signature is not known - using AVR Libc suggestion..."
+    SIGNATURE_0, SIGNATURE_1, SIGNATURE_2, 0
+#   else
+#     error "Device signature is not known, please edit main.c!"
+#   endif
 #endif
 };
 
@@ -243,7 +259,16 @@ asm  volatile  (
     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 */
-    
+
+/*
+ * There seems to be another funny compiler Bug.
+ * When gcc is using "eicall" opcode it forgets to modify EIND.
+ * On devices with large flash memory there are some target address bits
+ * missing. In this case some zero bits...
+ */
+#if (defined(EIND) && ((FLASHEND)>131071))
+  EIND=0;
+#endif
 /* 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
@@ -266,7 +291,7 @@ uchar usbFunctionSetup_USBASP_FUNC_TRANSMIT(usbRequest_t *rq) {
     rval = rq->wIndex.bytes[0] & 3;
     rval = signatureBytes[rval];
 #if HAVE_READ_LOCK_FUSE
-#if defined (__AVR_ATmega8__) || defined (__AVR_ATmega8A__) || defined (__AVR_ATmega32__)
+#if defined (__AVR_ATmega8__) || defined (__AVR_ATmega8A__) || defined (__AVR_ATmega16__) || defined (__AVR_ATmega32__)
   }else if(rq->wValue.bytes[0] == 0x58 && rq->wValue.bytes[1] == 0x00){  /* read lock bits */
       rval = boot_lock_fuse_bits_get(GET_LOCK_BITS);
   }else if(rq->wValue.bytes[0] == 0x50 && rq->wValue.bytes[1] == 0x00){  /* read lfuse bits */
@@ -280,9 +305,14 @@ defined (__AVR_ATmega164A__) || defined (__AVR_ATmega164P__)  ||                                                                 \
 defined (__AVR_ATmega168__)  || defined (__AVR_ATmega168A__)  || defined (__AVR_ATmega168P__)  || defined (__AVR_ATmega168PA__) ||  \
 defined (__AVR_ATmega324A__) || defined (__AVR_ATmega324P__)  ||                                                                     \
 defined (__AVR_ATmega328__)  || defined (__AVR_ATmega328P__)  ||                                                                     \
+defined (__AVR_ATmega640__)  ||                                                                                                        \
 defined (__AVR_ATmega644__)  || defined (__AVR_ATmega644A__)  || defined (__AVR_ATmega644P__) || defined (__AVR_ATmega644PA__)  ||  \
 defined (__AVR_ATmega128__)  ||                                                                                                              \
-defined (__AVR_ATmega1284__) || defined (__AVR_ATmega1284P__)
+defined (__AVR_ATmega1280__) ||                                                                                                        \
+defined (__AVR_ATmega1281__) ||                                                                                                        \
+defined (__AVR_ATmega1284__) || defined (__AVR_ATmega1284P__)  ||                                                                                                      \
+defined (__AVR_ATmega2560__) ||                                                                                                        \
+defined (__AVR_ATmega2561__)
   }else if(rq->wValue.bytes[0] == 0x58 && rq->wValue.bytes[1] == 0x00){  /* read lock bits */
       rval = boot_lock_fuse_bits_get(GET_LOCK_BITS);
   }else if(rq->wValue.bytes[0] == 0x50 && rq->wValue.bytes[1] == 0x00){  /* read lfuse bits */
@@ -347,7 +377,7 @@ usbRequest_t    *rq = (void *)data;
 uchar           len = 0;
 static uchar    replyBuffer[4];
 
-    usbMsgPtr = replyBuffer;
+    usbMsgPtr = (usbMsgPtr_t)replyBuffer;
     if(rq->bRequest == USBASP_FUNC_TRANSMIT){   /* emulate parts of ISP protocol */
         replyBuffer[3] = usbFunctionSetup_USBASP_FUNC_TRANSMIT(rq);
         len = 4;
@@ -622,6 +652,15 @@ int __attribute__((__noreturn__)) main(void)
 #endif
     if(bootLoaderCondition()){
 #if NEED_WATCHDOG
+#      if (defined(MCUSR) && defined(WDRF))
+       /* 
+        * Fix issue 6: (special thanks to coldtobi)
+        * 
+        * The WDRF bit in the MCUSR needs to be cleared first,
+        * otherwise it is not possible to disable the watchdog
+        */
+       MCUSR &= ~(_BV(WDRF));
+#      endif
        wdt_disable();    /* main app may have enabled watchdog */
 #endif
         initForUsbConnectivity();