2013-03-09 02:22:27 +00:00
# include <stdint.h>
# include <stdbool.h>
2012-06-30 02:19:07 +00:00
# include <avr/io.h>
# include <avr/interrupt.h>
2013-03-09 02:22:27 +00:00
# include <avr/wdt.h>
2012-06-30 02:19:07 +00:00
# include <util/delay.h>
# include "bootloader.h"
2011-09-22 07:56:36 +00:00
2013-03-09 02:22:27 +00:00
# ifdef PROTOCOL_LUFA
# include <LUFA/Drivers/USB/USB.h>
# endif
2011-09-22 07:56:36 +00:00
2013-03-10 06:05:28 +00:00
/* Boot Section Size in *BYTEs*
2013-03-10 06:36:07 +00:00
* Teensy halfKay 512
* Teensy + + halfKay 1024
* Atmel DFU loader 4096
* LUFA bootloader 4096
* USBaspLoader 2048
2012-06-30 02:19:07 +00:00
*/
2013-03-10 06:36:07 +00:00
# ifndef BOOTLOADER_SIZE
2013-03-11 04:32:46 +00:00
# warning To use bootloader_jump() you need to define BOOTLOADER_SIZE in config.h.
# define BOOTLOADER_SIZE 4096
2012-06-30 02:19:07 +00:00
# endif
2013-03-10 06:36:07 +00:00
2013-03-10 06:05:28 +00:00
# define FLASH_SIZE (FLASHEND + 1L)
2013-03-10 06:36:07 +00:00
# define BOOTLOADER_START (FLASH_SIZE - BOOTLOADER_SIZE)
2011-09-22 07:56:36 +00:00
2013-03-09 02:22:27 +00:00
/*
* Entering the Bootloader via Software
* http : //www.fourwalledcubicle.com/files/LUFA/Doc/120730/html/_page__software_bootloader_start.html
*/
# define BOOTLOADER_RESET_KEY 0xB007B007
uint32_t reset_key __attribute__ ( ( section ( " .noinit " ) ) ) ;
/* initialize MCU status by watchdog reset */
2012-06-30 02:19:07 +00:00
void bootloader_jump ( void ) {
2013-03-09 02:22:27 +00:00
# ifdef PROTOCOL_LUFA
USB_Disable ( ) ;
2012-06-30 02:19:07 +00:00
cli ( ) ;
2013-03-09 02:22:27 +00:00
_delay_ms ( 2000 ) ;
# endif
2012-06-30 05:44:14 +00:00
2013-03-09 02:22:27 +00:00
# ifdef PROTOCOL_PJRC
cli ( ) ;
2012-06-30 02:19:07 +00:00
UDCON = 1 ;
2013-03-09 02:22:27 +00:00
USBCON = ( 1 < < FRZCLK ) ;
2012-06-30 02:19:07 +00:00
UCSR1B = 0 ;
_delay_ms ( 5 ) ;
2012-06-30 05:44:14 +00:00
# endif
2013-03-09 02:22:27 +00:00
// watchdog reset
reset_key = BOOTLOADER_RESET_KEY ;
wdt_enable ( WDTO_250MS ) ;
for ( ; ; ) ;
}
/* this runs before main() */
void bootloader_jump_after_watchdog_reset ( void ) __attribute__ ( ( used , naked , section ( " .init3 " ) ) ) ;
void bootloader_jump_after_watchdog_reset ( void )
{
if ( ( MCUSR & ( 1 < < WDRF ) ) & & reset_key = = BOOTLOADER_RESET_KEY ) {
2013-03-10 06:05:28 +00:00
reset_key = 0 ;
2013-03-09 02:22:27 +00:00
2013-03-10 06:05:28 +00:00
// My custom USBasploader requires this to come up.
2013-03-09 02:22:27 +00:00
MCUSR = 0 ;
2013-03-10 06:05:28 +00:00
// Seems like Teensy halfkay loader requires clearing WDRF and disabling watchdog.
MCUSR & = ~ ( 1 < < WDRF ) ;
wdt_disable ( ) ;
2013-03-09 02:22:27 +00:00
( ( void ( * ) ( void ) ) BOOTLOADER_START ) ( ) ;
}
}
#if 0
/* Jumping To The Bootloader
* http : //www.pjrc.com/teensy/jump_to_bootloader.html
*
* This method doen ' t work when using LUFA . idk why .
* - needs to initialize more regisers or interrupt setting ?
*/
void bootloader_jump ( void ) {
# ifdef PROTOCOL_LUFA
USB_Disable ( ) ;
cli ( ) ;
_delay_ms ( 2000 ) ;
# endif
# ifdef PROTOCOL_PJRC
cli ( ) ;
UDCON = 1 ;
USBCON = ( 1 < < FRZCLK ) ;
UCSR1B = 0 ;
_delay_ms ( 5 ) ;
# endif
/*
* Initialize
*/
2012-06-30 02:19:07 +00:00
# if defined(__AVR_AT90USB162__)
EIMSK = 0 ; PCICR = 0 ; SPCR = 0 ; ACSR = 0 ; EECR = 0 ;
TIMSK0 = 0 ; TIMSK1 = 0 ; UCSR1B = 0 ;
DDRB = 0 ; DDRC = 0 ; DDRD = 0 ;
PORTB = 0 ; PORTC = 0 ; PORTD = 0 ;
# elif defined(__AVR_ATmega32U4__)
EIMSK = 0 ; PCICR = 0 ; SPCR = 0 ; ACSR = 0 ; EECR = 0 ; ADCSRA = 0 ;
TIMSK0 = 0 ; TIMSK1 = 0 ; TIMSK3 = 0 ; TIMSK4 = 0 ; UCSR1B = 0 ; TWCR = 0 ;
DDRB = 0 ; DDRC = 0 ; DDRD = 0 ; DDRE = 0 ; DDRF = 0 ; TWCR = 0 ;
PORTB = 0 ; PORTC = 0 ; PORTD = 0 ; PORTE = 0 ; PORTF = 0 ;
# elif defined(__AVR_AT90USB646__)
EIMSK = 0 ; PCICR = 0 ; SPCR = 0 ; ACSR = 0 ; EECR = 0 ; ADCSRA = 0 ;
TIMSK0 = 0 ; TIMSK1 = 0 ; TIMSK2 = 0 ; TIMSK3 = 0 ; UCSR1B = 0 ; TWCR = 0 ;
DDRA = 0 ; DDRB = 0 ; DDRC = 0 ; DDRD = 0 ; DDRE = 0 ; DDRF = 0 ;
PORTA = 0 ; PORTB = 0 ; PORTC = 0 ; PORTD = 0 ; PORTE = 0 ; PORTF = 0 ;
# elif defined(__AVR_AT90USB1286__)
EIMSK = 0 ; PCICR = 0 ; SPCR = 0 ; ACSR = 0 ; EECR = 0 ; ADCSRA = 0 ;
TIMSK0 = 0 ; TIMSK1 = 0 ; TIMSK2 = 0 ; TIMSK3 = 0 ; UCSR1B = 0 ; TWCR = 0 ;
DDRA = 0 ; DDRB = 0 ; DDRC = 0 ; DDRD = 0 ; DDRE = 0 ; DDRF = 0 ;
PORTA = 0 ; PORTB = 0 ; PORTC = 0 ; PORTD = 0 ; PORTE = 0 ; PORTF = 0 ;
# endif
2011-09-22 07:56:36 +00:00
2013-03-09 02:22:27 +00:00
/*
* USBaspLoader
*/
2012-10-15 09:14:59 +00:00
# if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
2012-06-30 05:44:14 +00:00
// This makes custom USBasploader come up.
MCUSR = 0 ;
// initialize ports
PORTB = 0 ; PORTC = 0 ; PORTD = 0 ;
DDRB = 0 ; DDRC = 0 ; DDRD = 0 ;
// disable interrupts
EIMSK = 0 ; EECR = 0 ; SPCR = 0 ;
ACSR = 0 ; SPMCSR = 0 ; WDTCSR = 0 ; PCICR = 0 ;
TIMSK0 = 0 ; TIMSK1 = 0 ; TIMSK2 = 0 ;
ADCSRA = 0 ; TWCR = 0 ; UCSR0B = 0 ;
# endif
2012-06-30 02:19:07 +00:00
// start Bootloader
( ( void ( * ) ( void ) ) BOOTLOADER_START ) ( ) ;
}
2013-03-10 06:05:28 +00:00
# endif