#include "BootloaderHID.h"
static bool RunBootloader = true;
uint16_t MagicBootKey ATTR_NO_INIT;
void Application_Jump_Check(void)
{
if ((MCUSR & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY))
{
MCUSR &= ~(1 << WDRF);
wdt_disable();
MagicBootKey = 0;
((void (*)(void))0x0000)();
}
}
int main(void)
{
SetupHardware();
GlobalInterruptEnable();
while (RunBootloader)
USB_USBTask();
_delay_us(1000);
USB_Detach();
MagicBootKey = MAGIC_BOOT_KEY;
wdt_enable(WDTO_250MS);
for (;;);
}
static void SetupHardware(void)
{
MCUSR &= ~(1 << WDRF);
wdt_disable();
clock_prescale_set(clock_div_1);
MCUCR = (1 << IVCE);
MCUCR = (1 << IVSEL);
USB_Init();
}
void EVENT_USB_Device_ConfigurationChanged(void)
{
Endpoint_ConfigureEndpoint(HID_IN_EPADDR, EP_TYPE_INTERRUPT, HID_IN_EPSIZE, 1);
}
void EVENT_USB_Device_ControlRequest(void)
{
if ((USB_ControlRequest.bmRequestType & (CONTROL_REQTYPE_TYPE | CONTROL_REQTYPE_RECIPIENT)) !=
(REQTYPE_CLASS | REQREC_INTERFACE))
{
return;
}
switch (USB_ControlRequest.bRequest)
{
case HID_REQ_SetReport:
Endpoint_ClearSETUP();
while (!(Endpoint_IsOUTReceived()));
#if (FLASHEND > 0xFFFF)
uint32_t PageAddress = ((uint32_t)Endpoint_Read_16_LE() << 8);
#else
uint16_t PageAddress = Endpoint_Read_16_LE();
#endif
bool PageAddressIsAligned = !(PageAddress & (SPM_PAGESIZE - 1));
#if (FLASHEND > 0xFFFF)
if ((uint16_t)(PageAddress >> 8) == COMMAND_STARTAPPLICATION)
#else
if (PageAddress == COMMAND_STARTAPPLICATION)
#endif
{
RunBootloader = false;
}
else if ((PageAddress < BOOT_START_ADDR) && PageAddressIsAligned)
{
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
boot_page_erase(PageAddress);
boot_spm_busy_wait();
}
for (uint8_t PageWord = 0; PageWord < (SPM_PAGESIZE / 2); PageWord++)
{
if (!(Endpoint_BytesInEndpoint()))
{
Endpoint_ClearOUT();
while (!(Endpoint_IsOUTReceived()));
}
boot_page_fill(PageAddress + ((uint16_t)PageWord << 1), Endpoint_Read_16_LE());
}
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
boot_page_write(PageAddress);
boot_spm_busy_wait();
}
boot_rww_enable();
}
Endpoint_ClearOUT();
Endpoint_ClearStatusStage();
break;
}
}