Dean Camera committed Mar 08, 2013 1 2 /* LUFA Library  Dean Camera committed Apr 18, 2017 3  Copyright (C) Dean Camera, 2017.  Dean Camera committed Mar 08, 2013 4 5 6 7 8 9  dean [at] fourwalledcubicle [dot] com www.lufa-lib.org */ /*  Dean Camera committed Apr 18, 2017 10  Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com)  Dean Camera committed Mar 08, 2013 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32  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 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 software without specific, written prior permission. 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 whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software. */ /** \file *  Dean Camera committed Mar 09, 2013 33  * Main source file for the Mass Storage class bootloader. This file contains the complete bootloader logic.  Dean Camera committed Mar 08, 2013 34 35  */  36 #define INCLUDE_FROM_BOOTLOADER_MASSSTORAGE_C  37 #include "BootloaderMassStorage.h"  Dean Camera committed Mar 08, 2013 38 39 40 41 42 43 44 45 46  /** LUFA Mass Storage Class driver interface configuration and state information. This structure is * passed to all Mass Storage Class driver functions, so that multiple instances of the same class * within a device can be differentiated from one another. */ USB_ClassInfo_MS_Device_t Disk_MS_Interface = { .Config = {  László Monda committed Oct 06, 2013 47  .InterfaceNumber = INTERFACE_ID_MassStorage,  Dean Camera committed Mar 08, 2013 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63  .DataINEndpoint = { .Address = MASS_STORAGE_IN_EPADDR, .Size = MASS_STORAGE_IO_EPSIZE, .Banks = 1, }, .DataOUTEndpoint = { .Address = MASS_STORAGE_OUT_EPADDR, .Size = MASS_STORAGE_IO_EPSIZE, .Banks = 1, }, .TotalLUNs = 1, }, };  64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 /** 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 * started via a forced watchdog reset. */ bool RunBootloader = true; /** 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. */ uint16_t MagicBootKey ATTR_NO_INIT; /** Indicates if the bootloader is allowed to exit immediately if \ref RunBootloader is \c false. During shutdown all * pending commands must be processed before jumping to the user-application, thus this tracks the main program loop * iterations since a SCSI command from the host was received. */ static uint8_t TicksSinceLastCommand = 0;  Dean Camera committed Mar 08, 2013 83   84 85 86 87 /** 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. */  Dean Camera committed Mar 18, 2013 88 89 90 91 92 93 void Application_Jump_Check(void) { bool JumpToApplication = false; #if (BOARD == BOARD_LEONARDO) /* Enable pull-up on the IO13 pin so we can use it to select the mode */  Dean Camera committed Oct 11, 2014 94  PORTC |= (1 << 7);  Dean Camera committed Mar 18, 2013 95  Delay_MS(10);  96 97  /* If IO13 is not jumpered to ground, start the user application instead */  Dean Camera committed Oct 11, 2014 98  JumpToApplication = ((PINC & (1 << 7)) != 0);  Dean Camera committed Mar 18, 2013 99   100 101 102  /* Disable pull-up after the check has completed */ PORTC &= ~(1 << 7); #elif ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))  103 104 105 106 107 108 109 110  /* Disable JTAG debugging */ JTAG_DISABLE(); /* 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 */  Dean Camera committed Oct 11, 2014 111  JumpToApplication = ((PINF & (1 << 4)) != 0);  112 113 114  /* Re-enable JTAG debugging */ JTAG_ENABLE();  Dean Camera committed Oct 11, 2014 115 116 117 118 119 120 121 122  #else /* Check if the device's BOOTRST fuse is set */ if (boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS) & FUSE_BOOTRST) { /* If the reset source was not an external reset or the key is correct, clear it and jump to the application */ if (!(MCUSR & (1 << EXTRF)) || (MagicBootKey == MAGIC_BOOT_KEY)) JumpToApplication = true;  123  /* Clear reset source */  Dean Camera committed Oct 11, 2014 124 125  MCUSR &= ~(1 << EXTRF); }  126 127 128 129 130 131 132 133 134 135  else { /* If the reset source was the bootloader and the key is correct, clear it and jump to the application; * this can happen in the HWBE fuse is set, and the HBE pin is low during the watchdog reset */ if ((MCUSR & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY)) JumpToApplication = true; /* Clear reset source */ MCUSR &= ~(1 << WDRF); }  136 137  #endif  138  /* Don't run the user application if the reset vector is blank (no app loaded) */  Dean Camera committed Oct 11, 2014 139  bool ApplicationValid = (pgm_read_word_near(0) != 0xFFFF);  140   141  /* If a request has been made to jump to the user application, honor it */  Dean Camera committed Oct 11, 2014 142  if (JumpToApplication && ApplicationValid)  Dean Camera committed Mar 18, 2013 143  {  144  /* Turn off the watchdog */  Dean Camera committed Oct 11, 2014 145  MCUSR &= ~(1 << WDRF);  146 147 148 149 150  wdt_disable(); /* Clear the boot key and jump to the user application */ MagicBootKey = 0;  Dean Camera committed Mar 18, 2013 151  // cppcheck-suppress constStatement  Dean Camera committed Jan 29, 2017 152  ((void (*)(void))0x0000)();  Dean Camera committed Mar 18, 2013 153 154 155  } }  Dean Camera committed Mar 10, 2013 156 157 /** Main program entry point. This routine configures the hardware required by the application, then * enters a loop to run the application tasks in sequence.  Dean Camera committed Mar 08, 2013 158 159 160 161 162 163 164 165  */ int main(void) { SetupHardware(); LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY); GlobalInterruptEnable();  166  while (RunBootloader || TicksSinceLastCommand++ < 0xFF)  Dean Camera committed Mar 08, 2013 167 168 169 170  { MS_Device_USBTask(&Disk_MS_Interface); USB_USBTask(); }  171 172 173 174 175 176 177 178 179 180 181  /* 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); for (;;);  Dean Camera committed Mar 08, 2013 182 183 184 } /** Configures the board hardware and chip peripherals for the demo's functionality. */  Dean Camera committed Mar 13, 2013 185 static void SetupHardware(void)  Dean Camera committed Mar 08, 2013 186 187 188 189 190 { /* Disable watchdog if enabled by bootloader/fuses */ MCUSR &= ~(1 << WDRF); wdt_disable();  Dean Camera committed Mar 18, 2013 191 192 193  /* Disable clock division */ clock_prescale_set(clock_div_1);  Dean Camera committed Mar 08, 2013 194 195 196 197 198 199 200  /* Relocate the interrupt vector table to the bootloader section */ MCUCR = (1 << IVCE); MCUCR = (1 << IVSEL); /* Hardware Initialization */ LEDs_Init(); USB_Init();  Dean Camera committed Mar 09, 2013 201 202 203 204 205 206 207 208 209 210  /* Bootloader active LED toggle timer initialization */ TIMSK1 = (1 << TOIE1); TCCR1B = ((1 << CS11) | (1 << CS10)); } /** ISR to periodically toggle the LEDs on the board to indicate that the bootloader is active. */ ISR(TIMER1_OVF_vect, ISR_BLOCK) { LEDs_ToggleLEDs(LEDS_LED1 | LEDS_LED2);  Dean Camera committed Mar 08, 2013 211 212 }  Dean Camera committed Mar 10, 2013 213 /** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs. */  Dean Camera committed Mar 08, 2013 214 215 void EVENT_USB_Device_Connect(void) {  Dean Camera committed Mar 10, 2013 216  /* Indicate USB enumerating */  Dean Camera committed Mar 08, 2013 217 218 219  LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING); }  Dean Camera committed Mar 10, 2013 220 221 222 /** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via * the status LEDs and stops the Mass Storage management task. */  Dean Camera committed Mar 08, 2013 223 224 void EVENT_USB_Device_Disconnect(void) {  Dean Camera committed Mar 10, 2013 225  /* Indicate USB not ready */  Dean Camera committed Mar 08, 2013 226 227 228 229 230 231 232 233  LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY); } /** Event handler for the library USB Configuration Changed event. */ void EVENT_USB_Device_ConfigurationChanged(void) { bool ConfigSuccess = true;  Dean Camera committed Mar 10, 2013 234  /* Setup Mass Storage Data Endpoints */  Dean Camera committed Mar 08, 2013 235 236  ConfigSuccess &= MS_Device_ConfigureEndpoints(&Disk_MS_Interface);  Dean Camera committed Mar 10, 2013 237  /* Indicate endpoint configuration success or failure */  Dean Camera committed Mar 08, 2013 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258  LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY : LEDMASK_USB_ERROR); } /** Event handler for the library USB Control Request reception event. */ void EVENT_USB_Device_ControlRequest(void) { MS_Device_ProcessControlRequest(&Disk_MS_Interface); } /** Mass Storage class driver callback function the reception of SCSI commands from the host, which must be processed. * * \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface configuration structure being referenced */ bool CALLBACK_MS_Device_SCSICommandReceived(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) { bool CommandSuccess; LEDs_SetAllLEDs(LEDMASK_USB_BUSY); CommandSuccess = SCSI_DecodeSCSICommand(MSInterfaceInfo); LEDs_SetAllLEDs(LEDMASK_USB_READY);  259 260 261  /* Signal that a command was processed, must not exit bootloader yet */ TicksSinceLastCommand = 0;  Dean Camera committed Mar 08, 2013 262 263  return CommandSuccess; }