Example #1
0
/** Configures all hardware required for the bootloader. */
void SetupHardware(void)
{
	/* Disable watchdog if enabled by bootloader/fuses */
	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);
	
	LED_SETUP();
	CPU_PRESCALE(0); 
	L_LED_OFF();
	TX_LED_OFF();
	RX_LED_OFF();
	
	/* Initialize TIMER1 to handle bootloader timeout and LED tasks.  
	 * With 16 MHz clock and 1/64 prescaler, timer 1 is clocked at 250 kHz
	 * Our chosen compare match generates an interrupt every 1 ms.
	 * This interrupt is disabled selectively when doing memory reading, erasing,
	 * or writing since SPM has tight timing requirements.
	 */ 
	OCR1AH = 0;
	OCR1AL = 250;
	TIMSK1 = (1 << OCIE1A);					// enable timer 1 output compare A match interrupt
	TCCR1B = ((1 << CS11) | (1 << CS10));	// 1/64 prescaler on timer 1 input

	/* Initialize USB Subsystem */
	USB_Init();
}
Example #2
0
/** Main program entry point. This routine configures the hardware required by the bootloader, then continuously
 *  runs the bootloader processing routine until it times out or is instructed to exit.
 */
int main(void)
{
	/* Save the value of the boot key memory before it is overwritten */
	uint8_t bootKeyPtrVal = *bootKeyPtr;
	*bootKeyPtr = 0;

	/* Check the reason for the reset so we can act accordingly */
	uint8_t  mcusr_state = MCUSR;		// store the initial state of the Status register
	MCUSR = 0;							// clear all reset flags	

	/* Watchdog may be configured with a 15 ms period so must disable it before going any further */
	// MAH 8/15/12- I removed this because wdt_disable() is the first thing SetupHardware() does- why
	//  do it twice right in a row?
	//wdt_disable();
	
	/* Setup hardware required for the bootloader */
	// MAH 8/15/12- Moved this up to before the bootloader go/no-go decision tree so I could use the
	//  timer in that decision tree. Removed the USBInit() call from it; if I'm not going to stay in
	//  the bootloader, there's no point spending the time initializing the USB.
	// SetupHardware();
	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);
	
	LED_SETUP();
	CPU_PRESCALE(0); 
	L_LED_OFF();
	TX_LED_OFF();
	RX_LED_OFF();
	
	// Initialize TIMER1 to handle bootloader timeout and LED tasks.  
	// With 16 MHz clock and 1/64 prescaler, timer 1 is clocked at 250 kHz
	// Our chosen compare match generates an interrupt every 1 ms.
	// This interrupt is disabled selectively when doing memory reading, erasing,
	// or writing since SPM has tight timing requirements. 

	OCR1AH = 0;
	OCR1AL = 250;
	TIMSK1 = (1 << OCIE1A);					// enable timer 1 output compare A match interrupt
	TCCR1B = ((1 << CS11) | (1 << CS10));	// 1/64 prescaler on timer 1 input
	
	
	// MAH 8/15/12- this replaces bulky pgm_read_word(0) calls later on, to save memory.
	if (pgm_read_word(0) != 0xFFFF) sketchPresent = true;
	
	// MAH 8/15/12- quite a bit changed in this section- let's just pretend nothing has been reserved
	//  and all comments throughout are from me.
	// First case: external reset, bootKey NOT in memory. We'll put the bootKey in memory, then spin
	//  our wheels for about 750ms, then proceed to the sketch, if there is one. If, during that 750ms,
	//  another external reset occurs, on the next pass through this decision tree, execution will fall
	//  through to the bootloader.
	if ( (mcusr_state & (1<<EXTRF)) && (bootKeyPtrVal != bootKey) ) {
		*bootKeyPtr = bootKey;
		sei();
		while (RunBootloader) 
		{
			if (resetTimeout > EXT_RESET_TIMEOUT_PERIOD)
				RunBootloader = false;
		}
		cli();
		*bootKeyPtr = 0;
		RunBootloader = true;
		if (sketchPresent) StartSketch();
	} 
	// On a power-on reset, we ALWAYS want to go to the sketch. If there is one.
	else if ( (mcusr_state & (1<<PORF)) && sketchPresent) {	
		StartSketch();
	} 
	// On a watchdog reset, if the bootKey isn't set, and there's a sketch, we should just
	//  go straight to the sketch.
	else if ( (mcusr_state & (1<<WDRF) ) && (bootKeyPtrVal != bootKey) && sketchPresent) {	
		// If it looks like an "accidental" watchdog reset then start the sketch.
		StartSketch();
	}
	
	// END ALL COMMENTS ON THIS SECTION FROM MAH.
	
	/* Initialize USB Subsystem */
	USB_Init();

	/* Enable global interrupts so that the USB stack can function */
	sei();
	
	Timeout = 0;
	
	while (RunBootloader)
	{
		CDC_Task();
		USB_USBTask();
		/* Time out and start the sketch if one is present */
		if (Timeout > TIMEOUT_PERIOD)
			RunBootloader = false;
			
		// MAH 8/15/12- This used to be a function call- inlining it saves a few bytes.
		LLEDPulse++;
		uint8_t p = LLEDPulse >> 8;
		if (p > 127)
			p = 254-p;
		p += p;
		if (((uint8_t)LLEDPulse) > p)
			L_LED_OFF();
		else
			L_LED_ON();
	}

	/* Disconnect from the host - USB interface will be reset later along with the AVR */
	USB_Detach();

	/* Jump to beginning of application space to run the sketch - do not reset */	
	StartSketch();
}
Example #3
0
/** Main program entry point. This routine configures the hardware required by the bootloader, then continuously
 *  runs the bootloader processing routine until it times out or is instructed to exit.
 */
