/** 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 */
	uint16_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 */
	wdt_disable();

#if DEVICE_PID == 0x606C   // Only on the BlinkyTape
	// Put the user button (B6) in input_pullup mode, so we can read the button state
	DDRB	&= ~(1<<DDB6);
	PORTB	|= (1<<DDB6);
#endif
	
	if (mcusr_state & (1<<EXTRF)) {
		// External reset -  we should continue to self-programming mode.
#if DEVICE_PID == 0x606C   // Only on the BlinkyTape
	} else if (!(PINB & (1<<DDB6))) {
		// User button held low- Jump into the bootloader, in case the application is borked.
#endif
	} else if ((mcusr_state & (1<<PORF)) && (pgm_read_word(0) != 0xFFFF)) {		
		// After a power-on reset skip the bootloader and jump straight to sketch 
		// if one exists.	
		StartSketch();
	} else if ((mcusr_state & (1<<WDRF)) && (bootKeyPtrVal != bootKey) && (pgm_read_word(0) != 0xFFFF)) {	
		// If it looks like an "accidental" watchdog reset then start the sketch.
		StartSketch();
	}
	
	/* Setup hardware required for the bootloader */
	SetupHardware();

	/* 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;

		LEDPulse();
	}

	/* 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();
}
Exemple #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 */
	uint16_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 */
	wdt_disable();

	// init HWB pin, wait a ms to allow caps to charge
	HWB_SETUP();
	_delay_ms(1);
	
	if ((mcusr_state & (1<<EXTRF)) && HWB_STATUS() && (pgm_read_word(0) != 0xFFFF)) {
		// External reset -  start the sketch if there is one and HWB jumper is not installed (HWB pin is read high)
		StartSketch();
	} else if ((mcusr_state & (1<<PORF)) && (pgm_read_word(0) != 0xFFFF)) {		
		// After a power-on reset skip the bootloader and jump straight to sketch 
		// if one exists.	
		StartSketch();
	} else if ((mcusr_state & (1<<WDRF)) && (bootKeyPtrVal != bootKey) && (pgm_read_word(0) != 0xFFFF)) {	
		// If it looks like an "accidental" watchdog reset then start the sketch.
		StartSketch();
	}
	// so only start programmimg mode when reset came from autoreset = watchdog reset and bootkey matches

	/* Setup hardware required for the bootloader */
	SetupHardware();

	/* 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;

		LEDPulse();
	}

	/* 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();
}
Exemple #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 */
	uint16_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 */
	wdt_disable();
	
	/* Jump to bootloader only if correct key is present in eeprom */
	if ((eeprom_read_word((uint16_t*)EEP_BOOTKEY_ADDR) != BOOTLOADER_BOOTKEY) && (eeprom_read_word((uint16_t*)EEP_BACKUP_BOOTKEY_ADDR) != BOOTLOADER_BOOTKEY))
	{
		StartSketch();
	}

	/* Setup hardware required for the bootloader */
	SetupHardware();

	/* 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;

		LEDPulse();
	}

	/* 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();
}
Exemple #4
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();
}
Exemple #5
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 */
	uint16_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 &= ~((1 << PORF) | (1 << EXTRF) | (1 << WDRF));	// clear reset flags that are used by the bootloader

	/* Watchdog may be configured with a 15 ms period so must disable it before going any further */
	wdt_disable();
	

	if (pgm_read_word(0) != 0xFFFF)
	{
		// There is a sketch (otherwise, skip these checks and just run the bootloader).
		
		if (mcusr_state & (1 << PORF))
		{
			// After power-on reset, clear BORF so sketch can tell it wasn't a brown-out reset,
			// then start the sketch.
			MCUSR &= ~(1 << BORF);
			StartSketch();
		}
		else if (mcusr_state & (1 << EXTRF))
		{
			// External reset.
			if (bootKeyPtrVal != bootKey)
			{
				// First reset button press. Set boot key for 750 ms so second reset button press
				// can be detected, then start the sketch if there isn't another reset.
				*bootKeyPtr = bootKey;
				_delay_ms(750);
				*bootKeyPtr = 0;
				StartSketch();
			}
			else
			{
				 // Second reset button press; boot key was already set. Fall through to bootloader.
			}
		}
		else if ((mcusr_state & (1 << WDRF)) && (bootKeyPtrVal == bootKey))
		{
			// Watchdog reset triggered by sketch to start bootloader. Fall through.
		}
		else
		{
			// Reset happened for some other reason; start the sketch.
			StartSketch();
		}
	}

	// Clear remaining reset flags so the sketch doesn't see info about an old reset when it runs later.
	MCUSR = 0;
	
	/* Setup hardware required for the bootloader */
	SetupHardware();

	/* 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;

		LEDPulse();
	}

	/* 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();
}
Exemple #6
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();
}