int __attribute__((noreturn)) main(void) { uint16_t idlePolls = 0; /* initialize */ wdt_disable(); /* main app may have enabled watchdog */ tiny85FlashInit(); bootLoaderInit(); if (bootLoaderCondition()) { initForUsbConnectivity(); do { usbPoll(); _delay_us(100); idlePolls++; if (events) idlePolls = 0; // these next two freeze the chip for ~ 4.5ms, breaking usb protocol // and usually both of these will activate in the same loop, so host // needs to wait > 9ms before next usb request if (isEvent(EVENT_ERASE_APPLICATION)) eraseApplication(); if (isEvent(EVENT_WRITE_PAGE)) tiny85FlashWrites(); if (isEvent(EVENT_FINISH)) { // || AUTO_EXIT_CONDITION()) { tiny85FinishWriting(); # if BOOTLOADER_CAN_EXIT _delay_ms(10); // removing delay causes USB errors break; # endif } // # if BOOTLOADER_CAN_EXIT // // exit if requested by the programming app, or if we timeout waiting for the pc with a valid app // if (isEvent(EVENT_EXIT_BOOTLOADER) || AUTO_EXIT_CONDITION()) { // //_delay_ms(10); // break; // } // # endif clearEvents(); } while(bootLoaderCondition()); /* main event loop */ } leaveBootloader(); }
static inline void tiny85FlashInit(void) { // check for erased first page (no bootloader interrupt vectors), add vectors if missing if(pgm_read_word(RESET_VECTOR_OFFSET * 2) != 0xC000 + (BOOTLOADER_ADDRESS/2) - 1 || pgm_read_word(USBPLUS_VECTOR_OFFSET * 2) != 0xC000 + (BOOTLOADER_ADDRESS/2) - 1) { // TODO: actually need to erase here? how could we end up with missing vectors but application data higher up? # if HAVE_CHIP_ERASE eraseApplication(); # else fillFlashWithVectors(); # endif } // TODO: necessary to reset CURRENT_ADDRESS? CURRENT_ADDRESS = 0; # ifdef APPCHECKSUM checksum = 0; # endif }
static inline void tiny85FlashWrites(void) { #if HAVE_CHIP_ERASE if(eraseRequested) { _delay_ms(2); cli(); eraseApplication(); sei(); #ifdef APPCHECKSUM checksum = 0; #endif eraseRequested = 0; } #endif if(flashPageLoaded) { _delay_ms(2); // write page to flash, interrupts will be disabled for several milliseconds cli(); if(CURRENT_ADDRESS % SPM_PAGESIZE) fillFlashWithVectors(); else writeFlashPage(); sei(); flashPageLoaded = 0; if(isLastPage) { // store number of bytes written so rest of flash can be filled later writeSize = CURRENT_ADDRESS; appWriteComplete = 1; } } }
int main(void) { /* initialize */ #ifdef RESTORE_OSCCAL uint8_t osccal_default = OSCCAL; #endif #if (!SET_CLOCK_PRESCALER) && LOW_POWER_MODE uint8_t prescaler_default = CLKPR; #endif wdt_disable(); /* main app may have enabled watchdog */ tiny85FlashInit(); bootLoaderInit(); if (bootLoaderStartCondition()) { #if LOW_POWER_MODE // turn off clock prescalling - chip must run at full speed for usb // if you might run chip at lower voltages, detect that in bootLoaderStartCondition CLKPR = 1 << CLKPCE; CLKPR = 0; #endif initForUsbConnectivity(); do { usbPoll(); _delay_us(100); idlePolls++; // these next two freeze the chip for ~ 4.5ms, breaking usb protocol // and usually both of these will activate in the same loop, so host // needs to wait > 9ms before next usb request if (isEvent(EVENT_ERASE_APPLICATION)) eraseApplication(); if (isEvent(EVENT_WRITE_PAGE)) tiny85FlashWrites(); # if BOOTLOADER_CAN_EXIT if (isEvent(EVENT_EXECUTE)) { // when host requests device run uploaded program break; } # endif clearEvents(); } while(bootLoaderCondition()); /* main event loop runs so long as bootLoaderCondition remains truthy */ } // set clock prescaler to desired clock speed (changing from clkdiv8, or no division, depending on fuses) #if LOW_POWER_MODE #ifdef SET_CLOCK_PRESCALER CLKPR = 1 << CLKPCE; CLKPR = SET_CLOCK_PRESCALER; #else CLKPR = 1 << CLKPCE; CLKPR = prescaler_default; #endif #endif // slowly bring down OSCCAL to it's original value before launching in to user program #ifdef RESTORE_OSCCAL while (OSCCAL > osccal_default) { OSCCAL -= 1; } #endif leaveBootloader(); }