int main(void)
{
	/* Save the value of the boot key memory before it is overwritten */
	uint8_t bootKeyPtrVal = *bootKeyPtr;
	*bootKeyPtr = 0;

	/* Check the reason for the reset so we can act accordingly */
	uint8_t  mcusr_state = MCUSR;		// store the initial state of the Status register
	MCUSR = 0;							// clear all reset flags

	/* Watchdog may be configured with a 15 ms period so must disable it before going any further */
	// MAH 8/15/12- I removed this because wdt_disable() is the first thing SetupHardware() does- why
	//  do it twice right in a row?
	//wdt_disable();

	/* Setup hardware required for the bootloader */
	// MAH 8/15/12- Moved this up to before the bootloader go/no-go decision tree so I could use the
	//  timer in that decision tree. Removed the USBInit() call from it; if I'm not going to stay in
	//  the bootloader, there's no point spending the time initializing the USB.
	// SetupHardware();
	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);

	LED_SETUP();
	CPU_PRESCALE(0);
	L_LED_OFF();
	TX_LED_OFF();
	RX_LED_OFF();

	// Initialize TIMER1 to handle bootloader timeout and LED tasks.
	// With 16 MHz clock and 1/64 prescaler, timer 1 is clocked at 250 kHz
	// Our chosen compare match generates an interrupt every 1 ms.
	// This interrupt is disabled selectively when doing memory reading, erasing,
	// or writing since SPM has tight timing requirements.

	OCR1AH = 0;
	OCR1AL = 250;
	TIMSK1 = (1 << OCIE1A);					// enable timer 1 output compare A match interrupt
	TCCR1B = ((1 << CS11) | (1 << CS10));	// 1/64 prescaler on timer 1 input


	// MAH 8/15/12- this replaces bulky pgm_read_word(0) calls later on, to save memory.
	if (pgm_read_word(0) != 0xFFFF) sketchPresent = true;

// MAH 26 Oct 2012- The "bootload or not?" section has been modified since the code released
//  with Arduino 1.0.1. The simplest modification is the replacement of equivalence checks on
//  the reset bits with masked checks, so if more than one reset occurs before the register is
//  checked, the check doesn't fail and fall through to the bootloader unnecessarily.

// The second, more in depth modification addresses behavior after an external reset (i.e.,
//  user pushes the reset button). The Leonardo treats all external resets as requests to
//  re-enter the bootloader and wait for code to be loaded. It remains in bootloader mode for
//  8 seconds before continuing on to the sketch (if one is present). By defining RESET_DELAY
//  equal to 1, this behavior will persist.

// However, if RESET_DELAY is defined to 0, the reset timeout before loading the sketch drops
//  to 750ms. If, during that 750ms, another external reset occurs, THEN an 8-second delay
//  in the bootloader will occur.

	// This is the "no-8-second-delay" code. If this is the first time through the loop, we
	//  don't expect to see the bootKey in memory.
	if ( (mcusr_state & (1<<EXTRF)) && (bootKeyPtrVal != bootKey) ) {
		*bootKeyPtr = bootKey;   // Put the bootKey in memory so if we get back to this
		                         //  point again, we know to jump into the bootloader
		sei();  // Enable interrupts, so we can use timer1 to track our time in the bootloader
		while (RunBootloader)
		{
			if (resetTimeout > EXT_RESET_TIMEOUT_PERIOD) // resetTimeout is getting incremeted
				RunBootloader = false;                   //  in the timer1 ISR.
		}
		// If we make it past that while loop, it's sketch loading time!
		*bootKeyPtr = 0;   // clear out the bootKey; from now on, we want to treat a reset like
						   //  a normal reset.
		cli();             // Disable interrupts, in case no sketch is present.
		RunBootloader = true;  // We want to hang out in the bootloader if no sketch is present.
		if (sketchPresent) StartSketch(); // If a sketch is present, go! Otherwise, wait around
										  //  in the bootloader until one is uploaded.
	}
	// On a power-on reset, we ALWAYS want to go to the sketch. If there is one.
	//  This is a place where the old code had an equivalence and now there is a mask.
	else if ( (mcusr_state & (1<<PORF)) && sketchPresent) {
		StartSketch();
	}
	// On a watchdog reset, if the bootKey isn't set, and there's a sketch, we should just
	//  go straight to the sketch.
	//  This is a place where the old code had an equivalence and now there is a mask.
	else if ( (mcusr_state & (1<<WDRF) ) && (bootKeyPtrVal != bootKey) && sketchPresent) {
		// If it looks like an "accidental" watchdog reset then start the sketch.
		StartSketch();
	}

	/* Initialize USB Subsystem */
	USB_Init();

	/* Enable global interrupts so that the USB stack can function */
	sei();

	Timeout = 0;

	while (RunBootloader)
	{
		CDC_Task();
		USB_USBTask();
		/* Time out and start the sketch if one is present */
		if (Timeout > TIMEOUT_PERIOD)
			RunBootloader = false;

		// MAH 8/15/12- This used to be a function call- inlining it saves a few bytes.
		LLEDPulse++;
		uint8_t p = LLEDPulse >> 8;
		if (p > 127)
			p = 254-p;
		p += p;
		if (((uint8_t)LLEDPulse) > p)
			L_LED_OFF();
		else
			L_LED_ON();
	}

	/* Disconnect from the host - USB interface will be reset later along with the AVR */
	USB_Detach();

	/* Jump to beginning of application space to run the sketch - do not reset */
	StartSketch();
}