A physical pin state is not the only way to make the device enter the bootloader; often it is necessary for the application to trigger a bootloader update. The example below shows a function that checks for a value in User Row or EEPROM to trigger an update:
static bool is_boot_requested(void) { /* Check for boot request from firmware */ if (USERROW.USERROW31 == 0xEB) { /* Clear boot request*/ USERROW.USERROW31 = 0xff; _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_PAGEERASEWRITE_gc); while(NVMCTRL.STATUS & NVMCTRL_EEBUSY_bm); } /* Check if SW1 (PC5) is low */ else if(VPORTC.IN & PIN5_bm) { return false; } return true; }
To enter Boot mode without pulling the pin low, byte 31 in User Row will need to be programmed either by the application or a programmer. The example below shows how to write the needed value and reset the device:
void enter_bootloader(void) { /* Write boot request */ USERROW.USERROW31 = 0xEB; _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_PAGEERASEWRITE_gc); while(NVMCTRL.STATUS & NVMCTRL_EEBUSY_bm); /* Issue system reset */ _PROTECTED_WRITE(RSTCTRL.SWRR, RSTCTRL_SWRE_bm); }
Together these two functions make it possible to enter Bootloader mode without needing power cycling and a physical pin.