From f991bf23b2a5186441fdc0a163120ca0ed92e91c Mon Sep 17 00:00:00 2001 From: Dirk Eichel Date: Wed, 27 Feb 2013 22:34:36 +0100 Subject: [PATCH] Add bootloader files for ATmega1284/Sanguino MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added the optiboot bootloader, uses only 512kB of FLASH Includes .hex file is for 20MHz µC Clock and serial speed of 57k6 --- .../Sanguino/bootloaders/atmega1284p/Makefile | 470 ++++++++++ .../Sanguino/bootloaders/atmega1284p/boot.h | 848 ++++++++++++++++++ .../bootloaders/atmega1284p/optiboot.c | 724 +++++++++++++++ .../optiboot_1284P_20MHz_57k6_baud.hex | 33 + .../bootloaders/atmega1284p/pin_defs.h | 81 ++ .../Sanguino/bootloaders/atmega1284p/stk500.h | 39 + 6 files changed, 2195 insertions(+) create mode 100644 ArduinoAddons/Arduino_0.xx/Sanguino/bootloaders/atmega1284p/Makefile create mode 100644 ArduinoAddons/Arduino_0.xx/Sanguino/bootloaders/atmega1284p/boot.h create mode 100644 ArduinoAddons/Arduino_0.xx/Sanguino/bootloaders/atmega1284p/optiboot.c create mode 100644 ArduinoAddons/Arduino_0.xx/Sanguino/bootloaders/atmega1284p/optiboot_1284P_20MHz_57k6_baud.hex create mode 100644 ArduinoAddons/Arduino_0.xx/Sanguino/bootloaders/atmega1284p/pin_defs.h create mode 100644 ArduinoAddons/Arduino_0.xx/Sanguino/bootloaders/atmega1284p/stk500.h diff --git a/ArduinoAddons/Arduino_0.xx/Sanguino/bootloaders/atmega1284p/Makefile b/ArduinoAddons/Arduino_0.xx/Sanguino/bootloaders/atmega1284p/Makefile new file mode 100644 index 0000000000..742fd4b798 --- /dev/null +++ b/ArduinoAddons/Arduino_0.xx/Sanguino/bootloaders/atmega1284p/Makefile @@ -0,0 +1,470 @@ +# Makefile for ATmegaBOOT +# E.Lins, 18.7.2005 +# $Id$ +# +# Instructions +# +# To make bootloader .hex file: +# make diecimila +# make lilypad +# make ng +# etc... +# +# To burn bootloader .hex file: +# make diecimila_isp +# make lilypad_isp +# make ng_isp +# etc... + +# program name should not be changed... +PROGRAM = optiboot + +# The default behavior is to build using tools that are in the users +# current path variables, but we can also build using an installed +# Arduino user IDE setup, or the Arduino source tree. +# Uncomment this next lines to build within the arduino environment, +# using the arduino-included avrgcc toolset (mac and pc) +# ENV ?= arduino +# ENV ?= arduinodev +# OS ?= macosx +# OS ?= windows + + +# enter the parameters for the avrdude isp tool +ISPTOOL = stk500v2 +ISPPORT = usb +ISPSPEED = -b 115200 + +MCU_TARGET = atmega168 +LDSECTIONS = -Wl,--section-start=.text=0x3e00 -Wl,--section-start=.version=0x3ffe + +# Build environments +# Start of some ugly makefile-isms to allow optiboot to be built +# in several different environments. See the README.TXT file for +# details. + +# default +fixpath = $(1) + +ifeq ($(ENV), arduino) +# For Arduino, we assume that we're connected to the optiboot directory +# included with the arduino distribution, which means that the full set +# of avr-tools are "right up there" in standard places. +TOOLROOT = ../../../tools +GCCROOT = $(TOOLROOT)/avr/bin/ +AVRDUDE_CONF = -C$(TOOLROOT)/avr/etc/avrdude.conf + +ifeq ($(OS), windows) +# On windows, SOME of the tool paths will need to have backslashes instead +# of forward slashes (because they use windows cmd.exe for execution instead +# of a unix/mingw shell?) We also have to ensure that a consistent shell +# is used even if a unix shell is installed (ie as part of WINAVR) +fixpath = $(subst /,\,$1) +SHELL = cmd.exe +endif + +else ifeq ($(ENV), arduinodev) +# Arduino IDE source code environment. Use the unpacked compilers created +# by the build (you'll need to do "ant build" first.) +ifeq ($(OS), macosx) +TOOLROOT = ../../../../build/macosx/work/Arduino.app/Contents/Resources/Java/hardware/tools +endif +ifeq ($(OS), windows) +TOOLROOT = ../../../../build/windows/work/hardware/tools +endif + +GCCROOT = $(TOOLROOT)/avr/bin/ +AVRDUDE_CONF = -C$(TOOLROOT)/avr/etc/avrdude.conf + +else +GCCROOT = +AVRDUDE_CONF = +endif +# +# End of build environment code. + + +# the efuse should really be 0xf8; since, however, only the lower +# three bits of that byte are used on the atmega168, avrdude gets +# confused if you specify 1's for the higher bits, see: +# http://tinker.it/now/2007/02/24/the-tale-of-avrdude-atmega168-and-extended-bits-fuses/ +# +# similarly, the lock bits should be 0xff instead of 0x3f (to +# unlock the bootloader section) and 0xcf instead of 0x2f (to +# lock it), but since the high two bits of the lock byte are +# unused, avrdude would get confused. + +ISPFUSES = $(GCCROOT)avrdude $(AVRDUDE_CONF) -c $(ISPTOOL) \ + -p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \ + -e -u -U lock:w:0x3f:m -U efuse:w:0x$(EFUSE):m \ + -U hfuse:w:0x$(HFUSE):m -U lfuse:w:0x$(LFUSE):m +ISPFLASH = $(GCCROOT)avrdude $(AVRDUDE_CONF) -c $(ISPTOOL) \ + -p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \ + -U flash:w:$(PROGRAM)_$(TARGET).hex -U lock:w:0x2f:m + +STK500 = "C:\Program Files\Atmel\AVR Tools\STK500\Stk500.exe" +STK500-1 = $(STK500) -e -d$(MCU_TARGET) -pf -vf -if$(PROGRAM)_$(TARGET).hex \ +-lFF -LFF -f$(HFUSE)$(LFUSE) -EF8 -ms -q -cUSB -I200kHz -s -wt +STK500-2 = $(STK500) -d$(MCU_TARGET) -ms -q -lCF -LCF -cUSB -I200kHz -s -wt + +OBJ = $(PROGRAM).o +OPTIMIZE = -Os -fno-inline-small-functions -fno-split-wide-types -mshort-calls + +DEFS = +LIBS = + +CC = $(GCCROOT)avr-gcc + +# Override is only needed by avr-lib build system. + +override CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) -DF_CPU=$(AVR_FREQ) $(DEFS) +override LDFLAGS = $(LDSECTIONS) -Wl,--relax -Wl,--gc-sections -nostartfiles -nostdlib + +OBJCOPY = $(GCCROOT)avr-objcopy +OBJDUMP = $(call fixpath,$(GCCROOT)avr-objdump) + +SIZE = $(GCCROOT)avr-size + +# Test platforms +# Virtual boot block test +virboot328: TARGET = atmega328 +virboot328: MCU_TARGET = atmega328p +virboot328: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' '-DVIRTUAL_BOOT' +virboot328: AVR_FREQ = 16000000L +virboot328: LDSECTIONS = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe +virboot328: $(PROGRAM)_atmega328.hex +virboot328: $(PROGRAM)_atmega328.lst + +# 20MHz clocked platforms +# +# These are capable of 230400 baud, or 115200 baud on PC (Arduino Avrdude issue) +# + +pro20: TARGET = pro_20mhz +pro20: MCU_TARGET = atmega168 +pro20: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' +pro20: AVR_FREQ = 20000000L +pro20: $(PROGRAM)_pro_20mhz.hex +pro20: $(PROGRAM)_pro_20mhz.lst + +pro20_isp: pro20 +pro20_isp: TARGET = pro_20mhz +# 2.7V brownout +pro20_isp: HFUSE = DD +# Full swing xtal (20MHz) 258CK/14CK+4.1ms +pro20_isp: LFUSE = C6 +# 512 byte boot +pro20_isp: EFUSE = 04 +pro20_isp: isp + +# 16MHz clocked platforms +# +# These are capable of 230400 baud, or 115200 baud on PC (Arduino Avrdude issue) +# + +pro16: TARGET = pro_16MHz +pro16: MCU_TARGET = atmega168 +pro16: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' +pro16: AVR_FREQ = 16000000L +pro16: $(PROGRAM)_pro_16MHz.hex +pro16: $(PROGRAM)_pro_16MHz.lst + +pro16_isp: pro16 +pro16_isp: TARGET = pro_16MHz +# 2.7V brownout +pro16_isp: HFUSE = DD +# Full swing xtal (20MHz) 258CK/14CK+4.1ms +pro16_isp: LFUSE = C6 +# 512 byte boot +pro16_isp: EFUSE = 04 +pro16_isp: isp + +# Diecimila, Duemilanove with m168, and NG use identical bootloaders +# Call it "atmega168" for generality and clarity, keep "diecimila" for +# backward compatibility of makefile +# +atmega168: TARGET = atmega168 +atmega168: MCU_TARGET = atmega168 +atmega168: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' +atmega168: AVR_FREQ = 16000000L +atmega168: $(PROGRAM)_atmega168.hex +atmega168: $(PROGRAM)_atmega168.lst + +atmega168_isp: atmega168 +atmega168_isp: TARGET = atmega168 +# 2.7V brownout +atmega168_isp: HFUSE = DD +# Low power xtal (16MHz) 16KCK/14CK+65ms +atmega168_isp: LFUSE = FF +# 512 byte boot +atmega168_isp: EFUSE = 04 +atmega168_isp: isp + +diecimila: TARGET = diecimila +diecimila: MCU_TARGET = atmega168 +diecimila: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' +diecimila: AVR_FREQ = 16000000L +diecimila: $(PROGRAM)_diecimila.hex +diecimila: $(PROGRAM)_diecimila.lst + +diecimila_isp: diecimila +diecimila_isp: TARGET = diecimila +# 2.7V brownout +diecimila_isp: HFUSE = DD +# Low power xtal (16MHz) 16KCK/14CK+65ms +diecimila_isp: LFUSE = FF +# 512 byte boot +diecimila_isp: EFUSE = 04 +diecimila_isp: isp + +atmega328: TARGET = atmega328 +atmega328: MCU_TARGET = atmega328p +atmega328: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' +atmega328: AVR_FREQ = 16000000L +atmega328: LDSECTIONS = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe +atmega328: $(PROGRAM)_atmega328.hex +atmega328: $(PROGRAM)_atmega328.lst + +atmega328_isp: atmega328 +atmega328_isp: TARGET = atmega328 +atmega328_isp: MCU_TARGET = atmega328p +# 512 byte boot, SPIEN +atmega328_isp: HFUSE = DE +# Low power xtal (16MHz) 16KCK/14CK+65ms +atmega328_isp: LFUSE = FF +# 2.7V brownout +atmega328_isp: EFUSE = 05 +atmega328_isp: isp + +atmega1284: TARGET = atmega1284p +atmega1284: MCU_TARGET = atmega1284p +atmega1284: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' '-DBIGBOOT' +atmega1284: AVR_FREQ = 16000000L +atmega1284: LDSECTIONS = -Wl,--section-start=.text=0x1fc00 +atmega1284: $(PROGRAM)_atmega1284p.hex +atmega1284: $(PROGRAM)_atmega1284p.lst + +atmega1284_isp: atmega1284 +atmega1284_isp: TARGET = atmega1284p +atmega1284_isp: MCU_TARGET = atmega1284p +# 1024 byte boot +atmega1284_isp: HFUSE = DE +# Low power xtal (16MHz) 16KCK/14CK+65ms +atmega1284_isp: LFUSE = FF +# 2.7V brownout +atmega1284_isp: EFUSE = FD +atmega1284_isp: isp + +# Sanguino has a minimum boot size of 1024 bytes, so enable extra functions +# +sanguino: TARGET = atmega644p +sanguino: MCU_TARGET = atmega644p +sanguino: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' '-DBIGBOOT' +sanguino: AVR_FREQ = 16000000L +sanguino: LDSECTIONS = -Wl,--section-start=.text=0xfc00 +sanguino: $(PROGRAM)_atmega644p.hex +sanguino: $(PROGRAM)_atmega644p.lst + +sanguino_isp: sanguino +sanguino_isp: TARGET = atmega644p +sanguino_isp: MCU_TARGET = atmega644p +# 1024 byte boot +sanguino_isp: HFUSE = DE +# Low power xtal (16MHz) 16KCK/14CK+65ms +sanguino_isp: LFUSE = FF +# 2.7V brownout +sanguino_isp: EFUSE = 05 +sanguino_isp: isp + +# Mega has a minimum boot size of 1024 bytes, so enable extra functions +#mega: TARGET = atmega1280 +mega: MCU_TARGET = atmega1280 +mega: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' '-DBIGBOOT' +mega: AVR_FREQ = 16000000L +mega: LDSECTIONS = -Wl,--section-start=.text=0x1fc00 +mega: $(PROGRAM)_atmega1280.hex +mega: $(PROGRAM)_atmega1280.lst + +mega_isp: mega +mega_isp: TARGET = atmega1280 +mega_isp: MCU_TARGET = atmega1280 +# 1024 byte boot +mega_isp: HFUSE = DE +# Low power xtal (16MHz) 16KCK/14CK+65ms +mega_isp: LFUSE = FF +# 2.7V brownout +mega_isp: EFUSE = 05 +mega_isp: isp + +# ATmega8 +# +atmega8: TARGET = atmega8 +atmega8: MCU_TARGET = atmega8 +atmega8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' +atmega8: AVR_FREQ = 16000000L +atmega8: LDSECTIONS = -Wl,--section-start=.text=0x1e00 -Wl,--section-start=.version=0x1ffe +atmega8: $(PROGRAM)_atmega8.hex +atmega8: $(PROGRAM)_atmega8.lst + +atmega8_isp: atmega8 +atmega8_isp: TARGET = atmega8 +atmega8_isp: MCU_TARGET = atmega8 +# SPIEN, CKOPT, Bootsize=512B +atmega8_isp: HFUSE = CC +# 2.7V brownout, Low power xtal (16MHz) 16KCK/14CK+65ms +atmega8_isp: LFUSE = BF +atmega8_isp: isp + +# ATmega88 +# +atmega88: TARGET = atmega88 +atmega88: MCU_TARGET = atmega88 +atmega88: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' +atmega88: AVR_FREQ = 16000000L +atmega88: LDSECTIONS = -Wl,--section-start=.text=0x1e00 -Wl,--section-start=.version=0x1ffe +atmega88: $(PROGRAM)_atmega88.hex +atmega88: $(PROGRAM)_atmega88.lst + +atmega88_isp: atmega88 +atmega88_isp: TARGET = atmega88 +atmega88_isp: MCU_TARGET = atmega88 +# 2.7V brownout +atmega88_isp: HFUSE = DD +# Low power xtal (16MHz) 16KCK/14CK+65ms +atemga88_isp: LFUSE = FF +# 512 byte boot +atmega88_isp: EFUSE = 04 +atmega88_isp: isp + + +# 8MHz clocked platforms +# +# These are capable of 115200 baud +# + +lilypad: TARGET = lilypad +lilypad: MCU_TARGET = atmega168 +lilypad: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' +lilypad: AVR_FREQ = 8000000L +lilypad: $(PROGRAM)_lilypad.hex +lilypad: $(PROGRAM)_lilypad.lst + +lilypad_isp: lilypad +lilypad_isp: TARGET = lilypad +# 2.7V brownout +lilypad_isp: HFUSE = DD +# Internal 8MHz osc (8MHz) Slow rising power +lilypad_isp: LFUSE = E2 +# 512 byte boot +lilypad_isp: EFUSE = 04 +lilypad_isp: isp + +lilypad_resonator: TARGET = lilypad_resonator +lilypad_resonator: MCU_TARGET = atmega168 +lilypad_resonator: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' +lilypad_resonator: AVR_FREQ = 8000000L +lilypad_resonator: $(PROGRAM)_lilypad_resonator.hex +lilypad_resonator: $(PROGRAM)_lilypad_resonator.lst + +lilypad_resonator_isp: lilypad_resonator +lilypad_resonator_isp: TARGET = lilypad_resonator +# 2.7V brownout +lilypad_resonator_isp: HFUSE = DD +# Full swing xtal (20MHz) 258CK/14CK+4.1ms +lilypad_resonator_isp: LFUSE = C6 +# 512 byte boot +lilypad_resonator_isp: EFUSE = 04 +lilypad_resonator_isp: isp + +pro8: TARGET = pro_8MHz +pro8: MCU_TARGET = atmega168 +pro8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' +pro8: AVR_FREQ = 8000000L +pro8: $(PROGRAM)_pro_8MHz.hex +pro8: $(PROGRAM)_pro_8MHz.lst + +pro8_isp: pro8 +pro8_isp: TARGET = pro_8MHz +# 2.7V brownout +pro8_isp: HFUSE = DD +# Full swing xtal (20MHz) 258CK/14CK+4.1ms +pro8_isp: LFUSE = C6 +# 512 byte boot +pro8_isp: EFUSE = 04 +pro8_isp: isp + +atmega328_pro8: TARGET = atmega328_pro_8MHz +atmega328_pro8: MCU_TARGET = atmega328p +atmega328_pro8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' +atmega328_pro8: AVR_FREQ = 8000000L +atmega328_pro8: LDSECTIONS = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe +atmega328_pro8: $(PROGRAM)_atmega328_pro_8MHz.hex +atmega328_pro8: $(PROGRAM)_atmega328_pro_8MHz.lst + +atmega328_pro8_isp: atmega328_pro8 +atmega328_pro8_isp: TARGET = atmega328_pro_8MHz +atmega328_pro8_isp: MCU_TARGET = atmega328p +# 512 byte boot, SPIEN +atmega328_pro8_isp: HFUSE = DE +# Low power xtal (16MHz) 16KCK/14CK+65ms +atmega328_pro8_isp: LFUSE = FF +# 2.7V brownout +atmega328_pro8_isp: EFUSE = 05 +atmega328_pro8_isp: isp + +# 1MHz clocked platforms +# +# These are capable of 9600 baud +# + +luminet: TARGET = luminet +luminet: MCU_TARGET = attiny84 +luminet: CFLAGS += '-DLED_START_FLASHES=3' '-DSOFT_UART' '-DBAUD_RATE=9600' +luminet: CFLAGS += '-DVIRTUAL_BOOT_PARTITION' +luminet: AVR_FREQ = 1000000L +luminet: LDSECTIONS = -Wl,--section-start=.text=0x1d00 -Wl,--section-start=.version=0x1efe +luminet: $(PROGRAM)_luminet.hex +luminet: $(PROGRAM)_luminet.lst + +luminet_isp: luminet +luminet_isp: TARGET = luminet +luminet_isp: MCU_TARGET = attiny84 +# Brownout disabled +luminet_isp: HFUSE = DF +# 1MHz internal oscillator, slowly rising power +luminet_isp: LFUSE = 62 +# Self-programming enable +luminet_isp: EFUSE = FE +luminet_isp: isp + +# +# Generic build instructions +# +# + +isp: $(TARGET) + $(ISPFUSES) + $(ISPFLASH) + +isp-stk500: $(PROGRAM)_$(TARGET).hex + $(STK500-1) + $(STK500-2) + +%.elf: $(OBJ) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) + $(SIZE) $@ + +clean: + rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex + +%.lst: %.elf + $(OBJDUMP) -h -S $< > $@ + +%.hex: %.elf + $(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O ihex $< $@ + +%.srec: %.elf + $(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O srec $< $@ + +%.bin: %.elf + $(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O binary $< $@ \ No newline at end of file diff --git a/ArduinoAddons/Arduino_0.xx/Sanguino/bootloaders/atmega1284p/boot.h b/ArduinoAddons/Arduino_0.xx/Sanguino/bootloaders/atmega1284p/boot.h new file mode 100644 index 0000000000..136273a23b --- /dev/null +++ b/ArduinoAddons/Arduino_0.xx/Sanguino/bootloaders/atmega1284p/boot.h @@ -0,0 +1,848 @@ +/* Modified to use out for SPM access +** Peter Knight, Optiboot project http://optiboot.googlecode.com +** +** Todo: Tidy up +** +** "_short" routines execute 1 cycle faster and use 1 less word of flash +** by using "out" instruction instead of "sts". +** +** Additional elpm variants that trust the value of RAMPZ +*/ + +/* Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 Eric B. Weddington + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of the copyright holders nor the names of + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. */ + +/* $Id: boot.h,v 1.27.2.3 2008/09/30 13:58:48 arcanum Exp $ */ + +#ifndef _AVR_BOOT_H_ +#define _AVR_BOOT_H_ 1 + +/** \file */ +/** \defgroup avr_boot : Bootloader Support Utilities + \code + #include + #include + \endcode + + The macros in this module provide a C language interface to the + bootloader support functionality of certain AVR processors. These + macros are designed to work with all sizes of flash memory. + + Global interrupts are not automatically disabled for these macros. It + is left up to the programmer to do this. See the code example below. + Also see the processor datasheet for caveats on having global interrupts + enabled during writing of the Flash. + + \note Not all AVR processors provide bootloader support. See your + processor datasheet to see if it provides bootloader support. + + \todo From email with Marek: On smaller devices (all except ATmega64/128), + __SPM_REG is in the I/O space, accessible with the shorter "in" and "out" + instructions - since the boot loader has a limited size, this could be an + important optimization. + + \par API Usage Example + The following code shows typical usage of the boot API. + + \code + #include + #include + #include + + void boot_program_page (uint32_t page, uint8_t *buf) + { + uint16_t i; + uint8_t sreg; + + // Disable interrupts. + + sreg = SREG; + cli(); + + eeprom_busy_wait (); + + boot_page_erase (page); + boot_spm_busy_wait (); // Wait until the memory is erased. + + for (i=0; i +#include +#include +#include + +/* Check for SPM Control Register in processor. */ +#if defined (SPMCSR) +# define __SPM_REG SPMCSR +#elif defined (SPMCR) +# define __SPM_REG SPMCR +#else +# error AVR processor does not provide bootloader support! +#endif + + +/* Check for SPM Enable bit. */ +#if defined(SPMEN) +# define __SPM_ENABLE SPMEN +#elif defined(SELFPRGEN) +# define __SPM_ENABLE SELFPRGEN +#else +# error Cannot find SPM Enable bit definition! +#endif + +/** \ingroup avr_boot + \def BOOTLOADER_SECTION + + Used to declare a function or variable to be placed into a + new section called .bootloader. This section and its contents + can then be relocated to any address (such as the bootloader + NRWW area) at link-time. */ + +#define BOOTLOADER_SECTION __attribute__ ((section (".bootloader"))) + +/* Create common bit definitions. */ +#ifdef ASB +#define __COMMON_ASB ASB +#else +#define __COMMON_ASB RWWSB +#endif + +#ifdef ASRE +#define __COMMON_ASRE ASRE +#else +#define __COMMON_ASRE RWWSRE +#endif + +/* Define the bit positions of the Boot Lock Bits. */ + +#define BLB12 5 +#define BLB11 4 +#define BLB02 3 +#define BLB01 2 + +/** \ingroup avr_boot + \def boot_spm_interrupt_enable() + Enable the SPM interrupt. */ + +#define boot_spm_interrupt_enable() (__SPM_REG |= (uint8_t)_BV(SPMIE)) + +/** \ingroup avr_boot + \def boot_spm_interrupt_disable() + Disable the SPM interrupt. */ + +#define boot_spm_interrupt_disable() (__SPM_REG &= (uint8_t)~_BV(SPMIE)) + +/** \ingroup avr_boot + \def boot_is_spm_interrupt() + Check if the SPM interrupt is enabled. */ + +#define boot_is_spm_interrupt() (__SPM_REG & (uint8_t)_BV(SPMIE)) + +/** \ingroup avr_boot + \def boot_rww_busy() + Check if the RWW section is busy. */ + +#define boot_rww_busy() (__SPM_REG & (uint8_t)_BV(__COMMON_ASB)) + +/** \ingroup avr_boot + \def boot_spm_busy() + Check if the SPM instruction is busy. */ + +#define boot_spm_busy() (__SPM_REG & (uint8_t)_BV(__SPM_ENABLE)) + +/** \ingroup avr_boot + \def boot_spm_busy_wait() + Wait while the SPM instruction is busy. */ + +#define boot_spm_busy_wait() do{}while(boot_spm_busy()) + +#define __BOOT_PAGE_ERASE (_BV(__SPM_ENABLE) | _BV(PGERS)) +#define __BOOT_PAGE_WRITE (_BV(__SPM_ENABLE) | _BV(PGWRT)) +#define __BOOT_PAGE_FILL _BV(__SPM_ENABLE) +#define __BOOT_RWW_ENABLE (_BV(__SPM_ENABLE) | _BV(__COMMON_ASRE)) +#define __BOOT_LOCK_BITS_SET (_BV(__SPM_ENABLE) | _BV(BLBSET)) + +#define __boot_page_fill_short(address, data) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "movw r0, %3\n\t" \ + "out %0, %1\n\t" \ + "spm\n\t" \ + "clr r1\n\t" \ + : \ + : "i" (_SFR_IO_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_PAGE_FILL), \ + "z" ((uint16_t)address), \ + "r" ((uint16_t)data) \ + : "r0" \ + ); \ +})) + +#define __boot_page_fill_normal(address, data) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "movw r0, %3\n\t" \ + "sts %0, %1\n\t" \ + "spm\n\t" \ + "clr r1\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_PAGE_FILL), \ + "z" ((uint16_t)address), \ + "r" ((uint16_t)data) \ + : "r0" \ + ); \ +})) + +#define __boot_page_fill_alternate(address, data)\ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "movw r0, %3\n\t" \ + "sts %0, %1\n\t" \ + "spm\n\t" \ + ".word 0xffff\n\t" \ + "nop\n\t" \ + "clr r1\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_PAGE_FILL), \ + "z" ((uint16_t)address), \ + "r" ((uint16_t)data) \ + : "r0" \ + ); \ +})) + +#define __boot_page_fill_extended(address, data) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "movw r0, %4\n\t" \ + "movw r30, %A3\n\t" \ + "sts %1, %C3\n\t" \ + "sts %0, %2\n\t" \ + "spm\n\t" \ + "clr r1\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "i" (_SFR_MEM_ADDR(RAMPZ)), \ + "r" ((uint8_t)__BOOT_PAGE_FILL), \ + "r" ((uint32_t)address), \ + "r" ((uint16_t)data) \ + : "r0", "r30", "r31" \ + ); \ +})) + +#define __boot_page_fill_extended_short(address, data) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "movw r0, %4\n\t" \ + "movw r30, %A3\n\t" \ + "out %1, %C3\n\t" \ + "out %0, %2\n\t" \ + "spm\n\t" \ + "clr r1\n\t" \ + : \ + : "i" (_SFR_IO_ADDR(__SPM_REG)), \ + "i" (_SFR_IO_ADDR(RAMPZ)), \ + "r" ((uint8_t)__BOOT_PAGE_FILL), \ + "r" ((uint32_t)address), \ + "r" ((uint16_t)data) \ + : "r0", "r30", "r31" \ + ); \ +})) + +#define __boot_page_erase_short(address) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "out %0, %1\n\t" \ + "spm\n\t" \ + : \ + : "i" (_SFR_IO_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_PAGE_ERASE), \ + "z" ((uint16_t)address) \ + ); \ +})) + + +#define __boot_page_erase_normal(address) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "sts %0, %1\n\t" \ + "spm\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_PAGE_ERASE), \ + "z" ((uint16_t)address) \ + ); \ +})) + +#define __boot_page_erase_alternate(address) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "sts %0, %1\n\t" \ + "spm\n\t" \ + ".word 0xffff\n\t" \ + "nop\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_PAGE_ERASE), \ + "z" ((uint16_t)address) \ + ); \ +})) + +#define __boot_page_erase_extended(address) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "movw r30, %A3\n\t" \ + "sts %1, %C3\n\t" \ + "sts %0, %2\n\t" \ + "spm\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "i" (_SFR_MEM_ADDR(RAMPZ)), \ + "r" ((uint8_t)__BOOT_PAGE_ERASE), \ + "r" ((uint32_t)address) \ + : "r30", "r31" \ + ); \ +})) +#define __boot_page_erase_extended_short(address) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "movw r30, %A3\n\t" \ + "out %1, %C3\n\t" \ + "out %0, %2\n\t" \ + "spm\n\t" \ + : \ + : "i" (_SFR_IO_ADDR(__SPM_REG)), \ + "i" (_SFR_IO_ADDR(RAMPZ)), \ + "r" ((uint8_t)__BOOT_PAGE_ERASE), \ + "r" ((uint32_t)address) \ + : "r30", "r31" \ + ); \ +})) + +#define __boot_page_write_short(address) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "out %0, %1\n\t" \ + "spm\n\t" \ + : \ + : "i" (_SFR_IO_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_PAGE_WRITE), \ + "z" ((uint16_t)address) \ + ); \ +})) + +#define __boot_page_write_normal(address) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "sts %0, %1\n\t" \ + "spm\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_PAGE_WRITE), \ + "z" ((uint16_t)address) \ + ); \ +})) + +#define __boot_page_write_alternate(address) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "sts %0, %1\n\t" \ + "spm\n\t" \ + ".word 0xffff\n\t" \ + "nop\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_PAGE_WRITE), \ + "z" ((uint16_t)address) \ + ); \ +})) + +#define __boot_page_write_extended(address) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "movw r30, %A3\n\t" \ + "sts %1, %C3\n\t" \ + "sts %0, %2\n\t" \ + "spm\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "i" (_SFR_MEM_ADDR(RAMPZ)), \ + "r" ((uint8_t)__BOOT_PAGE_WRITE), \ + "r" ((uint32_t)address) \ + : "r30", "r31" \ + ); \ +})) +#define __boot_page_write_extended_short(address) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "movw r30, %A3\n\t" \ + "out %1, %C3\n\t" \ + "out %0, %2\n\t" \ + "spm\n\t" \ + : \ + : "i" (_SFR_IO_ADDR(__SPM_REG)), \ + "i" (_SFR_IO_ADDR(RAMPZ)), \ + "r" ((uint8_t)__BOOT_PAGE_WRITE), \ + "r" ((uint32_t)address) \ + : "r30", "r31" \ + ); \ +})) + +#define __boot_rww_enable_short() \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "out %0, %1\n\t" \ + "spm\n\t" \ + : \ + : "i" (_SFR_IO_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_RWW_ENABLE) \ + ); \ +})) + +#define __boot_rww_enable() \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "sts %0, %1\n\t" \ + "spm\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_RWW_ENABLE) \ + ); \ +})) + +#define __boot_rww_enable_alternate() \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "sts %0, %1\n\t" \ + "spm\n\t" \ + ".word 0xffff\n\t" \ + "nop\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_RWW_ENABLE) \ + ); \ +})) + +/* From the mega16/mega128 data sheets (maybe others): + + Bits by SPM To set the Boot Loader Lock bits, write the desired data to + R0, write "X0001001" to SPMCR and execute SPM within four clock cycles + after writing SPMCR. The only accessible Lock bits are the Boot Lock bits + that may prevent the Application and Boot Loader section from any + software update by the MCU. + + If bits 5..2 in R0 are cleared (zero), the corresponding Boot Lock bit + will be programmed if an SPM instruction is executed within four cycles + after BLBSET and SPMEN (or SELFPRGEN) are set in SPMCR. The Z-pointer is + don't care during this operation, but for future compatibility it is + recommended to load the Z-pointer with $0001 (same as used for reading the + Lock bits). For future compatibility It is also recommended to set bits 7, + 6, 1, and 0 in R0 to 1 when writing the Lock bits. When programming the + Lock bits the entire Flash can be read during the operation. */ + +#define __boot_lock_bits_set_short(lock_bits) \ +(__extension__({ \ + uint8_t value = (uint8_t)(~(lock_bits)); \ + __asm__ __volatile__ \ + ( \ + "ldi r30, 1\n\t" \ + "ldi r31, 0\n\t" \ + "mov r0, %2\n\t" \ + "out %0, %1\n\t" \ + "spm\n\t" \ + : \ + : "i" (_SFR_IO_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_LOCK_BITS_SET), \ + "r" (value) \ + : "r0", "r30", "r31" \ + ); \ +})) + +#define __boot_lock_bits_set(lock_bits) \ +(__extension__({ \ + uint8_t value = (uint8_t)(~(lock_bits)); \ + __asm__ __volatile__ \ + ( \ + "ldi r30, 1\n\t" \ + "ldi r31, 0\n\t" \ + "mov r0, %2\n\t" \ + "sts %0, %1\n\t" \ + "spm\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_LOCK_BITS_SET), \ + "r" (value) \ + : "r0", "r30", "r31" \ + ); \ +})) + +#define __boot_lock_bits_set_alternate(lock_bits) \ +(__extension__({ \ + uint8_t value = (uint8_t)(~(lock_bits)); \ + __asm__ __volatile__ \ + ( \ + "ldi r30, 1\n\t" \ + "ldi r31, 0\n\t" \ + "mov r0, %2\n\t" \ + "sts %0, %1\n\t" \ + "spm\n\t" \ + ".word 0xffff\n\t" \ + "nop\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_LOCK_BITS_SET), \ + "r" (value) \ + : "r0", "r30", "r31" \ + ); \ +})) + +/* + Reading lock and fuse bits: + + Similarly to writing the lock bits above, set BLBSET and SPMEN (or + SELFPRGEN) bits in __SPMREG, and then (within four clock cycles) issue an + LPM instruction. + + Z address: contents: + 0x0000 low fuse bits + 0x0001 lock bits + 0x0002 extended fuse bits + 0x0003 high fuse bits + + Sounds confusing, doesn't it? + + Unlike the macros in pgmspace.h, no need to care for non-enhanced + cores here as these old cores do not provide SPM support anyway. + */ + +/** \ingroup avr_boot + \def GET_LOW_FUSE_BITS + address to read the low fuse bits, using boot_lock_fuse_bits_get + */ +#define GET_LOW_FUSE_BITS (0x0000) +/** \ingroup avr_boot + \def GET_LOCK_BITS + address to read the lock bits, using boot_lock_fuse_bits_get + */ +#define GET_LOCK_BITS (0x0001) +/** \ingroup avr_boot + \def GET_EXTENDED_FUSE_BITS + address to read the extended fuse bits, using boot_lock_fuse_bits_get + */ +#define GET_EXTENDED_FUSE_BITS (0x0002) +/** \ingroup avr_boot + \def GET_HIGH_FUSE_BITS + address to read the high fuse bits, using boot_lock_fuse_bits_get + */ +#define GET_HIGH_FUSE_BITS (0x0003) + +/** \ingroup avr_boot + \def boot_lock_fuse_bits_get(address) + + Read the lock or fuse bits at \c address. + + Parameter \c address can be any of GET_LOW_FUSE_BITS, + GET_LOCK_BITS, GET_EXTENDED_FUSE_BITS, or GET_HIGH_FUSE_BITS. + + \note The lock and fuse bits returned are the physical values, + i.e. a bit returned as 0 means the corresponding fuse or lock bit + is programmed. + */ +#define boot_lock_fuse_bits_get_short(address) \ +(__extension__({ \ + uint8_t __result; \ + __asm__ __volatile__ \ + ( \ + "ldi r30, %3\n\t" \ + "ldi r31, 0\n\t" \ + "out %1, %2\n\t" \ + "lpm %0, Z\n\t" \ + : "=r" (__result) \ + : "i" (_SFR_IO_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_LOCK_BITS_SET), \ + "M" (address) \ + : "r0", "r30", "r31" \ + ); \ + __result; \ +})) + +#define boot_lock_fuse_bits_get(address) \ +(__extension__({ \ + uint8_t __result; \ + __asm__ __volatile__ \ + ( \ + "ldi r30, %3\n\t" \ + "ldi r31, 0\n\t" \ + "sts %1, %2\n\t" \ + "lpm %0, Z\n\t" \ + : "=r" (__result) \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_LOCK_BITS_SET), \ + "M" (address) \ + : "r0", "r30", "r31" \ + ); \ + __result; \ +})) + +/** \ingroup avr_boot + \def boot_signature_byte_get(address) + + Read the Signature Row byte at \c address. For some MCU types, + this function can also retrieve the factory-stored oscillator + calibration bytes. + + Parameter \c address can be 0-0x1f as documented by the datasheet. + \note The values are MCU type dependent. +*/ + +#define __BOOT_SIGROW_READ (_BV(__SPM_ENABLE) | _BV(SIGRD)) + +#define boot_signature_byte_get_short(addr) \ +(__extension__({ \ + uint16_t __addr16 = (uint16_t)(addr); \ + uint8_t __result; \ + __asm__ __volatile__ \ + ( \ + "out %1, %2\n\t" \ + "lpm %0, Z" "\n\t" \ + : "=r" (__result) \ + : "i" (_SFR_IO_ADDR(__SPM_REG)), \ + "r" ((uint8_t) __BOOT_SIGROW_READ), \ + "z" (__addr16) \ + ); \ + __result; \ +})) + +#define boot_signature_byte_get(addr) \ +(__extension__({ \ + uint16_t __addr16 = (uint16_t)(addr); \ + uint8_t __result; \ + __asm__ __volatile__ \ + ( \ + "sts %1, %2\n\t" \ + "lpm %0, Z" "\n\t" \ + : "=r" (__result) \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "r" ((uint8_t) __BOOT_SIGROW_READ), \ + "z" (__addr16) \ + ); \ + __result; \ +})) + +/** \ingroup avr_boot + \def boot_page_fill(address, data) + + Fill the bootloader temporary page buffer for flash + address with data word. + + \note The address is a byte address. The data is a word. The AVR + writes data to the buffer a word at a time, but addresses the buffer + per byte! So, increment your address by 2 between calls, and send 2 + data bytes in a word format! The LSB of the data is written to the lower + address; the MSB of the data is written to the higher address.*/ + +/** \ingroup avr_boot + \def boot_page_erase(address) + + Erase the flash page that contains address. + + \note address is a byte address in flash, not a word address. */ + +/** \ingroup avr_boot + \def boot_page_write(address) + + Write the bootloader temporary page buffer + to flash page that contains address. + + \note address is a byte address in flash, not a word address. */ + +/** \ingroup avr_boot + \def boot_rww_enable() + + Enable the Read-While-Write memory section. */ + +/** \ingroup avr_boot + \def boot_lock_bits_set(lock_bits) + + Set the bootloader lock bits. + + \param lock_bits A mask of which Boot Loader Lock Bits to set. + + \note In this context, a 'set bit' will be written to a zero value. + Note also that only BLBxx bits can be programmed by this command. + + For example, to disallow the SPM instruction from writing to the Boot + Loader memory section of flash, you would use this macro as such: + + \code + boot_lock_bits_set (_BV (BLB11)); + \endcode + + \note Like any lock bits, the Boot Loader Lock Bits, once set, + cannot be cleared again except by a chip erase which will in turn + also erase the boot loader itself. */ + +/* Normal versions of the macros use 16-bit addresses. + Extended versions of the macros use 32-bit addresses. + Alternate versions of the macros use 16-bit addresses and require special + instruction sequences after LPM. + + FLASHEND is defined in the ioXXXX.h file. + USHRT_MAX is defined in . */ + +#if defined(__AVR_ATmega161__) || defined(__AVR_ATmega163__) \ + || defined(__AVR_ATmega323__) + +/* Alternate: ATmega161/163/323 and 16 bit address */ +#define boot_page_fill(address, data) __boot_page_fill_alternate(address, data) +#define boot_page_erase(address) __boot_page_erase_alternate(address) +#define boot_page_write(address) __boot_page_write_alternate(address) +#define boot_rww_enable() __boot_rww_enable_alternate() +#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_alternate(lock_bits) + +#elif (FLASHEND > USHRT_MAX) + +/* Extended: >16 bit address */ +#define boot_page_fill(address, data) __boot_page_fill_extended_short(address, data) +#define boot_page_erase(address) __boot_page_erase_extended_short(address) +#define boot_page_write(address) __boot_page_write_extended_short(address) +#define boot_rww_enable() __boot_rww_enable_short() +#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_short(lock_bits) + +#else + +/* Normal: 16 bit address */ +#define boot_page_fill(address, data) __boot_page_fill_short(address, data) +#define boot_page_erase(address) __boot_page_erase_short(address) +#define boot_page_write(address) __boot_page_write_short(address) +#define boot_rww_enable() __boot_rww_enable_short() +#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_short(lock_bits) + +#endif + +/** \ingroup avr_boot + + Same as boot_page_fill() except it waits for eeprom and spm operations to + complete before filling the page. */ + +#define boot_page_fill_safe(address, data) \ +do { \ + boot_spm_busy_wait(); \ + eeprom_busy_wait(); \ + boot_page_fill(address, data); \ +} while (0) + +/** \ingroup avr_boot + + Same as boot_page_erase() except it waits for eeprom and spm operations to + complete before erasing the page. */ + +#define boot_page_erase_safe(address) \ +do { \ + boot_spm_busy_wait(); \ + eeprom_busy_wait(); \ + boot_page_erase (address); \ +} while (0) + +/** \ingroup avr_boot + + Same as boot_page_write() except it waits for eeprom and spm operations to + complete before writing the page. */ + +#define boot_page_write_safe(address) \ +do { \ + boot_spm_busy_wait(); \ + eeprom_busy_wait(); \ + boot_page_write (address); \ +} while (0) + +/** \ingroup avr_boot + + Same as boot_rww_enable() except waits for eeprom and spm operations to + complete before enabling the RWW mameory. */ + +#define boot_rww_enable_safe() \ +do { \ + boot_spm_busy_wait(); \ + eeprom_busy_wait(); \ + boot_rww_enable(); \ +} while (0) + +/** \ingroup avr_boot + + Same as boot_lock_bits_set() except waits for eeprom and spm operations to + complete before setting the lock bits. */ + +#define boot_lock_bits_set_safe(lock_bits) \ +do { \ + boot_spm_busy_wait(); \ + eeprom_busy_wait(); \ + boot_lock_bits_set (lock_bits); \ +} while (0) + +#endif /* _AVR_BOOT_H_ */ \ No newline at end of file diff --git a/ArduinoAddons/Arduino_0.xx/Sanguino/bootloaders/atmega1284p/optiboot.c b/ArduinoAddons/Arduino_0.xx/Sanguino/bootloaders/atmega1284p/optiboot.c new file mode 100644 index 0000000000..031869612f --- /dev/null +++ b/ArduinoAddons/Arduino_0.xx/Sanguino/bootloaders/atmega1284p/optiboot.c @@ -0,0 +1,724 @@ +/**********************************************************/ +/* -Wl,-section-start=bootloader=0x1fc00 */ +/* Optiboot bootloader for Arduino */ +/* */ +/* http://optiboot.googlecode.com */ +/* */ +/* Arduino-maintained version : See README.TXT */ +/* http://code.google.com/p/arduino/ */ +/* */ +/* Heavily optimised bootloader that is faster and */ +/* smaller than the Arduino standard bootloader */ +/* */ +/* Enhancements: */ +/* Fits in 512 bytes, saving 1.5K of code space */ +/* Background page erasing speeds up programming */ +/* Higher baud rate speeds up programming */ +/* Written almost entirely in C */ +/* Customisable timeout with accurate timeconstant */ +/* Optional virtual UART. No hardware UART required. */ +/* Optional virtual boot partition for devices without. */ +/* */ +/* What you lose: */ +/* Implements a skeleton STK500 protocol which is */ +/* missing several features including EEPROM */ +/* programming and non-page-aligned writes */ +/* High baud rate breaks compatibility with standard */ +/* Arduino flash settings */ +/* */ +/* Fully supported: */ +/* ATmega168 based devices (Diecimila etc) */ +/* ATmega328P based devices (Duemilanove etc) */ +/* */ +/* Alpha test */ +/* ATmega1280 based devices (Arduino Mega) */ +/* */ +/* Work in progress: */ +/* ATmega644P based devices (Sanguino) */ +/* ATtiny84 based devices (Luminet) */ +/* */ +/* Does not support: */ +/* USB based devices (eg. Teensy) */ +/* */ +/* Assumptions: */ +/* The code makes several assumptions that reduce the */ +/* code size. They are all true after a hardware reset, */ +/* but may not be true if the bootloader is called by */ +/* other means or on other hardware. */ +/* No interrupts can occur */ +/* UART and Timer 1 are set to their reset state */ +/* SP points to RAMEND */ +/* */ +/* Code builds on code, libraries and optimisations from: */ +/* stk500boot.c by Jason P. Kyle */ +/* Arduino bootloader http://arduino.cc */ +/* Spiff's 1K bootloader http://spiffie.org/know/arduino_1k_bootloader/bootloader.shtml */ +/* avr-libc project http://nongnu.org/avr-libc */ +/* Adaboot http://www.ladyada.net/library/arduino/bootloader.html */ +/* AVR305 Atmel Application Note */ +/* */ +/* This program is free software; you can redistribute it */ +/* and/or modify it under the terms of the GNU General */ +/* Public License as published by the Free Software */ +/* Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without even the */ +/* implied warranty of MERCHANTABILITY or FITNESS FOR A */ +/* PARTICULAR PURPOSE. See the GNU General Public */ +/* License for more details. */ +/* */ +/* You should have received a copy of the GNU General */ +/* Public License along with this program; if not, write */ +/* to the Free Software Foundation, Inc., */ +/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* */ +/* Licence can be viewed at */ +/* http://www.fsf.org/licenses/gpl.txt */ +/* */ +/**********************************************************/ + + +/**********************************************************/ +/* */ +/* Optional defines: */ +/* */ +/**********************************************************/ +/* */ +/* BIG_BOOT: */ +/* Build a 1k bootloader, not 512 bytes. This turns on */ +/* extra functionality. */ +/* */ +/* BAUD_RATE: */ +/* Set bootloader baud rate. */ +/* */ +/* LUDICROUS_SPEED: */ +/* 230400 baud :-) */ +/* */ +/* SOFT_UART: */ +/* Use AVR305 soft-UART instead of hardware UART. */ +/* */ +/* LED_START_FLASHES: */ +/* Number of LED flashes on bootup. */ +/* */ +/* LED_DATA_FLASH: */ +/* Flash LED when transferring data. For boards without */ +/* TX or RX LEDs, or for people who like blinky lights. */ +/* */ +/* SUPPORT_EEPROM: */ +/* Support reading and writing from EEPROM. This is not */ +/* used by Arduino, so off by default. */ +/* */ +/* TIMEOUT_MS: */ +/* Bootloader timeout period, in milliseconds. */ +/* 500,1000,2000,4000,8000 supported. */ +/* */ +/**********************************************************/ + +/**********************************************************/ +/* Version Numbers! */ +/* */ +/* Arduino Optiboot now includes this Version number in */ +/* the source and object code. */ +/* */ +/* Version 3 was released as zip from the optiboot */ +/* repository and was distributed with Arduino 0022. */ +/* Version 4 starts with the arduino repository commit */ +/* that brought the arduino repository up-to-date with */ +/* the optiboot source tree changes since v3. */ +/* */ +/**********************************************************/ + +/**********************************************************/ +/* Edit History: */ +/* */ +/* Jan 2012: */ +/* 4.5 WestfW: fix NRWW value for m1284. */ +/* 4.4 WestfW: use attribute OS_main instead of naked for */ +/* main(). This allows optimizations that we */ +/* count on, which are prohibited in naked */ +/* functions due to PR42240. (keeps us less */ +/* than 512 bytes when compiler is gcc4.5 */ +/* (code from 4.3.2 remains the same.) */ +/* 4.4 WestfW and Maniacbug: Add m1284 support. This */ +/* does not change the 328 binary, so the */ +/* version number didn't change either. (?) */ +/* June 2011: */ +/* 4.4 WestfW: remove automatic soft_uart detect (didn't */ +/* know what it was doing or why.) Added a */ +/* check of the calculated BRG value instead. */ +/* Version stays 4.4; existing binaries are */ +/* not changed. */ +/* 4.4 WestfW: add initialization of address to keep */ +/* the compiler happy. Change SC'ed targets. */ +/* Return the SW version via READ PARAM */ +/* 4.3 WestfW: catch framing errors in getch(), so that */ +/* AVRISP works without HW kludges. */ +/* http://code.google.com/p/arduino/issues/detail?id=368n*/ +/* 4.2 WestfW: reduce code size, fix timeouts, change */ +/* verifySpace to use WDT instead of appstart */ +/* 4.1 WestfW: put version number in binary. */ +/**********************************************************/ + +#define OPTIBOOT_MAJVER 4 +#define OPTIBOOT_MINVER 5 + +#define MAKESTR(a) #a +#define MAKEVER(a, b) MAKESTR(a*256+b) + +asm(" .section .version\n" + "optiboot_version: .word " MAKEVER(OPTIBOOT_MAJVER, OPTIBOOT_MINVER) "\n" + " .section .text\n"); + +#include +#include +#include + +// uses sts instructions, but this version uses out instructions +// This saves cycles and program memory. +#include "boot.h" + + +// We don't use as those routines have interrupt overhead we don't need. + +#include "pin_defs.h" +#include "stk500.h" + +#ifndef LED_START_FLASHES +#define LED_START_FLASHES 0 +#endif + +#ifdef LUDICROUS_SPEED +#define BAUD_RATE 230400L +#endif + +/* set the UART baud rate defaults */ +#ifndef BAUD_RATE +#if F_CPU >= 8000000L +#define BAUD_RATE 115200L // Highest rate Avrdude win32 will support +#elsif F_CPU >= 1000000L +#define BAUD_RATE 9600L // 19200 also supported, but with significant error +#elsif F_CPU >= 128000L +#define BAUD_RATE 4800L // Good for 128kHz internal RC +#else +#define BAUD_RATE 1200L // Good even at 32768Hz +#endif +#endif + +#if 0 +/* Switch in soft UART for hard baud rates */ +/* + * I don't understand what this was supposed to accomplish, where the + * constant "280" came from, or why automatically (and perhaps unexpectedly) + * switching to a soft uart is a good thing, so I'm undoing this in favor + * of a range check using the same calc used to config the BRG... + */ +#if (F_CPU/BAUD_RATE) > 280 // > 57600 for 16MHz +#ifndef SOFT_UART +#define SOFT_UART +#endif +#endif +#else // 0 +#if (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 > 250 +#error Unachievable baud rate (too slow) BAUD_RATE +#endif // baud rate slow check +#if (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 < 3 +#error Unachievable baud rate (too fast) BAUD_RATE +#endif // baud rate fastn check +#endif + +/* Watchdog settings */ +#define WATCHDOG_OFF (0) +#define WATCHDOG_16MS (_BV(WDE)) +#define WATCHDOG_32MS (_BV(WDP0) | _BV(WDE)) +#define WATCHDOG_64MS (_BV(WDP1) | _BV(WDE)) +#define WATCHDOG_125MS (_BV(WDP1) | _BV(WDP0) | _BV(WDE)) +#define WATCHDOG_250MS (_BV(WDP2) | _BV(WDE)) +#define WATCHDOG_500MS (_BV(WDP2) | _BV(WDP0) | _BV(WDE)) +#define WATCHDOG_1S (_BV(WDP2) | _BV(WDP1) | _BV(WDE)) +#define WATCHDOG_2S (_BV(WDP2) | _BV(WDP1) | _BV(WDP0) | _BV(WDE)) +#ifndef __AVR_ATmega8__ +#define WATCHDOG_4S (_BV(WDP3) | _BV(WDE)) +#define WATCHDOG_8S (_BV(WDP3) | _BV(WDP0) | _BV(WDE)) +#endif + +/* Function Prototypes */ +/* The main function is in init9, which removes the interrupt vector table */ +/* we don't need. It is also 'naked', which means the compiler does not */ +/* generate any entry or exit code itself. */ +int main(void) __attribute__ ((OS_main)) __attribute__ ((section (".init9"))); +void putch(char); +uint8_t getch(void); +static inline void getNch(uint8_t); /* "static inline" is a compiler hint to reduce code size */ +void verifySpace(); +static inline void flash_led(uint8_t); +uint8_t getLen(); +static inline void watchdogReset(); +void watchdogConfig(uint8_t x); +#ifdef SOFT_UART +void uartDelay() __attribute__ ((naked)); +#endif +void appStart() __attribute__ ((naked)); + +/* + * NRWW memory + * Addresses below NRWW (Non-Read-While-Write) can be programmed while + * continuing to run code from flash, slightly speeding up programming + * time. Beware that Atmel data sheets specify this as a WORD address, + * while optiboot will be comparing against a 16-bit byte address. This + * means that on a part with 128kB of memory, the upper part of the lower + * 64k will get NRWW processing as well, even though it doesn't need it. + * That's OK. In fact, you can disable the overlapping processing for + * a part entirely by setting NRWWSTART to zero. This reduces code + * space a bit, at the expense of being slightly slower, overall. + * + * RAMSTART should be self-explanatory. It's bigger on parts with a + * lot of peripheral registers. + */ +#if defined(__AVR_ATmega168__) +#define RAMSTART (0x100) +#define NRWWSTART (0x3800) +#elif defined(__AVR_ATmega328P__) +#define RAMSTART (0x100) +#define NRWWSTART (0x7000) +#elif defined (__AVR_ATmega644P__) +#define RAMSTART (0x100) +#define NRWWSTART (0xE000) +#elif defined (__AVR_ATmega1284P__) +#define RAMSTART (0x100) +#define NRWWSTART (0xE000) +#elif defined(__AVR_ATtiny84__) +#define RAMSTART (0x100) +#define NRWWSTART (0x0000) +#elif defined(__AVR_ATmega1280__) +#define RAMSTART (0x200) +#define NRWWSTART (0xE000) +#elif defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__) +#define RAMSTART (0x100) +#define NRWWSTART (0x1800) +#endif + +/* C zero initialises all global variables. However, that requires */ +/* These definitions are NOT zero initialised, but that doesn't matter */ +/* This allows us to drop the zero init code, saving us memory */ +#define buff ((uint8_t*)(RAMSTART)) +#ifdef VIRTUAL_BOOT_PARTITION +#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4)) +#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6)) +#endif + +/* main program starts here */ +int main(void) { + uint8_t ch; + + /* + * Making these local and in registers prevents the need for initializing + * them, and also saves space because code no longer stores to memory. + * (initializing address keeps the compiler happy, but isn't really + * necessary, and uses 4 bytes of flash.) + */ + register uint16_t address = 0; + register uint8_t length; + + // After the zero init loop, this is the first code to run. + // + // This code makes the following assumptions: + // No interrupts will execute + // SP points to RAMEND + // r1 contains zero + // + // If not, uncomment the following instructions: + // cli(); + asm volatile ("clr __zero_reg__"); +#ifdef __AVR_ATmega8__ + SP=RAMEND; // This is done by hardware reset +#endif + + // Adaboot no-wait mod + ch = MCUSR; + MCUSR = 0; + if (!(ch & _BV(EXTRF))) appStart(); + +#if LED_START_FLASHES > 0 + // Set up Timer 1 for timeout counter + TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 +#endif +#ifndef SOFT_UART +#ifdef __AVR_ATmega8__ + UCSRA = _BV(U2X); //Double speed mode USART + UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx + UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1 + UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); +#else + UCSR0A = _BV(U2X0); //Double speed mode USART0 + UCSR0B = _BV(RXEN0) | _BV(TXEN0); + UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); + UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); +#endif +#endif + + // Set up watchdog to trigger after 500ms + watchdogConfig(WATCHDOG_1S); + + /* Set LED pin as output */ + LED_DDR |= _BV(LED); + +#ifdef SOFT_UART + /* Set TX pin as output */ + UART_DDR |= _BV(UART_TX_BIT); +#endif + +#if LED_START_FLASHES > 0 + /* Flash onboard LED to signal entering of bootloader */ + flash_led(LED_START_FLASHES * 2); +#endif + + /* Forever loop */ + for (;;) { + /* get character from UART */ + ch = getch(); + + if(ch == STK_GET_PARAMETER) { + unsigned char which = getch(); + verifySpace(); + if (which == 0x82) { + /* + * Send optiboot version as "minor SW version" + */ + putch(OPTIBOOT_MINVER); + } else if (which == 0x81) { + putch(OPTIBOOT_MAJVER); + } else { + /* + * GET PARAMETER returns a generic 0x03 reply for + * other parameters - enough to keep Avrdude happy + */ + putch(0x03); + } + } + else if(ch == STK_SET_DEVICE) { + // SET DEVICE is ignored + getNch(20); + } + else if(ch == STK_SET_DEVICE_EXT) { + // SET DEVICE EXT is ignored + getNch(5); + } + else if(ch == STK_LOAD_ADDRESS) { + // LOAD ADDRESS + uint16_t newAddress; + newAddress = getch(); + newAddress = (newAddress & 0xff) | (getch() << 8); +#ifdef RAMPZ + // Transfer top bit to RAMPZ + RAMPZ = (newAddress & 0x8000) ? 1 : 0; +#endif + newAddress += newAddress; // Convert from word address to byte address + address = newAddress; + verifySpace(); + } + else if(ch == STK_UNIVERSAL) { + // UNIVERSAL command is ignored + getNch(4); + putch(0x00); + } + /* Write memory, length is big endian and is in bytes */ + else if(ch == STK_PROG_PAGE) { + // PROGRAM PAGE - we support flash programming only, not EEPROM + uint8_t *bufPtr; + uint16_t addrPtr; + + getch(); /* getlen() */ + length = getch(); + getch(); + + // If we are in RWW section, immediately start page erase + if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); + + // While that is going on, read in page contents + bufPtr = buff; + do *bufPtr++ = getch(); + while (--length); + + // If we are in NRWW section, page erase has to be delayed until now. + // Todo: Take RAMPZ into account + if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address); + + // Read command terminator, start reply + verifySpace(); + + // If only a partial page is to be programmed, the erase might not be complete. + // So check that here + boot_spm_busy_wait(); + +#ifdef VIRTUAL_BOOT_PARTITION + if ((uint16_t)(void*)address == 0) { + // This is the reset vector page. We need to live-patch the code so the + // bootloader runs. + // + // Move RESET vector to WDT vector + uint16_t vect = buff[0] | (buff[1]<<8); + rstVect = vect; + wdtVect = buff[8] | (buff[9]<<8); + vect -= 4; // Instruction is a relative jump (rjmp), so recalculate. + buff[8] = vect & 0xff; + buff[9] = vect >> 8; + + // Add jump to bootloader at RESET vector + buff[0] = 0x7f; + buff[1] = 0xce; // rjmp 0x1d00 instruction + } +#endif + + // Copy buffer into programming buffer + bufPtr = buff; + addrPtr = (uint16_t)(void*)address; + ch = SPM_PAGESIZE / 2; + do { + uint16_t a; + a = *bufPtr++; + a |= (*bufPtr++) << 8; + __boot_page_fill_short((uint16_t)(void*)addrPtr,a); + addrPtr += 2; + } while (--ch); + + // Write from programming buffer + __boot_page_write_short((uint16_t)(void*)address); + boot_spm_busy_wait(); + +#if defined(RWWSRE) + // Reenable read access to flash + boot_rww_enable(); +#endif + + } + /* Read memory block mode, length is big endian. */ + else if(ch == STK_READ_PAGE) { + // READ PAGE - we only read flash + getch(); /* getlen() */ + length = getch(); + getch(); + + verifySpace(); +#ifdef VIRTUAL_BOOT_PARTITION + do { + // Undo vector patch in bottom page so verify passes + if (address == 0) ch=rstVect & 0xff; + else if (address == 1) ch=rstVect >> 8; + else if (address == 8) ch=wdtVect & 0xff; + else if (address == 9) ch=wdtVect >> 8; + else ch = pgm_read_byte_near(address); + address++; + putch(ch); + } while (--length); +#else +#ifdef RAMPZ +// Since RAMPZ should already be set, we need to use EPLM directly. +// do putch(pgm_read_byte_near(address++)); +// while (--length); + do { + uint8_t result; + __asm__ ("elpm %0,Z\n":"=r"(result):"z"(address)); + putch(result); + address++; + } + while (--length); +#else + do putch(pgm_read_byte_near(address++)); + while (--length); +#endif +#endif + } + + /* Get device signature bytes */ + else if(ch == STK_READ_SIGN) { + // READ SIGN - return what Avrdude wants to hear + verifySpace(); + putch(SIGNATURE_0); + putch(SIGNATURE_1); + putch(SIGNATURE_2); + } + else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */ + // Adaboot no-wait mod + watchdogConfig(WATCHDOG_16MS); + verifySpace(); + } + else { + // This covers the response to commands like STK_ENTER_PROGMODE + verifySpace(); + } + putch(STK_OK); + } +} + +void putch(char ch) { +#ifndef SOFT_UART + while (!(UCSR0A & _BV(UDRE0))); + UDR0 = ch; +#else + __asm__ __volatile__ ( + " com %[ch]\n" // ones complement, carry set + " sec\n" + "1: brcc 2f\n" + " cbi %[uartPort],%[uartBit]\n" + " rjmp 3f\n" + "2: sbi %[uartPort],%[uartBit]\n" + " nop\n" + "3: rcall uartDelay\n" + " rcall uartDelay\n" + " lsr %[ch]\n" + " dec %[bitcnt]\n" + " brne 1b\n" + : + : + [bitcnt] "d" (10), + [ch] "r" (ch), + [uartPort] "I" (_SFR_IO_ADDR(UART_PORT)), + [uartBit] "I" (UART_TX_BIT) + : + "r25" + ); +#endif +} + +uint8_t getch(void) { + uint8_t ch; + +#ifdef LED_DATA_FLASH +#ifdef __AVR_ATmega8__ + LED_PORT ^= _BV(LED); +#else + LED_PIN |= _BV(LED); +#endif +#endif + +#ifdef SOFT_UART + __asm__ __volatile__ ( + "1: sbic %[uartPin],%[uartBit]\n" // Wait for start edge + " rjmp 1b\n" + " rcall uartDelay\n" // Get to middle of start bit + "2: rcall uartDelay\n" // Wait 1 bit period + " rcall uartDelay\n" // Wait 1 bit period + " clc\n" + " sbic %[uartPin],%[uartBit]\n" + " sec\n" + " dec %[bitCnt]\n" + " breq 3f\n" + " ror %[ch]\n" + " rjmp 2b\n" + "3:\n" + : + [ch] "=r" (ch) + : + [bitCnt] "d" (9), + [uartPin] "I" (_SFR_IO_ADDR(UART_PIN)), + [uartBit] "I" (UART_RX_BIT) + : + "r25" +); +#else + while(!(UCSR0A & _BV(RXC0))) + ; + if (!(UCSR0A & _BV(FE0))) { + /* + * A Framing Error indicates (probably) that something is talking + * to us at the wrong bit rate. Assume that this is because it + * expects to be talking to the application, and DON'T reset the + * watchdog. This should cause the bootloader to abort and run + * the application "soon", if it keeps happening. (Note that we + * don't care that an invalid char is returned...) + */ + watchdogReset(); + } + + ch = UDR0; +#endif + +#ifdef LED_DATA_FLASH +#ifdef __AVR_ATmega8__ + LED_PORT ^= _BV(LED); +#else + LED_PIN |= _BV(LED); +#endif +#endif + + return ch; +} + +#ifdef SOFT_UART +// AVR305 equation: #define UART_B_VALUE (((F_CPU/BAUD_RATE)-23)/6) +// Adding 3 to numerator simulates nearest rounding for more accurate baud rates +#define UART_B_VALUE (((F_CPU/BAUD_RATE)-20)/6) +#if UART_B_VALUE > 255 +#error Baud rate too slow for soft UART +#endif + +void uartDelay() { + __asm__ __volatile__ ( + "ldi r25,%[count]\n" + "1:dec r25\n" + "brne 1b\n" + "ret\n" + ::[count] "M" (UART_B_VALUE) + ); +} +#endif + +void getNch(uint8_t count) { + do getch(); while (--count); + verifySpace(); +} + +void verifySpace() { + if (getch() != CRC_EOP) { + watchdogConfig(WATCHDOG_16MS); // shorten WD timeout + while (1) // and busy-loop so that WD causes + ; // a reset and app start. + } + putch(STK_INSYNC); +} + +#if LED_START_FLASHES > 0 +void flash_led(uint8_t count) { + do { + TCNT1 = -(F_CPU/(1024*16)); + TIFR1 = _BV(TOV1); + while(!(TIFR1 & _BV(TOV1))); +#ifdef __AVR_ATmega8__ + LED_PORT ^= _BV(LED); +#else + LED_PIN |= _BV(LED); +#endif + watchdogReset(); + } while (--count); +} +#endif + +// Watchdog functions. These are only safe with interrupts turned off. +void watchdogReset() { + __asm__ __volatile__ ( + "wdr\n" + ); +} + +void watchdogConfig(uint8_t x) { + WDTCSR = _BV(WDCE) | _BV(WDE); + WDTCSR = x; +} + +void appStart() { + watchdogConfig(WATCHDOG_OFF); + __asm__ __volatile__ ( +#ifdef VIRTUAL_BOOT_PARTITION + // Jump to WDT vector + "ldi r30,4\n" + "clr r31\n" +#else + // Jump to RST vector + "clr r30\n" + "clr r31\n" +#endif + "ijmp\n" + ); +} diff --git a/ArduinoAddons/Arduino_0.xx/Sanguino/bootloaders/atmega1284p/optiboot_1284P_20MHz_57k6_baud.hex b/ArduinoAddons/Arduino_0.xx/Sanguino/bootloaders/atmega1284p/optiboot_1284P_20MHz_57k6_baud.hex new file mode 100644 index 0000000000..98d96ea557 --- /dev/null +++ b/ArduinoAddons/Arduino_0.xx/Sanguino/bootloaders/atmega1284p/optiboot_1284P_20MHz_57k6_baud.hex @@ -0,0 +1,33 @@ +:020000021000EC +:10FE00000F92CDB7DEB7112484B714BE81FFDFD0C7 +:10FE100082E08093C00088E18093C10086E08093F7 +:10FE2000C2008AE28093C4008EE0BBD0209A00E03A +:10FE300010E0EE24E394E1E1DE2EF3E0FF2EA5D006 +:10FE4000813471F4A2D08983B2D08981823809F4D7 +:10FE50008BC0813811F484E001C083E08FD08BC067 +:10FE6000823411F484E103C0853419F485E0A7D00D +:10FE700082C0853591F489D0A82EBB2486D0082F66 +:10FE800010E0102F00270A291B29812F881F88279F +:10FE9000881F8BBF000F111F6DC0863521F484E0D1 +:10FEA0008ED080E0DBCF843609F040C06ED06DD0BC +:10FEB000C82E6BD080EE0030180718F4F801F7BE9A +:10FEC000E895A12C51E0B52E60D0F50181935F013A +:10FED000CE16D1F7F0EE00301F0718F0F801F7BE8C +:10FEE000E89565D007B600FCFDCFF801A0E0B1E0D1 +:10FEF0002C9130E011968C91119790E0982F8827E3 +:10FF0000822B932B12960C01E7BEE89511243296B2 +:10FF100082E0A030B80761F785E0F80187BFE89577 +:10FF200007B600FCFDCFD7BEE89525C08437A9F4FD +:10FF30002CD02BD0B82E29D03AD0CB2C4801F401AC +:10FF400086911CD00894811C911CCA94C1F70F5F44 +:10FF50001F4FBA940B0D111D0EC0853739F427D0F1 +:10FF60008EE10CD087E90AD085E078CF813511F495 +:10FF700088E017D01CD080E101D061CF9091C00003 +:10FF800095FFFCCF8093C60008958091C00087FF45 +:10FF9000FCCF8091C00084FD01C0A8958091C6006F +:10FFA0000895E0E6F0E098E1908380830895EDDF26 +:10FFB000803219F088E0F5DFFFCF84E1DFCFCF9307 +:10FFC000C82FE3DFC150E9F7F2DFCF91089580E059 +:08FFD000E8DFEE27FF2709948A +:040000031000FE00EB +:00000001FF diff --git a/ArduinoAddons/Arduino_0.xx/Sanguino/bootloaders/atmega1284p/pin_defs.h b/ArduinoAddons/Arduino_0.xx/Sanguino/bootloaders/atmega1284p/pin_defs.h new file mode 100644 index 0000000000..0a8a4ca99c --- /dev/null +++ b/ArduinoAddons/Arduino_0.xx/Sanguino/bootloaders/atmega1284p/pin_defs.h @@ -0,0 +1,81 @@ +#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega88) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__) +/* Onboard LED is connected to pin PB5 in Arduino NG, Diecimila, and Duemilanove */ +#define LED_DDR DDRB +#define LED_PORT PORTB +#define LED_PIN PINB +#define LED PINB5 + +/* Ports for soft UART */ +#ifdef SOFT_UART +#define UART_PORT PORTD +#define UART_PIN PIND +#define UART_DDR DDRD +#define UART_TX_BIT 1 +#define UART_RX_BIT 0 +#endif +#endif + +#if defined(__AVR_ATmega8__) + //Name conversion R.Wiersma + #define UCSR0A UCSRA + #define UDR0 UDR + #define UDRE0 UDRE + #define RXC0 RXC + #define FE0 FE + #define TIFR1 TIFR + #define WDTCSR WDTCR +#endif + +/* Luminet support */ +#if defined(__AVR_ATtiny84__) +/* Red LED is connected to pin PA4 */ +#define LED_DDR DDRA +#define LED_PORT PORTA +#define LED_PIN PINA +#define LED PINA4 +/* Ports for soft UART - left port only for now. TX/RX on PA2/PA3 */ +#ifdef SOFT_UART +#define UART_PORT PORTA +#define UART_PIN PINA +#define UART_DDR DDRA +#define UART_TX_BIT 2 +#define UART_RX_BIT 3 +#endif +#endif + +/* Sanguino support */ +#if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__) +/* Onboard LED is connected to pin PB0 on Sanguino */ +#define LED_DDR DDRB +#define LED_PORT PORTB +#define LED_PIN PINB +#define LED PINB0 + +/* Ports for soft UART */ +#ifdef SOFT_UART +#define UART_PORT PORTD +#define UART_PIN PIND +#define UART_DDR DDRD +#define UART_TX_BIT 1 +#define UART_RX_BIT 0 +#endif +#endif + +/* Mega support */ +#if defined(__AVR_ATmega1280__) +/* Onboard LED is connected to pin PB7 on Arduino Mega */ +#define LED_DDR DDRB +#define LED_PORT PORTB +#define LED_PIN PINB +#define LED PINB7 + +/* Ports for soft UART */ +#ifdef SOFT_UART +#define UART_PORT PORTE +#define UART_PIN PINE +#define UART_DDR DDRE +#define UART_TX_BIT 1 +#define UART_RX_BIT 0 +#endif +#endif + diff --git a/ArduinoAddons/Arduino_0.xx/Sanguino/bootloaders/atmega1284p/stk500.h b/ArduinoAddons/Arduino_0.xx/Sanguino/bootloaders/atmega1284p/stk500.h new file mode 100644 index 0000000000..ca0dd91dfe --- /dev/null +++ b/ArduinoAddons/Arduino_0.xx/Sanguino/bootloaders/atmega1284p/stk500.h @@ -0,0 +1,39 @@ +/* STK500 constants list, from AVRDUDE */ +#define STK_OK 0x10 +#define STK_FAILED 0x11 // Not used +#define STK_UNKNOWN 0x12 // Not used +#define STK_NODEVICE 0x13 // Not used +#define STK_INSYNC 0x14 // ' ' +#define STK_NOSYNC 0x15 // Not used +#define ADC_CHANNEL_ERROR 0x16 // Not used +#define ADC_MEASURE_OK 0x17 // Not used +#define PWM_CHANNEL_ERROR 0x18 // Not used +#define PWM_ADJUST_OK 0x19 // Not used +#define CRC_EOP 0x20 // 'SPACE' +#define STK_GET_SYNC 0x30 // '0' +#define STK_GET_SIGN_ON 0x31 // '1' +#define STK_SET_PARAMETER 0x40 // '@' +#define STK_GET_PARAMETER 0x41 // 'A' +#define STK_SET_DEVICE 0x42 // 'B' +#define STK_SET_DEVICE_EXT 0x45 // 'E' +#define STK_ENTER_PROGMODE 0x50 // 'P' +#define STK_LEAVE_PROGMODE 0x51 // 'Q' +#define STK_CHIP_ERASE 0x52 // 'R' +#define STK_CHECK_AUTOINC 0x53 // 'S' +#define STK_LOAD_ADDRESS 0x55 // 'U' +#define STK_UNIVERSAL 0x56 // 'V' +#define STK_PROG_FLASH 0x60 // '`' +#define STK_PROG_DATA 0x61 // 'a' +#define STK_PROG_FUSE 0x62 // 'b' +#define STK_PROG_LOCK 0x63 // 'c' +#define STK_PROG_PAGE 0x64 // 'd' +#define STK_PROG_FUSE_EXT 0x65 // 'e' +#define STK_READ_FLASH 0x70 // 'p' +#define STK_READ_DATA 0x71 // 'q' +#define STK_READ_FUSE 0x72 // 'r' +#define STK_READ_LOCK 0x73 // 's' +#define STK_READ_PAGE 0x74 // 't' +#define STK_READ_SIGN 0x75 // 'u' +#define STK_READ_OSCCAL 0x76 // 'v' +#define STK_READ_FUSE_EXT 0x77 // 'w' +#define STK_READ_OSCCAL_EXT 0x78 // 'x'