// reset system to a normal state and launch user program static inline void leaveBootloader(void) { _delay_ms(10); // removing delay causes USB errors //DBG1(0x01, 0, 0); bootLoaderExit(); cli(); USB_INTR_ENABLE = 0; USB_INTR_CFG = 0; /* also reset config bits */ // clear magic word from bottom of stack before jumping to the app *(uint8_t*)(RAMEND) = 0x00; *(uint8_t*)(RAMEND-1) = 0x00; // adjust clock to previous calibration value, so user program always starts with same calibration // as when it was uploaded originally // TODO: Test this and find out, do we need the +1 offset? unsigned char stored_osc_calibration = pgm_read_byte(BOOTLOADER_ADDRESS - TINYVECTOR_OSCCAL_OFFSET); if (stored_osc_calibration != 0xFF && stored_osc_calibration != 0x00) { //OSCCAL = stored_osc_calibration; // this should really be a gradual change, but maybe it's alright anyway? // do the gradual change - failed to score extra free bytes anyway in 1.06 while (OSCCAL > stored_osc_calibration) OSCCAL--; while (OSCCAL < stored_osc_calibration) OSCCAL++; } // jump to application reset vector at end of flash asm volatile ("rjmp __vectors - 4"); }
static void leaveBootloader( void ) { usbDeviceDisconnect(); USB_INTR_ENABLE = 0; USB_INTR_CFG = 0; // also reset config bits bootLoaderExit(); typedef void (*vector_t)( void ) __attribute__((noreturn)); vector_t user_reset = (vector_t) (USER_RESET_ADDR / 2); user_reset(); }
// reset system to a normal state and launch user program static inline __attribute__((noreturn)) void leaveBootloader(void) { //DBG1(0x01, 0, 0); bootLoaderExit(); cli(); USB_INTR_ENABLE = 0; USB_INTR_CFG = 0; /* also reset config bits */ // clear magic word from bottom of stack before jumping to the app *(uint8_t*)(RAMEND) = 0x00; *(uint8_t*)(RAMEND-1) = 0x00; // jump to application reset vector at end of flash asm volatile ("rjmp __vectors - 4"); }
static inline __attribute__((noreturn)) void leaveBootloader(void) { DBG1(0x01, 0, 0); bootLoaderExit(); cli(); USB_INTR_ENABLE = 0; USB_INTR_CFG = 0; /* also reset config bits */ #ifdef TINY85MODE // make sure remainder of flash is erased and write checksum and application reset vectors if(appWriteComplete) { CURRENT_ADDRESS = writeSize; while(CURRENT_ADDRESS < BOOTLOADER_ADDRESS) { fillFlashWithVectors(); } } #else GICR = (1 << IVCE); /* enable change of interrupt vectors */ GICR = (0 << IVSEL); /* move interrupts to application flash section */ #endif // TODO: watchdog reset instead to reset registers? #ifdef APPCHECKSUM if(!testForValidApplication()) asm volatile ("rjmp __vectors"); #endif #ifdef TINY85MODE // clear magic word from bottom of stack before jumping to the app *(uint8_t*)(RAMEND) = 0x00; *(uint8_t*)(RAMEND-1) = 0x00; // jump to application reset vector at end of flash asm volatile ("rjmp __vectors - 4"); #else /* 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 * handled correctly by the assembler. */ nullVector(); #endif }
static void leaveBootloader() { DBG1(0x01, 0, 0); bootLoaderExit(); cli(); boot_rww_enable(); USB_INTR_ENABLE = 0; USB_INTR_CFG = 0; /* also reset config bits */ #if F_CPU == 12800000 TCCR0 = 0; /* default value */ #endif 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 * handled correctly by the assembler. */ nullVector(); }