/*
LUFA Library
- Copyright (C) Dean Camera, 2012.
+ Copyright (C) Dean Camera, 2021.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
- Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+ Copyright 2021 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
- The author disclaim all warranties with regard to this
+ The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
* low when the application attempts to start via a watchdog reset, the bootloader will re-start. If set to the value
* \ref MAGIC_BOOT_KEY the special init function \ref Application_Jump_Check() will force the application to start.
*/
-uint32_t MagicBootKey ATTR_NO_INIT;
+uint16_t MagicBootKey ATTR_NO_INIT;
/** Special startup routine to check if the bootloader was started via a watchdog reset, and if the magic application
/* If the reset source was the bootloader and the key is correct, clear it and jump to the application */
if ((MCUSR & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY))
{
+ /* Turn off the watchdog */
+ MCUSR &= ~(1 << WDRF);
+ wdt_disable();
+
+ /* Clear the boot key and jump to the user application */
MagicBootKey = 0;
+
// cppcheck-suppress constStatement
((void (*)(void))0x0000)();
}
SetupHardware();
/* Enable global interrupts so that the USB stack can function */
- sei();
+ GlobalInterruptEnable();
while (RunBootloader)
USB_USBTask();
+ /* Wait a short time to end all USB transactions and then disconnect */
+ _delay_us(1000);
+
/* Disconnect from the host - USB interface will be reset later along with the AVR */
USB_Detach();
MCUSR &= ~(1 << WDRF);
wdt_disable();
+ /* Disable clock division */
+ clock_prescale_set(clock_div_1);
+
/* Relocate the interrupt vector table to the bootloader section */
MCUCR = (1 << IVCE);
MCUCR = (1 << IVSEL);
uint16_t PageAddress = Endpoint_Read_16_LE();
#endif
+ /* Determine if the given page address is correctly aligned to the
+ start of a flash page. */
+ bool PageAddressIsAligned = !(PageAddress & (SPM_PAGESIZE - 1));
+
/* Check if the command is a program page command, or a start application command */
#if (FLASHEND > 0xFFFF)
if ((uint16_t)(PageAddress >> 8) == COMMAND_STARTAPPLICATION)
{
RunBootloader = false;
}
- else
+ else if ((PageAddress < BOOT_START_ADDR) && PageAddressIsAligned)
{
/* Erase the given FLASH page, ready to be programmed */
- boot_page_erase(PageAddress);
- boot_spm_busy_wait();
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+ {
+ boot_page_erase(PageAddress);
+ boot_spm_busy_wait();
+ }
/* Write each of the FLASH page's bytes in sequence */
for (uint8_t PageWord = 0; PageWord < (SPM_PAGESIZE / 2); PageWord++)
}
/* Write the filled FLASH page to memory */
- boot_page_write(PageAddress);
- boot_spm_busy_wait();
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+ {
+ boot_page_write(PageAddress);
+ boot_spm_busy_wait();
+ }
/* Re-enable RWW section */
boot_rww_enable();