661 lines
24 KiB
C
661 lines
24 KiB
C
/* Name: bootloaderconfig.h
|
|
* Project: USBaspLoader
|
|
* Author: Christian Starkjohann
|
|
* Author: Stephan Baerwolf
|
|
* Creation Date: 2007-12-08
|
|
* Modification Date: 2013-03-31
|
|
* Tabsize: 4
|
|
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
|
|
* License: GNU GPL v2 (see License.txt)
|
|
*/
|
|
|
|
#ifndef __bootloaderconfig_h_included__
|
|
#define __bootloaderconfig_h_included__
|
|
#include "../misc/iofixes.h"
|
|
|
|
/*
|
|
General Description:
|
|
This file (together with some settings in Makefile) configures the boot loader
|
|
according to the hardware.
|
|
|
|
This file contains (besides the hardware configuration normally found in
|
|
usbconfig.h) two functions or macros: bootLoaderInit() and
|
|
bootLoaderCondition(). Whether you implement them as macros or as static
|
|
inline functions is up to you, decide based on code size and convenience.
|
|
|
|
bootLoaderInit() is called as one of the first actions after reset. It should
|
|
be a minimum initialization of the hardware so that the boot loader condition
|
|
can be read. This will usually consist of activating a pull-up resistor for an
|
|
external jumper which selects boot loader mode.
|
|
|
|
bootLoaderCondition() is called immediately after initialization and in each
|
|
main loop iteration. If it returns TRUE, the boot loader will be active. If it
|
|
returns FALSE, the boot loader jumps to address 0 (the loaded application)
|
|
immediately.
|
|
|
|
For compatibility with Thomas Fischl's avrusbboot, we also support the macro
|
|
names BOOTLOADER_INIT and BOOTLOADER_CONDITION for this functionality. If
|
|
these macros are defined, the boot loader usees them.
|
|
*/
|
|
|
|
/* ---------------------------- Macro Magic ---------------------------- */
|
|
#define PIN_CONCAT(a,b) a ## b
|
|
#define PIN_CONCAT3(a,b,c) a ## b ## c
|
|
|
|
#define PIN_PORT(a) PIN_CONCAT(PORT, a)
|
|
#define PIN_PIN(a) PIN_CONCAT(PIN, a)
|
|
#define PIN_DDR(a) PIN_CONCAT(DDR, a)
|
|
|
|
#define PIN(a, b) PIN_CONCAT3(P, a, b)
|
|
|
|
/* ---------------------------- Hardware Config ---------------------------- */
|
|
|
|
#ifndef USB_CFG_IOPORTNAME
|
|
#define USB_CFG_IOPORTNAME D
|
|
#endif
|
|
/* This is the port where the USB bus is connected. When you configure it to
|
|
* "B", the registers PORTB, PINB and DDRB will be used.
|
|
*/
|
|
#ifndef USB_CFG_INTPORT_BIT
|
|
#if (defined(__AVR_ATmega640__) || defined (__AVR_ATmega128__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__))
|
|
#define USB_CFG_INTPORT_BIT 0
|
|
#else
|
|
#define USB_CFG_INTPORT_BIT 2
|
|
#endif
|
|
#endif
|
|
/* Not all devices have their INT0 on PD2.
|
|
* Since "INT0" and "USB_CFG_DPLUS_BIT" should get the same signals,
|
|
* map them to be ideally the same:
|
|
* So abstract "USB_CFG_DPLUS_BIT" to this one here.
|
|
*/
|
|
|
|
#ifndef USB_CFG_DMINUS_BIT
|
|
/* This is Revision 3 and later (where PD6 and PD7 were swapped */
|
|
#define USB_CFG_DMINUS_BIT 3 /* Rev.2 and previous was 6 */
|
|
#endif
|
|
/* This is the bit number in USB_CFG_IOPORT where the USB D- line is connected.
|
|
* This may be any bit in the port.
|
|
*/
|
|
#ifndef USB_CFG_DPLUS_BIT
|
|
#define USB_CFG_DPLUS_BIT USB_CFG_INTPORT_BIT
|
|
#endif
|
|
/* This is the bit number in USB_CFG_IOPORT where the USB D+ line is connected.
|
|
* This may be any bit in the port. Please note that D+ must also be connected
|
|
* to interrupt pin INT0!
|
|
*/
|
|
#ifndef JUMPER_PORT
|
|
#define JUMPER_PORT USB_CFG_IOPORTNAME
|
|
#endif
|
|
/*
|
|
* jumper is connected to this port
|
|
*/
|
|
#ifndef JUMPER_BIT
|
|
/* This is Revision 3 and later (where PD6 and PD7 were swapped */
|
|
#define JUMPER_BIT 7 /* Rev.2 and previous was 7 */
|
|
#endif
|
|
/*
|
|
* jumper is connected to this bit in port "JUMPER_PORT", active low
|
|
*/
|
|
|
|
#define USB_CFG_CLOCK_KHZ (F_CPU/1000)
|
|
/* Clock rate of the AVR in MHz. Legal values are 12000, 16000 or 16500.
|
|
* The 16.5 MHz version of the code requires no crystal, it tolerates +/- 1%
|
|
* deviation from the nominal frequency. All other rates require a precision
|
|
* of 2000 ppm and thus a crystal!
|
|
* Default if not specified: 12 MHz
|
|
*/
|
|
|
|
/* ----------------------- Optional Hardware Config ------------------------ */
|
|
|
|
/* #define USB_CFG_PULLUP_IOPORTNAME D */
|
|
/* If you connect the 1.5k pullup resistor from D- to a port pin instead of
|
|
* V+, you can connect and disconnect the device from firmware by calling
|
|
* the macros usbDeviceConnect() and usbDeviceDisconnect() (see usbdrv.h).
|
|
* This constant defines the port on which the pullup resistor is connected.
|
|
*/
|
|
/* #define USB_CFG_PULLUP_BIT 4 */
|
|
/* This constant defines the bit number in USB_CFG_PULLUP_IOPORT (defined
|
|
* above) where the 1.5k pullup resistor is connected. See description
|
|
* above for details.
|
|
*/
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* ---------------------- feature / code size options ---------------------- */
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
#ifndef CONFIG_NO__HAVE_READ_LOCK_FUSE
|
|
#define HAVE_READ_LOCK_FUSE 1
|
|
#else
|
|
#define HAVE_READ_LOCK_FUSE 0
|
|
#endif
|
|
/*
|
|
* enable the loaders capability to load its lfuse, hfuse and lockbits
|
|
* ...However, programming of these is prohibited...
|
|
*/
|
|
|
|
#ifndef CONFIG_NO__HAVE_BLB11_SOFTW_LOCKBIT
|
|
#define HAVE_BLB11_SOFTW_LOCKBIT 1
|
|
#else
|
|
#define HAVE_BLB11_SOFTW_LOCKBIT 0
|
|
#endif
|
|
/*
|
|
* The IC itself do not need to prgra BLB11, but the bootloader will avaoid
|
|
* to erase itself from the bootregion
|
|
*/
|
|
|
|
#ifndef CONFIG_NO__HAVE_SPMINTEREFACE
|
|
#define HAVE_SPMINTEREFACE 1
|
|
#else
|
|
#define HAVE_SPMINTEREFACE 0
|
|
#endif
|
|
/*
|
|
* Since code within normal section of application memory (rww-section) is
|
|
* not able to call spm for programming flash-pages, this option (when
|
|
* enabled) will insert a small subroutine into the bootloader-section
|
|
* to enable applications to circumvent this limitation and make them
|
|
* able to program the flash in a similar way as the bootloader does, too.
|
|
* For further details see "spminterface.h", which implements this
|
|
* feature.
|
|
*/
|
|
|
|
#define HAVE_SPMINTEREFACE_NORETMAGIC 1
|
|
/*
|
|
* If sth. went wrong within "bootloader__do_spm" and this macro is ACTIVATED,
|
|
* then "bootloader__do_spm" will not return the call and loop infinity instead.
|
|
*
|
|
* This feature prevents old updaters to do sth. undefined on wrong magic.
|
|
*/
|
|
|
|
/* all boards should use a magic to make it safe to confuse updatefiles :-) */
|
|
#define HAVE_SPMINTEREFACE_MAGICVALUE 0
|
|
/* If this feature is enabled (value != 0), the configured 32bit value is
|
|
* used as a magic value within spminterface. "bootloader__do_spm" will check
|
|
* additional four (4) registers for this value and only proceed, if they contain
|
|
* the right value. With this feature you can identify your board and avoid
|
|
* updating the wrong bootloader to the wrong board!
|
|
*
|
|
* Not all values are possible - "SPMINTEREFACE_MAGICVALUE" must be very sparse!
|
|
* To avoid collisions, magic-values will be organized centrally by Stephan
|
|
* Following values are definitly blocked or reserved and must not be used:
|
|
* 0x00000000, 0x12345678,
|
|
* 0x00a500a5, 0x00a5a500, 0xa50000a5, 0xa500a500,
|
|
* 0x005a005a, 0x005a5a00, 0x5a00005a, 0x5a005a00,
|
|
* 0x5aa55aa5, 0x5aa5a55a, 0xa55a5aa5, 0xa55aa55a,
|
|
* 0x5a5a5a5a, 0xa5a5a5a5,
|
|
* 0xffa5ffa5, 0xffa5a5ff, 0xa5ffffa5, 0xa5ffa5ff,
|
|
* 0xff5aff5a, 0xff5a5aff, 0x5affff5a, 0x5aff5aff,
|
|
* 0x00ff00ff, 0x00ffff00, 0xff0000ff, 0xff00ff00,
|
|
* 0xffffffff
|
|
*
|
|
* To request your own magic, please send at least following information
|
|
* about yourself and your board together within an informal request to:
|
|
* stephan@matrixstorm.com / matrixstorm@gmx.de / stephan.baerwolf@tu-ilmenau.de
|
|
* - your name
|
|
* - your e-mail
|
|
* - your project (maybe an url?)
|
|
* - your type of MCU used
|
|
* --> your used "BOOTLOADER_ADDRESS" (since same magics can be reused for different "BOOTLOADER_ADDRESS")
|
|
*
|
|
* There may be no garanty for it, but Stephan will then send you an
|
|
* response with a "SPMINTEREFACE_MAGICVALUE" just for your board/project...
|
|
* WITH REQUESTING A MAGIC YOU AGREE TO PUBLISHED YOUR DATA SEND WITHIN THE REQUEST
|
|
*
|
|
*
|
|
* ***************************************************************************
|
|
* ***************************************************************************
|
|
*
|
|
* Because of pressing interest there will be following free-for-use scheme.
|
|
* It will always start with 0xf as the 4 most significant bits, and then
|
|
* can be encoded based of the signature of the AVR, the IO-Port used for USB,
|
|
* the USB dataline PINs, the external interrupt used for USB, the clock frequency
|
|
* the BOD voltage and if the watchdog is enabled by fuses.
|
|
*
|
|
* The magic will be: 0xf??????? in binary 0b1111ZZZZ YYYYYYYY WXXXVUUU TTSSSRRR
|
|
*
|
|
* --> where the 4 bit of Z correspond to the middle of the 3 byte AVR signature:
|
|
* SIGNATURE_1 == 0x90 <--> ZZZZ == 0b0000
|
|
* SIGNATURE_1 == 0x91 <--> ZZZZ == 0b0001
|
|
* SIGNATURE_1 == 0x92 <--> ZZZZ == 0b0010
|
|
* SIGNATURE_1 == 0x93 <--> ZZZZ == 0b0011
|
|
* SIGNATURE_1 == 0x94 <--> ZZZZ == 0b0100
|
|
* SIGNATURE_1 == 0x95 <--> ZZZZ == 0b0101
|
|
* SIGNATURE_1 == 0x96 <--> ZZZZ == 0b0110
|
|
* SIGNATURE_1 == 0x97 <--> ZZZZ == 0b0111
|
|
* SIGNATURE_1 == 0x98 <--> ZZZZ == 0b1000
|
|
* SIGNATURE_1 == 0xA6 <--> ZZZZ == 0b1001
|
|
* SIGNATURE_1 == 0xA7 <--> ZZZZ == 0b1010 *
|
|
* SIGNATURE_1 == 0xA8 <--> ZZZZ == 0b1011
|
|
* reserved ZZZZ == 0b1100 *
|
|
* not free (database magics) ZZZZ == 0b1101 *
|
|
* not free (database magics) ZZZZ == 0b1110 *
|
|
* not free (database magics) ZZZZ == 0b1111 *
|
|
* If the AVRs SIGNATURE_1 is different from the presented 12, this coding scheme is
|
|
* not applicable for you - please ask for a personal magic in this case.
|
|
*
|
|
*
|
|
* --> where the 8 bit of Y are the SIGNATURE_2 byte (for example 0b00000111 on ATmega8)
|
|
*
|
|
*
|
|
* --> where the 1 bit of W is watchdog enabled by fuse: 0=no, 1=yes (WD enabled)
|
|
*
|
|
*
|
|
* --> where the 3 bit of X are the (external) crystal clockspeed
|
|
* 12MHz external crystal <--> XXX == 0b000
|
|
* 12.8MHz external crystal <--> XXX == 0b001
|
|
* reserved <--> XXX == 0b010
|
|
* 15MHz external crystal <--> XXX == 0b011
|
|
* 16MHz external crystal <--> XXX == 0b100
|
|
* 16.5MHz external crystal <--> XXX == 0b101
|
|
* 18MHz external crystal <--> XXX == 0b110
|
|
* 20MHz external crystal <--> XXX == 0b111
|
|
* If your clockspeed is different from the presented 8, this coding scheme is
|
|
* not applicable for you - please ask for a personal magic in this case.
|
|
*
|
|
*
|
|
* --> where the 1 bit of V depends on the controllers Vcc:
|
|
* 4.5V (ususally 5V) <--> V == 0
|
|
* 3.3V <--> V == 1
|
|
*
|
|
*
|
|
* --> where the 3 bit of U define the PORT (USB_CFG_IOPORTNAME) for USB
|
|
* PORTA <--> UUU == 0b000
|
|
* PORTB <--> UUU == 0b001
|
|
* PORTC <--> UUU == 0b010
|
|
* PORTD <--> UUU == 0b011
|
|
* PORTE <--> UUU == 0b100
|
|
* PORTF <--> UUU == 0b101
|
|
* PORTG <--> UUU == 0b110
|
|
* PORTH <--> UUU == 0b111
|
|
* If your PORT is different from the presented 8:
|
|
* This coding scheme is more an example. UUU=0b000 really means, the first GPIO port
|
|
* on the specified MCU. (0b001 is the second, 0b010 the third...)
|
|
* Normally there aren't more then 8 GPIO ports on an AVR - so this coding works.
|
|
* If there are more then 8, only the first 8 ports can be encoded and otherwise
|
|
* this coding scheme is not applicable for you - please ask for a personal magic in this case.
|
|
*
|
|
*
|
|
* --> where the 2 bit of T define the external interrupt used for USBD
|
|
* INT0 <--> TT == 0b00
|
|
* INT1 <--> TT == 0b01
|
|
* INT2 <--> TT == 0b10
|
|
* INT3 <--> TT == 0b11
|
|
* If you use a different interrupt, this coding scheme is not applicable
|
|
* for you - please ask for a personal magic in this case.
|
|
*
|
|
*
|
|
* --> where the 3 bit of S define the PIN (on the previous encoded port) for USB+
|
|
* (basically the value of USB_CFG_DPLUS_BIT)
|
|
* 0 <--> SSS == 0b000
|
|
* 1 <--> SSS == 0b001
|
|
* ...
|
|
* 7 <--> SSS == 0b111
|
|
*
|
|
*
|
|
* --> where the 3 bit of R define the PIN (on the previous encoded port) for USB-
|
|
* (basically the value of USB_CFG_DMINUS_BIT)
|
|
* 0 <--> RRR == 0b000
|
|
* 1 <--> RRR == 0b001
|
|
* ...
|
|
* 7 <--> RRR == 0b111
|
|
*
|
|
*
|
|
* WARNING:
|
|
* Please note, that this 0xf------- magic does not include
|
|
* any information about the bootloader condition pin (and port)!
|
|
* This magic just ensures basic protection against different
|
|
* layouts. (Which only covers essential data)
|
|
*
|
|
* ?Maybe as a heuristic?:
|
|
* The bootloader condition pin should be the same port as USB,
|
|
* at the pin before USB_CFG_DMINUS_BIT.
|
|
*
|
|
* If you want to be very safe, request your own magic...
|
|
*
|
|
*
|
|
*
|
|
* Examples (USB pinning are defaults from this file):
|
|
*
|
|
* "ATmega8@16MHz powered with 5V and no watchdog fused": 0xf3078317
|
|
* The same just for ATmega328p: 0xf50f8317
|
|
*
|
|
* "ATmega1024p @ 20MHz powered with 3V and watchdog fused active": 0xf705fb17
|
|
* "ATmega2560 @ 12MHz powered with 5V and watchdog fused active": 0xf8010307
|
|
*
|
|
* ***************************************************************************
|
|
* ***************************************************************************
|
|
*
|
|
*/
|
|
|
|
#ifndef CONFIG_NO__EEPROM_PAGED_ACCESS
|
|
# define HAVE_EEPROM_PAGED_ACCESS 1
|
|
#else
|
|
# define HAVE_EEPROM_PAGED_ACCESS 0
|
|
#endif
|
|
/* If HAVE_EEPROM_PAGED_ACCESS is defined to 1, page mode access to EEPROM is
|
|
* compiled in. Whether page mode or byte mode access is used by AVRDUDE
|
|
* depends on the target device. Page mode is only used if the device supports
|
|
* it, e.g. for the ATMega88, 168 etc. You can save quite a bit of memory by
|
|
* disabling page mode EEPROM access. Costs ~ 138 bytes.
|
|
*/
|
|
|
|
#ifndef CONFIG_NO__EEPROM_BYTE_ACCESS
|
|
# define HAVE_EEPROM_BYTE_ACCESS 1
|
|
#else
|
|
# define HAVE_EEPROM_BYTE_ACCESS 0
|
|
#endif
|
|
/* If HAVE_EEPROM_BYTE_ACCESS is defined to 1, byte mode access to EEPROM is
|
|
* compiled in. Byte mode is only used if the device (as identified by its
|
|
* signature) does not support page mode for EEPROM. It is required for
|
|
* accessing the EEPROM on the ATMega8. Costs ~54 bytes.
|
|
*/
|
|
|
|
#ifndef CONFIG_NO__BOOTLOADER_CAN_EXIT
|
|
# define BOOTLOADER_CAN_EXIT 1
|
|
#else
|
|
# define BOOTLOADER_CAN_EXIT 0
|
|
#endif
|
|
/* If this macro is defined to 1, the boot loader will exit shortly after the
|
|
* programmer closes the connection to the device. Costs extra bytes.
|
|
*/
|
|
|
|
#ifndef CONFIG_NO__CHIP_ERASE
|
|
# define HAVE_CHIP_ERASE 1
|
|
#else
|
|
# define HAVE_CHIP_ERASE 0
|
|
#endif
|
|
/* If this macro is defined to 1, the boot loader implements the Chip Erase
|
|
* ISP command. Otherwise pages are erased on demand before they are written.
|
|
*/
|
|
#ifndef CONFIG_NO__ONDEMAND_PAGEERASE
|
|
# define HAVE_ONDEMAND_PAGEERASE 1
|
|
#else
|
|
# define HAVE_ONDEMAND_PAGEERASE 0
|
|
#endif
|
|
/* Even if "HAVE_CHIP_ERASE" is avtivated - enabling the "HAVE_ONDEMAND_PAGEERASE"-
|
|
* feature the bootloader will erase pages on demand short before writing new data
|
|
* to it.
|
|
* If pages are not erase before reprogram (for example because user call avrdude -D)
|
|
* then data may become inconsistent since writing only allow to unset bits in the flash.
|
|
* This feature may prevent this...
|
|
*/
|
|
|
|
#ifndef CONFIG_NO__NEED_WATCHDOG
|
|
# define NEED_WATCHDOG 1
|
|
#else
|
|
# define NEED_WATCHDOG 0
|
|
#endif
|
|
/* ATTANTION: This macro MUST BE 1, if the MCU has reset enabled watchdog (WDTON is 0).
|
|
* If this macro is defined to 1, the bootloader implements an additional "wdt_disable()"
|
|
* after its contional entry point.
|
|
* If the used MCU is fused not to enable watchdog after reset (WDTON is 1 - safty level 1)
|
|
* then "NEED_WATCHDOG" may be deactivated in order to save some memory.
|
|
*/
|
|
|
|
#ifndef CONFIG_NO__PRESERVE_WATCHDOG
|
|
# define PRESERVE_WATCHDOG 1
|
|
#else
|
|
# define PRESERVE_WATCHDOG 0
|
|
#endif
|
|
/* In case a watchdog is supported (NEED_WATCHDOG) and USE_EXCESSIVE_ASSEMBLER is false,
|
|
* the bootloader will run with active watchdog instead of disabling it.
|
|
* After leaving the bootloader, the original watchdog state is restored.
|
|
* WARNING: This might break compatibility with user firmwares, since they
|
|
* need to be aware of watchdog enabled. (which could be enabled by some
|
|
* previous running firmware and not neccessarily only by the WDTON FUSE)
|
|
*/
|
|
|
|
#ifndef CONFIG_NO__PRECISESLEEP
|
|
# define HAVE_UNPRECISEWAIT 0
|
|
#else
|
|
# define HAVE_UNPRECISEWAIT 1
|
|
#endif
|
|
/* This macro enables hand-optimized assembler code
|
|
* instead to use _sleep_ms for delaying USB enumeration.
|
|
* Because normally these timings do not need to be exact,
|
|
* the optimized assembler code does not need to be precise.
|
|
* Therefore it is very small, which saves some PROGMEM bytes!
|
|
*/
|
|
|
|
#ifndef CONFIG_NO__FLASH_BYTE_READACCESS
|
|
# define HAVE_FLASH_BYTE_READACCESS 1
|
|
#else
|
|
# define HAVE_FLASH_BYTE_READACCESS 0
|
|
#endif
|
|
/* If HAVE_FLASH_BYTE_READACCESS is defined to 1, byte mode access to FLASH is
|
|
* compiled in. Byte mode sometimes might be used by some programming softwares
|
|
* (avrdude in terminal mode). Without this feature the device would return "0"
|
|
* instead the right content of the flash memory.
|
|
*/
|
|
|
|
#ifdef CONFIG_USE__EXCESSIVE_ASSEMBLER
|
|
# define USE_EXCESSIVE_ASSEMBLER 1
|
|
#else
|
|
# define USE_EXCESSIVE_ASSEMBLER 0
|
|
#endif
|
|
/* This macro enables large codeareas of hand-optimized assembler code.
|
|
* WARNING:
|
|
* It will only work properly on devices with <64k of flash memory and SRAM.
|
|
* Some configuration macros (when changed) may not be applied correctly
|
|
* (since their behaviour is raced within asm)!
|
|
* Nevertheless this feature saves lots of memory.
|
|
*/
|
|
|
|
#ifdef CONFIG_USE__BOOTUP_CLEARRAM
|
|
# define USE_BOOTUP_CLEARRAM 1
|
|
#else
|
|
# define USE_BOOTUP_CLEARRAM 0
|
|
#endif
|
|
/* This macro enables some (init3) code, executed at bootup.
|
|
* This codefragment will safely overwrite the whole SRAM with "0"
|
|
* (except registers and IO), since RESET will NOT clear old RAM content.
|
|
*/
|
|
|
|
#ifdef CONFIG_NO__BOOTLOADERENTRY_FROMSOFTWARE
|
|
# define HAVE_BOOTLOADERENTRY_FROMSOFTWARE 0
|
|
#else
|
|
# define HAVE_BOOTLOADERENTRY_FROMSOFTWARE 1
|
|
#endif
|
|
/*
|
|
* Enable firmware to boot the bootloader without
|
|
* user intervention
|
|
*/
|
|
|
|
#ifdef CONFIG_NO__BOOTLOADER_HIDDENEXITCOMMAND
|
|
# define HAVE_BOOTLOADER_HIDDENEXITCOMMAND 0
|
|
#else
|
|
# define HAVE_BOOTLOADER_HIDDENEXITCOMMAND 0xff
|
|
#endif
|
|
/*
|
|
* When enabling "BOOTLOADER_HIDDENEXITCOMMAND", then
|
|
* sending the RAW-ISP command "0xff 0xXX 0xXX 0xXX"
|
|
* will cause the bootloader to start the firmware
|
|
* as soon as the programming software disconnects.
|
|
*/
|
|
|
|
#ifdef CONFIG_BOOTLOADER_LOOPCYCLES_TIMEOUT
|
|
# define BOOTLOADER_LOOPCYCLES_TIMEOUT (CONFIG_BOOTLOADER_LOOPCYCLES_TIMEOUT)
|
|
#else
|
|
# define BOOTLOADER_LOOPCYCLES_TIMEOUT (0)
|
|
#endif
|
|
/*
|
|
* When greater than "0", "BOOTLOADER_LOOPCYCLES_TIMEOUT"
|
|
* defines how many 16bit loopcycles can be cycled,
|
|
* before bootloader times out and starts user
|
|
* firmware.
|
|
* Of course "BOOTLOADER_CAN_EXIT" must be enabled.
|
|
* If value is even too small, bootloader will not
|
|
* exit as long as bootLoaderConditionSimple stays on.
|
|
*/
|
|
|
|
#ifdef CONFIG_HAVE__BOOTLOADER_ABORTTIMEOUTONACT
|
|
#endif
|
|
/*
|
|
* When defined, the bootloader will abort the timeout when
|
|
* it sees some activity (bootLoaderConditionSimple() or
|
|
* programming).
|
|
* After aborting timeout, the bootloader falls back to
|
|
* conventional exitting.
|
|
*/
|
|
|
|
#ifdef CONFIG_HAVE__BOOTLOADER_ALWAYSENTERPROGRAMMODE
|
|
# if (BOOTLOADER_CAN_EXIT)
|
|
# define BOOTLOADER_ALWAYSENTERPROGRAMMODE 1
|
|
# else
|
|
# define BOOTLOADER_ALWAYSENTERPROGRAMMODE 0
|
|
# endif
|
|
#else
|
|
# define BOOTLOADER_ALWAYSENTERPROGRAMMODE 0
|
|
#endif
|
|
/*
|
|
* Ignore bootLoaderCondition() (BUT NOT bootLoaderConditionSimple())
|
|
* and always enter the program-mode.
|
|
* This is helpful to emulate behaviour of Arduino bootloaders
|
|
*
|
|
* However, this feature may be dangerous, since bootloader may never exit.
|
|
* So it is enabled, only if "CONFIG_NO__BOOTLOADER_CAN_EXIT" is disabled.
|
|
*
|
|
*/
|
|
|
|
#ifdef CONFIG_HAVE__BOOTLOADER_IGNOREPROGBUTTON
|
|
# if ( (BOOTLOADER_ALWAYSENTERPROGRAMMODE) && (defined(BOOTLOADER_CAN_EXIT)) && (BOOTLOADER_LOOPCYCLES_TIMEOUT >= 8) )
|
|
# define BOOTLOADER_IGNOREPROGBUTTON 1
|
|
# else
|
|
# define BOOTLOADER_IGNOREPROGBUTTON 0
|
|
# endif
|
|
#endif
|
|
/*
|
|
* Generates an USBaspLoader without using the PROGBUTTON.
|
|
* It can be used to reduce the required PINcount for USBaspLoader
|
|
* on the MCU.
|
|
* However this feature is very dangerous, so it becomes only
|
|
* enabled, if "CONFIG_HAVE__BOOTLOADER_ALWAYSENTERPROGRAMMODE" is
|
|
* enabled and "CONFIG_NO__BOOTLOADER_CAN_EXIT" is disabled, too.
|
|
* Additionally "BOOTLOADER_LOOPCYCLES_TIMEOUT" must be greater
|
|
* or equal than 8 (In order to give user enough time to program).
|
|
*
|
|
* When active, "JUMPER_PORT" and "JUMPER_BIT" are ignored and
|
|
* can be soldered otherwise.
|
|
*/
|
|
|
|
#ifdef CONFIG_NO__BOOTLOADER_ADDITIONALDEVICEWAIT
|
|
# define HAVE_BOOTLOADER_ADDITIONALMSDEVICEWAIT 0
|
|
#else
|
|
# define HAVE_BOOTLOADER_ADDITIONALMSDEVICEWAIT 50
|
|
#endif
|
|
/*
|
|
* When enabling "HAVE_BOOTLOADER_ADDITIONALMSDEVICEWAIT", then
|
|
* the bootloader will alway delay its bootup by the configured
|
|
* number of milliseconds.
|
|
* This gives the pullups additional time to charge up.
|
|
*/
|
|
|
|
//#define SIGNATURE_BYTES 0x1e, 0x93, 0x07, 0 /* ATMega8 */
|
|
/* This macro defines the signature bytes returned by the emulated USBasp to
|
|
* the programmer software. They should match the actual device at least in
|
|
* memory size and features. If you don't define this, values for ATMega8,
|
|
* ATMega88, ATMega168 and ATMega328 are guessed correctly.
|
|
*/
|
|
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
/* Example configuration: Port D bit 3 is connected to a jumper which ties
|
|
* this pin to GND if the boot loader is requested. Initialization allows
|
|
* several clock cycles for the input voltage to stabilize before
|
|
* bootLoaderCondition() samples the value.
|
|
* We use a function for bootLoaderInit() for convenience and a macro for
|
|
* bootLoaderCondition() for efficiency.
|
|
*/
|
|
|
|
#ifndef __ASSEMBLER__ /* assembler cannot parse function definitions */
|
|
|
|
#ifndef MCUCSR /* compatibility between ATMega8 and ATMega88 */
|
|
# define MCUCSR MCUSR
|
|
# define __MCUCSR_COMPATMODE 1
|
|
#endif
|
|
|
|
#ifndef WDTCR /* another compatibility between ATMega8 and ATMega88 */
|
|
# define WDTCR WDTCSR
|
|
# define __WDTCR_COMPATMODE 1
|
|
#endif
|
|
|
|
/* WARNING:
|
|
* following commands and macros may not be evaluated properly when 'USE_EXCESSIVE_ASSEMBLER"
|
|
*/
|
|
|
|
static inline void bootLoaderInit(void)
|
|
{
|
|
#if (BOOTLOADER_IGNOREPROGBUTTON)
|
|
#else
|
|
PIN_DDR(JUMPER_PORT) = 0;
|
|
PIN_PORT(JUMPER_PORT) = (1<< PIN(JUMPER_PORT, JUMPER_BIT)); /* activate pull-up */
|
|
#endif
|
|
|
|
// deactivated by Stephan - reset after each avrdude op is annoing!
|
|
// if(!(MCUCSR & (1 << EXTRF))) /* If this was not an external reset, ignore */
|
|
// leaveBootloader();
|
|
}
|
|
|
|
static inline void bootLoaderExit(void)
|
|
{
|
|
#if (BOOTLOADER_IGNOREPROGBUTTON)
|
|
#else
|
|
PIN_PORT(JUMPER_PORT) = 0; /* undo bootLoaderInit() changes */
|
|
#endif
|
|
}
|
|
|
|
|
|
#if (BOOTLOADER_IGNOREPROGBUTTON)
|
|
# define bootLoaderConditionSimple() (false)
|
|
#else
|
|
# define bootLoaderConditionSimple() ((PIN_PIN(JUMPER_PORT) & (1 << PIN(JUMPER_PORT, JUMPER_BIT))) == 0)
|
|
#endif
|
|
|
|
#if (HAVE_BOOTLOADERENTRY_FROMSOFTWARE)
|
|
/*
|
|
* How it works: The idea
|
|
*
|
|
* During normal C initialization, the stackpointer (SP) always is pointed to
|
|
* SRAMs end, where it grows towards RAMSTART.
|
|
*
|
|
* Check if last possible pushed address in stack is bootloaders address.
|
|
* Store investigation result into "__BOOTLOADERENTRY_FROMSOFTWARE__bootup_RAMEND_doesmatch"
|
|
* Result will be "0xff" in case of mismatch.
|
|
*/
|
|
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
|
|
#define __BOOTLOADERENTRY_FROMSOFTWARE__EXPECTEDADDRESS (BOOTLOADER_ADDRESS>>1)
|
|
static volatile uint8_t __BOOTLOADERENTRY_FROMSOFTWARE__bootup_RAMEND_doesmatch __attribute__ ((section(".noinit")));
|
|
static volatile uint8_t __BOOTLOADERENTRY_FROMSOFTWARE__bootup_MCUCSR __attribute__ ((section(".noinit")));
|
|
|
|
# if (BOOTLOADER_ALWAYSENTERPROGRAMMODE)
|
|
# define bootLoaderCondition() (true)
|
|
# else
|
|
static inline bool bootLoaderCondition(void)
|
|
{
|
|
if (__BOOTLOADERENTRY_FROMSOFTWARE__bootup_MCUCSR & (~(_BV(WDRF)))) {
|
|
} else {
|
|
if (__BOOTLOADERENTRY_FROMSOFTWARE__bootup_RAMEND_doesmatch == (__BOOTLOADERENTRY_FROMSOFTWARE__EXPECTEDADDRESS & 0xff)) {
|
|
// anything else: match - the firmware is calling the bootloader
|
|
return true;
|
|
}
|
|
}
|
|
return bootLoaderConditionSimple();
|
|
}
|
|
# endif
|
|
#else
|
|
# if (BOOTLOADER_ALWAYSENTERPROGRAMMODE)
|
|
# define bootLoaderCondition() (true)
|
|
# else
|
|
# define bootLoaderCondition bootLoaderConditionSimple
|
|
# endif
|
|
#endif
|
|
|
|
#endif /* __ASSEMBLER__ */
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
#endif /* __bootloader_h_included__ */
|