USBaspLoader v0.97 stable release
[pub/USBaspLoader.git] / firmware / main.c
index 038368c..fccec56 100644 (file)
@@ -11,7 +11,8 @@
 
 #include "spminterface.h"  /* must be included as first! */
 
-#include <avr/io.h>
+#include "../misc/iofixes.h"
+
 #include <avr/interrupt.h>
 #include <avr/pgmspace.h>
 #include <avr/wdt.h>
@@ -124,12 +125,13 @@ static volatile uint8_t timeout_remaining;
 static volatile uint16_t timeout_remaining;
 #              endif
 #      endif
+
+#      define stayinloader_initialValue 0xfe
 #      if ((HAVE_UNPRECISEWAIT))
 /* here we have to assume we need to optimize for every byte */
-#define __REGISTER_stayinloader_initialValue 0xfe
 volatile register uint8_t stayinloader __asm__("r17");
 #      else
-static volatile uint8_t stayinloader = 0xfe;
+static volatile uint8_t stayinloader;
 #      endif
 #endif
 
@@ -163,6 +165,8 @@ static const uchar  signatureBytes[4] = {
     0x1e, 0x93, 0x0a, 0
 #elif defined (__AVR_ATmega88PA__)
     0x1e, 0x93, 0x0F, 0
+#elif defined (__AVR_ATmega162__)
+    0x1e, 0x94, 0x04, 0
 #elif defined (__AVR_ATmega164A__)
     0x1e, 0x94, 0x0f, 0
 #elif defined (__AVR_ATmega164P__) || defined (__AVR_ATmega164PA__)
@@ -213,18 +217,6 @@ static const uchar  signatureBytes[4] = {
 
 /* ------------------------------------------------------------------------ */
 
-#if (__REGISTER_stayinloader_initialValue)
-/* need to put it after libc init - otherwise it fucks up the register */
-void __attribute__ ((section(".init8"),naked,used,no_instrument_function)) __REGISTER_stayinloader_initialValue_INITIALIZATION(void);
-void __REGISTER_stayinloader_initialValue_INITIALIZATION(void) {
-  asm volatile (
-    "ldi       %[silreg]       ,       %[silval]\n\t"
-    : [silreg]         "=a" (stayinloader)
-    : [silval]         "M"  (__REGISTER_stayinloader_initialValue)
-  );
-}
-#endif
-
 #if (HAVE_BOOTLOADERENTRY_FROMSOFTWARE)
 void __attribute__ ((section(".init3"),naked,used,no_instrument_function)) __BOOTLOADERENTRY_FROMSOFTWARE__bootup_investigate_RAMEND(void);
 void __BOOTLOADERENTRY_FROMSOFTWARE__bootup_investigate_RAMEND(void) {
@@ -374,6 +366,7 @@ uchar usbFunctionSetup_USBASP_FUNC_TRANSMIT(usbRequest_t *rq) {
 
 #elif defined (__AVR_ATmega48__)   || defined (__AVR_ATmega48A__)   || defined (__AVR_ATmega48P__)   || defined (__AVR_ATmega48PA__)  ||  \
 defined (__AVR_ATmega88__)   || defined (__AVR_ATmega88A__)   || defined (__AVR_ATmega88P__)   || defined (__AVR_ATmega88PA__)  ||  \
+defined (__AVR_ATmega162__)  ||                                                                                                      \
 defined (__AVR_ATmega164A__) || defined (__AVR_ATmega164P__)  ||                                                                     \
 defined (__AVR_ATmega168__)  || defined (__AVR_ATmega168A__)  || defined (__AVR_ATmega168P__)  || defined (__AVR_ATmega168PA__) ||  \
 defined (__AVR_ATmega324A__) || defined (__AVR_ATmega324P__)  ||                                                                     \
@@ -702,32 +695,35 @@ uchar   i;
 
 /* ------------------------------------------------------------------------ */
 
-static void initForUsbConnectivity(void)
-{
-#if HAVE_UNPRECISEWAIT
-    /* (0.25s*F_CPU)/(4 cycles per loop) ~ (65536*waitloopcnt)
-     * F_CPU/(16*65536) ~ waitloopcnt
-     * F_CPU / 1048576 ~ waitloopcnt
-     */
-    uint8_t waitloopcnt = 1 + (F_CPU/1048576);
-#endif
-    usbInit();
-    /* enforce USB re-enumerate: */
-    usbDeviceDisconnect();  /* do this while interrupts are disabled */
 #if HAVE_UNPRECISEWAIT
+static void _mywait(uint8_t waitloopcnt) {
     asm volatile (
       /*we really don't care what value Z has...
        * ...if we loop 65536/F_CPU more or less...
        * ...unimportant - just save some opcodes
        */
-"initForUsbConnectivity_sleeploop:                     \n\t"
+"_mywait_sleeploop%=:                                  \n\t"
       "sbiw    r30,    1                               \n\t"
       "sbci    %0,     0                               \n\t"
-      "brne    initForUsbConnectivity_sleeploop        \n\t"
+      "brne    _mywait_sleeploop%=                     \n\t"
       : "+d" (waitloopcnt)
       :
       : "r30","r31"
     );
+}
+#endif
+
+static void initForUsbConnectivity(void)
+{
+    usbInit();
+    /* enforce USB re-enumerate: */
+    usbDeviceDisconnect();  /* do this while interrupts are disabled */
+#if HAVE_UNPRECISEWAIT
+    /* (0.25s*F_CPU)/(4 cycles per loop) ~ (65536*waitloopcnt)
+     * F_CPU/(16*65536) ~ waitloopcnt
+     * F_CPU / 1048576 ~ waitloopcnt
+     */
+    _mywait(1 + (F_CPU/1048576));
 #else
     _delay_ms(260);         /* fake USB disconnect for > 250 ms */
 #endif
@@ -749,7 +745,39 @@ int __attribute__((__noreturn__)) main(void)
     GICR = (1 << IVCE);  /* enable change of interrupt vectors */
     GICR = (1 << IVSEL); /* move interrupts to boot flash section */
 #endif
+#if (HAVE_BOOTLOADER_ADDITIONALMSDEVICEWAIT>0)    
+#      if HAVE_UNPRECISEWAIT
+    _mywait(1+((HAVE_BOOTLOADER_ADDITIONALMSDEVICEWAIT*F_CPU)/262144000));
+#      else
+    _delay_ms(HAVE_BOOTLOADER_ADDITIONALMSDEVICEWAIT);
+#      endif
+#endif
     if(bootLoaderCondition()){
+#if (BOOTLOADER_CAN_EXIT)
+#      if (USE_EXCESSIVE_ASSEMBLER)
+asm  volatile  (
+  "ldi         %[sil],         %[normval]\n\t"
+#              if ((defined(CONFIG_HAVE__BOOTLOADER_ABORTTIMEOUTONACT)) && (!(BOOTLOADER_IGNOREPROGBUTTON)) && (BOOTLOADER_LOOPCYCLES_TIMEOUT))
+  "sbis                %[pin],         %[bit]\n\t"
+  "subi                %[sil],         0x02\n\t"
+#              endif
+  : [sil]        "=d" (stayinloader)
+  : [normval]     "M" (stayinloader_initialValue)
+#              if (!(BOOTLOADER_IGNOREPROGBUTTON))
+                                                    ,
+    [pin]         "I" (_SFR_IO_ADDR(PIN_PIN(JUMPER_PORT))),
+    [bit]         "I" (PIN(JUMPER_PORT, JUMPER_BIT))
+#              endif    
+);
+#      else
+#              if ((defined(CONFIG_HAVE__BOOTLOADER_ABORTTIMEOUTONACT)) && (!(BOOTLOADER_IGNOREPROGBUTTON)) && (BOOTLOADER_LOOPCYCLES_TIMEOUT))
+      if (bootLoaderConditionSimple()) {
+       stayinloader = stayinloader_initialValue - 0x02;
+      } else
+#              endif
+             stayinloader = stayinloader_initialValue;
+#      endif
+#endif
 #if NEED_WATCHDOG
 #      if (defined(MCUSR) && defined(WDRF))
        /*