X-Git-Url: http://git.linex4red.de/pub/USBasp.git/blobdiff_plain/0c2ad9eb349e1a5676468af3b407329dde4a53b4..6f90d45684206e5dfca3c4554a14a5784da49d92:/Bootloaders/HID/BootloaderHID.c diff --git a/Bootloaders/HID/BootloaderHID.c b/Bootloaders/HID/BootloaderHID.c index f4cb0f1a1..acc351a30 100644 --- a/Bootloaders/HID/BootloaderHID.c +++ b/Bootloaders/HID/BootloaderHID.c @@ -1,21 +1,21 @@ /* LUFA Library - Copyright (C) Dean Camera, 2011. + Copyright (C) Dean Camera, 2012. dean [at] fourwalledcubicle [dot] com www.lufa-lib.org */ /* - Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com) - Permission to use, copy, modify, distribute, and sell this + Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in + without fee, provided that the above copyright notice appear in all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the software without specific, written prior permission. The author disclaim all warranties with regard to this @@ -32,7 +32,7 @@ * * Main source file for the HID class bootloader. This file contains the complete bootloader logic. */ - + #include "BootloaderHID.h" /** Flag to indicate if the bootloader should be running, or should exit and allow the application code to run @@ -41,23 +41,49 @@ */ static bool RunBootloader = true; -/** Main program entry point. This routine configures the hardware required by the bootloader, then continuously +/** Magic lock for forced application start. If the HWBE fuse is programmed and BOOTRST is unprogrammed, the bootloader + * will start if the /HWB line of the AVR is held low and the system is reset. However, if the /HWB line is still held + * 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; + + +/** Special startup routine to check if the bootloader was started via a watchdog reset, and if the magic application + * start key has been loaded into \ref MagicBootKey. If the bootloader started via the watchdog and the key is valid, + * this will force the user application to start via a software jump. + */ +void Application_Jump_Check(void) +{ + /* 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)) + { + MagicBootKey = 0; + // cppcheck-suppress constStatement + ((void (*)(void))0x0000)(); + } +} + +/** Main program entry point. This routine configures the hardware required by the bootloader, then continuously * runs the bootloader processing routine until instructed to soft-exit. */ int main(void) { /* Setup hardware required for the bootloader */ SetupHardware(); - + /* Enable global interrupts so that the USB stack can function */ sei(); while (RunBootloader) USB_USBTask(); - + /* Disconnect from the host - USB interface will be reset later along with the AVR */ USB_Detach(); + /* Unlock the forced application start mode of the bootloader if it is restarted */ + MagicBootKey = MAGIC_BOOT_KEY; + /* Enable the watchdog and force a timeout to reset the AVR */ wdt_enable(WDTO_250MS); @@ -65,7 +91,7 @@ int main(void) } /** Configures all hardware required for the bootloader. */ -void SetupHardware(void) +static void SetupHardware(void) { /* Disable watchdog if enabled by bootloader/fuses */ MCUSR &= ~(1 << WDRF); @@ -85,9 +111,7 @@ void SetupHardware(void) void EVENT_USB_Device_ConfigurationChanged(void) { /* Setup HID Report Endpoint */ - Endpoint_ConfigureEndpoint(HID_IN_EPNUM, EP_TYPE_INTERRUPT, - ENDPOINT_DIR_IN, HID_IN_EPSIZE, - ENDPOINT_BANK_SINGLE); + Endpoint_ConfigureEndpoint(HID_IN_EPADDR, EP_TYPE_INTERRUPT, HID_IN_EPSIZE, 1); } /** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent to @@ -108,17 +132,17 @@ void EVENT_USB_Device_ControlRequest(void) { case HID_REQ_SetReport: Endpoint_ClearSETUP(); - + /* Wait until the command has been sent by the host */ while (!(Endpoint_IsOUTReceived())); - + /* Read in the write destination address */ #if (FLASHEND > 0xFFFF) uint32_t PageAddress = ((uint32_t)Endpoint_Read_16_LE() << 8); #else uint16_t PageAddress = Endpoint_Read_16_LE(); #endif - + /* Check if the command is a program page command, or a start application command */ #if (FLASHEND > 0xFFFF) if ((uint16_t)(PageAddress >> 8) == COMMAND_STARTAPPLICATION) @@ -133,9 +157,9 @@ void EVENT_USB_Device_ControlRequest(void) /* Erase the given FLASH page, ready to be programmed */ 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++) + for (uint8_t PageWord = 0; PageWord < (SPM_PAGESIZE / 2); PageWord++) { /* Check if endpoint is empty - if so clear it and wait until ready for next packet */ if (!(Endpoint_BytesInEndpoint())) @@ -162,3 +186,4 @@ void EVENT_USB_Device_ControlRequest(void) break; } } +