/*
LUFA Library
- Copyright (C) Dean Camera, 2010.
+ Copyright (C) Dean Camera, 2011.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
- Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+ Copyright 2011 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
/** Flag to indicate if the bootloader is currently running in secure mode, disallowing memory operations
* other than erase. This is initially set to the value set by SECURE_MODE, and cleared by the bootloader
- * once a memory erase has completed.
+ * once a memory erase has completed in a bootloader session.
*/
-bool IsSecure = SECURE_MODE;
+static bool IsSecure = SECURE_MODE;
/** Flag to indicate if the bootloader should be running, or should exit and allow the application code to run
* via a soft reset. When cleared, the bootloader will abort, the USB interface will shut down and the application
* jumped to via an indirect jump to location 0x0000 (or other location specified by the host).
*/
-bool RunBootloader = true;
+static bool RunBootloader = true;
/** Flag to indicate if the bootloader is waiting to exit. When the host requests the bootloader to exit and
* jump to the application address it specifies, it sends two sequential commands which must be properly
* acknowledged. Upon reception of the first the RunBootloader flag is cleared and the WaitForExit flag is set,
* causing the bootloader to wait for the final exit command before shutting down.
*/
-bool WaitForExit = false;
+static bool WaitForExit = false;
/** Current DFU state machine state, one of the values in the DFU_State_t enum. */
-uint8_t DFU_State = dfuIDLE;
+static uint8_t DFU_State = dfuIDLE;
/** Status code of the last executed DFU command. This is set to one of the values in the DFU_Status_t enum after
* each operation, and returned to the host when a Get Status DFU request is issued.
*/
-uint8_t DFU_Status = OK;
+static uint8_t DFU_Status = OK;
/** Data containing the DFU command sent from the host. */
-DFU_Command_t SentCommand;
+static DFU_Command_t SentCommand;
/** Response to the last issued Read Data DFU command. Unlike other DFU commands, the read command
* requires a single byte response from the bootloader containing the read data when the next DFU_UPLOAD command
* is issued by the host.
*/
-uint8_t ResponseByte;
+static uint8_t ResponseByte;
/** Pointer to the start of the user application. By default this is 0x0000 (the reset vector), however the host
* may specify an alternate address when issuing the application soft-start command.
*/
-AppPtr_t AppStartPtr = (AppPtr_t)0x0000;
+static AppPtr_t AppStartPtr = (AppPtr_t)0x0000;
/** 64-bit flash page number. This is concatenated with the current 16-bit address on USB AVRs containing more than
* 64KB of flash memory.
*/
-uint8_t Flash64KBPage = 0;
+static uint8_t Flash64KBPage = 0;
/** Memory start address, indicating the current address in the memory being addressed (either FLASH or EEPROM
* depending on the issued command from the host).
*/
-uint16_t StartAddr = 0x0000;
+static uint16_t StartAddr = 0x0000;
/** Memory end address, indicating the end address to read to/write from in the memory being addressed (either FLASH
* of EEPROM depending on the issued command from the host).
*/
-uint16_t EndAddr = 0x0000;
+static uint16_t EndAddr = 0x0000;
/** Main program entry point. This routine configures the hardware required by the bootloader, then continuously
/* Configure hardware required by the bootloader */
SetupHardware();
+ #if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
+ /* Disable JTAG debugging */
+ MCUCR |= (1 << JTD);
+ MCUCR |= (1 << JTD);
+
+ /* Enable pull-up on the JTAG TCK pin so we can use it to select the mode */
+ PORTF |= (1 << 4);
+ _delay_ms(10);
+
+ /* If the TCK pin is not jumpered to ground, start the user application instead */
+ RunBootloader = (!(PINF & (1 << 4)));
+
+ /* Re-enable JTAG debugging */
+ MCUCR &= ~(1 << JTD);
+ MCUCR &= ~(1 << JTD);
+ #endif
+
/* Enable global interrupts so that the USB stack can function */
sei();
void ResetHardware(void)
{
/* Shut down the USB subsystem */
- USB_ShutDown();
+ USB_Disable();
/* Relocate the interrupt vector table back to the application section */
MCUCR = (1 << IVCE);
MCUCR = 0;
}
-/** Event handler for the USB_UnhandledControlRequest event. This is used to catch standard and class specific
- * control requests that are not handled internally by the USB library (including the DFU commands, which are
- * all issued via the control endpoint), so that they can be handled appropriately for the application.
+/** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent to
+ * the device from the USB host before passing along unhandled control requests to the library for processing
+ * internally.
*/
-void EVENT_USB_Device_UnhandledControlRequest(void)
+void EVENT_USB_Device_ControlRequest(void)
{
/* Get the size of the command and data from the wLength value */
SentCommand.DataSize = USB_ControlRequest.wLength;
+
+ /* Ignore any requests that aren't directed to the DFU interface */
+ if ((USB_ControlRequest.bmRequestType & (CONTROL_REQTYPE_TYPE | CONTROL_REQTYPE_RECIPIENT)) !=
+ (REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ return;
+ }
switch (USB_ControlRequest.bRequest)
{
- case REQ_DFU_DNLOAD:
+ case DFU_REQ_DNLOAD:
Endpoint_ClearSETUP();
/* Check if bootloader is waiting to terminate */
Endpoint_ClearStatusStage();
break;
- case REQ_DFU_UPLOAD:
+ case DFU_REQ_UPLOAD:
Endpoint_ClearSETUP();
while (!(Endpoint_IsINReady()))
Endpoint_ClearStatusStage();
break;
- case REQ_DFU_GETSTATUS:
+ case DFU_REQ_GETSTATUS:
Endpoint_ClearSETUP();
/* Write 8-bit status value */
Endpoint_ClearStatusStage();
break;
- case REQ_DFU_CLRSTATUS:
+ case DFU_REQ_CLRSTATUS:
Endpoint_ClearSETUP();
/* Reset the status value variable to the default OK status */
Endpoint_ClearStatusStage();
break;
- case REQ_DFU_GETSTATE:
+ case DFU_REQ_GETSTATE:
Endpoint_ClearSETUP();
/* Write the current device state to the endpoint */
Endpoint_ClearStatusStage();
break;
- case REQ_DFU_ABORT:
+ case DFU_REQ_ABORT:
Endpoint_ClearSETUP();
/* Reset the current state variable to the default idle state */