Codebase list arduino-mighty-1284p / 99ceacf
Imported Upstream version 1 Bas Wijnen 9 years ago
12 changed file(s) with 3291 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 *.o
1 *.elf
2 *.hex
3 *.lst
0 Version 1:
1
2 * *: Fork from https://github.com/maniacbug/mighty-1284p/.
3 * README.md: Update.
4 * .gitignore: Update.
5 * cores: Remove outdated copy of Arduino source tree.
6 * bootloaders: Build from source.
7 * variants: Remove alternative pinouts.
8 * variants/standard/pins_arduino.h: Correct NUM_DIGITAL_PINS.
0 # Mighty 1284P: Platform files for Arduino to run on ATmega1284P
1
2 ## What is it?
3
4 Everything you need to run Arduino on ATmega1284P.
5
6 ## Current state
7
8 This is a fork of Maniacbug's work, which seems to have been abandoned. It uses upstream Arduino files as much as possible instead of (out of date) copies. It has been tested and is considered complete. Please report any bugs you may find.
9
10 ## Installation
11
12 Recommended method: on your Debian system, install the package from the repository. Alternatively:
13
14 1. Download the [ZIP File](https://github.com/wijnen/mighty-1284p/zipball/master)
15 2. Unzip it a folder called 'hardware' in your sketchbook directory, e.g. ~/Arduino/hardware/mighty-1284p
16 3. Restart the IDE
17 4. Select Tools > Board > Mighty 1284p 16MHz using Optiboot
18 5. To burn the bootloader, follow the Arduino [Bootloader](http://arduino.cc/en/Hacking/Bootloader) instructions.
19
20 ## Requirements
21
22 * Works only on Arduino >= 1.0
23 * Cannot be burned using [USBtinyISP](http://www.ladyada.net/make/usbtinyisp/). That programmer cannot flash to chips with >64k flash size.
24
25 ## See also
26
27 http://maniacbug.wordpress.com/2011/11/27/arduino-on-atmega1284p-4/
28
29 ## Supported Boards
30
31 * 'Mighty 1284p using Optiboot'.
32 * 'Original Mighty 1284p'. Uses a different booloader; if you have a board with this, burning optiboot is recommended.
0 ##############################################################
1
2 mighty_opt.name=Mighty 1284p using Optiboot
3 mighty_opt.upload.protocol=arduino
4 mighty_opt.upload.maximum_size=130048
5 mighty_opt.upload.speed=115200
6 mighty_opt.bootloader.low_fuses=0xff
7 mighty_opt.bootloader.high_fuses=0xde
8 mighty_opt.bootloader.extended_fuses=0xfd
9 mighty_opt.bootloader.path=optiboot
10 mighty_opt.bootloader.file=optiboot_atmega1284p.hex
11 mighty_opt.bootloader.unlock_bits=0x3F
12 mighty_opt.bootloader.lock_bits=0x0F
13 mighty_opt.build.mcu=atmega1284p
14 mighty_opt.build.f_cpu=16000000L
15 mighty_opt.build.core=arduino:arduino
16 mighty_opt.build.variant=standard
17
18 ##############################################################
19
20 mighty.name=Original Mighty 1284p
21 mighty.upload.protocol=stk500v1
22 mighty.upload.maximum_size=129024
23 mighty.upload.speed=57600
24 mighty.bootloader.low_fuses=0xff
25 mighty.bootloader.high_fuses=0xdc
26 mighty.bootloader.extended_fuses=0xfd
27 mighty.bootloader.path=standard
28 mighty.bootloader.file=ATmegaBOOT_1284P.hex
29 mighty.bootloader.unlock_bits=0x3F
30 mighty.bootloader.lock_bits=0x0F
31 mighty.build.mcu=atmega1284p
32 mighty.build.f_cpu=16000000L
33 mighty.build.core=arduino:arduino
34 mighty.build.variant=standard
0 # Makefile for ATmegaBOOT
1 # E.Lins, 18.7.2005
2 # $Id$
3 #
4 # Instructions
5 #
6 # To make bootloader .hex file:
7 # make diecimila
8 # make lilypad
9 # make ng
10 # etc...
11 #
12 # To burn bootloader .hex file:
13 # make diecimila_isp
14 # make lilypad_isp
15 # make ng_isp
16 # etc...
17
18 # program name should not be changed...
19 PROGRAM = optiboot
20
21 # The default behavior is to build using tools that are in the users
22 # current path variables, but we can also build using an installed
23 # Arduino user IDE setup, or the Arduino source tree.
24 # Uncomment this next lines to build within the arduino environment,
25 # using the arduino-included avrgcc toolset (mac and pc)
26 # ENV ?= arduino
27 # ENV ?= arduinodev
28 # OS ?= macosx
29 # OS ?= windows
30
31 # enter the parameters for the avrdude isp tool
32 ISPTOOL = avrisp
33 ISPPORT = /dev/ttyUSB0
34 ISPSPEED = -b 19200
35
36 MCU_TARGET = atmega168
37 LDSECTIONS = -Wl,--section-start=.text=0x3e00 -Wl,--section-start=.version=0x3ffe
38
39 # Build environments
40 # Start of some ugly makefile-isms to allow optiboot to be built
41 # in several different environments. See the README.TXT file for
42 # details.
43
44 # default
45 fixpath = $(1)
46
47 # the efuse should really be 0xf8; since, however, only the lower
48 # three bits of that byte are used on the atmega168, avrdude gets
49 # confused if you specify 1's for the higher bits, see:
50 # http://tinker.it/now/2007/02/24/the-tale-of-avrdude-atmega168-and-extended-bits-fuses/
51 #
52 # similarly, the lock bits should be 0xff instead of 0x3f (to
53 # unlock the bootloader section) and 0xcf instead of 0x2f (to
54 # lock it), but since the high two bits of the lock byte are
55 # unused, avrdude would get confused.
56
57 ISPFUSES = $(AVRDUDE_ROOT)avrdude $(AVRDUDE_CONF) -c $(ISPTOOL) \
58 -p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \
59 -e -u -U lock:w:0x3f:m -U efuse:w:0x$(EFUSE):m \
60 -U hfuse:w:0x$(HFUSE):m -U lfuse:w:0x$(LFUSE):m
61 ISPFLASH = $(AVRDUDE_ROOT)avrdude $(AVRDUDE_CONF) -c $(ISPTOOL) \
62 -p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) -V \
63 -U flash:w:$(PROGRAM)_$(TARGET).hex -U lock:w:0x2f:m
64
65 STK500 = "C:\Program Files\Atmel\AVR Tools\STK500\Stk500.exe"
66 STK500-1 = $(STK500) -e -d$(MCU_TARGET) -pf -vf -if$(PROGRAM)_$(TARGET).hex \
67 -lFF -LFF -f$(HFUSE)$(LFUSE) -EF8 -ms -q -cUSB -I200kHz -s -wt
68 STK500-2 = $(STK500) -d$(MCU_TARGET) -ms -q -lCF -LCF -cUSB -I200kHz -s -wt
69
70 OBJ = $(PROGRAM).o
71 OPTIMIZE = -Os -fno-inline-small-functions -fno-split-wide-types
72
73 DEFS =
74 LIBS =
75
76 CC = $(GCCROOT)avr-gcc
77
78 # Override is only needed by avr-lib build system.
79
80 override CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) -DF_CPU=$(AVR_FREQ) $(DEFS)
81 override LDFLAGS = $(LDSECTIONS) -Wl,--relax -Wl,--gc-sections -nostartfiles -nostdlib
82
83 OBJCOPY = $(GCCROOT)avr-objcopy
84 OBJDUMP = $(call fixpath,$(GCCROOT)avr-objdump)
85
86 SIZE = $(GCCROOT)avr-size
87
88 atmega1284: TARGET = atmega1284p
89 atmega1284: MCU_TARGET = atmega1284p
90 atmega1284: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' '-DBIGBOOT'
91 atmega1284: AVR_FREQ = 16000000L
92 atmega1284: LDSECTIONS = -Wl,--section-start=.text=0x1fc00
93 atmega1284: $(PROGRAM)_atmega1284p.hex
94 atmega1284: $(PROGRAM)_atmega1284p.lst
95
96 atmega1284_isp: atmega1284
97 atmega1284_isp: TARGET = atmega1284p
98 atmega1284_isp: MCU_TARGET = atmega1284p
99 # 1024 byte boot
100 atmega1284_isp: HFUSE = DE
101 # Low power xtal (16MHz) 16KCK/14CK+65ms
102 atmega1284_isp: LFUSE = FF
103 # 2.7V brownout
104 atmega1284_isp: EFUSE = FD
105 atmega1284_isp: isp
106
107 atmega1284_slow: TARGET = atmega1284p_slow
108 atmega1284_slow: MCU_TARGET = atmega1284p
109 atmega1284_slow: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=19200' '-DBIGBOOT'
110 atmega1284_slow: AVR_FREQ = 16000000L
111 atmega1284_slow: LDSECTIONS = -Wl,--section-start=.text=0x1fc00
112 atmega1284_slow: $(PROGRAM)_atmega1284p_slow.hex
113 atmega1284_slow: $(PROGRAM)_atmega1284p_slow.lst
114
115 atmega1284_slow_isp: atmega1284_slow
116 atmega1284_slow_isp: TARGET = atmega1284p_slow
117 atmega1284_slow_isp: MCU_TARGET = atmega1284p
118 # 1024 byte boot
119 atmega1284_slow_isp: HFUSE = DE
120 # Low power xtal (16MHz) 16KCK/14CK+65ms
121 atmega1284_slow_isp: LFUSE = FF
122 # 2.7V brownout
123 atmega1284_slow_isp: EFUSE = FD
124 atmega1284_slow_isp: isp
125
126 #
127 # Generic build instructions
128 #
129 #
130
131 isp: $(TARGET)
132 $(ISPFUSES)
133 $(ISPFLASH)
134
135 isp-stk500: $(PROGRAM)_$(TARGET).hex
136 $(STK500-1)
137 $(STK500-2)
138
139 %.elf: $(OBJ)
140 $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
141 $(SIZE) $@
142
143 clean:
144 rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex
145
146 %.lst: %.elf
147 $(OBJDUMP) -h -S $< > $@
148
149 %.hex: %.elf
150 $(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O ihex $< $@
151
152 %.srec: %.elf
153 $(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O srec $< $@
154
155 %.bin: %.elf
156 $(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O binary $< $@
0 /* Modified to use out for SPM access
1 ** Peter Knight, Optiboot project http://optiboot.googlecode.com
2 **
3 ** Todo: Tidy up
4 **
5 ** "_short" routines execute 1 cycle faster and use 1 less word of flash
6 ** by using "out" instruction instead of "sts".
7 **
8 ** Additional elpm variants that trust the value of RAMPZ
9 */
10
11 /* Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 Eric B. Weddington
12 All rights reserved.
13
14 Redistribution and use in source and binary forms, with or without
15 modification, are permitted provided that the following conditions are met:
16
17 * Redistributions of source code must retain the above copyright
18 notice, this list of conditions and the following disclaimer.
19 * Redistributions in binary form must reproduce the above copyright
20 notice, this list of conditions and the following disclaimer in
21 the documentation and/or other materials provided with the
22 distribution.
23 * Neither the name of the copyright holders nor the names of
24 contributors may be used to endorse or promote products derived
25 from this software without specific prior written permission.
26
27 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
31 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 POSSIBILITY OF SUCH DAMAGE. */
38
39 /* $Id: boot.h,v 1.27.2.3 2008/09/30 13:58:48 arcanum Exp $ */
40
41 #ifndef _AVR_BOOT_H_
42 #define _AVR_BOOT_H_ 1
43
44 /** \file */
45 /** \defgroup avr_boot <avr/boot.h>: Bootloader Support Utilities
46 \code
47 #include <avr/io.h>
48 #include <avr/boot.h>
49 \endcode
50
51 The macros in this module provide a C language interface to the
52 bootloader support functionality of certain AVR processors. These
53 macros are designed to work with all sizes of flash memory.
54
55 Global interrupts are not automatically disabled for these macros. It
56 is left up to the programmer to do this. See the code example below.
57 Also see the processor datasheet for caveats on having global interrupts
58 enabled during writing of the Flash.
59
60 \note Not all AVR processors provide bootloader support. See your
61 processor datasheet to see if it provides bootloader support.
62
63 \todo From email with Marek: On smaller devices (all except ATmega64/128),
64 __SPM_REG is in the I/O space, accessible with the shorter "in" and "out"
65 instructions - since the boot loader has a limited size, this could be an
66 important optimization.
67
68 \par API Usage Example
69 The following code shows typical usage of the boot API.
70
71 \code
72 #include <inttypes.h>
73 #include <avr/interrupt.h>
74 #include <avr/pgmspace.h>
75
76 void boot_program_page (uint32_t page, uint8_t *buf)
77 {
78 uint16_t i;
79 uint8_t sreg;
80
81 // Disable interrupts.
82
83 sreg = SREG;
84 cli();
85
86 eeprom_busy_wait ();
87
88 boot_page_erase (page);
89 boot_spm_busy_wait (); // Wait until the memory is erased.
90
91 for (i=0; i<SPM_PAGESIZE; i+=2)
92 {
93 // Set up little-endian word.
94
95 uint16_t w = *buf++;
96 w += (*buf++) << 8;
97
98 boot_page_fill (page + i, w);
99 }
100
101 boot_page_write (page); // Store buffer in flash page.
102 boot_spm_busy_wait(); // Wait until the memory is written.
103
104 // Reenable RWW-section again. We need this if we want to jump back
105 // to the application after bootloading.
106
107 boot_rww_enable ();
108
109 // Re-enable interrupts (if they were ever enabled).
110
111 SREG = sreg;
112 }\endcode */
113
114 #include <avr/eeprom.h>
115 #include <avr/io.h>
116 #include <inttypes.h>
117 #include <limits.h>
118
119 /* Check for SPM Control Register in processor. */
120 #if defined (SPMCSR)
121 # define __SPM_REG SPMCSR
122 #elif defined (SPMCR)
123 # define __SPM_REG SPMCR
124 #else
125 # error AVR processor does not provide bootloader support!
126 #endif
127
128
129 /* Check for SPM Enable bit. */
130 #if defined(SPMEN)
131 # define __SPM_ENABLE SPMEN
132 #elif defined(SELFPRGEN)
133 # define __SPM_ENABLE SELFPRGEN
134 #else
135 # error Cannot find SPM Enable bit definition!
136 #endif
137
138 /** \ingroup avr_boot
139 \def BOOTLOADER_SECTION
140
141 Used to declare a function or variable to be placed into a
142 new section called .bootloader. This section and its contents
143 can then be relocated to any address (such as the bootloader
144 NRWW area) at link-time. */
145
146 #define BOOTLOADER_SECTION __attribute__ ((section (".bootloader")))
147
148 /* Create common bit definitions. */
149 #ifdef ASB
150 #define __COMMON_ASB ASB
151 #else
152 #define __COMMON_ASB RWWSB
153 #endif
154
155 #ifdef ASRE
156 #define __COMMON_ASRE ASRE
157 #else
158 #define __COMMON_ASRE RWWSRE
159 #endif
160
161 /* Define the bit positions of the Boot Lock Bits. */
162
163 #define BLB12 5
164 #define BLB11 4
165 #define BLB02 3
166 #define BLB01 2
167
168 /** \ingroup avr_boot
169 \def boot_spm_interrupt_enable()
170 Enable the SPM interrupt. */
171
172 #define boot_spm_interrupt_enable() (__SPM_REG |= (uint8_t)_BV(SPMIE))
173
174 /** \ingroup avr_boot
175 \def boot_spm_interrupt_disable()
176 Disable the SPM interrupt. */
177
178 #define boot_spm_interrupt_disable() (__SPM_REG &= (uint8_t)~_BV(SPMIE))
179
180 /** \ingroup avr_boot
181 \def boot_is_spm_interrupt()
182 Check if the SPM interrupt is enabled. */
183
184 #define boot_is_spm_interrupt() (__SPM_REG & (uint8_t)_BV(SPMIE))
185
186 /** \ingroup avr_boot
187 \def boot_rww_busy()
188 Check if the RWW section is busy. */
189
190 #define boot_rww_busy() (__SPM_REG & (uint8_t)_BV(__COMMON_ASB))
191
192 /** \ingroup avr_boot
193 \def boot_spm_busy()
194 Check if the SPM instruction is busy. */
195
196 #define boot_spm_busy() (__SPM_REG & (uint8_t)_BV(__SPM_ENABLE))
197
198 /** \ingroup avr_boot
199 \def boot_spm_busy_wait()
200 Wait while the SPM instruction is busy. */
201
202 #define boot_spm_busy_wait() do{}while(boot_spm_busy())
203
204 #define __BOOT_PAGE_ERASE (_BV(__SPM_ENABLE) | _BV(PGERS))
205 #define __BOOT_PAGE_WRITE (_BV(__SPM_ENABLE) | _BV(PGWRT))
206 #define __BOOT_PAGE_FILL _BV(__SPM_ENABLE)
207 #define __BOOT_RWW_ENABLE (_BV(__SPM_ENABLE) | _BV(__COMMON_ASRE))
208 #define __BOOT_LOCK_BITS_SET (_BV(__SPM_ENABLE) | _BV(BLBSET))
209
210 #define __boot_page_fill_short(address, data) \
211 (__extension__({ \
212 __asm__ __volatile__ \
213 ( \
214 "movw r0, %3\n\t" \
215 "out %0, %1\n\t" \
216 "spm\n\t" \
217 "clr r1\n\t" \
218 : \
219 : "i" (_SFR_IO_ADDR(__SPM_REG)), \
220 "r" ((uint8_t)__BOOT_PAGE_FILL), \
221 "z" ((uint16_t)address), \
222 "r" ((uint16_t)data) \
223 : "r0" \
224 ); \
225 }))
226
227 #define __boot_page_fill_normal(address, data) \
228 (__extension__({ \
229 __asm__ __volatile__ \
230 ( \
231 "movw r0, %3\n\t" \
232 "sts %0, %1\n\t" \
233 "spm\n\t" \
234 "clr r1\n\t" \
235 : \
236 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
237 "r" ((uint8_t)__BOOT_PAGE_FILL), \
238 "z" ((uint16_t)address), \
239 "r" ((uint16_t)data) \
240 : "r0" \
241 ); \
242 }))
243
244 #define __boot_page_fill_alternate(address, data)\
245 (__extension__({ \
246 __asm__ __volatile__ \
247 ( \
248 "movw r0, %3\n\t" \
249 "sts %0, %1\n\t" \
250 "spm\n\t" \
251 ".word 0xffff\n\t" \
252 "nop\n\t" \
253 "clr r1\n\t" \
254 : \
255 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
256 "r" ((uint8_t)__BOOT_PAGE_FILL), \
257 "z" ((uint16_t)address), \
258 "r" ((uint16_t)data) \
259 : "r0" \
260 ); \
261 }))
262
263 #define __boot_page_fill_extended(address, data) \
264 (__extension__({ \
265 __asm__ __volatile__ \
266 ( \
267 "movw r0, %4\n\t" \
268 "movw r30, %A3\n\t" \
269 "sts %1, %C3\n\t" \
270 "sts %0, %2\n\t" \
271 "spm\n\t" \
272 "clr r1\n\t" \
273 : \
274 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
275 "i" (_SFR_MEM_ADDR(RAMPZ)), \
276 "r" ((uint8_t)__BOOT_PAGE_FILL), \
277 "r" ((uint32_t)address), \
278 "r" ((uint16_t)data) \
279 : "r0", "r30", "r31" \
280 ); \
281 }))
282
283 #define __boot_page_fill_extended_short(address, data) \
284 (__extension__({ \
285 __asm__ __volatile__ \
286 ( \
287 "movw r0, %4\n\t" \
288 "movw r30, %A3\n\t" \
289 "out %1, %C3\n\t" \
290 "out %0, %2\n\t" \
291 "spm\n\t" \
292 "clr r1\n\t" \
293 : \
294 : "i" (_SFR_IO_ADDR(__SPM_REG)), \
295 "i" (_SFR_IO_ADDR(RAMPZ)), \
296 "r" ((uint8_t)__BOOT_PAGE_FILL), \
297 "r" ((uint32_t)address), \
298 "r" ((uint16_t)data) \
299 : "r0", "r30", "r31" \
300 ); \
301 }))
302
303 #define __boot_page_erase_short(address) \
304 (__extension__({ \
305 __asm__ __volatile__ \
306 ( \
307 "out %0, %1\n\t" \
308 "spm\n\t" \
309 : \
310 : "i" (_SFR_IO_ADDR(__SPM_REG)), \
311 "r" ((uint8_t)__BOOT_PAGE_ERASE), \
312 "z" ((uint16_t)address) \
313 ); \
314 }))
315
316
317 #define __boot_page_erase_normal(address) \
318 (__extension__({ \
319 __asm__ __volatile__ \
320 ( \
321 "sts %0, %1\n\t" \
322 "spm\n\t" \
323 : \
324 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
325 "r" ((uint8_t)__BOOT_PAGE_ERASE), \
326 "z" ((uint16_t)address) \
327 ); \
328 }))
329
330 #define __boot_page_erase_alternate(address) \
331 (__extension__({ \
332 __asm__ __volatile__ \
333 ( \
334 "sts %0, %1\n\t" \
335 "spm\n\t" \
336 ".word 0xffff\n\t" \
337 "nop\n\t" \
338 : \
339 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
340 "r" ((uint8_t)__BOOT_PAGE_ERASE), \
341 "z" ((uint16_t)address) \
342 ); \
343 }))
344
345 #define __boot_page_erase_extended(address) \
346 (__extension__({ \
347 __asm__ __volatile__ \
348 ( \
349 "movw r30, %A3\n\t" \
350 "sts %1, %C3\n\t" \
351 "sts %0, %2\n\t" \
352 "spm\n\t" \
353 : \
354 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
355 "i" (_SFR_MEM_ADDR(RAMPZ)), \
356 "r" ((uint8_t)__BOOT_PAGE_ERASE), \
357 "r" ((uint32_t)address) \
358 : "r30", "r31" \
359 ); \
360 }))
361 #define __boot_page_erase_extended_short(address) \
362 (__extension__({ \
363 __asm__ __volatile__ \
364 ( \
365 "movw r30, %A3\n\t" \
366 "out %1, %C3\n\t" \
367 "out %0, %2\n\t" \
368 "spm\n\t" \
369 : \
370 : "i" (_SFR_IO_ADDR(__SPM_REG)), \
371 "i" (_SFR_IO_ADDR(RAMPZ)), \
372 "r" ((uint8_t)__BOOT_PAGE_ERASE), \
373 "r" ((uint32_t)address) \
374 : "r30", "r31" \
375 ); \
376 }))
377
378 #define __boot_page_write_short(address) \
379 (__extension__({ \
380 __asm__ __volatile__ \
381 ( \
382 "out %0, %1\n\t" \
383 "spm\n\t" \
384 : \
385 : "i" (_SFR_IO_ADDR(__SPM_REG)), \
386 "r" ((uint8_t)__BOOT_PAGE_WRITE), \
387 "z" ((uint16_t)address) \
388 ); \
389 }))
390
391 #define __boot_page_write_normal(address) \
392 (__extension__({ \
393 __asm__ __volatile__ \
394 ( \
395 "sts %0, %1\n\t" \
396 "spm\n\t" \
397 : \
398 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
399 "r" ((uint8_t)__BOOT_PAGE_WRITE), \
400 "z" ((uint16_t)address) \
401 ); \
402 }))
403
404 #define __boot_page_write_alternate(address) \
405 (__extension__({ \
406 __asm__ __volatile__ \
407 ( \
408 "sts %0, %1\n\t" \
409 "spm\n\t" \
410 ".word 0xffff\n\t" \
411 "nop\n\t" \
412 : \
413 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
414 "r" ((uint8_t)__BOOT_PAGE_WRITE), \
415 "z" ((uint16_t)address) \
416 ); \
417 }))
418
419 #define __boot_page_write_extended(address) \
420 (__extension__({ \
421 __asm__ __volatile__ \
422 ( \
423 "movw r30, %A3\n\t" \
424 "sts %1, %C3\n\t" \
425 "sts %0, %2\n\t" \
426 "spm\n\t" \
427 : \
428 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
429 "i" (_SFR_MEM_ADDR(RAMPZ)), \
430 "r" ((uint8_t)__BOOT_PAGE_WRITE), \
431 "r" ((uint32_t)address) \
432 : "r30", "r31" \
433 ); \
434 }))
435 #define __boot_page_write_extended_short(address) \
436 (__extension__({ \
437 __asm__ __volatile__ \
438 ( \
439 "movw r30, %A3\n\t" \
440 "out %1, %C3\n\t" \
441 "out %0, %2\n\t" \
442 "spm\n\t" \
443 : \
444 : "i" (_SFR_IO_ADDR(__SPM_REG)), \
445 "i" (_SFR_IO_ADDR(RAMPZ)), \
446 "r" ((uint8_t)__BOOT_PAGE_WRITE), \
447 "r" ((uint32_t)address) \
448 : "r30", "r31" \
449 ); \
450 }))
451
452 #define __boot_rww_enable_short() \
453 (__extension__({ \
454 __asm__ __volatile__ \
455 ( \
456 "out %0, %1\n\t" \
457 "spm\n\t" \
458 : \
459 : "i" (_SFR_IO_ADDR(__SPM_REG)), \
460 "r" ((uint8_t)__BOOT_RWW_ENABLE) \
461 ); \
462 }))
463
464 #define __boot_rww_enable() \
465 (__extension__({ \
466 __asm__ __volatile__ \
467 ( \
468 "sts %0, %1\n\t" \
469 "spm\n\t" \
470 : \
471 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
472 "r" ((uint8_t)__BOOT_RWW_ENABLE) \
473 ); \
474 }))
475
476 #define __boot_rww_enable_alternate() \
477 (__extension__({ \
478 __asm__ __volatile__ \
479 ( \
480 "sts %0, %1\n\t" \
481 "spm\n\t" \
482 ".word 0xffff\n\t" \
483 "nop\n\t" \
484 : \
485 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
486 "r" ((uint8_t)__BOOT_RWW_ENABLE) \
487 ); \
488 }))
489
490 /* From the mega16/mega128 data sheets (maybe others):
491
492 Bits by SPM To set the Boot Loader Lock bits, write the desired data to
493 R0, write "X0001001" to SPMCR and execute SPM within four clock cycles
494 after writing SPMCR. The only accessible Lock bits are the Boot Lock bits
495 that may prevent the Application and Boot Loader section from any
496 software update by the MCU.
497
498 If bits 5..2 in R0 are cleared (zero), the corresponding Boot Lock bit
499 will be programmed if an SPM instruction is executed within four cycles
500 after BLBSET and SPMEN (or SELFPRGEN) are set in SPMCR. The Z-pointer is
501 don't care during this operation, but for future compatibility it is
502 recommended to load the Z-pointer with $0001 (same as used for reading the
503 Lock bits). For future compatibility It is also recommended to set bits 7,
504 6, 1, and 0 in R0 to 1 when writing the Lock bits. When programming the
505 Lock bits the entire Flash can be read during the operation. */
506
507 #define __boot_lock_bits_set_short(lock_bits) \
508 (__extension__({ \
509 uint8_t value = (uint8_t)(~(lock_bits)); \
510 __asm__ __volatile__ \
511 ( \
512 "ldi r30, 1\n\t" \
513 "ldi r31, 0\n\t" \
514 "mov r0, %2\n\t" \
515 "out %0, %1\n\t" \
516 "spm\n\t" \
517 : \
518 : "i" (_SFR_IO_ADDR(__SPM_REG)), \
519 "r" ((uint8_t)__BOOT_LOCK_BITS_SET), \
520 "r" (value) \
521 : "r0", "r30", "r31" \
522 ); \
523 }))
524
525 #define __boot_lock_bits_set(lock_bits) \
526 (__extension__({ \
527 uint8_t value = (uint8_t)(~(lock_bits)); \
528 __asm__ __volatile__ \
529 ( \
530 "ldi r30, 1\n\t" \
531 "ldi r31, 0\n\t" \
532 "mov r0, %2\n\t" \
533 "sts %0, %1\n\t" \
534 "spm\n\t" \
535 : \
536 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
537 "r" ((uint8_t)__BOOT_LOCK_BITS_SET), \
538 "r" (value) \
539 : "r0", "r30", "r31" \
540 ); \
541 }))
542
543 #define __boot_lock_bits_set_alternate(lock_bits) \
544 (__extension__({ \
545 uint8_t value = (uint8_t)(~(lock_bits)); \
546 __asm__ __volatile__ \
547 ( \
548 "ldi r30, 1\n\t" \
549 "ldi r31, 0\n\t" \
550 "mov r0, %2\n\t" \
551 "sts %0, %1\n\t" \
552 "spm\n\t" \
553 ".word 0xffff\n\t" \
554 "nop\n\t" \
555 : \
556 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
557 "r" ((uint8_t)__BOOT_LOCK_BITS_SET), \
558 "r" (value) \
559 : "r0", "r30", "r31" \
560 ); \
561 }))
562
563 /*
564 Reading lock and fuse bits:
565
566 Similarly to writing the lock bits above, set BLBSET and SPMEN (or
567 SELFPRGEN) bits in __SPMREG, and then (within four clock cycles) issue an
568 LPM instruction.
569
570 Z address: contents:
571 0x0000 low fuse bits
572 0x0001 lock bits
573 0x0002 extended fuse bits
574 0x0003 high fuse bits
575
576 Sounds confusing, doesn't it?
577
578 Unlike the macros in pgmspace.h, no need to care for non-enhanced
579 cores here as these old cores do not provide SPM support anyway.
580 */
581
582 /** \ingroup avr_boot
583 \def GET_LOW_FUSE_BITS
584 address to read the low fuse bits, using boot_lock_fuse_bits_get
585 */
586 #define GET_LOW_FUSE_BITS (0x0000)
587 /** \ingroup avr_boot
588 \def GET_LOCK_BITS
589 address to read the lock bits, using boot_lock_fuse_bits_get
590 */
591 #define GET_LOCK_BITS (0x0001)
592 /** \ingroup avr_boot
593 \def GET_EXTENDED_FUSE_BITS
594 address to read the extended fuse bits, using boot_lock_fuse_bits_get
595 */
596 #define GET_EXTENDED_FUSE_BITS (0x0002)
597 /** \ingroup avr_boot
598 \def GET_HIGH_FUSE_BITS
599 address to read the high fuse bits, using boot_lock_fuse_bits_get
600 */
601 #define GET_HIGH_FUSE_BITS (0x0003)
602
603 /** \ingroup avr_boot
604 \def boot_lock_fuse_bits_get(address)
605
606 Read the lock or fuse bits at \c address.
607
608 Parameter \c address can be any of GET_LOW_FUSE_BITS,
609 GET_LOCK_BITS, GET_EXTENDED_FUSE_BITS, or GET_HIGH_FUSE_BITS.
610
611 \note The lock and fuse bits returned are the physical values,
612 i.e. a bit returned as 0 means the corresponding fuse or lock bit
613 is programmed.
614 */
615 #define boot_lock_fuse_bits_get_short(address) \
616 (__extension__({ \
617 uint8_t __result; \
618 __asm__ __volatile__ \
619 ( \
620 "ldi r30, %3\n\t" \
621 "ldi r31, 0\n\t" \
622 "out %1, %2\n\t" \
623 "lpm %0, Z\n\t" \
624 : "=r" (__result) \
625 : "i" (_SFR_IO_ADDR(__SPM_REG)), \
626 "r" ((uint8_t)__BOOT_LOCK_BITS_SET), \
627 "M" (address) \
628 : "r0", "r30", "r31" \
629 ); \
630 __result; \
631 }))
632
633 #define boot_lock_fuse_bits_get(address) \
634 (__extension__({ \
635 uint8_t __result; \
636 __asm__ __volatile__ \
637 ( \
638 "ldi r30, %3\n\t" \
639 "ldi r31, 0\n\t" \
640 "sts %1, %2\n\t" \
641 "lpm %0, Z\n\t" \
642 : "=r" (__result) \
643 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
644 "r" ((uint8_t)__BOOT_LOCK_BITS_SET), \
645 "M" (address) \
646 : "r0", "r30", "r31" \
647 ); \
648 __result; \
649 }))
650
651 /** \ingroup avr_boot
652 \def boot_signature_byte_get(address)
653
654 Read the Signature Row byte at \c address. For some MCU types,
655 this function can also retrieve the factory-stored oscillator
656 calibration bytes.
657
658 Parameter \c address can be 0-0x1f as documented by the datasheet.
659 \note The values are MCU type dependent.
660 */
661
662 #define __BOOT_SIGROW_READ (_BV(__SPM_ENABLE) | _BV(SIGRD))
663
664 #define boot_signature_byte_get_short(addr) \
665 (__extension__({ \
666 uint16_t __addr16 = (uint16_t)(addr); \
667 uint8_t __result; \
668 __asm__ __volatile__ \
669 ( \
670 "out %1, %2\n\t" \
671 "lpm %0, Z" "\n\t" \
672 : "=r" (__result) \
673 : "i" (_SFR_IO_ADDR(__SPM_REG)), \
674 "r" ((uint8_t) __BOOT_SIGROW_READ), \
675 "z" (__addr16) \
676 ); \
677 __result; \
678 }))
679
680 #define boot_signature_byte_get(addr) \
681 (__extension__({ \
682 uint16_t __addr16 = (uint16_t)(addr); \
683 uint8_t __result; \
684 __asm__ __volatile__ \
685 ( \
686 "sts %1, %2\n\t" \
687 "lpm %0, Z" "\n\t" \
688 : "=r" (__result) \
689 : "i" (_SFR_MEM_ADDR(__SPM_REG)), \
690 "r" ((uint8_t) __BOOT_SIGROW_READ), \
691 "z" (__addr16) \
692 ); \
693 __result; \
694 }))
695
696 /** \ingroup avr_boot
697 \def boot_page_fill(address, data)
698
699 Fill the bootloader temporary page buffer for flash
700 address with data word.
701
702 \note The address is a byte address. The data is a word. The AVR
703 writes data to the buffer a word at a time, but addresses the buffer
704 per byte! So, increment your address by 2 between calls, and send 2
705 data bytes in a word format! The LSB of the data is written to the lower
706 address; the MSB of the data is written to the higher address.*/
707
708 /** \ingroup avr_boot
709 \def boot_page_erase(address)
710
711 Erase the flash page that contains address.
712
713 \note address is a byte address in flash, not a word address. */
714
715 /** \ingroup avr_boot
716 \def boot_page_write(address)
717
718 Write the bootloader temporary page buffer
719 to flash page that contains address.
720
721 \note address is a byte address in flash, not a word address. */
722
723 /** \ingroup avr_boot
724 \def boot_rww_enable()
725
726 Enable the Read-While-Write memory section. */
727
728 /** \ingroup avr_boot
729 \def boot_lock_bits_set(lock_bits)
730
731 Set the bootloader lock bits.
732
733 \param lock_bits A mask of which Boot Loader Lock Bits to set.
734
735 \note In this context, a 'set bit' will be written to a zero value.
736 Note also that only BLBxx bits can be programmed by this command.
737
738 For example, to disallow the SPM instruction from writing to the Boot
739 Loader memory section of flash, you would use this macro as such:
740
741 \code
742 boot_lock_bits_set (_BV (BLB11));
743 \endcode
744
745 \note Like any lock bits, the Boot Loader Lock Bits, once set,
746 cannot be cleared again except by a chip erase which will in turn
747 also erase the boot loader itself. */
748
749 /* Normal versions of the macros use 16-bit addresses.
750 Extended versions of the macros use 32-bit addresses.
751 Alternate versions of the macros use 16-bit addresses and require special
752 instruction sequences after LPM.
753
754 FLASHEND is defined in the ioXXXX.h file.
755 USHRT_MAX is defined in <limits.h>. */
756
757 #if defined(__AVR_ATmega161__) || defined(__AVR_ATmega163__) \
758 || defined(__AVR_ATmega323__)
759
760 /* Alternate: ATmega161/163/323 and 16 bit address */
761 #define boot_page_fill(address, data) __boot_page_fill_alternate(address, data)
762 #define boot_page_erase(address) __boot_page_erase_alternate(address)
763 #define boot_page_write(address) __boot_page_write_alternate(address)
764 #define boot_rww_enable() __boot_rww_enable_alternate()
765 #define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_alternate(lock_bits)
766
767 #elif (FLASHEND > USHRT_MAX)
768
769 /* Extended: >16 bit address */
770 #define boot_page_fill(address, data) __boot_page_fill_extended_short(address, data)
771 #define boot_page_erase(address) __boot_page_erase_extended_short(address)
772 #define boot_page_write(address) __boot_page_write_extended_short(address)
773 #define boot_rww_enable() __boot_rww_enable_short()
774 #define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_short(lock_bits)
775
776 #else
777
778 /* Normal: 16 bit address */
779 #define boot_page_fill(address, data) __boot_page_fill_short(address, data)
780 #define boot_page_erase(address) __boot_page_erase_short(address)
781 #define boot_page_write(address) __boot_page_write_short(address)
782 #define boot_rww_enable() __boot_rww_enable_short()
783 #define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_short(lock_bits)
784
785 #endif
786
787 /** \ingroup avr_boot
788
789 Same as boot_page_fill() except it waits for eeprom and spm operations to
790 complete before filling the page. */
791
792 #define boot_page_fill_safe(address, data) \
793 do { \
794 boot_spm_busy_wait(); \
795 eeprom_busy_wait(); \
796 boot_page_fill(address, data); \
797 } while (0)
798
799 /** \ingroup avr_boot
800
801 Same as boot_page_erase() except it waits for eeprom and spm operations to
802 complete before erasing the page. */
803
804 #define boot_page_erase_safe(address) \
805 do { \
806 boot_spm_busy_wait(); \
807 eeprom_busy_wait(); \
808 boot_page_erase (address); \
809 } while (0)
810
811 /** \ingroup avr_boot
812
813 Same as boot_page_write() except it waits for eeprom and spm operations to
814 complete before writing the page. */
815
816 #define boot_page_write_safe(address) \
817 do { \
818 boot_spm_busy_wait(); \
819 eeprom_busy_wait(); \
820 boot_page_write (address); \
821 } while (0)
822
823 /** \ingroup avr_boot
824
825 Same as boot_rww_enable() except waits for eeprom and spm operations to
826 complete before enabling the RWW mameory. */
827
828 #define boot_rww_enable_safe() \
829 do { \
830 boot_spm_busy_wait(); \
831 eeprom_busy_wait(); \
832 boot_rww_enable(); \
833 } while (0)
834
835 /** \ingroup avr_boot
836
837 Same as boot_lock_bits_set() except waits for eeprom and spm operations to
838 complete before setting the lock bits. */
839
840 #define boot_lock_bits_set_safe(lock_bits) \
841 do { \
842 boot_spm_busy_wait(); \
843 eeprom_busy_wait(); \
844 boot_lock_bits_set (lock_bits); \
845 } while (0)
846
847 #endif /* _AVR_BOOT_H_ */
0 /**********************************************************/
1 /* Optiboot bootloader for Arduino */
2 /* */
3 /* http://optiboot.googlecode.com */
4 /* */
5 /* Arduino-maintained version : See README.TXT */
6 /* http://code.google.com/p/arduino/ */
7 /* */
8 /* Heavily optimised bootloader that is faster and */
9 /* smaller than the Arduino standard bootloader */
10 /* */
11 /* Enhancements: */
12 /* Fits in 512 bytes, saving 1.5K of code space */
13 /* Background page erasing speeds up programming */
14 /* Higher baud rate speeds up programming */
15 /* Written almost entirely in C */
16 /* Customisable timeout with accurate timeconstant */
17 /* Optional virtual UART. No hardware UART required. */
18 /* Optional virtual boot partition for devices without. */
19 /* */
20 /* What you lose: */
21 /* Implements a skeleton STK500 protocol which is */
22 /* missing several features including EEPROM */
23 /* programming and non-page-aligned writes */
24 /* High baud rate breaks compatibility with standard */
25 /* Arduino flash settings */
26 /* */
27 /* Fully supported: */
28 /* ATmega168 based devices (Diecimila etc) */
29 /* ATmega328P based devices (Duemilanove etc) */
30 /* */
31 /* Alpha test */
32 /* ATmega1280 based devices (Arduino Mega) */
33 /* */
34 /* Work in progress: */
35 /* ATmega644P based devices (Sanguino) */
36 /* ATtiny84 based devices (Luminet) */
37 /* */
38 /* Does not support: */
39 /* USB based devices (eg. Teensy) */
40 /* */
41 /* Assumptions: */
42 /* The code makes several assumptions that reduce the */
43 /* code size. They are all true after a hardware reset, */
44 /* but may not be true if the bootloader is called by */
45 /* other means or on other hardware. */
46 /* No interrupts can occur */
47 /* UART and Timer 1 are set to their reset state */
48 /* SP points to RAMEND */
49 /* */
50 /* Code builds on code, libraries and optimisations from: */
51 /* stk500boot.c by Jason P. Kyle */
52 /* Arduino bootloader http://arduino.cc */
53 /* Spiff's 1K bootloader http://spiffie.org/know/arduino_1k_bootloader/bootloader.shtml */
54 /* avr-libc project http://nongnu.org/avr-libc */
55 /* Adaboot http://www.ladyada.net/library/arduino/bootloader.html */
56 /* AVR305 Atmel Application Note */
57 /* */
58 /* This program is free software; you can redistribute it */
59 /* and/or modify it under the terms of the GNU General */
60 /* Public License as published by the Free Software */
61 /* Foundation; either version 2 of the License, or */
62 /* (at your option) any later version. */
63 /* */
64 /* This program is distributed in the hope that it will */
65 /* be useful, but WITHOUT ANY WARRANTY; without even the */
66 /* implied warranty of MERCHANTABILITY or FITNESS FOR A */
67 /* PARTICULAR PURPOSE. See the GNU General Public */
68 /* License for more details. */
69 /* */
70 /* You should have received a copy of the GNU General */
71 /* Public License along with this program; if not, write */
72 /* to the Free Software Foundation, Inc., */
73 /* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
74 /* */
75 /* Licence can be viewed at */
76 /* http://www.fsf.org/licenses/gpl.txt */
77 /* */
78 /**********************************************************/
79
80
81 /**********************************************************/
82 /* */
83 /* Optional defines: */
84 /* */
85 /**********************************************************/
86 /* */
87 /* BIG_BOOT: */
88 /* Build a 1k bootloader, not 512 bytes. This turns on */
89 /* extra functionality. */
90 /* */
91 /* BAUD_RATE: */
92 /* Set bootloader baud rate. */
93 /* */
94 /* LUDICROUS_SPEED: */
95 /* 230400 baud :-) */
96 /* */
97 /* SOFT_UART: */
98 /* Use AVR305 soft-UART instead of hardware UART. */
99 /* */
100 /* LED_START_FLASHES: */
101 /* Number of LED flashes on bootup. */
102 /* */
103 /* LED_DATA_FLASH: */
104 /* Flash LED when transferring data. For boards without */
105 /* TX or RX LEDs, or for people who like blinky lights. */
106 /* */
107 /* SUPPORT_EEPROM: */
108 /* Support reading and writing from EEPROM. This is not */
109 /* used by Arduino, so off by default. */
110 /* */
111 /* TIMEOUT_MS: */
112 /* Bootloader timeout period, in milliseconds. */
113 /* 500,1000,2000,4000,8000 supported. */
114 /* */
115 /**********************************************************/
116
117 /**********************************************************/
118 /* Version Numbers! */
119 /* */
120 /* Arduino Optiboot now includes this Version number in */
121 /* the source and object code. */
122 /* */
123 /* Version 3 was released as zip from the optiboot */
124 /* repository and was distributed with Arduino 0022. */
125 /* Version 4 starts with the arduino repository commit */
126 /* that brought the arduino repository up-to-date with */
127 /* the optiboot source tree changes since v3. */
128 /* */
129 /**********************************************************/
130
131 /**********************************************************/
132 /* Edit History: */
133 /* */
134 /* Jan 2012: */
135 /* 4.5 WestfW: fix NRWW value for m1284. */
136 /* 4.4 WestfW: use attribute OS_main instead of naked for */
137 /* main(). This allows optimizations that we */
138 /* count on, which are prohibited in naked */
139 /* functions due to PR42240. (keeps us less */
140 /* than 512 bytes when compiler is gcc4.5 */
141 /* (code from 4.3.2 remains the same.) */
142 /* 4.4 WestfW and Maniacbug: Add m1284 support. This */
143 /* does not change the 328 binary, so the */
144 /* version number didn't change either. (?) */
145 /* June 2011: */
146 /* 4.4 WestfW: remove automatic soft_uart detect (didn't */
147 /* know what it was doing or why.) Added a */
148 /* check of the calculated BRG value instead. */
149 /* Version stays 4.4; existing binaries are */
150 /* not changed. */
151 /* 4.4 WestfW: add initialization of address to keep */
152 /* the compiler happy. Change SC'ed targets. */
153 /* Return the SW version via READ PARAM */
154 /* 4.3 WestfW: catch framing errors in getch(), so that */
155 /* AVRISP works without HW kludges. */
156 /* http://code.google.com/p/arduino/issues/detail?id=368n*/
157 /* 4.2 WestfW: reduce code size, fix timeouts, change */
158 /* verifySpace to use WDT instead of appstart */
159 /* 4.1 WestfW: put version number in binary. */
160 /**********************************************************/
161
162 #define OPTIBOOT_MAJVER 4
163 #define OPTIBOOT_MINVER 5
164
165 #define MAKESTR(a) #a
166 #define MAKEVER(a, b) MAKESTR(a*256+b)
167
168 asm(" .section .version\n"
169 "optiboot_version: .word " MAKEVER(OPTIBOOT_MAJVER, OPTIBOOT_MINVER) "\n"
170 " .section .text\n");
171
172 #include <inttypes.h>
173 #include <avr/io.h>
174 #include <avr/pgmspace.h>
175
176 // <avr/boot.h> uses sts instructions, but this version uses out instructions
177 // This saves cycles and program memory.
178 #include "boot.h"
179
180
181 // We don't use <avr/wdt.h> as those routines have interrupt overhead we don't need.
182
183 #include "pin_defs.h"
184 #include "stk500.h"
185
186 #ifndef LED_START_FLASHES
187 #define LED_START_FLASHES 0
188 #endif
189
190 #ifdef LUDICROUS_SPEED
191 #define BAUD_RATE 230400L
192 #endif
193
194 /* set the UART baud rate defaults */
195 #ifndef BAUD_RATE
196 #if F_CPU >= 8000000L
197 #define BAUD_RATE 115200L // Highest rate Avrdude win32 will support
198 #elsif F_CPU >= 1000000L
199 #define BAUD_RATE 9600L // 19200 also supported, but with significant error
200 #elsif F_CPU >= 128000L
201 #define BAUD_RATE 4800L // Good for 128kHz internal RC
202 #else
203 #define BAUD_RATE 1200L // Good even at 32768Hz
204 #endif
205 #endif
206
207 #if 0
208 /* Switch in soft UART for hard baud rates */
209 /*
210 * I don't understand what this was supposed to accomplish, where the
211 * constant "280" came from, or why automatically (and perhaps unexpectedly)
212 * switching to a soft uart is a good thing, so I'm undoing this in favor
213 * of a range check using the same calc used to config the BRG...
214 */
215 #if (F_CPU/BAUD_RATE) > 280 // > 57600 for 16MHz
216 #ifndef SOFT_UART
217 #define SOFT_UART
218 #endif
219 #endif
220 #else // 0
221 #if (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 > 250
222 #error Unachievable baud rate (too slow) BAUD_RATE
223 #endif // baud rate slow check
224 #if (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 < 3
225 #error Unachievable baud rate (too fast) BAUD_RATE
226 #endif // baud rate fastn check
227 #endif
228
229 /* Watchdog settings */
230 #define WATCHDOG_OFF (0)
231 #define WATCHDOG_16MS (_BV(WDE))
232 #define WATCHDOG_32MS (_BV(WDP0) | _BV(WDE))
233 #define WATCHDOG_64MS (_BV(WDP1) | _BV(WDE))
234 #define WATCHDOG_125MS (_BV(WDP1) | _BV(WDP0) | _BV(WDE))
235 #define WATCHDOG_250MS (_BV(WDP2) | _BV(WDE))
236 #define WATCHDOG_500MS (_BV(WDP2) | _BV(WDP0) | _BV(WDE))
237 #define WATCHDOG_1S (_BV(WDP2) | _BV(WDP1) | _BV(WDE))
238 #define WATCHDOG_2S (_BV(WDP2) | _BV(WDP1) | _BV(WDP0) | _BV(WDE))
239 #ifndef __AVR_ATmega8__
240 #define WATCHDOG_4S (_BV(WDP3) | _BV(WDE))
241 #define WATCHDOG_8S (_BV(WDP3) | _BV(WDP0) | _BV(WDE))
242 #endif
243
244 /* Function Prototypes */
245 /* The main function is in init9, which removes the interrupt vector table */
246 /* we don't need. It is also 'naked', which means the compiler does not */
247 /* generate any entry or exit code itself. */
248 int main(void) __attribute__ ((OS_main)) __attribute__ ((section (".init9")));
249 void putch(char);
250 uint8_t getch(void);
251 static inline void getNch(uint8_t); /* "static inline" is a compiler hint to reduce code size */
252 void verifySpace();
253 static inline void flash_led(uint8_t);
254 uint8_t getLen();
255 static inline void watchdogReset();
256 void watchdogConfig(uint8_t x);
257 #ifdef SOFT_UART
258 void uartDelay() __attribute__ ((naked));
259 #endif
260 void appStart() __attribute__ ((naked));
261
262 /*
263 * NRWW memory
264 * Addresses below NRWW (Non-Read-While-Write) can be programmed while
265 * continuing to run code from flash, slightly speeding up programming
266 * time. Beware that Atmel data sheets specify this as a WORD address,
267 * while optiboot will be comparing against a 16-bit byte address. This
268 * means that on a part with 128kB of memory, the upper part of the lower
269 * 64k will get NRWW processing as well, even though it doesn't need it.
270 * That's OK. In fact, you can disable the overlapping processing for
271 * a part entirely by setting NRWWSTART to zero. This reduces code
272 * space a bit, at the expense of being slightly slower, overall.
273 *
274 * RAMSTART should be self-explanatory. It's bigger on parts with a
275 * lot of peripheral registers.
276 */
277 #if defined(__AVR_ATmega168__)
278 #define RAMSTART (0x100)
279 #define NRWWSTART (0x3800)
280 #elif defined(__AVR_ATmega328P__)
281 #define RAMSTART (0x100)
282 #define NRWWSTART (0x7000)
283 #elif defined (__AVR_ATmega644P__)
284 #define RAMSTART (0x100)
285 #define NRWWSTART (0xE000)
286 #elif defined (__AVR_ATmega1284P__)
287 #define RAMSTART (0x100)
288 #define NRWWSTART (0xE000)
289 #elif defined(__AVR_ATtiny84__)
290 #define RAMSTART (0x100)
291 #define NRWWSTART (0x0000)
292 #elif defined(__AVR_ATmega1280__)
293 #define RAMSTART (0x200)
294 #define NRWWSTART (0xE000)
295 #elif defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__)
296 #define RAMSTART (0x100)
297 #define NRWWSTART (0x1800)
298 #endif
299
300 /* C zero initialises all global variables. However, that requires */
301 /* These definitions are NOT zero initialised, but that doesn't matter */
302 /* This allows us to drop the zero init code, saving us memory */
303 #define buff ((uint8_t*)(RAMSTART))
304 #ifdef VIRTUAL_BOOT_PARTITION
305 #define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
306 #define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
307 #endif
308
309 /* main program starts here */
310 int main(void) {
311 uint8_t ch;
312
313 /*
314 * Making these local and in registers prevents the need for initializing
315 * them, and also saves space because code no longer stores to memory.
316 * (initializing address keeps the compiler happy, but isn't really
317 * necessary, and uses 4 bytes of flash.)
318 */
319 register uint16_t address = 0;
320 register uint8_t length;
321
322 // After the zero init loop, this is the first code to run.
323 //
324 // This code makes the following assumptions:
325 // No interrupts will execute
326 // SP points to RAMEND
327 // r1 contains zero
328 //
329 // If not, uncomment the following instructions:
330 // cli();
331 asm volatile ("clr __zero_reg__");
332 #ifdef __AVR_ATmega8__
333 SP=RAMEND; // This is done by hardware reset
334 #endif
335
336 // Adaboot no-wait mod
337 ch = MCUSR;
338 MCUSR = 0;
339 if (!(ch & _BV(EXTRF))) appStart();
340
341 #if LED_START_FLASHES > 0
342 // Set up Timer 1 for timeout counter
343 TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
344 #endif
345 #ifndef SOFT_UART
346 #ifdef __AVR_ATmega8__
347 UCSRA = _BV(U2X); //Double speed mode USART
348 UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx
349 UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1
350 UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
351 #else
352 UCSR0A = _BV(U2X0); //Double speed mode USART0
353 UCSR0B = _BV(RXEN0) | _BV(TXEN0);
354 UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
355 UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
356 #endif
357 #endif
358
359 // Set up watchdog to trigger after 500ms
360 watchdogConfig(WATCHDOG_1S);
361
362 /* Set LED pin as output */
363 LED_DDR |= _BV(LED);
364
365 #ifdef SOFT_UART
366 /* Set TX pin as output */
367 UART_DDR |= _BV(UART_TX_BIT);
368 #endif
369
370 #if LED_START_FLASHES > 0
371 /* Flash onboard LED to signal entering of bootloader */
372 flash_led(LED_START_FLASHES * 2);
373 #endif
374
375 /* Forever loop */
376 for (;;) {
377 /* get character from UART */
378 ch = getch();
379
380 if(ch == STK_GET_PARAMETER) {
381 unsigned char which = getch();
382 verifySpace();
383 if (which == 0x82) {
384 /*
385 * Send optiboot version as "minor SW version"
386 */
387 putch(OPTIBOOT_MINVER);
388 } else if (which == 0x81) {
389 putch(OPTIBOOT_MAJVER);
390 } else {
391 /*
392 * GET PARAMETER returns a generic 0x03 reply for
393 * other parameters - enough to keep Avrdude happy
394 */
395 putch(0x03);
396 }
397 }
398 else if(ch == STK_SET_DEVICE) {
399 // SET DEVICE is ignored
400 getNch(20);
401 }
402 else if(ch == STK_SET_DEVICE_EXT) {
403 // SET DEVICE EXT is ignored
404 getNch(5);
405 }
406 else if(ch == STK_LOAD_ADDRESS) {
407 // LOAD ADDRESS
408 uint16_t newAddress;
409 newAddress = getch();
410 newAddress = (newAddress & 0xff) | (getch() << 8);
411 #ifdef RAMPZ
412 // Transfer top bit to RAMPZ
413 RAMPZ = (newAddress & 0x8000) ? 1 : 0;
414 #endif
415 newAddress += newAddress; // Convert from word address to byte address
416 address = newAddress;
417 verifySpace();
418 }
419 else if(ch == STK_UNIVERSAL) {
420 // UNIVERSAL command is ignored
421 getNch(4);
422 putch(0x00);
423 }
424 /* Write memory, length is big endian and is in bytes */
425 else if(ch == STK_PROG_PAGE) {
426 // PROGRAM PAGE - we support flash programming only, not EEPROM
427 uint8_t *bufPtr;
428 uint16_t addrPtr;
429
430 getch(); /* getlen() */
431 length = getch();
432 getch();
433
434 // If we are in RWW section, immediately start page erase
435 if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address);
436
437 // While that is going on, read in page contents
438 bufPtr = buff;
439 do *bufPtr++ = getch();
440 while (--length);
441
442 // If we are in NRWW section, page erase has to be delayed until now.
443 // Todo: Take RAMPZ into account
444 if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address);
445
446 // Read command terminator, start reply
447 verifySpace();
448
449 // If only a partial page is to be programmed, the erase might not be complete.
450 // So check that here
451 boot_spm_busy_wait();
452
453 #ifdef VIRTUAL_BOOT_PARTITION
454 if ((uint16_t)(void*)address == 0) {
455 // This is the reset vector page. We need to live-patch the code so the
456 // bootloader runs.
457 //
458 // Move RESET vector to WDT vector
459 uint16_t vect = buff[0] | (buff[1]<<8);
460 rstVect = vect;
461 wdtVect = buff[8] | (buff[9]<<8);
462 vect -= 4; // Instruction is a relative jump (rjmp), so recalculate.
463 buff[8] = vect & 0xff;
464 buff[9] = vect >> 8;
465
466 // Add jump to bootloader at RESET vector
467 buff[0] = 0x7f;
468 buff[1] = 0xce; // rjmp 0x1d00 instruction
469 }
470 #endif
471
472 // Copy buffer into programming buffer
473 bufPtr = buff;
474 addrPtr = (uint16_t)(void*)address;
475 ch = SPM_PAGESIZE / 2;
476 do {
477 uint16_t a;
478 a = *bufPtr++;
479 a |= (*bufPtr++) << 8;
480 __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
481 addrPtr += 2;
482 } while (--ch);
483
484 // Write from programming buffer
485 __boot_page_write_short((uint16_t)(void*)address);
486 boot_spm_busy_wait();
487
488 #if defined(RWWSRE)
489 // Reenable read access to flash
490 boot_rww_enable();
491 #endif
492
493 }
494 /* Read memory block mode, length is big endian. */
495 else if(ch == STK_READ_PAGE) {
496 // READ PAGE - we only read flash
497 getch(); /* getlen() */
498 length = getch();
499 getch();
500
501 verifySpace();
502 #ifdef VIRTUAL_BOOT_PARTITION
503 do {
504 // Undo vector patch in bottom page so verify passes
505 if (address == 0) ch=rstVect & 0xff;
506 else if (address == 1) ch=rstVect >> 8;
507 else if (address == 8) ch=wdtVect & 0xff;
508 else if (address == 9) ch=wdtVect >> 8;
509 else ch = pgm_read_byte_near(address);
510 address++;
511 putch(ch);
512 } while (--length);
513 #else
514 #ifdef RAMPZ
515 // Since RAMPZ should already be set, we need to use EPLM directly.
516 // do putch(pgm_read_byte_near(address++));
517 // while (--length);
518 do {
519 uint8_t result;
520 __asm__ ("elpm %0,Z\n":"=r"(result):"z"(address));
521 putch(result);
522 address++;
523 }
524 while (--length);
525 #else
526 do putch(pgm_read_byte_near(address++));
527 while (--length);
528 #endif
529 #endif
530 }
531
532 /* Get device signature bytes */
533 else if(ch == STK_READ_SIGN) {
534 // READ SIGN - return what Avrdude wants to hear
535 verifySpace();
536 putch(SIGNATURE_0);
537 putch(SIGNATURE_1);
538 putch(SIGNATURE_2);
539 }
540 else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */
541 // Adaboot no-wait mod
542 watchdogConfig(WATCHDOG_16MS);
543 verifySpace();
544 }
545 else {
546 // This covers the response to commands like STK_ENTER_PROGMODE
547 verifySpace();
548 }
549 putch(STK_OK);
550 }
551 }
552
553 void putch(char ch) {
554 #ifndef SOFT_UART
555 while (!(UCSR0A & _BV(UDRE0)));
556 UDR0 = ch;
557 #else
558 __asm__ __volatile__ (
559 " com %[ch]\n" // ones complement, carry set
560 " sec\n"
561 "1: brcc 2f\n"
562 " cbi %[uartPort],%[uartBit]\n"
563 " rjmp 3f\n"
564 "2: sbi %[uartPort],%[uartBit]\n"
565 " nop\n"
566 "3: rcall uartDelay\n"
567 " rcall uartDelay\n"
568 " lsr %[ch]\n"
569 " dec %[bitcnt]\n"
570 " brne 1b\n"
571 :
572 :
573 [bitcnt] "d" (10),
574 [ch] "r" (ch),
575 [uartPort] "I" (_SFR_IO_ADDR(UART_PORT)),
576 [uartBit] "I" (UART_TX_BIT)
577 :
578 "r25"
579 );
580 #endif
581 }
582
583 uint8_t getch(void) {
584 uint8_t ch;
585
586 #ifdef LED_DATA_FLASH
587 #ifdef __AVR_ATmega8__
588 LED_PORT ^= _BV(LED);
589 #else
590 LED_PIN |= _BV(LED);
591 #endif
592 #endif
593
594 #ifdef SOFT_UART
595 __asm__ __volatile__ (
596 "1: sbic %[uartPin],%[uartBit]\n" // Wait for start edge
597 " rjmp 1b\n"
598 " rcall uartDelay\n" // Get to middle of start bit
599 "2: rcall uartDelay\n" // Wait 1 bit period
600 " rcall uartDelay\n" // Wait 1 bit period
601 " clc\n"
602 " sbic %[uartPin],%[uartBit]\n"
603 " sec\n"
604 " dec %[bitCnt]\n"
605 " breq 3f\n"
606 " ror %[ch]\n"
607 " rjmp 2b\n"
608 "3:\n"
609 :
610 [ch] "=r" (ch)
611 :
612 [bitCnt] "d" (9),
613 [uartPin] "I" (_SFR_IO_ADDR(UART_PIN)),
614 [uartBit] "I" (UART_RX_BIT)
615 :
616 "r25"
617 );
618 #else
619 while(!(UCSR0A & _BV(RXC0)))
620 ;
621 if (!(UCSR0A & _BV(FE0))) {
622 /*
623 * A Framing Error indicates (probably) that something is talking
624 * to us at the wrong bit rate. Assume that this is because it
625 * expects to be talking to the application, and DON'T reset the
626 * watchdog. This should cause the bootloader to abort and run
627 * the application "soon", if it keeps happening. (Note that we
628 * don't care that an invalid char is returned...)
629 */
630 watchdogReset();
631 }
632
633 ch = UDR0;
634 #endif
635
636 #ifdef LED_DATA_FLASH
637 #ifdef __AVR_ATmega8__
638 LED_PORT ^= _BV(LED);
639 #else
640 LED_PIN |= _BV(LED);
641 #endif
642 #endif
643
644 return ch;
645 }
646
647 #ifdef SOFT_UART
648 // AVR305 equation: #define UART_B_VALUE (((F_CPU/BAUD_RATE)-23)/6)
649 // Adding 3 to numerator simulates nearest rounding for more accurate baud rates
650 #define UART_B_VALUE (((F_CPU/BAUD_RATE)-20)/6)
651 #if UART_B_VALUE > 255
652 #error Baud rate too slow for soft UART
653 #endif
654
655 void uartDelay() {
656 __asm__ __volatile__ (
657 "ldi r25,%[count]\n"
658 "1:dec r25\n"
659 "brne 1b\n"
660 "ret\n"
661 ::[count] "M" (UART_B_VALUE)
662 );
663 }
664 #endif
665
666 void getNch(uint8_t count) {
667 do getch(); while (--count);
668 verifySpace();
669 }
670
671 void verifySpace() {
672 if (getch() != CRC_EOP) {
673 watchdogConfig(WATCHDOG_16MS); // shorten WD timeout
674 while (1) // and busy-loop so that WD causes
675 ; // a reset and app start.
676 }
677 putch(STK_INSYNC);
678 }
679
680 #if LED_START_FLASHES > 0
681 void flash_led(uint8_t count) {
682 do {
683 TCNT1 = -(F_CPU/(1024*16));
684 TIFR1 = _BV(TOV1);
685 while(!(TIFR1 & _BV(TOV1)));
686 #ifdef __AVR_ATmega8__
687 LED_PORT ^= _BV(LED);
688 #else
689 LED_PIN |= _BV(LED);
690 #endif
691 watchdogReset();
692 } while (--count);
693 }
694 #endif
695
696 // Watchdog functions. These are only safe with interrupts turned off.
697 void watchdogReset() {
698 __asm__ __volatile__ (
699 "wdr\n"
700 );
701 }
702
703 void watchdogConfig(uint8_t x) {
704 WDTCSR = _BV(WDCE) | _BV(WDE);
705 WDTCSR = x;
706 }
707
708 void appStart() {
709 watchdogConfig(WATCHDOG_OFF);
710 __asm__ __volatile__ (
711 #ifdef VIRTUAL_BOOT_PARTITION
712 // Jump to WDT vector
713 "ldi r30,4\n"
714 "clr r31\n"
715 #else
716 // Jump to RST vector
717 "clr r30\n"
718 "clr r31\n"
719 #endif
720 "ijmp\n"
721 );
722 }
0 #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega88) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__)
1 /* Onboard LED is connected to pin PB5 in Arduino NG, Diecimila, and Duemilanove */
2 #define LED_DDR DDRB
3 #define LED_PORT PORTB
4 #define LED_PIN PINB
5 #define LED PINB5
6
7 /* Ports for soft UART */
8 #ifdef SOFT_UART
9 #define UART_PORT PORTD
10 #define UART_PIN PIND
11 #define UART_DDR DDRD
12 #define UART_TX_BIT 1
13 #define UART_RX_BIT 0
14 #endif
15 #endif
16
17 #if defined(__AVR_ATmega8__)
18 //Name conversion R.Wiersma
19 #define UCSR0A UCSRA
20 #define UDR0 UDR
21 #define UDRE0 UDRE
22 #define RXC0 RXC
23 #define FE0 FE
24 #define TIFR1 TIFR
25 #define WDTCSR WDTCR
26 #endif
27
28 /* Luminet support */
29 #if defined(__AVR_ATtiny84__)
30 /* Red LED is connected to pin PA4 */
31 #define LED_DDR DDRA
32 #define LED_PORT PORTA
33 #define LED_PIN PINA
34 #define LED PINA4
35 /* Ports for soft UART - left port only for now. TX/RX on PA2/PA3 */
36 #ifdef SOFT_UART
37 #define UART_PORT PORTA
38 #define UART_PIN PINA
39 #define UART_DDR DDRA
40 #define UART_TX_BIT 2
41 #define UART_RX_BIT 3
42 #endif
43 #endif
44
45 /* Sanguino support */
46 #if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)
47 /* Onboard LED is connected to pin PB0 on Sanguino */
48 #define LED_DDR DDRB
49 #define LED_PORT PORTB
50 #define LED_PIN PINB
51 #define LED PINB1
52
53 /* Ports for soft UART */
54 #ifdef SOFT_UART
55 #define UART_PORT PORTD
56 #define UART_PIN PIND
57 #define UART_DDR DDRD
58 #define UART_TX_BIT 1
59 #define UART_RX_BIT 0
60 #endif
61 #endif
62
63 /* Mega support */
64 #if defined(__AVR_ATmega1280__)
65 /* Onboard LED is connected to pin PB7 on Arduino Mega */
66 #define LED_DDR DDRB
67 #define LED_PORT PORTB
68 #define LED_PIN PINB
69 #define LED PINB7
70
71 /* Ports for soft UART */
72 #ifdef SOFT_UART
73 #define UART_PORT PORTE
74 #define UART_PIN PINE
75 #define UART_DDR DDRE
76 #define UART_TX_BIT 1
77 #define UART_RX_BIT 0
78 #endif
79 #endif
0 /* STK500 constants list, from AVRDUDE */
1 #define STK_OK 0x10
2 #define STK_FAILED 0x11 // Not used
3 #define STK_UNKNOWN 0x12 // Not used
4 #define STK_NODEVICE 0x13 // Not used
5 #define STK_INSYNC 0x14 // ' '
6 #define STK_NOSYNC 0x15 // Not used
7 #define ADC_CHANNEL_ERROR 0x16 // Not used
8 #define ADC_MEASURE_OK 0x17 // Not used
9 #define PWM_CHANNEL_ERROR 0x18 // Not used
10 #define PWM_ADJUST_OK 0x19 // Not used
11 #define CRC_EOP 0x20 // 'SPACE'
12 #define STK_GET_SYNC 0x30 // '0'
13 #define STK_GET_SIGN_ON 0x31 // '1'
14 #define STK_SET_PARAMETER 0x40 // '@'
15 #define STK_GET_PARAMETER 0x41 // 'A'
16 #define STK_SET_DEVICE 0x42 // 'B'
17 #define STK_SET_DEVICE_EXT 0x45 // 'E'
18 #define STK_ENTER_PROGMODE 0x50 // 'P'
19 #define STK_LEAVE_PROGMODE 0x51 // 'Q'
20 #define STK_CHIP_ERASE 0x52 // 'R'
21 #define STK_CHECK_AUTOINC 0x53 // 'S'
22 #define STK_LOAD_ADDRESS 0x55 // 'U'
23 #define STK_UNIVERSAL 0x56 // 'V'
24 #define STK_PROG_FLASH 0x60 // '`'
25 #define STK_PROG_DATA 0x61 // 'a'
26 #define STK_PROG_FUSE 0x62 // 'b'
27 #define STK_PROG_LOCK 0x63 // 'c'
28 #define STK_PROG_PAGE 0x64 // 'd'
29 #define STK_PROG_FUSE_EXT 0x65 // 'e'
30 #define STK_READ_FLASH 0x70 // 'p'
31 #define STK_READ_DATA 0x71 // 'q'
32 #define STK_READ_FUSE 0x72 // 'r'
33 #define STK_READ_LOCK 0x73 // 's'
34 #define STK_READ_PAGE 0x74 // 't'
35 #define STK_READ_SIGN 0x75 // 'u'
36 #define STK_READ_OSCCAL 0x76 // 'v'
37 #define STK_READ_FUSE_EXT 0x77 // 'w'
38 #define STK_READ_OSCCAL_EXT 0x78 // 'x'
0 /**********************************************************/
1 /* Serial Bootloader for Atmel megaAVR Controllers */
2 /* */
3 /* tested with ATmega8, ATmega128 and ATmega168 */
4 /* should work with other mega's, see code for details */
5 /* */
6 /* ATmegaBOOT.c */
7 /* */
8 /* */
9 /* 20090308: integrated Mega changes into main bootloader */
10 /* source by D. Mellis */
11 /* 20080930: hacked for Arduino Mega (with the 1280 */
12 /* processor, backwards compatible) */
13 /* by D. Cuartielles */
14 /* 20070626: hacked for Arduino Diecimila (which auto- */
15 /* resets when a USB connection is made to it) */
16 /* by D. Mellis */
17 /* 20060802: hacked for Arduino by D. Cuartielles */
18 /* based on a previous hack by D. Mellis */
19 /* and D. Cuartielles */
20 /* */
21 /* Monitor and debug functions were added to the original */
22 /* code by Dr. Erik Lins, chip45.com. (See below) */
23 /* */
24 /* Thanks to Karl Pitrich for fixing a bootloader pin */
25 /* problem and more informative LED blinking! */
26 /* */
27 /* For the latest version see: */
28 /* http://www.chip45.com/ */
29 /* */
30 /* ------------------------------------------------------ */
31 /* */
32 /* based on stk500boot.c */
33 /* Copyright (c) 2003, Jason P. Kyle */
34 /* All rights reserved. */
35 /* see avr1.org for original file and information */
36 /* */
37 /* This program is free software; you can redistribute it */
38 /* and/or modify it under the terms of the GNU General */
39 /* Public License as published by the Free Software */
40 /* Foundation; either version 2 of the License, or */
41 /* (at your option) any later version. */
42 /* */
43 /* This program is distributed in the hope that it will */
44 /* be useful, but WITHOUT ANY WARRANTY; without even the */
45 /* implied warranty of MERCHANTABILITY or FITNESS FOR A */
46 /* PARTICULAR PURPOSE. See the GNU General Public */
47 /* License for more details. */
48 /* */
49 /* You should have received a copy of the GNU General */
50 /* Public License along with this program; if not, write */
51 /* to the Free Software Foundation, Inc., */
52 /* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
53 /* */
54 /* Licence can be viewed at */
55 /* http://www.fsf.org/licenses/gpl.txt */
56 /* */
57 /* Target = Atmel AVR m128,m64,m32,m16,m8,m162,m163,m169, */
58 /* m8515,m8535. ATmega161 has a very small boot block so */
59 /* isn't supported. */
60 /* */
61 /* Tested with m168 */
62 /**********************************************************/
63
64 /* $Id$ */
65
66
67 /* some includes */
68 #include <inttypes.h>
69 #include <avr/io.h>
70 #include <avr/pgmspace.h>
71 #include <avr/interrupt.h>
72 #include <avr/wdt.h>
73 #include <util/delay.h>
74
75 /* the current avr-libc eeprom functions do not support the ATmega168 */
76 /* own eeprom write/read functions are used instead */
77 #if !defined(__AVR_ATmega168__) || !defined(__AVR_ATmega328P__)
78 #include <avr/eeprom.h>
79 #endif
80
81 /* Use the F_CPU defined in Makefile */
82
83 /* 20060803: hacked by DojoCorp */
84 /* 20070626: hacked by David A. Mellis to decrease waiting time for auto-reset */
85 /* set the waiting time for the bootloader */
86 /* get this from the Makefile instead */
87 /* #define MAX_TIME_COUNT (F_CPU>>4) */
88
89 /* 20070707: hacked by David A. Mellis - after this many errors give up and launch application */
90 #define MAX_ERROR_COUNT 5
91 #define NUM_LED_FLASHES 3
92 /* set the UART baud rate */
93 /* 20060803: hacked by DojoCorp */
94 //#define BAUD_RATE 115200
95 #ifndef BAUD_RATE
96 #define BAUD_RATE 19200
97 #endif
98
99
100 /* SW_MAJOR and MINOR needs to be updated from time to time to avoid warning message from AVR Studio */
101 /* never allow AVR Studio to do an update !!!! */
102 #define HW_VER 0x02
103 #define SW_MAJOR 0x01
104 #define SW_MINOR 0x10
105
106
107 /* Adjust to suit whatever pin your hardware uses to enter the bootloader */
108 /* ATmega128 has two UARTS so two pins are used to enter bootloader and select UART */
109 /* ATmega1280 has four UARTS, but for Arduino Mega, we will only use RXD0 to get code */
110 /* BL0... means UART0, BL1... means UART1 */
111 #ifdef __AVR_ATmega128__
112 #define BL_DDR DDRF
113 #define BL_PORT PORTF
114 #define BL_PIN PINF
115 #define BL0 PINF7
116 #define BL1 PINF6
117 #elif defined __AVR_ATmega1280__
118 /* we just don't do anything for the MEGA and enter bootloader on reset anyway*/
119 #elif defined __AVR_ATmega1284P__
120
121 #else
122 /* other ATmegas have only one UART, so only one pin is defined to enter bootloader */
123 #define BL_DDR DDRD
124 #define BL_PORT PORTD
125 #define BL_PIN PIND
126 #define BL PIND6
127 #endif
128
129
130 /* onboard LED is used to indicate, that the bootloader was entered (3x flashing) */
131 /* if monitor functions are included, LED goes on after monitor was entered */
132 #if defined __AVR_ATmega128__ || defined __AVR_ATmega1280__
133 /* Onboard LED is connected to pin PB7 (e.g. Crumb128, PROBOmega128, Savvy128, Arduino Mega) */
134 #define LED_DDR DDRB
135 #define LED_PORT PORTB
136 #define LED_PIN PINB
137 #define LED PINB7
138 #elif defined __AVR_ATmega1284P__
139 #define LED_DDR DDRB
140 #define LED_PORT PORTB
141 #define LED_PIN PINB
142 #define LED PINB0
143 #else
144 /* Onboard LED is connected to pin PB5 in Arduino NG, Diecimila, and Duomilanuove */
145 /* other boards like e.g. Crumb8, Crumb168 are using PB2 */
146 #define LED_DDR DDRB
147 #define LED_PORT PORTB
148 #define LED_PIN PINB
149 #define LED PINB5
150 #endif
151
152
153 /* monitor functions will only be compiled when using ATmega128, due to bootblock size constraints */
154 #if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
155 #define MONITOR 1
156 #endif
157
158
159 /* define various device id's */
160 /* manufacturer byte is always the same */
161 #define SIG1 0x1E // Yep, Atmel is the only manufacturer of AVR micros. Single source :(
162
163 #if defined __AVR_ATmega1280__
164 #define SIG2 0x97
165 #define SIG3 0x03
166 #define PAGE_SIZE 0x80U //128 words
167
168 #elif defined __AVR_ATmega1284P__
169 #define SIG2 0x97
170 #define SIG3 0x05
171 #define PAGE_SIZE 0x080U //128 words
172
173 #elif defined __AVR_ATmega1281__
174 #define SIG2 0x97
175 #define SIG3 0x04
176 #define PAGE_SIZE 0x80U //128 words
177
178 #elif defined __AVR_ATmega128__
179 #define SIG2 0x97
180 #define SIG3 0x02
181 #define PAGE_SIZE 0x80U //128 words
182
183 #elif defined __AVR_ATmega64__
184 #define SIG2 0x96
185 #define SIG3 0x02
186 #define PAGE_SIZE 0x80U //128 words
187
188 #elif defined __AVR_ATmega32__
189 #define SIG2 0x95
190 #define SIG3 0x02
191 #define PAGE_SIZE 0x40U //64 words
192
193 #elif defined __AVR_ATmega16__
194 #define SIG2 0x94
195 #define SIG3 0x03
196 #define PAGE_SIZE 0x40U //64 words
197
198 #elif defined __AVR_ATmega8__
199 #define SIG2 0x93
200 #define SIG3 0x07
201 #define PAGE_SIZE 0x20U //32 words
202
203 #elif defined __AVR_ATmega88__
204 #define SIG2 0x93
205 #define SIG3 0x0a
206 #define PAGE_SIZE 0x20U //32 words
207
208 #elif defined __AVR_ATmega168__
209 #define SIG2 0x94
210 #define SIG3 0x06
211 #define PAGE_SIZE 0x40U //64 words
212
213 #elif defined __AVR_ATmega328P__
214 #define SIG2 0x95
215 #define SIG3 0x0F
216 #define PAGE_SIZE 0x40U //64 words
217
218 #elif defined __AVR_ATmega162__
219 #define SIG2 0x94
220 #define SIG3 0x04
221 #define PAGE_SIZE 0x40U //64 words
222
223 #elif defined __AVR_ATmega163__
224 #define SIG2 0x94
225 #define SIG3 0x02
226 #define PAGE_SIZE 0x40U //64 words
227
228 #elif defined __AVR_ATmega169__
229 #define SIG2 0x94
230 #define SIG3 0x05
231 #define PAGE_SIZE 0x40U //64 words
232
233 #elif defined __AVR_ATmega8515__
234 #define SIG2 0x93
235 #define SIG3 0x06
236 #define PAGE_SIZE 0x20U //32 words
237
238 #elif defined __AVR_ATmega8535__
239 #define SIG2 0x93
240 #define SIG3 0x08
241 #define PAGE_SIZE 0x20U //32 words
242 #endif
243
244
245 /* function prototypes */
246 void putch(char);
247 char getch(void);
248 void getNch(uint8_t);
249 void byte_response(uint8_t);
250 void nothing_response(void);
251 char gethex(void);
252 void puthex(char);
253 void flash_led(uint8_t);
254
255 /* some variables */
256 union address_union
257 {
258 uint16_t word;
259 uint8_t byte[2];
260 } address;
261
262 union length_union
263 {
264 uint16_t word;
265 uint8_t byte[2];
266 } length;
267
268 struct flags_struct
269 {
270 unsigned eeprom : 1;
271 unsigned rampz : 1;
272 } flags;
273
274 uint8_t buff[256];
275 uint8_t address_high;
276
277 uint8_t pagesz=0x80;
278
279 uint8_t i;
280 uint8_t bootuart = 0;
281
282 uint8_t error_count = 0;
283
284 void (*app_start)(void) = 0x0000;
285
286
287 /* main program starts here */
288 int main(void)
289 {
290 uint8_t ch,ch2;
291 uint16_t w;
292 #ifdef WATCHDOG_MODS
293 ch = MCUSR;
294 MCUSR = 0;
295 WDTCSR |= _BV(WDCE) | _BV(WDE);
296 WDTCSR = 0;
297 // Check if the WDT was used to reset, in which case we dont bootload and skip straight to the code. woot.
298 if (! (ch & _BV(EXTRF))) // if its a not an external reset...
299 app_start(); // skip bootloader
300 #else
301 asm volatile("nop\n\t");
302 #endif
303 /* set pin direction for bootloader pin and enable pullup */
304 /* for ATmega128, two pins need to be initialized */
305 #ifdef __AVR_ATmega128__
306 BL_DDR &= ~_BV(BL0);
307 BL_DDR &= ~_BV(BL1);
308 BL_PORT |= _BV(BL0);
309 BL_PORT |= _BV(BL1);
310 #else
311 /* We run the bootloader regardless of the state of this pin. Thus, don't
312 put it in a different state than the other pins. --DAM, 070709
313 This also applies to Arduino Mega -- DC, 080930
314 BL_DDR &= ~_BV(BL);
315 BL_PORT |= _BV(BL);
316 */
317 #endif
318 #ifdef __AVR_ATmega128__
319 /* check which UART should be used for booting */
320 if(bit_is_clear(BL_PIN, BL0))
321 {
322 bootuart = 1;
323 }
324 else if(bit_is_clear(BL_PIN, BL1))
325 {
326 bootuart = 2;
327 }
328 #endif
329 #if defined __AVR_ATmega1280__ || defined __AVR_ATmega1284P__
330 /* the mega1280 chip has four serial ports ... we could eventually use any of them, or not? */
331 /* however, we don't wanna confuse people, to avoid making a mess, we will stick to RXD0, TXD0 */
332 bootuart = 1;
333 #endif
334 /* check if flash is programmed already, if not start bootloader anyway */
335 if(pgm_read_byte_near(0x0000) != 0xFF)
336 {
337 #ifdef __AVR_ATmega128__
338 /* no UART was selected, start application */
339 if(!bootuart)
340 {
341 app_start();
342 }
343 #else
344 /* check if bootloader pin is set low */
345 /* we don't start this part neither for the m8, nor m168 */
346 //if(bit_is_set(BL_PIN, BL)) {
347 // app_start();
348 // }
349 #endif
350 }
351 #ifdef __AVR_ATmega128__
352 /* no bootuart was selected, default to uart 0 */
353 if(!bootuart)
354 {
355 bootuart = 1;
356 }
357 #endif
358 /* initialize UART(s) depending on CPU defined */
359 #if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1284P__)
360 if(bootuart == 1)
361 {
362 UBRR0L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
363 UBRR0H = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
364 UCSR0A = 0x00;
365 UCSR0C = 0x06;
366 UCSR0B = _BV(TXEN0)|_BV(RXEN0);
367 }
368 if(bootuart == 2)
369 {
370 UBRR1L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
371 UBRR1H = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
372 UCSR1A = 0x00;
373 UCSR1C = 0x06;
374 UCSR1B = _BV(TXEN1)|_BV(RXEN1);
375 }
376 #elif defined __AVR_ATmega163__
377 UBRR = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
378 UBRRHI = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
379 UCSRA = 0x00;
380 UCSRB = _BV(TXEN)|_BV(RXEN);
381 #elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
382 #ifdef DOUBLE_SPEED
383 UCSR0A = (1<<U2X0); //Double speed mode USART0
384 UBRR0L = (uint8_t)(F_CPU/(BAUD_RATE*8L)-1);
385 UBRR0H = (F_CPU/(BAUD_RATE*8L)-1) >> 8;
386 #else
387 UBRR0L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
388 UBRR0H = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
389 #endif
390 UCSR0B = (1<<RXEN0) | (1<<TXEN0);
391 UCSR0C = (1<<UCSZ00) | (1<<UCSZ01);
392 /* Enable internal pull-up resistor on pin D0 (RX), in order
393 to supress line noise that prevents the bootloader from
394 timing out (DAM: 20070509) */
395 DDRD &= ~_BV(PIND0);
396 PORTD |= _BV(PIND0);
397 #elif defined __AVR_ATmega8__
398 /* m8 */
399 UBRRH = (((F_CPU/BAUD_RATE)/16)-1)>>8; // set baud rate
400 UBRRL = (((F_CPU/BAUD_RATE)/16)-1);
401 UCSRB = (1<<RXEN)|(1<<TXEN); // enable Rx & Tx
402 UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); // config USART; 8N1
403 #else
404 /* m16,m32,m169,m8515,m8535 */
405 UBRRL = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
406 UBRRH = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
407 UCSRA = 0x00;
408 UCSRC = 0x06;
409 UCSRB = _BV(TXEN)|_BV(RXEN);
410 #endif
411 #if defined __AVR_ATmega1280__
412 /* Enable internal pull-up resistor on pin D0 (RX), in order
413 to supress line noise that prevents the bootloader from
414 timing out (DAM: 20070509) */
415 /* feature added to the Arduino Mega --DC: 080930 */
416 DDRE &= ~_BV(PINE0);
417 PORTE |= _BV(PINE0);
418 #endif
419 /* set LED pin as output */
420 LED_DDR |= _BV(LED);
421 /* flash onboard LED to signal entering of bootloader */
422 #if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1284P__)
423 // 4x for UART0, 5x for UART1
424 flash_led(NUM_LED_FLASHES + bootuart);
425 #else
426 flash_led(NUM_LED_FLASHES);
427 #endif
428 /* 20050803: by DojoCorp, this is one of the parts provoking the
429 system to stop listening, cancelled from the original */
430 //putch('\0');
431 /* forever loop */
432 for (;;)
433 {
434 /* get character from UART */
435 ch = getch();
436 /* A bunch of if...else if... gives smaller code than switch...case ! */
437 /* Hello is anyone home ? */
438 if(ch=='0')
439 {
440 nothing_response();
441 }
442 /* Request programmer ID */
443 /* Not using PROGMEM string due to boot block in m128 being beyond 64kB boundry */
444 /* Would need to selectively manipulate RAMPZ, and it's only 9 characters anyway so who cares. */
445 else if(ch=='1')
446 {
447 if (getch() == ' ')
448 {
449 putch(0x14);
450 putch('A');
451 putch('V');
452 putch('R');
453 putch(' ');
454 putch('I');
455 putch('S');
456 putch('P');
457 putch(0x10);
458 }
459 else
460 {
461 if (++error_count == MAX_ERROR_COUNT)
462 app_start();
463 }
464 }
465 /* AVR ISP/STK500 board commands DON'T CARE so default nothing_response */
466 else if(ch=='@')
467 {
468 ch2 = getch();
469 if (ch2>0x85) getch();
470 nothing_response();
471 }
472 /* AVR ISP/STK500 board requests */
473 else if(ch=='A')
474 {
475 ch2 = getch();
476 if(ch2==0x80) byte_response(HW_VER); // Hardware version
477 else if(ch2==0x81) byte_response(SW_MAJOR); // Software major version
478 else if(ch2==0x82) byte_response(SW_MINOR); // Software minor version
479 else if(ch2==0x98) byte_response(0x03); // Unknown but seems to be required by avr studio 3.56
480 else byte_response(0x00); // Covers various unnecessary responses we don't care about
481 }
482 /* Device Parameters DON'T CARE, DEVICE IS FIXED */
483 else if(ch=='B')
484 {
485 getNch(20);
486 nothing_response();
487 }
488 /* Parallel programming stuff DON'T CARE */
489 else if(ch=='E')
490 {
491 getNch(5);
492 nothing_response();
493 }
494 /* P: Enter programming mode */
495 /* R: Erase device, don't care as we will erase one page at a time anyway. */
496 else if(ch=='P' || ch=='R')
497 {
498 nothing_response();
499 }
500 /* Leave programming mode */
501 else if(ch=='Q')
502 {
503 nothing_response();
504 #ifdef WATCHDOG_MODS
505 // autoreset via watchdog (sneaky!)
506 WDTCSR = _BV(WDE);
507 while (1); // 16 ms
508 #endif
509 }
510 /* Set address, little endian. EEPROM in bytes, FLASH in words */
511 /* Perhaps extra address bytes may be added in future to support > 128kB FLASH. */
512 /* This might explain why little endian was used here, big endian used everywhere else. */
513 else if(ch=='U')
514 {
515 address.byte[0] = getch();
516 address.byte[1] = getch();
517 nothing_response();
518 }
519 /* Universal SPI programming command, disabled. Would be used for fuses and lock bits. */
520 else if(ch=='V')
521 {
522 if (getch() == 0x30)
523 {
524 getch();
525 ch = getch();
526 getch();
527 if (ch == 0)
528 {
529 byte_response(SIG1);
530 }
531 else if (ch == 1)
532 {
533 byte_response(SIG2);
534 }
535 else
536 {
537 byte_response(SIG3);
538 }
539 }
540 else
541 {
542 getNch(3);
543 byte_response(0x00);
544 }
545 }
546 /* Write memory, length is big endian and is in bytes */
547 else if(ch=='d')
548 {
549 length.byte[1] = getch();
550 length.byte[0] = getch();
551 flags.eeprom = 0;
552 if (getch() == 'E') flags.eeprom = 1;
553 for (w=0; w<length.word; w++)
554 {
555 buff[w] = getch(); // Store data in buffer, can't keep up with serial data stream whilst programming pages
556 }
557 if (getch() == ' ')
558 {
559 if (flags.eeprom) //Write to EEPROM one byte at a time
560 {
561 address.word <<= 1;
562 for(w=0; w<length.word; w++)
563 {
564 #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
565 while(EECR & (1<<EEPE));
566 EEAR = (uint16_t)(void *)address.word;
567 EEDR = buff[w];
568 EECR |= (1<<EEMPE);
569 EECR |= (1<<EEPE);
570 #else
571 eeprom_write_byte((void *)address.word,buff[w]);
572 #endif
573 address.word++;
574 }
575 }
576 else //Write to FLASH one page at a time
577 {
578 if (address.byte[1]>127) address_high = 0x01; //Only possible with m128, m256 will need 3rd address byte. FIXME
579 else address_high = 0x00;
580 #if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega1284P__)
581 RAMPZ = address_high;
582 #endif
583 address.word = address.word << 1; //address * 2 -> byte location
584 /* if ((length.byte[0] & 0x01) == 0x01) length.word++; //Even up an odd number of bytes */
585 if ((length.byte[0] & 0x01)) length.word++; //Even up an odd number of bytes
586 cli(); //Disable interrupts, just to be sure
587 #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega1284P__)
588 while(bit_is_set(EECR,EEPE)); //Wait for previous EEPROM writes to complete
589 #else
590 while(bit_is_set(EECR,EEWE)); //Wait for previous EEPROM writes to complete
591 #endif
592 asm volatile(
593 "clr r17 \n\t" //page_word_count
594 "lds r30,address \n\t" //Address of FLASH location (in bytes)
595 "lds r31,address+1 \n\t"
596 "ldi r28,lo8(buff) \n\t" //Start of buffer array in RAM
597 "ldi r29,hi8(buff) \n\t"
598 "lds r24,length \n\t" //Length of data to be written (in bytes)
599 "lds r25,length+1 \n\t"
600 "length_loop: \n\t" //Main loop, repeat for number of words in block
601 "cpi r17,0x00 \n\t" //If page_word_count=0 then erase page
602 "brne no_page_erase \n\t"
603 "wait_spm1: \n\t"
604 "lds r16,%0 \n\t" //Wait for previous spm to complete
605 "andi r16,1 \n\t"
606 "cpi r16,1 \n\t"
607 "breq wait_spm1 \n\t"
608 "ldi r16,0x03 \n\t" //Erase page pointed to by Z
609 "sts %0,r16 \n\t"
610 "spm \n\t"
611 #ifdef __AVR_ATmega163__
612 ".word 0xFFFF \n\t"
613 "nop \n\t"
614 #endif
615 "wait_spm2: \n\t"
616 "lds r16,%0 \n\t" //Wait for previous spm to complete
617 "andi r16,1 \n\t"
618 "cpi r16,1 \n\t"
619 "breq wait_spm2 \n\t"
620 "ldi r16,0x11 \n\t" //Re-enable RWW section
621 "sts %0,r16 \n\t"
622 "spm \n\t"
623 #ifdef __AVR_ATmega163__
624 ".word 0xFFFF \n\t"
625 "nop \n\t"
626 #endif
627 "no_page_erase: \n\t"
628 "ld r0,Y+ \n\t" //Write 2 bytes into page buffer
629 "ld r1,Y+ \n\t"
630 "wait_spm3: \n\t"
631 "lds r16,%0 \n\t" //Wait for previous spm to complete
632 "andi r16,1 \n\t"
633 "cpi r16,1 \n\t"
634 "breq wait_spm3 \n\t"
635 "ldi r16,0x01 \n\t" //Load r0,r1 into FLASH page buffer
636 "sts %0,r16 \n\t"
637 "spm \n\t"
638 "inc r17 \n\t" //page_word_count++
639 "cpi r17,%1 \n\t"
640 "brlo same_page \n\t" //Still same page in FLASH
641 "write_page: \n\t"
642 "clr r17 \n\t" //New page, write current one first
643 "wait_spm4: \n\t"
644 "lds r16,%0 \n\t" //Wait for previous spm to complete
645 "andi r16,1 \n\t"
646 "cpi r16,1 \n\t"
647 "breq wait_spm4 \n\t"
648 #ifdef __AVR_ATmega163__
649 "andi r30,0x80 \n\t" // m163 requires Z6:Z1 to be zero during page write
650 #endif
651 "ldi r16,0x05 \n\t" //Write page pointed to by Z
652 "sts %0,r16 \n\t"
653 "spm \n\t"
654 #ifdef __AVR_ATmega163__
655 ".word 0xFFFF \n\t"
656 "nop \n\t"
657 "ori r30,0x7E \n\t" // recover Z6:Z1 state after page write (had to be zero during write)
658 #endif
659 "wait_spm5: \n\t"
660 "lds r16,%0 \n\t" //Wait for previous spm to complete
661 "andi r16,1 \n\t"
662 "cpi r16,1 \n\t"
663 "breq wait_spm5 \n\t"
664 "ldi r16,0x11 \n\t" //Re-enable RWW section
665 "sts %0,r16 \n\t"
666 "spm \n\t"
667 #ifdef __AVR_ATmega163__
668 ".word 0xFFFF \n\t"
669 "nop \n\t"
670 #endif
671 "same_page: \n\t"
672 "adiw r30,2 \n\t" //Next word in FLASH
673 "sbiw r24,2 \n\t" //length-2
674 "breq final_write \n\t" //Finished
675 "rjmp length_loop \n\t"
676 "final_write: \n\t"
677 "cpi r17,0 \n\t"
678 "breq block_done \n\t"
679 "adiw r24,2 \n\t" //length+2, fool above check on length after short page write
680 "rjmp write_page \n\t"
681 "block_done: \n\t"
682 "clr __zero_reg__ \n\t" //restore zero register
683 #if defined __AVR_ATmega168__ || __AVR_ATmega328P__ || __AVR_ATmega128__ || __AVR_ATmega1280__ || __AVR_ATmega1281__ || __AVR_ATmega1284P__
684 : "=m" (SPMCSR) : "M" (PAGE_SIZE) : "r0","r16","r17","r24","r25","r28","r29","r30","r31"
685 #else
686 : "=m" (SPMCR) : "M" (PAGE_SIZE) : "r0","r16","r17","r24","r25","r28","r29","r30","r31"
687 #endif
688 );
689 /* Should really add a wait for RWW section to be enabled, don't actually need it since we never */
690 /* exit the bootloader without a power cycle anyhow */
691 }
692 putch(0x14);
693 putch(0x10);
694 }
695 else
696 {
697 if (++error_count == MAX_ERROR_COUNT)
698 app_start();
699 }
700 }
701 /* Read memory block mode, length is big endian. */
702 else if(ch=='t')
703 {
704 length.byte[1] = getch();
705 length.byte[0] = getch();
706 #if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1284P__)
707 if (address.word>0x7FFF) flags.rampz = 1; // No go with m256, FIXME
708 else flags.rampz = 0;
709 #endif
710 address.word = address.word << 1; // address * 2 -> byte location
711 if (getch() == 'E') flags.eeprom = 1;
712 else flags.eeprom = 0;
713 if (getch() == ' ') // Command terminator
714 {
715 putch(0x14);
716 for (w=0; w < length.word; w++) // Can handle odd and even lengths okay
717 {
718 if (flags.eeprom) // Byte access EEPROM read
719 {
720 #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
721 while(EECR & (1<<EEPE));
722 EEAR = (uint16_t)(void *)address.word;
723 EECR |= (1<<EERE);
724 putch(EEDR);
725 #else
726 putch(eeprom_read_byte((void *)address.word));
727 #endif
728 address.word++;
729 }
730 else
731 {
732 if (!flags.rampz) putch(pgm_read_byte_near(address.word));
733 #if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1284P__)
734 else putch(pgm_read_byte_far(address.word + 0x10000));
735 // Hmmmm, yuck FIXME when m256 arrvies
736 #endif
737 address.word++;
738 }
739 }
740 putch(0x10);
741 }
742 }
743 /* Get device signature bytes */
744 else if(ch=='u')
745 {
746 if (getch() == ' ')
747 {
748 putch(0x14);
749 putch(SIG1);
750 putch(SIG2);
751 putch(SIG3);
752 putch(0x10);
753 }
754 else
755 {
756 if (++error_count == MAX_ERROR_COUNT)
757 app_start();
758 }
759 }
760 /* Read oscillator calibration byte */
761 else if(ch=='v')
762 {
763 byte_response(0x00);
764 }
765 #if defined MONITOR
766 /* here come the extended monitor commands by Erik Lins */
767 /* check for three times exclamation mark pressed */
768 else if(ch=='!')
769 {
770 ch = getch();
771 if(ch=='!')
772 {
773 ch = getch();
774 if(ch=='!')
775 {
776 PGM_P welcome = "";
777 #if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
778 uint16_t extaddr;
779 #endif
780 uint8_t addrl, addrh;
781 #ifdef CRUMB128
782 welcome = "ATmegaBOOT / Crumb128 - (C) J.P.Kyle, E.Lins - 050815\n\r";
783 #elif defined PROBOMEGA128
784 welcome = "ATmegaBOOT / PROBOmega128 - (C) J.P.Kyle, E.Lins - 050815\n\r";
785 #elif defined SAVVY128
786 welcome = "ATmegaBOOT / Savvy128 - (C) J.P.Kyle, E.Lins - 050815\n\r";
787 #elif defined __AVR_ATmega1280__
788 welcome = "ATmegaBOOT / Arduino Mega - (C) Arduino LLC - 090930\n\r";
789 #endif
790 /* turn on LED */
791 LED_DDR |= _BV(LED);
792 LED_PORT &= ~_BV(LED);
793 /* print a welcome message and command overview */
794 for(i=0; welcome[i] != '\0'; ++i)
795 {
796 putch(welcome[i]);
797 }
798 /* test for valid commands */
799 for(;;)
800 {
801 putch('\n');
802 putch('\r');
803 putch(':');
804 putch(' ');
805 ch = getch();
806 putch(ch);
807 /* toggle LED */
808 if(ch == 't')
809 {
810 if(bit_is_set(LED_PIN,LED))
811 {
812 LED_PORT &= ~_BV(LED);
813 putch('1');
814 }
815 else
816 {
817 LED_PORT |= _BV(LED);
818 putch('0');
819 }
820 }
821 /* read byte from address */
822 else if(ch == 'r')
823 {
824 ch = getch();
825 putch(ch);
826 addrh = gethex();
827 addrl = gethex();
828 putch('=');
829 ch = *(uint8_t *)((addrh << 8) + addrl);
830 puthex(ch);
831 }
832 /* write a byte to address */
833 else if(ch == 'w')
834 {
835 ch = getch();
836 putch(ch);
837 addrh = gethex();
838 addrl = gethex();
839 ch = getch();
840 putch(ch);
841 ch = gethex();
842 *(uint8_t *)((addrh << 8) + addrl) = ch;
843 }
844 /* read from uart and echo back */
845 else if(ch == 'u')
846 {
847 for(;;)
848 {
849 putch(getch());
850 }
851 }
852 #if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
853 /* external bus loop */
854 else if(ch == 'b')
855 {
856 putch('b');
857 putch('u');
858 putch('s');
859 MCUCR = 0x80;
860 XMCRA = 0;
861 XMCRB = 0;
862 extaddr = 0x1100;
863 for(;;)
864 {
865 ch = *(volatile uint8_t *)extaddr;
866 if(++extaddr == 0)
867 {
868 extaddr = 0x1100;
869 }
870 }
871 }
872 #endif
873 else if(ch == 'j')
874 {
875 app_start();
876 }
877 } /* end of monitor functions */
878 }
879 }
880 }
881 /* end of monitor */
882 #endif
883 else if (++error_count == MAX_ERROR_COUNT)
884 {
885 app_start();
886 }
887 } /* end of forever loop */
888 }
889
890
891 char gethexnib(void)
892 {
893 char a;
894 a = getch();
895 putch(a);
896 if(a >= 'a')
897 {
898 return (a - 'a' + 0x0a);
899 }
900 else if(a >= '0')
901 {
902 return(a - '0');
903 }
904 return a;
905 }
906
907
908 char gethex(void)
909 {
910 return (gethexnib() << 4) + gethexnib();
911 }
912
913
914 void puthex(char ch)
915 {
916 char ah;
917 ah = ch >> 4;
918 if(ah >= 0x0a)
919 {
920 ah = ah - 0x0a + 'a';
921 }
922 else
923 {
924 ah += '0';
925 }
926 ch &= 0x0f;
927 if(ch >= 0x0a)
928 {
929 ch = ch - 0x0a + 'a';
930 }
931 else
932 {
933 ch += '0';
934 }
935 putch(ah);
936 putch(ch);
937 }
938
939
940 void putch(char ch)
941 {
942 #if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1284P__)
943 if(bootuart == 1)
944 {
945 while (!(UCSR0A & _BV(UDRE0)));
946 UDR0 = ch;
947 }
948 else if (bootuart == 2)
949 {
950 while (!(UCSR1A & _BV(UDRE1)));
951 UDR1 = ch;
952 }
953 #elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
954 while (!(UCSR0A & _BV(UDRE0)));
955 UDR0 = ch;
956 #else
957 /* m8,16,32,169,8515,8535,163 */
958 while (!(UCSRA & _BV(UDRE)));
959 UDR = ch;
960 #endif
961 }
962
963
964 char getch(void)
965 {
966 #if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1284P__)
967 uint32_t count = 0;
968 if(bootuart == 1)
969 {
970 while(!(UCSR0A & _BV(RXC0)))
971 {
972 /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/
973 /* HACKME:: here is a good place to count times*/
974 count++;
975 if (count > MAX_TIME_COUNT)
976 app_start();
977 }
978 return UDR0;
979 }
980 else if(bootuart == 2)
981 {
982 while(!(UCSR1A & _BV(RXC1)))
983 {
984 /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/
985 /* HACKME:: here is a good place to count times*/
986 count++;
987 if (count > MAX_TIME_COUNT)
988 app_start();
989 }
990 return UDR1;
991 }
992 return 0;
993 #elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
994 uint32_t count = 0;
995 while(!(UCSR0A & _BV(RXC0)))
996 {
997 /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/
998 /* HACKME:: here is a good place to count times*/
999 count++;
1000 if (count > MAX_TIME_COUNT)
1001 app_start();
1002 }
1003 return UDR0;
1004 #else
1005 /* m8,16,32,169,8515,8535,163 */
1006 uint32_t count = 0;
1007 while(!(UCSRA & _BV(RXC)))
1008 {
1009 /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/
1010 /* HACKME:: here is a good place to count times*/
1011 count++;
1012 if (count > MAX_TIME_COUNT)
1013 app_start();
1014 }
1015 return UDR;
1016 #endif
1017 }
1018
1019
1020 void getNch(uint8_t count)
1021 {
1022 while(count--)
1023 {
1024 #if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1284P__)
1025 if(bootuart == 1)
1026 {
1027 while(!(UCSR0A & _BV(RXC0)));
1028 UDR0;
1029 }
1030 else if(bootuart == 2)
1031 {
1032 while(!(UCSR1A & _BV(RXC1)));
1033 UDR1;
1034 }
1035 #elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
1036 getch();
1037 #else
1038 /* m8,16,32,169,8515,8535,163 */
1039 /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/
1040 //while(!(UCSRA & _BV(RXC)));
1041 //UDR;
1042 getch(); // need to handle time out
1043 #endif
1044 }
1045 }
1046
1047
1048 void byte_response(uint8_t val)
1049 {
1050 if (getch() == ' ')
1051 {
1052 putch(0x14);
1053 putch(val);
1054 putch(0x10);
1055 }
1056 else
1057 {
1058 if (++error_count == MAX_ERROR_COUNT)
1059 app_start();
1060 }
1061 }
1062
1063
1064 void nothing_response(void)
1065 {
1066 if (getch() == ' ')
1067 {
1068 putch(0x14);
1069 putch(0x10);
1070 }
1071 else
1072 {
1073 if (++error_count == MAX_ERROR_COUNT)
1074 app_start();
1075 }
1076 }
1077
1078 void flash_led(uint8_t count)
1079 {
1080 while (count--)
1081 {
1082 LED_PORT |= _BV(LED);
1083 _delay_ms(100);
1084 LED_PORT &= ~_BV(LED);
1085 _delay_ms(100);
1086 }
1087 }
1088
1089
1090 /* end of file ATmegaBOOT.c */
0 # Makefile for ATmegaBOOT
1 # E.Lins, 18.7.2005
2 # $Id$
3
4
5 # program name should not be changed...
6 PROGRAM = ATmegaBOOT_1284P
7
8 # enter the target CPU frequency
9 AVR_FREQ = 16000000L
10
11 MCU_TARGET = atmega1284p
12 LDSECTION = --section-start=.text=0x1F800
13
14 OBJ = $(PROGRAM).o
15 OPTIMIZE = -Os
16
17 DEFS = -DWATCHDOG_MODS -DBAUD_RATE=57600
18 LIBS =
19
20 CC = avr-gcc
21
22
23 # Override is only needed by avr-lib build system.
24
25 override CFLAGS = -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) -DF_CPU=$(AVR_FREQ) $(DEFS)
26 override LDFLAGS = -Wl,$(LDSECTION)
27 #override LDFLAGS = -Wl,-Map,$(PROGRAM).map,$(LDSECTION)
28
29 OBJCOPY = avr-objcopy
30 OBJDUMP = avr-objdump
31
32 all: CFLAGS += '-DMAX_TIME_COUNT=16000000L>>1' -DADABOOT
33 all: $(PROGRAM).hex
34
35 $(PROGRAM).hex: $(PROGRAM).elf
36 $(OBJCOPY) -j .text -j .data -O ihex $< $@
37
38 $(PROGRAM).elf: $(OBJ)
39 $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
40
41 $(OBJ): ATmegaBOOT.c
42 avr-gcc $(CFLAGS) $(LDFLAGS) -c -Wall -mmcu=$(MCU_TARGET) ATmegaBOOT.c -o $(PROGRAM).o
43
44 %.lst: %.elf
45 $(OBJDUMP) -h -S $< > $@
46
47 %.srec: %.elf
48 $(OBJCOPY) -j .text -j .data -O srec $< $@
49
50 %.bin: %.elf
51 $(OBJCOPY) -j .text -j .data -O binary $< $@
52
53 clean:
54 rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex
55
0 #ifndef Pins_Arduino_h
1 #define Pins_Arduino_h
2
3 #include <avr/pgmspace.h>
4
5 // ATMEL ATMEGA1284P
6 //
7 // +---\/---+
8 // (D 0) PB0 1| |40 PA0 (AI 0 / D24)
9 // (D 1) PB1 2| |39 PA1 (AI 1 / D25)
10 // INT2 (D 2) PB2 3| |38 PA2 (AI 2 / D26)
11 // PWM (D 3) PB3 4| |37 PA3 (AI 3 / D27)
12 // PWM/SS (D 4) PB4 5| |36 PA4 (AI 4 / D28)
13 // MOSI (D 5) PB5 6| |35 PA5 (AI 5 / D29)
14 // PWM/MISO (D 6) PB6 7| |34 PA6 (AI 6 / D30)
15 // PWM/SCK (D 7) PB7 8| |33 PA7 (AI 7 / D31)
16 // RST 9| |32 AREF
17 // VCC 10| |31 GND
18 // GND 11| |30 AVCC
19 // XTAL2 12| |29 PC7 (D 23)
20 // XTAL1 13| |28 PC6 (D 22)
21 // RX0 (D 8) PD0 14| |27 PC5 (D 21) TDI
22 // TX0 (D 9) PD1 15| |26 PC4 (D 20) TDO
23 // RX1/INT0 (D 10) PD2 16| |25 PC3 (D 19) TMS
24 // TX1/INT1 (D 11) PD3 17| |24 PC2 (D 18) TCK
25 // PWM (D 12) PD4 18| |23 PC1 (D 17) SDA
26 // PWM (D 13) PD5 19| |22 PC0 (D 16) SCL
27 // PWM (D 14) PD6 20| |21 PD7 (D 15) PWM
28 // +--------+
29 //
30
31 /*
32 PCINT15-8: D7-0 : bit 1
33 PCINT31-24: D15-8 : bit 3
34 PCINT23-16: D23-16 : bit 2
35 PCINT7-0: D31-24 : bit 0
36 */
37
38 #define NUM_DIGITAL_PINS 32
39 #define NUM_ANALOG_INPUTS 8
40 #define analogInputToDigitalPin(p) ((p < NUM_ANALOG_INPUTS) ? (p) + 24 : -1)
41
42 #define digitalPinHasPWM(p) ((p) == 3 || (p) == 4 || (p) == 6 || (p) == 7 || (p) == 12 || (p) == 13 || (p) == 14 || (p) == 15)
43
44 static const uint8_t SS = 4;
45 static const uint8_t MOSI = 5;
46 static const uint8_t MISO = 6;
47 static const uint8_t SCK = 7;
48
49 static const uint8_t SDA = 17;
50 static const uint8_t SCL = 16;
51 static const uint8_t LED = 7;
52
53 static const uint8_t A0 = 24;
54 static const uint8_t A1 = 25;
55 static const uint8_t A2 = 26;
56 static const uint8_t A3 = 27;
57 static const uint8_t A4 = 28;
58 static const uint8_t A5 = 29;
59 static const uint8_t A6 = 30;
60 static const uint8_t A7 = 31;
61
62 #define digitalPinToPCICR(p) (((p) >= 0 && (p) < NUM_DIGITAL_PINS) ? (&PCICR) : ((uint8_t *)0))
63 #define digitalPinToPCICRbit(p) (((p) <= 7) ? 1 : (((p) <= 15) ? 3 : (((p) <= 23) ? 2 : 0)))
64 #define digitalPinToPCMSK(p) (((p) <= 7) ? (&PCMSK2) : (((p) <= 13) ? (&PCMSK0) : (((p) <= 21) ? (&PCMSK1) : ((uint8_t *)0))))
65 #define digitalPinToPCMSKbit(p) ((p) % 8)
66
67 #ifdef ARDUINO_MAIN
68
69 #define PA 1
70 #define PB 2
71 #define PC 3
72 #define PD 4
73
74 // these arrays map port names (e.g. port B) to the
75 // appropriate addresses for various functions (e.g. reading
76 // and writing)
77 const uint16_t PROGMEM port_to_mode_PGM[] =
78 {
79 NOT_A_PORT,
80 (uint16_t) &DDRA,
81 (uint16_t) &DDRB,
82 (uint16_t) &DDRC,
83 (uint16_t) &DDRD,
84 };
85
86 const uint16_t PROGMEM port_to_output_PGM[] =
87 {
88 NOT_A_PORT,
89 (uint16_t) &PORTA,
90 (uint16_t) &PORTB,
91 (uint16_t) &PORTC,
92 (uint16_t) &PORTD,
93 };
94
95 const uint16_t PROGMEM port_to_input_PGM[] =
96 {
97 NOT_A_PORT,
98 (uint16_t) &PINA,
99 (uint16_t) &PINB,
100 (uint16_t) &PINC,
101 (uint16_t) &PIND,
102 };
103
104 const uint8_t PROGMEM digital_pin_to_port_PGM[] =
105 {
106 PB, /* 0 */
107 PB,
108 PB,
109 PB,
110 PB,
111 PB,
112 PB,
113 PB,
114 PD, /* 8 */
115 PD,
116 PD,
117 PD,
118 PD,
119 PD,
120 PD,
121 PD,
122 PC, /* 16 */
123 PC,
124 PC,
125 PC,
126 PC,
127 PC,
128 PC,
129 PC,
130 PA, /* 24 */
131 PA,
132 PA,
133 PA,
134 PA,
135 PA,
136 PA,
137 PA /* 31 */
138 };
139
140 const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] =
141 {
142 _BV(0), /* 0, port B */
143 _BV(1),
144 _BV(2),
145 _BV(3),
146 _BV(4),
147 _BV(5),
148 _BV(6),
149 _BV(7),
150 _BV(0), /* 8, port D */
151 _BV(1),
152 _BV(2),
153 _BV(3),
154 _BV(4),
155 _BV(5),
156 _BV(6),
157 _BV(7),
158 _BV(0), /* 16, port C */
159 _BV(1),
160 _BV(2),
161 _BV(3),
162 _BV(4),
163 _BV(5),
164 _BV(6),
165 _BV(7),
166 _BV(0), /* 24, port A */
167 _BV(1),
168 _BV(2),
169 _BV(3),
170 _BV(4),
171 _BV(5),
172 _BV(6),
173 _BV(7)
174 };
175
176 const uint8_t PROGMEM digital_pin_to_timer_PGM[] =
177 {
178 NOT_ON_TIMER, /* 0 - PB0 */
179 NOT_ON_TIMER, /* 1 - PB1 */
180 NOT_ON_TIMER, /* 2 - PB2 */
181 TIMER0A, /* 3 - PB3 */
182 TIMER0B, /* 4 - PB4 */
183 NOT_ON_TIMER, /* 5 - PB5 */
184 TIMER3A, /* 6 - PB6 */
185 TIMER3B, /* 7 - PB7 */
186 NOT_ON_TIMER, /* 8 - PD0 */
187 NOT_ON_TIMER, /* 9 - PD1 */
188 NOT_ON_TIMER, /* 10 - PD2 */
189 NOT_ON_TIMER, /* 11 - PD3 */
190 TIMER1B, /* 12 - PD4 */
191 TIMER1A, /* 13 - PD5 */
192 TIMER2B, /* 14 - PD6 */
193 TIMER2A, /* 15 - PD7 */
194 NOT_ON_TIMER, /* 16 - PC0 */
195 NOT_ON_TIMER, /* 17 - PC1 */
196 NOT_ON_TIMER, /* 18 - PC2 */
197 NOT_ON_TIMER, /* 19 - PC3 */
198 NOT_ON_TIMER, /* 20 - PC4 */
199 NOT_ON_TIMER, /* 21 - PC5 */
200 NOT_ON_TIMER, /* 22 - PC6 */
201 NOT_ON_TIMER, /* 23 - PC7 */
202 NOT_ON_TIMER, /* 24 - PA0 */
203 NOT_ON_TIMER, /* 25 - PA1 */
204 NOT_ON_TIMER, /* 26 - PA2 */
205 NOT_ON_TIMER, /* 27 - PA3 */
206 NOT_ON_TIMER, /* 28 - PA4 */
207 NOT_ON_TIMER, /* 29 - PA5 */
208 NOT_ON_TIMER, /* 30 - PA6 */
209 NOT_ON_TIMER /* 31 - PA7 */
210 };
211
212 #endif // ARDUINO_MAIN
213
214 #endif // Pins_Arduino_h
215 // vim:ai:cin:sts=2 sw=2 ft=cpp