Browse Source

Add bootloader files for ATmega1284/Sanguino

Added the optiboot bootloader, uses only 512kB of FLASH
Includes .hex file is for 20MHz µC Clock and serial speed of 57k6
Dirk Eichel 11 years ago
parent
commit
f991bf23b2

+ 470
- 0
ArduinoAddons/Arduino_0.xx/Sanguino/bootloaders/atmega1284p/Makefile View File

@@ -0,0 +1,470 @@
1
+# Makefile for ATmegaBOOT
2
+# E.Lins, 18.7.2005
3
+# $Id$
4
+#
5
+# Instructions
6
+#
7
+# To make bootloader .hex file:
8
+# make diecimila
9
+# make lilypad
10
+# make ng
11
+# etc...
12
+#
13
+# To burn bootloader .hex file:
14
+# make diecimila_isp
15
+# make lilypad_isp
16
+# make ng_isp
17
+# etc...
18
+
19
+# program name should not be changed...
20
+PROGRAM    = optiboot
21
+
22
+# The default behavior is to build using tools that are in the users
23
+# current path variables, but we can also build using an installed
24
+# Arduino user IDE setup, or the Arduino source tree.
25
+# Uncomment this next lines to build within the arduino environment,
26
+# using the arduino-included avrgcc toolset (mac and pc)
27
+# ENV ?= arduino
28
+# ENV ?= arduinodev
29
+# OS ?= macosx
30
+# OS ?= windows
31
+
32
+
33
+# enter the parameters for the avrdude isp tool
34
+ISPTOOL    = stk500v2
35
+ISPPORT    = usb
36
+ISPSPEED   = -b 115200
37
+
38
+MCU_TARGET = atmega168
39
+LDSECTIONS  = -Wl,--section-start=.text=0x3e00 -Wl,--section-start=.version=0x3ffe
40
+
41
+# Build environments
42
+# Start of some ugly makefile-isms to allow optiboot to be built
43
+# in several different environments.  See the README.TXT file for
44
+# details.
45
+
46
+# default
47
+fixpath = $(1)
48
+
49
+ifeq ($(ENV), arduino)
50
+# For Arduino, we assume that we're connected to the optiboot directory
51
+# included with the arduino distribution, which means that the full set
52
+# of avr-tools are "right up there" in standard places.
53
+TOOLROOT = ../../../tools
54
+GCCROOT = $(TOOLROOT)/avr/bin/
55
+AVRDUDE_CONF = -C$(TOOLROOT)/avr/etc/avrdude.conf
56
+
57
+ifeq ($(OS), windows)
58
+# On windows, SOME of the tool paths will need to have backslashes instead
59
+# of forward slashes (because they use windows cmd.exe for execution instead
60
+# of a unix/mingw shell?)  We also have to ensure that a consistent shell
61
+# is used even if a unix shell is installed (ie as part of WINAVR)
62
+fixpath = $(subst /,\,$1)
63
+SHELL = cmd.exe
64
+endif
65
+
66
+else ifeq ($(ENV), arduinodev)
67
+# Arduino IDE source code environment.  Use the unpacked compilers created
68
+# by the build (you'll need to do "ant build" first.)
69
+ifeq ($(OS), macosx)
70
+TOOLROOT = ../../../../build/macosx/work/Arduino.app/Contents/Resources/Java/hardware/tools
71
+endif
72
+ifeq ($(OS), windows)
73
+TOOLROOT = ../../../../build/windows/work/hardware/tools
74
+endif
75
+
76
+GCCROOT = $(TOOLROOT)/avr/bin/
77
+AVRDUDE_CONF = -C$(TOOLROOT)/avr/etc/avrdude.conf
78
+
79
+else
80
+GCCROOT =
81
+AVRDUDE_CONF =
82
+endif
83
+#
84
+# End of build environment code.
85
+
86
+
87
+# the efuse should really be 0xf8; since, however, only the lower
88
+# three bits of that byte are used on the atmega168, avrdude gets
89
+# confused if you specify 1's for the higher bits, see:
90
+# http://tinker.it/now/2007/02/24/the-tale-of-avrdude-atmega168-and-extended-bits-fuses/
91
+#
92
+# similarly, the lock bits should be 0xff instead of 0x3f (to
93
+# unlock the bootloader section) and 0xcf instead of 0x2f (to
94
+# lock it), but since the high two bits of the lock byte are
95
+# unused, avrdude would get confused.
96
+
97
+ISPFUSES    = $(GCCROOT)avrdude $(AVRDUDE_CONF) -c $(ISPTOOL) \
98
+              -p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \
99
+              -e -u -U lock:w:0x3f:m -U efuse:w:0x$(EFUSE):m \
100
+              -U hfuse:w:0x$(HFUSE):m -U lfuse:w:0x$(LFUSE):m
101
+ISPFLASH    = $(GCCROOT)avrdude $(AVRDUDE_CONF) -c $(ISPTOOL) \
102
+              -p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \
103
+              -U flash:w:$(PROGRAM)_$(TARGET).hex -U lock:w:0x2f:m
104
+
105
+STK500 = "C:\Program Files\Atmel\AVR Tools\STK500\Stk500.exe"
106
+STK500-1 = $(STK500) -e -d$(MCU_TARGET) -pf -vf -if$(PROGRAM)_$(TARGET).hex \
107
+-lFF -LFF -f$(HFUSE)$(LFUSE) -EF8 -ms -q -cUSB -I200kHz -s -wt
108
+STK500-2 = $(STK500) -d$(MCU_TARGET) -ms -q -lCF -LCF -cUSB -I200kHz -s -wt
109
+
110
+OBJ        = $(PROGRAM).o
111
+OPTIMIZE = -Os -fno-inline-small-functions -fno-split-wide-types -mshort-calls
112
+
113
+DEFS       = 
114
+LIBS       =
115
+
116
+CC         = $(GCCROOT)avr-gcc
117
+
118
+# Override is only needed by avr-lib build system.
119
+
120
+override CFLAGS        = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) -DF_CPU=$(AVR_FREQ) $(DEFS)
121
+override LDFLAGS       = $(LDSECTIONS) -Wl,--relax -Wl,--gc-sections -nostartfiles -nostdlib
122
+
123
+OBJCOPY        = $(GCCROOT)avr-objcopy
124
+OBJDUMP        = $(call fixpath,$(GCCROOT)avr-objdump)
125
+
126
+SIZE           = $(GCCROOT)avr-size
127
+
128
+# Test platforms
129
+# Virtual boot block test
130
+virboot328: TARGET = atmega328
131
+virboot328: MCU_TARGET = atmega328p
132
+virboot328: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' '-DVIRTUAL_BOOT'
133
+virboot328: AVR_FREQ = 16000000L
134
+virboot328: LDSECTIONS  = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
135
+virboot328: $(PROGRAM)_atmega328.hex
136
+virboot328: $(PROGRAM)_atmega328.lst
137
+
138
+# 20MHz clocked platforms
139
+#
140
+# These are capable of 230400 baud, or 115200 baud on PC (Arduino Avrdude issue)
141
+#
142
+
143
+pro20: TARGET = pro_20mhz
144
+pro20: MCU_TARGET = atmega168
145
+pro20: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200'
146
+pro20: AVR_FREQ = 20000000L
147
+pro20: $(PROGRAM)_pro_20mhz.hex
148
+pro20: $(PROGRAM)_pro_20mhz.lst
149
+
150
+pro20_isp: pro20
151
+pro20_isp: TARGET = pro_20mhz
152
+# 2.7V brownout
153
+pro20_isp: HFUSE = DD
154
+# Full swing xtal (20MHz) 258CK/14CK+4.1ms
155
+pro20_isp: LFUSE = C6
156
+# 512 byte boot
157
+pro20_isp: EFUSE = 04
158
+pro20_isp: isp
159
+
160
+# 16MHz clocked platforms
161
+#
162
+# These are capable of 230400 baud, or 115200 baud on PC (Arduino Avrdude issue)
163
+#
164
+
165
+pro16: TARGET = pro_16MHz
166
+pro16: MCU_TARGET = atmega168
167
+pro16: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200'
168
+pro16: AVR_FREQ = 16000000L
169
+pro16: $(PROGRAM)_pro_16MHz.hex
170
+pro16: $(PROGRAM)_pro_16MHz.lst
171
+
172
+pro16_isp: pro16
173
+pro16_isp: TARGET = pro_16MHz
174
+# 2.7V brownout
175
+pro16_isp: HFUSE = DD
176
+# Full swing xtal (20MHz) 258CK/14CK+4.1ms
177
+pro16_isp: LFUSE = C6
178
+# 512 byte boot
179
+pro16_isp: EFUSE = 04
180
+pro16_isp: isp
181
+
182
+# Diecimila, Duemilanove with m168, and NG use identical bootloaders
183
+# Call it "atmega168" for generality and clarity, keep "diecimila" for
184
+# backward compatibility of makefile
185
+#
186
+atmega168: TARGET = atmega168
187
+atmega168: MCU_TARGET = atmega168
188
+atmega168: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200'
189
+atmega168: AVR_FREQ = 16000000L 
190
+atmega168: $(PROGRAM)_atmega168.hex
191
+atmega168: $(PROGRAM)_atmega168.lst
192
+
193
+atmega168_isp: atmega168
194
+atmega168_isp: TARGET = atmega168
195
+# 2.7V brownout
196
+atmega168_isp: HFUSE = DD
197
+# Low power xtal (16MHz) 16KCK/14CK+65ms
198
+atmega168_isp: LFUSE = FF
199
+# 512 byte boot
200
+atmega168_isp: EFUSE = 04
201
+atmega168_isp: isp
202
+
203
+diecimila: TARGET = diecimila
204
+diecimila: MCU_TARGET = atmega168
205
+diecimila: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200'
206
+diecimila: AVR_FREQ = 16000000L 
207
+diecimila: $(PROGRAM)_diecimila.hex
208
+diecimila: $(PROGRAM)_diecimila.lst
209
+
210
+diecimila_isp: diecimila
211
+diecimila_isp: TARGET = diecimila
212
+# 2.7V brownout
213
+diecimila_isp: HFUSE = DD
214
+# Low power xtal (16MHz) 16KCK/14CK+65ms
215
+diecimila_isp: LFUSE = FF
216
+# 512 byte boot
217
+diecimila_isp: EFUSE = 04
218
+diecimila_isp: isp
219
+
220
+atmega328: TARGET = atmega328
221
+atmega328: MCU_TARGET = atmega328p
222
+atmega328: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200'
223
+atmega328: AVR_FREQ = 16000000L
224
+atmega328: LDSECTIONS  = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
225
+atmega328: $(PROGRAM)_atmega328.hex
226
+atmega328: $(PROGRAM)_atmega328.lst
227
+
228
+atmega328_isp: atmega328
229
+atmega328_isp: TARGET = atmega328
230
+atmega328_isp: MCU_TARGET = atmega328p
231
+# 512 byte boot, SPIEN
232
+atmega328_isp: HFUSE = DE
233
+# Low power xtal (16MHz) 16KCK/14CK+65ms
234
+atmega328_isp: LFUSE = FF
235
+# 2.7V brownout
236
+atmega328_isp: EFUSE = 05
237
+atmega328_isp: isp
238
+
239
+atmega1284: TARGET = atmega1284p
240
+atmega1284: MCU_TARGET = atmega1284p
241
+atmega1284: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' '-DBIGBOOT'
242
+atmega1284: AVR_FREQ = 16000000L
243
+atmega1284: LDSECTIONS  = -Wl,--section-start=.text=0x1fc00
244
+atmega1284: $(PROGRAM)_atmega1284p.hex
245
+atmega1284: $(PROGRAM)_atmega1284p.lst
246
+
247
+atmega1284_isp: atmega1284
248
+atmega1284_isp: TARGET = atmega1284p
249
+atmega1284_isp: MCU_TARGET = atmega1284p
250
+# 1024 byte boot
251
+atmega1284_isp: HFUSE = DE
252
+# Low power xtal (16MHz) 16KCK/14CK+65ms
253
+atmega1284_isp: LFUSE = FF
254
+# 2.7V brownout
255
+atmega1284_isp: EFUSE = FD
256
+atmega1284_isp: isp
257
+
258
+# Sanguino has a minimum boot size of 1024 bytes, so enable extra functions
259
+#
260
+sanguino: TARGET = atmega644p
261
+sanguino: MCU_TARGET = atmega644p
262
+sanguino: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' '-DBIGBOOT'
263
+sanguino: AVR_FREQ = 16000000L
264
+sanguino: LDSECTIONS  = -Wl,--section-start=.text=0xfc00
265
+sanguino: $(PROGRAM)_atmega644p.hex
266
+sanguino: $(PROGRAM)_atmega644p.lst
267
+
268
+sanguino_isp: sanguino
269
+sanguino_isp: TARGET = atmega644p
270
+sanguino_isp: MCU_TARGET = atmega644p
271
+# 1024 byte boot
272
+sanguino_isp: HFUSE = DE
273
+# Low power xtal (16MHz) 16KCK/14CK+65ms
274
+sanguino_isp: LFUSE = FF
275
+# 2.7V brownout
276
+sanguino_isp: EFUSE = 05
277
+sanguino_isp: isp
278
+
279
+# Mega has a minimum boot size of 1024 bytes, so enable extra functions
280
+#mega: TARGET = atmega1280
281
+mega: MCU_TARGET = atmega1280
282
+mega: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' '-DBIGBOOT'
283
+mega: AVR_FREQ = 16000000L
284
+mega: LDSECTIONS  = -Wl,--section-start=.text=0x1fc00
285
+mega: $(PROGRAM)_atmega1280.hex
286
+mega: $(PROGRAM)_atmega1280.lst
287
+
288
+mega_isp: mega
289
+mega_isp: TARGET = atmega1280
290
+mega_isp: MCU_TARGET = atmega1280
291
+# 1024 byte boot
292
+mega_isp: HFUSE = DE
293
+# Low power xtal (16MHz) 16KCK/14CK+65ms
294
+mega_isp: LFUSE = FF
295
+# 2.7V brownout
296
+mega_isp: EFUSE = 05
297
+mega_isp: isp
298
+
299
+# ATmega8
300
+#
301
+atmega8: TARGET = atmega8
302
+atmega8: MCU_TARGET = atmega8
303
+atmega8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200'
304
+atmega8: AVR_FREQ = 16000000L 
305
+atmega8: LDSECTIONS  = -Wl,--section-start=.text=0x1e00 -Wl,--section-start=.version=0x1ffe
306
+atmega8: $(PROGRAM)_atmega8.hex
307
+atmega8: $(PROGRAM)_atmega8.lst
308
+
309
+atmega8_isp: atmega8
310
+atmega8_isp: TARGET = atmega8
311
+atmega8_isp: MCU_TARGET = atmega8
312
+# SPIEN, CKOPT, Bootsize=512B
313
+atmega8_isp: HFUSE = CC
314
+# 2.7V brownout, Low power xtal (16MHz) 16KCK/14CK+65ms
315
+atmega8_isp: LFUSE = BF
316
+atmega8_isp: isp
317
+
318
+# ATmega88
319
+#
320
+atmega88: TARGET = atmega88
321
+atmega88: MCU_TARGET = atmega88
322
+atmega88: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200'
323
+atmega88: AVR_FREQ = 16000000L 
324
+atmega88: LDSECTIONS  = -Wl,--section-start=.text=0x1e00 -Wl,--section-start=.version=0x1ffe
325
+atmega88: $(PROGRAM)_atmega88.hex
326
+atmega88: $(PROGRAM)_atmega88.lst
327
+
328
+atmega88_isp: atmega88
329
+atmega88_isp: TARGET = atmega88
330
+atmega88_isp: MCU_TARGET = atmega88
331
+# 2.7V brownout
332
+atmega88_isp: HFUSE = DD
333
+# Low power xtal (16MHz) 16KCK/14CK+65ms
334
+atemga88_isp: LFUSE = FF
335
+# 512 byte boot
336
+atmega88_isp: EFUSE = 04
337
+atmega88_isp: isp
338
+
339
+
340
+# 8MHz clocked platforms
341
+#
342
+# These are capable of 115200 baud
343
+#
344
+
345
+lilypad: TARGET = lilypad
346
+lilypad: MCU_TARGET = atmega168
347
+lilypad: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200'
348
+lilypad: AVR_FREQ = 8000000L
349
+lilypad: $(PROGRAM)_lilypad.hex
350
+lilypad: $(PROGRAM)_lilypad.lst
351
+
352
+lilypad_isp: lilypad
353
+lilypad_isp: TARGET = lilypad
354
+# 2.7V brownout
355
+lilypad_isp: HFUSE = DD
356
+# Internal 8MHz osc (8MHz) Slow rising power
357
+lilypad_isp: LFUSE = E2
358
+# 512 byte boot
359
+lilypad_isp: EFUSE = 04
360
+lilypad_isp: isp
361
+
362
+lilypad_resonator: TARGET = lilypad_resonator
363
+lilypad_resonator: MCU_TARGET = atmega168
364
+lilypad_resonator: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200'
365
+lilypad_resonator: AVR_FREQ = 8000000L
366
+lilypad_resonator: $(PROGRAM)_lilypad_resonator.hex
367
+lilypad_resonator: $(PROGRAM)_lilypad_resonator.lst
368
+
369
+lilypad_resonator_isp: lilypad_resonator
370
+lilypad_resonator_isp: TARGET = lilypad_resonator
371
+# 2.7V brownout
372
+lilypad_resonator_isp: HFUSE = DD
373
+# Full swing xtal (20MHz) 258CK/14CK+4.1ms
374
+lilypad_resonator_isp: LFUSE = C6
375
+# 512 byte boot
376
+lilypad_resonator_isp: EFUSE = 04
377
+lilypad_resonator_isp: isp
378
+
379
+pro8: TARGET = pro_8MHz
380
+pro8: MCU_TARGET = atmega168
381
+pro8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200'
382
+pro8: AVR_FREQ = 8000000L
383
+pro8: $(PROGRAM)_pro_8MHz.hex
384
+pro8: $(PROGRAM)_pro_8MHz.lst
385
+
386
+pro8_isp: pro8
387
+pro8_isp: TARGET = pro_8MHz
388
+# 2.7V brownout
389
+pro8_isp: HFUSE = DD
390
+# Full swing xtal (20MHz) 258CK/14CK+4.1ms
391
+pro8_isp: LFUSE = C6
392
+# 512 byte boot
393
+pro8_isp: EFUSE = 04
394
+pro8_isp: isp
395
+
396
+atmega328_pro8: TARGET = atmega328_pro_8MHz
397
+atmega328_pro8: MCU_TARGET = atmega328p
398
+atmega328_pro8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200'
399
+atmega328_pro8: AVR_FREQ = 8000000L
400
+atmega328_pro8: LDSECTIONS = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
401
+atmega328_pro8: $(PROGRAM)_atmega328_pro_8MHz.hex
402
+atmega328_pro8: $(PROGRAM)_atmega328_pro_8MHz.lst
403
+
404
+atmega328_pro8_isp: atmega328_pro8
405
+atmega328_pro8_isp: TARGET = atmega328_pro_8MHz
406
+atmega328_pro8_isp: MCU_TARGET = atmega328p
407
+# 512 byte boot, SPIEN
408
+atmega328_pro8_isp: HFUSE = DE
409
+# Low power xtal (16MHz) 16KCK/14CK+65ms
410
+atmega328_pro8_isp: LFUSE = FF
411
+# 2.7V brownout
412
+atmega328_pro8_isp: EFUSE = 05
413
+atmega328_pro8_isp: isp
414
+
415
+# 1MHz clocked platforms
416
+#
417
+# These are capable of 9600 baud
418
+#
419
+
420
+luminet: TARGET = luminet
421
+luminet: MCU_TARGET = attiny84
422
+luminet: CFLAGS += '-DLED_START_FLASHES=3' '-DSOFT_UART' '-DBAUD_RATE=9600'
423
+luminet: CFLAGS += '-DVIRTUAL_BOOT_PARTITION'
424
+luminet: AVR_FREQ = 1000000L
425
+luminet: LDSECTIONS = -Wl,--section-start=.text=0x1d00 -Wl,--section-start=.version=0x1efe
426
+luminet: $(PROGRAM)_luminet.hex
427
+luminet: $(PROGRAM)_luminet.lst
428
+
429
+luminet_isp: luminet
430
+luminet_isp: TARGET = luminet
431
+luminet_isp: MCU_TARGET = attiny84
432
+# Brownout disabled
433
+luminet_isp: HFUSE = DF
434
+# 1MHz internal oscillator, slowly rising power
435
+luminet_isp: LFUSE = 62
436
+# Self-programming enable
437
+luminet_isp: EFUSE = FE
438
+luminet_isp: isp
439
+
440
+#
441
+# Generic build instructions
442
+#
443
+#
444
+
445
+isp: $(TARGET)
446
+        $(ISPFUSES)
447
+        $(ISPFLASH)
448
+
449
+isp-stk500: $(PROGRAM)_$(TARGET).hex
450
+        $(STK500-1)
451
+        $(STK500-2)
452
+
453
+%.elf: $(OBJ)
454
+        $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
455
+        $(SIZE) $@
456
+
457
+clean:
458
+        rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex
459
+
460
+%.lst: %.elf
461
+        $(OBJDUMP) -h -S $< > $@
462
+
463
+%.hex: %.elf
464
+        $(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O ihex $< $@
465
+
466
+%.srec: %.elf
467
+        $(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O srec $< $@
468
+
469
+%.bin: %.elf
470
+        $(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O binary $< $@

+ 848
- 0
ArduinoAddons/Arduino_0.xx/Sanguino/bootloaders/atmega1284p/boot.h View File

@@ -0,0 +1,848 @@
1
+/* Modified to use out for SPM access
2
+** Peter Knight, Optiboot project http://optiboot.googlecode.com
3
+**
4
+** Todo: Tidy up
5
+**
6
+** "_short" routines execute 1 cycle faster and use 1 less word of flash
7
+** by using "out" instruction instead of "sts".
8
+**
9
+** Additional elpm variants that trust the value of RAMPZ
10
+*/
11
+
12
+/* Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007  Eric B. Weddington
13
+   All rights reserved.
14
+
15
+   Redistribution and use in source and binary forms, with or without
16
+   modification, are permitted provided that the following conditions are met:
17
+
18
+   * Redistributions of source code must retain the above copyright
19
+     notice, this list of conditions and the following disclaimer.
20
+   * Redistributions in binary form must reproduce the above copyright
21
+     notice, this list of conditions and the following disclaimer in
22
+     the documentation and/or other materials provided with the
23
+     distribution.
24
+   * Neither the name of the copyright holders nor the names of
25
+     contributors may be used to endorse or promote products derived
26
+     from this software without specific prior written permission.
27
+
28
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31
+  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
32
+  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36
+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38
+  POSSIBILITY OF SUCH DAMAGE. */
39
+
40
+/* $Id: boot.h,v 1.27.2.3 2008/09/30 13:58:48 arcanum Exp $ */
41
+
42
+#ifndef _AVR_BOOT_H_
43
+#define _AVR_BOOT_H_    1
44
+
45
+/** \file */
46
+/** \defgroup avr_boot <avr/boot.h>: Bootloader Support Utilities
47
+    \code
48
+    #include <avr/io.h>
49
+    #include <avr/boot.h>
50
+    \endcode
51
+
52
+    The macros in this module provide a C language interface to the
53
+    bootloader support functionality of certain AVR processors. These
54
+    macros are designed to work with all sizes of flash memory.
55
+
56
+    Global interrupts are not automatically disabled for these macros. It
57
+    is left up to the programmer to do this. See the code example below. 
58
+    Also see the processor datasheet for caveats on having global interrupts 
59
+    enabled during writing of the Flash.
60
+
61
+    \note Not all AVR processors provide bootloader support. See your
62
+    processor datasheet to see if it provides bootloader support.
63
+
64
+    \todo From email with Marek: On smaller devices (all except ATmega64/128),
65
+    __SPM_REG is in the I/O space, accessible with the shorter "in" and "out"
66
+    instructions - since the boot loader has a limited size, this could be an
67
+    important optimization.
68
+
69
+    \par API Usage Example
70
+    The following code shows typical usage of the boot API.
71
+
72
+    \code
73
+    #include <inttypes.h>
74
+    #include <avr/interrupt.h>
75
+    #include <avr/pgmspace.h>
76
+    
77
+    void boot_program_page (uint32_t page, uint8_t *buf)
78
+    {
79
+        uint16_t i;
80
+        uint8_t sreg;
81
+
82
+        // Disable interrupts.
83
+
84
+        sreg = SREG;
85
+        cli();
86
+    
87
+        eeprom_busy_wait ();
88
+
89
+        boot_page_erase (page);
90
+        boot_spm_busy_wait ();      // Wait until the memory is erased.
91
+
92
+        for (i=0; i<SPM_PAGESIZE; i+=2)
93
+        {
94
+            // Set up little-endian word.
95
+
96
+            uint16_t w = *buf++;
97
+            w += (*buf++) << 8;
98
+        
99
+            boot_page_fill (page + i, w);
100
+        }
101
+
102
+        boot_page_write (page);     // Store buffer in flash page.
103
+        boot_spm_busy_wait();       // Wait until the memory is written.
104
+
105
+        // Reenable RWW-section again. We need this if we want to jump back
106
+        // to the application after bootloading.
107
+
108
+        boot_rww_enable ();
109
+
110
+        // Re-enable interrupts (if they were ever enabled).
111
+
112
+        SREG = sreg;
113
+    }\endcode */
114
+
115
+#include <avr/eeprom.h>
116
+#include <avr/io.h>
117
+#include <inttypes.h>
118
+#include <limits.h>
119
+
120
+/* Check for SPM Control Register in processor. */
121
+#if defined (SPMCSR)
122
+#  define __SPM_REG    SPMCSR
123
+#elif defined (SPMCR)
124
+#  define __SPM_REG    SPMCR
125
+#else
126
+#  error AVR processor does not provide bootloader support!
127
+#endif
128
+
129
+
130
+/* Check for SPM Enable bit. */
131
+#if defined(SPMEN)
132
+#  define __SPM_ENABLE  SPMEN
133
+#elif defined(SELFPRGEN)
134
+#  define __SPM_ENABLE  SELFPRGEN
135
+#else
136
+#  error Cannot find SPM Enable bit definition!
137
+#endif
138
+
139
+/** \ingroup avr_boot
140
+    \def BOOTLOADER_SECTION
141
+
142
+    Used to declare a function or variable to be placed into a
143
+    new section called .bootloader. This section and its contents
144
+    can then be relocated to any address (such as the bootloader
145
+    NRWW area) at link-time. */
146
+
147
+#define BOOTLOADER_SECTION    __attribute__ ((section (".bootloader")))
148
+
149
+/* Create common bit definitions. */
150
+#ifdef ASB
151
+#define __COMMON_ASB    ASB
152
+#else
153
+#define __COMMON_ASB    RWWSB
154
+#endif
155
+
156
+#ifdef ASRE
157
+#define __COMMON_ASRE   ASRE
158
+#else
159
+#define __COMMON_ASRE   RWWSRE
160
+#endif
161
+
162
+/* Define the bit positions of the Boot Lock Bits. */
163
+
164
+#define BLB12           5
165
+#define BLB11           4
166
+#define BLB02           3
167
+#define BLB01           2
168
+
169
+/** \ingroup avr_boot
170
+    \def boot_spm_interrupt_enable()
171
+    Enable the SPM interrupt. */
172
+
173
+#define boot_spm_interrupt_enable()   (__SPM_REG |= (uint8_t)_BV(SPMIE))
174
+
175
+/** \ingroup avr_boot
176
+    \def boot_spm_interrupt_disable()
177
+    Disable the SPM interrupt. */
178
+
179
+#define boot_spm_interrupt_disable()  (__SPM_REG &= (uint8_t)~_BV(SPMIE))
180
+
181
+/** \ingroup avr_boot
182
+    \def boot_is_spm_interrupt()
183
+    Check if the SPM interrupt is enabled. */
184
+
185
+#define boot_is_spm_interrupt()       (__SPM_REG & (uint8_t)_BV(SPMIE))
186
+
187
+/** \ingroup avr_boot
188
+    \def boot_rww_busy()
189
+    Check if the RWW section is busy. */
190
+
191
+#define boot_rww_busy()          (__SPM_REG & (uint8_t)_BV(__COMMON_ASB))
192
+
193
+/** \ingroup avr_boot
194
+    \def boot_spm_busy()
195
+    Check if the SPM instruction is busy. */
196
+
197
+#define boot_spm_busy()               (__SPM_REG & (uint8_t)_BV(__SPM_ENABLE))
198
+
199
+/** \ingroup avr_boot
200
+    \def boot_spm_busy_wait()
201
+    Wait while the SPM instruction is busy. */
202
+
203
+#define boot_spm_busy_wait()          do{}while(boot_spm_busy())
204
+
205
+#define __BOOT_PAGE_ERASE         (_BV(__SPM_ENABLE) | _BV(PGERS))
206
+#define __BOOT_PAGE_WRITE         (_BV(__SPM_ENABLE) | _BV(PGWRT))
207
+#define __BOOT_PAGE_FILL          _BV(__SPM_ENABLE)
208
+#define __BOOT_RWW_ENABLE         (_BV(__SPM_ENABLE) | _BV(__COMMON_ASRE))
209
+#define __BOOT_LOCK_BITS_SET      (_BV(__SPM_ENABLE) | _BV(BLBSET))
210
+
211
+#define __boot_page_fill_short(address, data)   \
212
+(__extension__({                                 \
213
+    __asm__ __volatile__                         \
214
+    (                                            \
215
+        "movw  r0, %3\n\t"                       \
216
+        "out %0, %1\n\t"                         \
217
+        "spm\n\t"                                \
218
+        "clr  r1\n\t"                            \
219
+        :                                        \
220
+        : "i" (_SFR_IO_ADDR(__SPM_REG)),        \
221
+          "r" ((uint8_t)__BOOT_PAGE_FILL),       \
222
+          "z" ((uint16_t)address),               \
223
+          "r" ((uint16_t)data)                   \
224
+        : "r0"                                   \
225
+    );                                           \
226
+}))
227
+
228
+#define __boot_page_fill_normal(address, data)   \
229
+(__extension__({                                 \
230
+    __asm__ __volatile__                         \
231
+    (                                            \
232
+        "movw  r0, %3\n\t"                       \
233
+        "sts %0, %1\n\t"                         \
234
+        "spm\n\t"                                \
235
+        "clr  r1\n\t"                            \
236
+        :                                        \
237
+        : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
238
+          "r" ((uint8_t)__BOOT_PAGE_FILL),       \
239
+          "z" ((uint16_t)address),               \
240
+          "r" ((uint16_t)data)                   \
241
+        : "r0"                                   \
242
+    );                                           \
243
+}))
244
+
245
+#define __boot_page_fill_alternate(address, data)\
246
+(__extension__({                                 \
247
+    __asm__ __volatile__                         \
248
+    (                                            \
249
+        "movw  r0, %3\n\t"                       \
250
+        "sts %0, %1\n\t"                         \
251
+        "spm\n\t"                                \
252
+        ".word 0xffff\n\t"                       \
253
+        "nop\n\t"                                \
254
+        "clr  r1\n\t"                            \
255
+        :                                        \
256
+        : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
257
+          "r" ((uint8_t)__BOOT_PAGE_FILL),       \
258
+          "z" ((uint16_t)address),               \
259
+          "r" ((uint16_t)data)                   \
260
+        : "r0"                                   \
261
+    );                                           \
262
+}))
263
+
264
+#define __boot_page_fill_extended(address, data) \
265
+(__extension__({                                 \
266
+    __asm__ __volatile__                         \
267
+    (                                            \
268
+        "movw  r0, %4\n\t"                       \
269
+        "movw r30, %A3\n\t"                      \
270
+        "sts %1, %C3\n\t"                        \
271
+        "sts %0, %2\n\t"                         \
272
+        "spm\n\t"                                \
273
+        "clr  r1\n\t"                            \
274
+        :                                        \
275
+        : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
276
+          "i" (_SFR_MEM_ADDR(RAMPZ)),            \
277
+          "r" ((uint8_t)__BOOT_PAGE_FILL),       \
278
+          "r" ((uint32_t)address),               \
279
+          "r" ((uint16_t)data)                   \
280
+        : "r0", "r30", "r31"                     \
281
+    );                                           \
282
+}))
283
+
284
+#define __boot_page_fill_extended_short(address, data) \
285
+(__extension__({                                 \
286
+    __asm__ __volatile__                         \
287
+    (                                            \
288
+        "movw  r0, %4\n\t"                       \
289
+        "movw r30, %A3\n\t"                      \
290
+        "out %1, %C3\n\t"                        \
291
+        "out %0, %2\n\t"                         \
292
+        "spm\n\t"                                \
293
+        "clr  r1\n\t"                            \
294
+        :                                        \
295
+        : "i" (_SFR_IO_ADDR(__SPM_REG)),        \
296
+          "i" (_SFR_IO_ADDR(RAMPZ)),            \
297
+          "r" ((uint8_t)__BOOT_PAGE_FILL),       \
298
+          "r" ((uint32_t)address),               \
299
+          "r" ((uint16_t)data)                   \
300
+        : "r0", "r30", "r31"                     \
301
+    );                                           \
302
+}))
303
+
304
+#define __boot_page_erase_short(address)        \
305
+(__extension__({                                 \
306
+    __asm__ __volatile__                         \
307
+    (                                            \
308
+        "out %0, %1\n\t"                         \
309
+        "spm\n\t"                                \
310
+        :                                        \
311
+        : "i" (_SFR_IO_ADDR(__SPM_REG)),        \
312
+          "r" ((uint8_t)__BOOT_PAGE_ERASE),      \
313
+          "z" ((uint16_t)address)                \
314
+    );                                           \
315
+}))
316
+
317
+
318
+#define __boot_page_erase_normal(address)        \
319
+(__extension__({                                 \
320
+    __asm__ __volatile__                         \
321
+    (                                            \
322
+        "sts %0, %1\n\t"                         \
323
+        "spm\n\t"                                \
324
+        :                                        \
325
+        : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
326
+          "r" ((uint8_t)__BOOT_PAGE_ERASE),      \
327
+          "z" ((uint16_t)address)                \
328
+    );                                           \
329
+}))
330
+
331
+#define __boot_page_erase_alternate(address)     \
332
+(__extension__({                                 \
333
+    __asm__ __volatile__                         \
334
+    (                                            \
335
+        "sts %0, %1\n\t"                         \
336
+        "spm\n\t"                                \
337
+        ".word 0xffff\n\t"                       \
338
+        "nop\n\t"                                \
339
+        :                                        \
340
+        : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
341
+          "r" ((uint8_t)__BOOT_PAGE_ERASE),      \
342
+          "z" ((uint16_t)address)                \
343
+    );                                           \
344
+}))
345
+
346
+#define __boot_page_erase_extended(address)      \
347
+(__extension__({                                 \
348
+    __asm__ __volatile__                         \
349
+    (                                            \
350
+        "movw r30, %A3\n\t"                      \
351
+        "sts  %1, %C3\n\t"                       \
352
+        "sts %0, %2\n\t"                         \
353
+        "spm\n\t"                                \
354
+        :                                        \
355
+        : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
356
+          "i" (_SFR_MEM_ADDR(RAMPZ)),            \
357
+          "r" ((uint8_t)__BOOT_PAGE_ERASE),      \
358
+          "r" ((uint32_t)address)                \
359
+        : "r30", "r31"                           \
360
+    );                                           \
361
+}))
362
+#define __boot_page_erase_extended_short(address)      \
363
+(__extension__({                                 \
364
+    __asm__ __volatile__                         \
365
+    (                                            \
366
+        "movw r30, %A3\n\t"                      \
367
+        "out  %1, %C3\n\t"                       \
368
+        "out %0, %2\n\t"                         \
369
+        "spm\n\t"                                \
370
+        :                                        \
371
+        : "i" (_SFR_IO_ADDR(__SPM_REG)),        \
372
+          "i" (_SFR_IO_ADDR(RAMPZ)),            \
373
+          "r" ((uint8_t)__BOOT_PAGE_ERASE),      \
374
+          "r" ((uint32_t)address)                \
375
+        : "r30", "r31"                           \
376
+    );                                           \
377
+}))
378
+
379
+#define __boot_page_write_short(address)        \
380
+(__extension__({                                 \
381
+    __asm__ __volatile__                         \
382
+    (                                            \
383
+        "out %0, %1\n\t"                         \
384
+        "spm\n\t"                                \
385
+        :                                        \
386
+        : "i" (_SFR_IO_ADDR(__SPM_REG)),        \
387
+          "r" ((uint8_t)__BOOT_PAGE_WRITE),      \
388
+          "z" ((uint16_t)address)                \
389
+    );                                           \
390
+}))
391
+
392
+#define __boot_page_write_normal(address)        \
393
+(__extension__({                                 \
394
+    __asm__ __volatile__                         \
395
+    (                                            \
396
+        "sts %0, %1\n\t"                         \
397
+        "spm\n\t"                                \
398
+        :                                        \
399
+        : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
400
+          "r" ((uint8_t)__BOOT_PAGE_WRITE),      \
401
+          "z" ((uint16_t)address)                \
402
+    );                                           \
403
+}))
404
+
405
+#define __boot_page_write_alternate(address)     \
406
+(__extension__({                                 \
407
+    __asm__ __volatile__                         \
408
+    (                                            \
409
+        "sts %0, %1\n\t"                         \
410
+        "spm\n\t"                                \
411
+        ".word 0xffff\n\t"                       \
412
+        "nop\n\t"                                \
413
+        :                                        \
414
+        : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
415
+          "r" ((uint8_t)__BOOT_PAGE_WRITE),      \
416
+          "z" ((uint16_t)address)                \
417
+    );                                           \
418
+}))
419
+
420
+#define __boot_page_write_extended(address)      \
421
+(__extension__({                                 \
422
+    __asm__ __volatile__                         \
423
+    (                                            \
424
+        "movw r30, %A3\n\t"                      \
425
+        "sts %1, %C3\n\t"                        \
426
+        "sts %0, %2\n\t"                         \
427
+        "spm\n\t"                                \
428
+        :                                        \
429
+        : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
430
+          "i" (_SFR_MEM_ADDR(RAMPZ)),            \
431
+          "r" ((uint8_t)__BOOT_PAGE_WRITE),      \
432
+          "r" ((uint32_t)address)                \
433
+        : "r30", "r31"                           \
434
+    );                                           \
435
+}))
436
+#define __boot_page_write_extended_short(address)      \
437
+(__extension__({                                 \
438
+    __asm__ __volatile__                         \
439
+    (                                            \
440
+        "movw r30, %A3\n\t"                      \
441
+        "out %1, %C3\n\t"                        \
442
+        "out %0, %2\n\t"                         \
443
+        "spm\n\t"                                \
444
+        :                                        \
445
+        : "i" (_SFR_IO_ADDR(__SPM_REG)),        \
446
+          "i" (_SFR_IO_ADDR(RAMPZ)),            \
447
+          "r" ((uint8_t)__BOOT_PAGE_WRITE),      \
448
+          "r" ((uint32_t)address)                \
449
+        : "r30", "r31"                           \
450
+    );                                           \
451
+}))
452
+
453
+#define __boot_rww_enable_short()                      \
454
+(__extension__({                                 \
455
+    __asm__ __volatile__                         \
456
+    (                                            \
457
+        "out %0, %1\n\t"                         \
458
+        "spm\n\t"                                \
459
+        :                                        \
460
+        : "i" (_SFR_IO_ADDR(__SPM_REG)),        \
461
+          "r" ((uint8_t)__BOOT_RWW_ENABLE)       \
462
+    );                                           \
463
+}))
464
+
465
+#define __boot_rww_enable()                      \
466
+(__extension__({                                 \
467
+    __asm__ __volatile__                         \
468
+    (                                            \
469
+        "sts %0, %1\n\t"                         \
470
+        "spm\n\t"                                \
471
+        :                                        \
472
+        : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
473
+          "r" ((uint8_t)__BOOT_RWW_ENABLE)       \
474
+    );                                           \
475
+}))
476
+
477
+#define __boot_rww_enable_alternate()            \
478
+(__extension__({                                 \
479
+    __asm__ __volatile__                         \
480
+    (                                            \
481
+        "sts %0, %1\n\t"                         \
482
+        "spm\n\t"                                \
483
+        ".word 0xffff\n\t"                       \
484
+        "nop\n\t"                                \
485
+        :                                        \
486
+        : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
487
+          "r" ((uint8_t)__BOOT_RWW_ENABLE)       \
488
+    );                                           \
489
+}))
490
+
491
+/* From the mega16/mega128 data sheets (maybe others):
492
+
493
+     Bits by SPM To set the Boot Loader Lock bits, write the desired data to
494
+     R0, write "X0001001" to SPMCR and execute SPM within four clock cycles
495
+     after writing SPMCR. The only accessible Lock bits are the Boot Lock bits
496
+     that may prevent the Application and Boot Loader section from any
497
+     software update by the MCU.
498
+
499
+     If bits 5..2 in R0 are cleared (zero), the corresponding Boot Lock bit
500
+     will be programmed if an SPM instruction is executed within four cycles
501
+     after BLBSET and SPMEN (or SELFPRGEN) are set in SPMCR. The Z-pointer is 
502
+     don't care during this operation, but for future compatibility it is 
503
+     recommended to load the Z-pointer with $0001 (same as used for reading the 
504
+     Lock bits). For future compatibility It is also recommended to set bits 7, 
505
+     6, 1, and 0 in R0 to 1 when writing the Lock bits. When programming the 
506
+     Lock bits the entire Flash can be read during the operation. */
507
+
508
+#define __boot_lock_bits_set_short(lock_bits)                    \
509
+(__extension__({                                           \
510
+    uint8_t value = (uint8_t)(~(lock_bits));               \
511
+    __asm__ __volatile__                                   \
512
+    (                                                      \
513
+        "ldi r30, 1\n\t"                                   \
514
+        "ldi r31, 0\n\t"                                   \
515
+        "mov r0, %2\n\t"                                   \
516
+        "out %0, %1\n\t"                                   \
517
+        "spm\n\t"                                          \
518
+        :                                                  \
519
+        : "i" (_SFR_IO_ADDR(__SPM_REG)),                  \
520
+          "r" ((uint8_t)__BOOT_LOCK_BITS_SET),             \
521
+          "r" (value)                                      \
522
+        : "r0", "r30", "r31"                               \
523
+    );                                                     \
524
+}))
525
+
526
+#define __boot_lock_bits_set(lock_bits)                    \
527
+(__extension__({                                           \
528
+    uint8_t value = (uint8_t)(~(lock_bits));               \
529
+    __asm__ __volatile__                                   \
530
+    (                                                      \
531
+        "ldi r30, 1\n\t"                                   \
532
+        "ldi r31, 0\n\t"                                   \
533
+        "mov r0, %2\n\t"                                   \
534
+        "sts %0, %1\n\t"                                   \
535
+        "spm\n\t"                                          \
536
+        :                                                  \
537
+        : "i" (_SFR_MEM_ADDR(__SPM_REG)),                  \
538
+          "r" ((uint8_t)__BOOT_LOCK_BITS_SET),             \
539
+          "r" (value)                                      \
540
+        : "r0", "r30", "r31"                               \
541
+    );                                                     \
542
+}))
543
+
544
+#define __boot_lock_bits_set_alternate(lock_bits)          \
545
+(__extension__({                                           \
546
+    uint8_t value = (uint8_t)(~(lock_bits));               \
547
+    __asm__ __volatile__                                   \
548
+    (                                                      \
549
+        "ldi r30, 1\n\t"                                   \
550
+        "ldi r31, 0\n\t"                                   \
551
+        "mov r0, %2\n\t"                                   \
552
+        "sts %0, %1\n\t"                                   \
553
+        "spm\n\t"                                          \
554
+        ".word 0xffff\n\t"                                 \
555
+        "nop\n\t"                                          \
556
+        :                                                  \
557
+        : "i" (_SFR_MEM_ADDR(__SPM_REG)),                  \
558
+          "r" ((uint8_t)__BOOT_LOCK_BITS_SET),             \
559
+          "r" (value)                                      \
560
+        : "r0", "r30", "r31"                               \
561
+    );                                                     \
562
+}))
563
+
564
+/*
565
+   Reading lock and fuse bits:
566
+
567
+     Similarly to writing the lock bits above, set BLBSET and SPMEN (or 
568
+     SELFPRGEN) bits in __SPMREG, and then (within four clock cycles) issue an 
569
+     LPM instruction.
570
+
571
+     Z address:       contents:
572
+     0x0000           low fuse bits
573
+     0x0001           lock bits
574
+     0x0002           extended fuse bits
575
+     0x0003           high fuse bits
576
+
577
+     Sounds confusing, doesn't it?
578
+
579
+     Unlike the macros in pgmspace.h, no need to care for non-enhanced
580
+     cores here as these old cores do not provide SPM support anyway.
581
+ */
582
+
583
+/** \ingroup avr_boot
584
+    \def GET_LOW_FUSE_BITS
585
+    address to read the low fuse bits, using boot_lock_fuse_bits_get
586
+ */
587
+#define GET_LOW_FUSE_BITS           (0x0000)
588
+/** \ingroup avr_boot
589
+    \def GET_LOCK_BITS
590
+    address to read the lock bits, using boot_lock_fuse_bits_get
591
+ */
592
+#define GET_LOCK_BITS               (0x0001)
593
+/** \ingroup avr_boot
594
+    \def GET_EXTENDED_FUSE_BITS
595
+    address to read the extended fuse bits, using boot_lock_fuse_bits_get
596
+ */
597
+#define GET_EXTENDED_FUSE_BITS      (0x0002)
598
+/** \ingroup avr_boot
599
+    \def GET_HIGH_FUSE_BITS
600
+    address to read the high fuse bits, using boot_lock_fuse_bits_get
601
+ */
602
+#define GET_HIGH_FUSE_BITS          (0x0003)
603
+
604
+/** \ingroup avr_boot
605
+    \def boot_lock_fuse_bits_get(address)
606
+
607
+    Read the lock or fuse bits at \c address.
608
+
609
+    Parameter \c address can be any of GET_LOW_FUSE_BITS,
610
+    GET_LOCK_BITS, GET_EXTENDED_FUSE_BITS, or GET_HIGH_FUSE_BITS.
611
+
612
+    \note The lock and fuse bits returned are the physical values,
613
+    i.e. a bit returned as 0 means the corresponding fuse or lock bit
614
+    is programmed.
615
+ */
616
+#define boot_lock_fuse_bits_get_short(address)                   \
617
+(__extension__({                                           \
618
+    uint8_t __result;                                      \
619
+    __asm__ __volatile__                                   \
620
+    (                                                      \
621
+        "ldi r30, %3\n\t"                                  \
622
+        "ldi r31, 0\n\t"                                   \
623
+        "out %1, %2\n\t"                                   \
624
+        "lpm %0, Z\n\t"                                    \
625
+        : "=r" (__result)                                  \
626
+        : "i" (_SFR_IO_ADDR(__SPM_REG)),                  \
627
+          "r" ((uint8_t)__BOOT_LOCK_BITS_SET),             \
628
+          "M" (address)                                    \
629
+        : "r0", "r30", "r31"                               \
630
+    );                                                     \
631
+    __result;                                              \
632
+}))
633
+
634
+#define boot_lock_fuse_bits_get(address)                   \
635
+(__extension__({                                           \
636
+    uint8_t __result;                                      \
637
+    __asm__ __volatile__                                   \
638
+    (                                                      \
639
+        "ldi r30, %3\n\t"                                  \
640
+        "ldi r31, 0\n\t"                                   \
641
+        "sts %1, %2\n\t"                                   \
642
+        "lpm %0, Z\n\t"                                    \
643
+        : "=r" (__result)                                  \
644
+        : "i" (_SFR_MEM_ADDR(__SPM_REG)),                  \
645
+          "r" ((uint8_t)__BOOT_LOCK_BITS_SET),             \
646
+          "M" (address)                                    \
647
+        : "r0", "r30", "r31"                               \
648
+    );                                                     \
649
+    __result;                                              \
650
+}))
651
+
652
+/** \ingroup avr_boot
653
+    \def boot_signature_byte_get(address)
654
+
655
+    Read the Signature Row byte at \c address.  For some MCU types,
656
+    this function can also retrieve the factory-stored oscillator
657
+    calibration bytes.
658
+
659
+    Parameter \c address can be 0-0x1f as documented by the datasheet.
660
+    \note The values are MCU type dependent.
661
+*/
662
+
663
+#define __BOOT_SIGROW_READ (_BV(__SPM_ENABLE) | _BV(SIGRD))
664
+
665
+#define boot_signature_byte_get_short(addr) \
666
+(__extension__({                      \
667
+      uint16_t __addr16 = (uint16_t)(addr);     \
668
+      uint8_t __result;                         \
669
+      __asm__ __volatile__                      \
670
+      (                                         \
671
+        "out %1, %2\n\t"                        \
672
+        "lpm %0, Z" "\n\t"                      \
673
+        : "=r" (__result)                       \
674
+        : "i" (_SFR_IO_ADDR(__SPM_REG)),        \
675
+          "r" ((uint8_t) __BOOT_SIGROW_READ),   \
676
+          "z" (__addr16)                        \
677
+      );                                        \
678
+      __result;                                 \
679
+}))
680
+
681
+#define boot_signature_byte_get(addr) \
682
+(__extension__({                      \
683
+      uint16_t __addr16 = (uint16_t)(addr);     \
684
+      uint8_t __result;                         \
685
+      __asm__ __volatile__                      \
686
+      (                                         \
687
+        "sts %1, %2\n\t"                        \
688
+        "lpm %0, Z" "\n\t"                      \
689
+        : "=r" (__result)                       \
690
+        : "i" (_SFR_MEM_ADDR(__SPM_REG)),       \
691
+          "r" ((uint8_t) __BOOT_SIGROW_READ),   \
692
+          "z" (__addr16)                        \
693
+      );                                        \
694
+      __result;                                 \
695
+}))
696
+
697
+/** \ingroup avr_boot
698
+    \def boot_page_fill(address, data)
699
+
700
+    Fill the bootloader temporary page buffer for flash 
701
+    address with data word. 
702
+
703
+    \note The address is a byte address. The data is a word. The AVR 
704
+    writes data to the buffer a word at a time, but addresses the buffer
705
+    per byte! So, increment your address by 2 between calls, and send 2
706
+    data bytes in a word format! The LSB of the data is written to the lower 
707
+    address; the MSB of the data is written to the higher address.*/
708
+
709
+/** \ingroup avr_boot
710
+    \def boot_page_erase(address)
711
+
712
+    Erase the flash page that contains address.
713
+
714
+    \note address is a byte address in flash, not a word address. */
715
+
716
+/** \ingroup avr_boot
717
+    \def boot_page_write(address)
718
+
719
+    Write the bootloader temporary page buffer 
720
+    to flash page that contains address.
721
+    
722
+    \note address is a byte address in flash, not a word address. */
723
+
724
+/** \ingroup avr_boot
725
+    \def boot_rww_enable()
726
+
727
+    Enable the Read-While-Write memory section. */
728
+
729
+/** \ingroup avr_boot
730
+    \def boot_lock_bits_set(lock_bits)
731
+
732
+    Set the bootloader lock bits.
733
+
734
+    \param lock_bits A mask of which Boot Loader Lock Bits to set.
735
+
736
+    \note In this context, a 'set bit' will be written to a zero value.
737
+    Note also that only BLBxx bits can be programmed by this command.
738
+
739
+    For example, to disallow the SPM instruction from writing to the Boot
740
+    Loader memory section of flash, you would use this macro as such:
741
+
742
+    \code
743
+    boot_lock_bits_set (_BV (BLB11));
744
+    \endcode
745
+
746
+    \note Like any lock bits, the Boot Loader Lock Bits, once set,
747
+    cannot be cleared again except by a chip erase which will in turn
748
+    also erase the boot loader itself. */
749
+
750
+/* Normal versions of the macros use 16-bit addresses.
751
+   Extended versions of the macros use 32-bit addresses.
752
+   Alternate versions of the macros use 16-bit addresses and require special
753
+   instruction sequences after LPM.
754
+
755
+   FLASHEND is defined in the ioXXXX.h file.
756
+   USHRT_MAX is defined in <limits.h>. */ 
757
+
758
+#if defined(__AVR_ATmega161__) || defined(__AVR_ATmega163__) \
759
+    || defined(__AVR_ATmega323__)
760
+
761
+/* Alternate: ATmega161/163/323 and 16 bit address */
762
+#define boot_page_fill(address, data) __boot_page_fill_alternate(address, data)
763
+#define boot_page_erase(address)      __boot_page_erase_alternate(address)
764
+#define boot_page_write(address)      __boot_page_write_alternate(address)
765
+#define boot_rww_enable()             __boot_rww_enable_alternate()
766
+#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_alternate(lock_bits)
767
+
768
+#elif (FLASHEND > USHRT_MAX)
769
+
770
+/* Extended: >16 bit address */
771
+#define boot_page_fill(address, data) __boot_page_fill_extended_short(address, data)
772
+#define boot_page_erase(address)      __boot_page_erase_extended_short(address)
773
+#define boot_page_write(address)      __boot_page_write_extended_short(address)
774
+#define boot_rww_enable()             __boot_rww_enable_short()
775
+#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_short(lock_bits)
776
+
777
+#else
778
+
779
+/* Normal: 16 bit address */
780
+#define boot_page_fill(address, data) __boot_page_fill_short(address, data)
781
+#define boot_page_erase(address)      __boot_page_erase_short(address)
782
+#define boot_page_write(address)      __boot_page_write_short(address)
783
+#define boot_rww_enable()             __boot_rww_enable_short()
784
+#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_short(lock_bits)
785
+
786
+#endif
787
+
788
+/** \ingroup avr_boot
789
+
790
+    Same as boot_page_fill() except it waits for eeprom and spm operations to
791
+    complete before filling the page. */
792
+
793
+#define boot_page_fill_safe(address, data) \
794
+do { \
795
+    boot_spm_busy_wait();                       \
796
+    eeprom_busy_wait();                         \
797
+    boot_page_fill(address, data);              \
798
+} while (0)
799
+
800
+/** \ingroup avr_boot
801
+
802
+    Same as boot_page_erase() except it waits for eeprom and spm operations to
803
+    complete before erasing the page. */
804
+
805
+#define boot_page_erase_safe(address) \
806
+do { \
807
+    boot_spm_busy_wait();                       \
808
+    eeprom_busy_wait();                         \
809
+    boot_page_erase (address);                  \
810
+} while (0)
811
+
812
+/** \ingroup avr_boot
813
+
814
+    Same as boot_page_write() except it waits for eeprom and spm operations to
815
+    complete before writing the page. */
816
+
817
+#define boot_page_write_safe(address) \
818
+do { \
819
+    boot_spm_busy_wait();                       \
820
+    eeprom_busy_wait();                         \
821
+    boot_page_write (address);                  \
822
+} while (0)
823
+
824
+/** \ingroup avr_boot
825
+
826
+    Same as boot_rww_enable() except waits for eeprom and spm operations to
827
+    complete before enabling the RWW mameory. */
828
+
829
+#define boot_rww_enable_safe() \
830
+do { \
831
+    boot_spm_busy_wait();                       \
832
+    eeprom_busy_wait();                         \
833
+    boot_rww_enable();                          \
834
+} while (0)
835
+
836
+/** \ingroup avr_boot
837
+
838
+    Same as boot_lock_bits_set() except waits for eeprom and spm operations to
839
+    complete before setting the lock bits. */
840
+
841
+#define boot_lock_bits_set_safe(lock_bits) \
842
+do { \
843
+    boot_spm_busy_wait();                       \
844
+    eeprom_busy_wait();                         \
845
+    boot_lock_bits_set (lock_bits);             \
846
+} while (0)
847
+
848
+#endif /* _AVR_BOOT_H_ */

+ 724
- 0
ArduinoAddons/Arduino_0.xx/Sanguino/bootloaders/atmega1284p/optiboot.c View File

@@ -0,0 +1,724 @@
1
+/**********************************************************/
2
+/* -Wl,-section-start=bootloader=0x1fc00 */
3
+/* Optiboot bootloader for Arduino                        */
4
+/*                                                        */
5
+/* http://optiboot.googlecode.com                         */
6
+/*                                                        */
7
+/* Arduino-maintained version : See README.TXT            */
8
+/* http://code.google.com/p/arduino/                      */
9
+/*                                                        */
10
+/* Heavily optimised bootloader that is faster and        */
11
+/* smaller than the Arduino standard bootloader           */
12
+/*                                                        */
13
+/* Enhancements:                                          */
14
+/*   Fits in 512 bytes, saving 1.5K of code space         */
15
+/*   Background page erasing speeds up programming        */
16
+/*   Higher baud rate speeds up programming               */
17
+/*   Written almost entirely in C                         */
18
+/*   Customisable timeout with accurate timeconstant      */
19
+/*   Optional virtual UART. No hardware UART required.    */
20
+/*   Optional virtual boot partition for devices without. */
21
+/*                                                        */
22
+/* What you lose:                                         */
23
+/*   Implements a skeleton STK500 protocol which is       */
24
+/*     missing several features including EEPROM          */
25
+/*     programming and non-page-aligned writes            */
26
+/*   High baud rate breaks compatibility with standard    */
27
+/*     Arduino flash settings                             */
28
+/*                                                        */
29
+/* Fully supported:                                       */
30
+/*   ATmega168 based devices  (Diecimila etc)             */
31
+/*   ATmega328P based devices (Duemilanove etc)           */
32
+/*                                                        */
33
+/* Alpha test                                             */
34
+/*   ATmega1280 based devices (Arduino Mega)              */
35
+/*                                                        */
36
+/* Work in progress:                                      */
37
+/*   ATmega644P based devices (Sanguino)                  */
38
+/*   ATtiny84 based devices (Luminet)                     */
39
+/*                                                        */
40
+/* Does not support:                                      */
41
+/*   USB based devices (eg. Teensy)                       */
42
+/*                                                        */
43
+/* Assumptions:                                           */
44
+/*   The code makes several assumptions that reduce the   */
45
+/*   code size. They are all true after a hardware reset, */
46
+/*   but may not be true if the bootloader is called by   */
47
+/*   other means or on other hardware.                    */
48
+/*     No interrupts can occur                            */
49
+/*     UART and Timer 1 are set to their reset state      */
50
+/*     SP points to RAMEND                                */
51
+/*                                                        */
52
+/* Code builds on code, libraries and optimisations from: */
53
+/*   stk500boot.c          by Jason P. Kyle               */
54
+/*   Arduino bootloader    http://arduino.cc              */
55
+/*   Spiff's 1K bootloader http://spiffie.org/know/arduino_1k_bootloader/bootloader.shtml */
56
+/*   avr-libc project      http://nongnu.org/avr-libc     */
57
+/*   Adaboot               http://www.ladyada.net/library/arduino/bootloader.html */
58
+/*   AVR305                Atmel Application Note         */
59
+/*                                                        */
60
+/* This program is free software; you can redistribute it */
61
+/* and/or modify it under the terms of the GNU General    */
62
+/* Public License as published by the Free Software       */
63
+/* Foundation; either version 2 of the License, or        */
64
+/* (at your option) any later version.                    */
65
+/*                                                        */
66
+/* This program is distributed in the hope that it will   */
67
+/* be useful, but WITHOUT ANY WARRANTY; without even the  */
68
+/* implied warranty of MERCHANTABILITY or FITNESS FOR A   */
69
+/* PARTICULAR PURPOSE.  See the GNU General Public        */
70
+/* License for more details.                              */
71
+/*                                                        */
72
+/* You should have received a copy of the GNU General     */
73
+/* Public License along with this program; if not, write  */
74
+/* to the Free Software Foundation, Inc.,                 */
75
+/* 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA */
76
+/*                                                        */
77
+/* Licence can be viewed at                               */
78
+/* http://www.fsf.org/licenses/gpl.txt                    */
79
+/*                                                        */
80
+/**********************************************************/
81
+
82
+
83
+/**********************************************************/
84
+/*                                                        */
85
+/* Optional defines:                                      */
86
+/*                                                        */
87
+/**********************************************************/
88
+/*                                                        */
89
+/* BIG_BOOT:                                              */
90
+/* Build a 1k bootloader, not 512 bytes. This turns on    */
91
+/* extra functionality.                                   */
92
+/*                                                        */
93
+/* BAUD_RATE:                                             */
94
+/* Set bootloader baud rate.                              */
95
+/*                                                        */
96
+/* LUDICROUS_SPEED:                                       */
97
+/* 230400 baud :-)                                        */
98
+/*                                                        */
99
+/* SOFT_UART:                                             */
100
+/* Use AVR305 soft-UART instead of hardware UART.         */
101
+/*                                                        */
102
+/* LED_START_FLASHES:                                     */
103
+/* Number of LED flashes on bootup.                       */
104
+/*                                                        */
105
+/* LED_DATA_FLASH:                                        */
106
+/* Flash LED when transferring data. For boards without   */
107
+/* TX or RX LEDs, or for people who like blinky lights.   */
108
+/*                                                        */
109
+/* SUPPORT_EEPROM:                                        */
110
+/* Support reading and writing from EEPROM. This is not   */
111
+/* used by Arduino, so off by default.                    */
112
+/*                                                        */
113
+/* TIMEOUT_MS:                                            */
114
+/* Bootloader timeout period, in milliseconds.            */
115
+/* 500,1000,2000,4000,8000 supported.                     */
116
+/*                                                        */
117
+/**********************************************************/
118
+
119
+/**********************************************************/
120
+/* Version Numbers!                                       */
121
+/*                                                        */
122
+/* Arduino Optiboot now includes this Version number in   */
123
+/* the source and object code.                            */
124
+/*                                                        */
125
+/* Version 3 was released as zip from the optiboot        */
126
+/*  repository and was distributed with Arduino 0022.     */
127
+/* Version 4 starts with the arduino repository commit    */
128
+/*  that brought the arduino repository up-to-date with   */
129
+/* the optiboot source tree changes since v3.             */
130
+/*                                                        */
131
+/**********************************************************/
132
+
133
+/**********************************************************/
134
+/* Edit History:                                          */
135
+/*                                                        */
136
+/* Jan 2012:                                              */
137
+/* 4.5 WestfW: fix NRWW value for m1284.                  */
138
+/* 4.4 WestfW: use attribute OS_main instead of naked for */
139
+/*             main().  This allows optimizations that we */
140
+/*             count on, which are prohibited in naked    */
141
+/*             functions due to PR42240.  (keeps us less  */
142
+/*             than 512 bytes when compiler is gcc4.5     */
143
+/*             (code from 4.3.2 remains the same.)        */
144
+/* 4.4 WestfW and Maniacbug:  Add m1284 support.  This    */
145
+/*             does not change the 328 binary, so the     */
146
+/*             version number didn't change either. (?)   */
147
+/* June 2011:                                             */
148
+/* 4.4 WestfW: remove automatic soft_uart detect (didn't  */
149
+/*             know what it was doing or why.)  Added a   */
150
+/*             check of the calculated BRG value instead. */
151
+/*             Version stays 4.4; existing binaries are   */
152
+/*             not changed.                               */
153
+/* 4.4 WestfW: add initialization of address to keep      */
154
+/*             the compiler happy.  Change SC'ed targets. */
155
+/*             Return the SW version via READ PARAM       */
156
+/* 4.3 WestfW: catch framing errors in getch(), so that   */
157
+/*             AVRISP works without HW kludges.           */
158
+/*  http://code.google.com/p/arduino/issues/detail?id=368n*/
159
+/* 4.2 WestfW: reduce code size, fix timeouts, change     */
160
+/*             verifySpace to use WDT instead of appstart */
161
+/* 4.1 WestfW: put version number in binary.              */
162
+/**********************************************************/
163
+
164
+#define OPTIBOOT_MAJVER 4
165
+#define OPTIBOOT_MINVER 5
166
+
167
+#define MAKESTR(a) #a
168
+#define MAKEVER(a, b) MAKESTR(a*256+b)
169
+
170
+asm("  .section .version\n"
171
+    "optiboot_version:  .word " MAKEVER(OPTIBOOT_MAJVER, OPTIBOOT_MINVER) "\n"
172
+    "  .section .text\n");
173
+
174
+#include <inttypes.h>
175
+#include <avr/io.h>
176
+#include <avr/pgmspace.h>
177
+
178
+// <avr/boot.h> uses sts instructions, but this version uses out instructions
179
+// This saves cycles and program memory.
180
+#include "boot.h"
181
+
182
+
183
+// We don't use <avr/wdt.h> as those routines have interrupt overhead we don't need.
184
+
185
+#include "pin_defs.h"
186
+#include "stk500.h"
187
+
188
+#ifndef LED_START_FLASHES
189
+#define LED_START_FLASHES 0
190
+#endif
191
+
192
+#ifdef LUDICROUS_SPEED
193
+#define BAUD_RATE 230400L
194
+#endif
195
+
196
+/* set the UART baud rate defaults */
197
+#ifndef BAUD_RATE
198
+#if F_CPU >= 8000000L
199
+#define BAUD_RATE   115200L // Highest rate Avrdude win32 will support
200
+#elsif F_CPU >= 1000000L
201
+#define BAUD_RATE   9600L   // 19200 also supported, but with significant error
202
+#elsif F_CPU >= 128000L
203
+#define BAUD_RATE   4800L   // Good for 128kHz internal RC
204
+#else
205
+#define BAUD_RATE 1200L     // Good even at 32768Hz
206
+#endif
207
+#endif
208
+
209
+#if 0
210
+/* Switch in soft UART for hard baud rates */
211
+/*
212
+ * I don't understand what this was supposed to accomplish, where the
213
+ * constant "280" came from, or why automatically (and perhaps unexpectedly)
214
+ * switching to a soft uart is a good thing, so I'm undoing this in favor
215
+ * of a range check using the same calc used to config the BRG...
216
+ */
217
+#if (F_CPU/BAUD_RATE) > 280 // > 57600 for 16MHz
218
+#ifndef SOFT_UART
219
+#define SOFT_UART
220
+#endif
221
+#endif
222
+#else // 0
223
+#if (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 > 250
224
+#error Unachievable baud rate (too slow) BAUD_RATE 
225
+#endif // baud rate slow check
226
+#if (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 < 3
227
+#error Unachievable baud rate (too fast) BAUD_RATE 
228
+#endif // baud rate fastn check
229
+#endif
230
+
231
+/* Watchdog settings */
232
+#define WATCHDOG_OFF    (0)
233
+#define WATCHDOG_16MS   (_BV(WDE))
234
+#define WATCHDOG_32MS   (_BV(WDP0) | _BV(WDE))
235
+#define WATCHDOG_64MS   (_BV(WDP1) | _BV(WDE))
236
+#define WATCHDOG_125MS  (_BV(WDP1) | _BV(WDP0) | _BV(WDE))
237
+#define WATCHDOG_250MS  (_BV(WDP2) | _BV(WDE))
238
+#define WATCHDOG_500MS  (_BV(WDP2) | _BV(WDP0) | _BV(WDE))
239
+#define WATCHDOG_1S     (_BV(WDP2) | _BV(WDP1) | _BV(WDE))
240
+#define WATCHDOG_2S     (_BV(WDP2) | _BV(WDP1) | _BV(WDP0) | _BV(WDE))
241
+#ifndef __AVR_ATmega8__
242
+#define WATCHDOG_4S     (_BV(WDP3) | _BV(WDE))
243
+#define WATCHDOG_8S     (_BV(WDP3) | _BV(WDP0) | _BV(WDE))
244
+#endif
245
+
246
+/* Function Prototypes */
247
+/* The main function is in init9, which removes the interrupt vector table */
248
+/* we don't need. It is also 'naked', which means the compiler does not    */
249
+/* generate any entry or exit code itself. */
250
+int main(void) __attribute__ ((OS_main)) __attribute__ ((section (".init9")));
251
+void putch(char);
252
+uint8_t getch(void);
253
+static inline void getNch(uint8_t); /* "static inline" is a compiler hint to reduce code size */
254
+void verifySpace();
255
+static inline void flash_led(uint8_t);
256
+uint8_t getLen();
257
+static inline void watchdogReset();
258
+void watchdogConfig(uint8_t x);
259
+#ifdef SOFT_UART
260
+void uartDelay() __attribute__ ((naked));
261
+#endif
262
+void appStart() __attribute__ ((naked));
263
+
264
+/*
265
+ * NRWW memory
266
+ * Addresses below NRWW (Non-Read-While-Write) can be programmed while
267
+ * continuing to run code from flash, slightly speeding up programming
268
+ * time.  Beware that Atmel data sheets specify this as a WORD address,
269
+ * while optiboot will be comparing against a 16-bit byte address.  This
270
+ * means that on a part with 128kB of memory, the upper part of the lower
271
+ * 64k will get NRWW processing as well, even though it doesn't need it.
272
+ * That's OK.  In fact, you can disable the overlapping processing for
273
+ * a part entirely by setting NRWWSTART to zero.  This reduces code
274
+ * space a bit, at the expense of being slightly slower, overall.
275
+ *
276
+ * RAMSTART should be self-explanatory.  It's bigger on parts with a
277
+ * lot of peripheral registers.
278
+ */
279
+#if defined(__AVR_ATmega168__)
280
+#define RAMSTART (0x100)
281
+#define NRWWSTART (0x3800)
282
+#elif defined(__AVR_ATmega328P__)
283
+#define RAMSTART (0x100)
284
+#define NRWWSTART (0x7000)
285
+#elif defined (__AVR_ATmega644P__)
286
+#define RAMSTART (0x100)
287
+#define NRWWSTART (0xE000)
288
+#elif defined (__AVR_ATmega1284P__)
289
+#define RAMSTART (0x100)
290
+#define NRWWSTART (0xE000)
291
+#elif defined(__AVR_ATtiny84__)
292
+#define RAMSTART (0x100)
293
+#define NRWWSTART (0x0000)
294
+#elif defined(__AVR_ATmega1280__)
295
+#define RAMSTART (0x200)
296
+#define NRWWSTART (0xE000)
297
+#elif defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__)
298
+#define RAMSTART (0x100)
299
+#define NRWWSTART (0x1800)
300
+#endif
301
+
302
+/* C zero initialises all global variables. However, that requires */
303
+/* These definitions are NOT zero initialised, but that doesn't matter */
304
+/* This allows us to drop the zero init code, saving us memory */
305
+#define buff    ((uint8_t*)(RAMSTART))
306
+#ifdef VIRTUAL_BOOT_PARTITION
307
+#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
308
+#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
309
+#endif
310
+
311
+/* main program starts here */
312
+int main(void) {
313
+  uint8_t ch;
314
+
315
+  /*
316
+   * Making these local and in registers prevents the need for initializing
317
+   * them, and also saves space because code no longer stores to memory.
318
+   * (initializing address keeps the compiler happy, but isn't really
319
+   *  necessary, and uses 4 bytes of flash.)
320
+   */
321
+  register uint16_t address = 0;
322
+  register uint8_t  length;
323
+
324
+  // After the zero init loop, this is the first code to run.
325
+  //
326
+  // This code makes the following assumptions:
327
+  //  No interrupts will execute
328
+  //  SP points to RAMEND
329
+  //  r1 contains zero
330
+  //
331
+  // If not, uncomment the following instructions:
332
+  // cli();
333
+  asm volatile ("clr __zero_reg__");
334
+#ifdef __AVR_ATmega8__
335
+  SP=RAMEND;  // This is done by hardware reset
336
+#endif
337
+
338
+  // Adaboot no-wait mod
339
+  ch = MCUSR;
340
+  MCUSR = 0;
341
+  if (!(ch & _BV(EXTRF))) appStart();
342
+
343
+#if LED_START_FLASHES > 0
344
+  // Set up Timer 1 for timeout counter
345
+  TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
346
+#endif
347
+#ifndef SOFT_UART
348
+#ifdef __AVR_ATmega8__
349
+  UCSRA = _BV(U2X); //Double speed mode USART
350
+  UCSRB = _BV(RXEN) | _BV(TXEN);  // enable Rx & Tx
351
+  UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0);  // config USART; 8N1
352
+  UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
353
+#else
354
+  UCSR0A = _BV(U2X0); //Double speed mode USART0
355
+  UCSR0B = _BV(RXEN0) | _BV(TXEN0);
356
+  UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
357
+  UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
358
+#endif
359
+#endif
360
+
361
+  // Set up watchdog to trigger after 500ms
362
+  watchdogConfig(WATCHDOG_1S);
363
+
364
+  /* Set LED pin as output */
365
+  LED_DDR |= _BV(LED);
366
+
367
+#ifdef SOFT_UART
368
+  /* Set TX pin as output */
369
+  UART_DDR |= _BV(UART_TX_BIT);
370
+#endif
371
+
372
+#if LED_START_FLASHES > 0
373
+  /* Flash onboard LED to signal entering of bootloader */
374
+  flash_led(LED_START_FLASHES * 2);
375
+#endif
376
+
377
+  /* Forever loop */
378
+  for (;;) {
379
+    /* get character from UART */
380
+    ch = getch();
381
+
382
+    if(ch == STK_GET_PARAMETER) {
383
+      unsigned char which = getch();
384
+      verifySpace();
385
+      if (which == 0x82) {
386
+        /*
387
+         * Send optiboot version as "minor SW version"
388
+         */
389
+        putch(OPTIBOOT_MINVER);
390
+      } else if (which == 0x81) {
391
+          putch(OPTIBOOT_MAJVER);
392
+      } else {
393
+        /*
394
+         * GET PARAMETER returns a generic 0x03 reply for
395
+         * other parameters - enough to keep Avrdude happy
396
+         */
397
+        putch(0x03);
398
+      }
399
+    }
400
+    else if(ch == STK_SET_DEVICE) {
401
+      // SET DEVICE is ignored
402
+      getNch(20);
403
+    }
404
+    else if(ch == STK_SET_DEVICE_EXT) {
405
+      // SET DEVICE EXT is ignored
406
+      getNch(5);
407
+    }
408
+    else if(ch == STK_LOAD_ADDRESS) {
409
+      // LOAD ADDRESS
410
+      uint16_t newAddress;
411
+      newAddress = getch();
412
+      newAddress = (newAddress & 0xff) | (getch() << 8);
413
+#ifdef RAMPZ
414
+      // Transfer top bit to RAMPZ
415
+      RAMPZ = (newAddress & 0x8000) ? 1 : 0;
416
+#endif
417
+      newAddress += newAddress; // Convert from word address to byte address
418
+      address = newAddress;
419
+      verifySpace();
420
+    }
421
+    else if(ch == STK_UNIVERSAL) {
422
+      // UNIVERSAL command is ignored
423
+      getNch(4);
424
+      putch(0x00);
425
+    }
426
+    /* Write memory, length is big endian and is in bytes */
427
+    else if(ch == STK_PROG_PAGE) {
428
+      // PROGRAM PAGE - we support flash programming only, not EEPROM
429
+      uint8_t *bufPtr;
430
+      uint16_t addrPtr;
431
+
432
+      getch();                  /* getlen() */
433
+      length = getch();
434
+      getch();
435
+
436
+      // If we are in RWW section, immediately start page erase
437
+      if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address);
438
+
439
+      // While that is going on, read in page contents
440
+      bufPtr = buff;
441
+      do *bufPtr++ = getch();
442
+      while (--length);
443
+
444
+      // If we are in NRWW section, page erase has to be delayed until now.
445
+      // Todo: Take RAMPZ into account
446
+      if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address);
447
+
448
+      // Read command terminator, start reply
449
+      verifySpace();
450
+
451
+      // If only a partial page is to be programmed, the erase might not be complete.
452
+      // So check that here
453
+      boot_spm_busy_wait();
454
+
455
+#ifdef VIRTUAL_BOOT_PARTITION
456
+      if ((uint16_t)(void*)address == 0) {
457
+        // This is the reset vector page. We need to live-patch the code so the
458
+        // bootloader runs.
459
+        //
460
+        // Move RESET vector to WDT vector
461
+        uint16_t vect = buff[0] | (buff[1]<<8);
462
+        rstVect = vect;
463
+        wdtVect = buff[8] | (buff[9]<<8);
464
+        vect -= 4; // Instruction is a relative jump (rjmp), so recalculate.
465
+        buff[8] = vect & 0xff;
466
+        buff[9] = vect >> 8;
467
+
468
+        // Add jump to bootloader at RESET vector
469
+        buff[0] = 0x7f;
470
+        buff[1] = 0xce; // rjmp 0x1d00 instruction
471
+      }
472
+#endif
473
+
474
+      // Copy buffer into programming buffer
475
+      bufPtr = buff;
476
+      addrPtr = (uint16_t)(void*)address;
477
+      ch = SPM_PAGESIZE / 2;
478
+      do {
479
+        uint16_t a;
480
+        a = *bufPtr++;
481
+        a |= (*bufPtr++) << 8;
482
+        __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
483
+        addrPtr += 2;
484
+      } while (--ch);
485
+
486
+      // Write from programming buffer
487
+      __boot_page_write_short((uint16_t)(void*)address);
488
+      boot_spm_busy_wait();
489
+
490
+#if defined(RWWSRE)
491
+      // Reenable read access to flash
492
+      boot_rww_enable();
493
+#endif
494
+
495
+    }
496
+    /* Read memory block mode, length is big endian.  */
497
+    else if(ch == STK_READ_PAGE) {
498
+      // READ PAGE - we only read flash
499
+      getch();                  /* getlen() */
500
+      length = getch();
501
+      getch();
502
+
503
+      verifySpace();
504
+#ifdef VIRTUAL_BOOT_PARTITION
505
+      do {
506
+        // Undo vector patch in bottom page so verify passes
507
+        if (address == 0)       ch=rstVect & 0xff;
508
+        else if (address == 1)  ch=rstVect >> 8;
509
+        else if (address == 8)  ch=wdtVect & 0xff;
510
+        else if (address == 9) ch=wdtVect >> 8;
511
+        else ch = pgm_read_byte_near(address);
512
+        address++;
513
+        putch(ch);
514
+      } while (--length);
515
+#else
516
+#ifdef RAMPZ
517
+// Since RAMPZ should already be set, we need to use EPLM directly.
518
+//      do putch(pgm_read_byte_near(address++));
519
+//      while (--length);
520
+      do {
521
+        uint8_t result;
522
+        __asm__ ("elpm %0,Z\n":"=r"(result):"z"(address));
523
+        putch(result);
524
+        address++;
525
+      }
526
+      while (--length);
527
+#else
528
+      do putch(pgm_read_byte_near(address++));
529
+      while (--length);
530
+#endif
531
+#endif
532
+    }
533
+
534
+    /* Get device signature bytes  */
535
+    else if(ch == STK_READ_SIGN) {
536
+      // READ SIGN - return what Avrdude wants to hear
537
+      verifySpace();
538
+      putch(SIGNATURE_0);
539
+      putch(SIGNATURE_1);
540
+      putch(SIGNATURE_2);
541
+    }
542
+    else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */
543
+      // Adaboot no-wait mod
544
+      watchdogConfig(WATCHDOG_16MS);
545
+      verifySpace();
546
+    }
547
+    else {
548
+      // This covers the response to commands like STK_ENTER_PROGMODE
549
+      verifySpace();
550
+    }
551
+    putch(STK_OK);
552
+  }
553
+}
554
+
555
+void putch(char ch) {
556
+#ifndef SOFT_UART
557
+  while (!(UCSR0A & _BV(UDRE0)));
558
+  UDR0 = ch;
559
+#else
560
+  __asm__ __volatile__ (
561
+    "   com %[ch]\n" // ones complement, carry set
562
+    "   sec\n"
563
+    "1: brcc 2f\n"
564
+    "   cbi %[uartPort],%[uartBit]\n"
565
+    "   rjmp 3f\n"
566
+    "2: sbi %[uartPort],%[uartBit]\n"
567
+    "   nop\n"
568
+    "3: rcall uartDelay\n"
569
+    "   rcall uartDelay\n"
570
+    "   lsr %[ch]\n"
571
+    "   dec %[bitcnt]\n"
572
+    "   brne 1b\n"
573
+    :
574
+    :
575
+      [bitcnt] "d" (10),
576
+      [ch] "r" (ch),
577
+      [uartPort] "I" (_SFR_IO_ADDR(UART_PORT)),
578
+      [uartBit] "I" (UART_TX_BIT)
579
+    :
580
+      "r25"
581
+  );
582
+#endif
583
+}
584
+
585
+uint8_t getch(void) {
586
+  uint8_t ch;
587
+
588
+#ifdef LED_DATA_FLASH
589
+#ifdef __AVR_ATmega8__
590
+  LED_PORT ^= _BV(LED);
591
+#else
592
+  LED_PIN |= _BV(LED);
593
+#endif
594
+#endif
595
+
596
+#ifdef SOFT_UART
597
+  __asm__ __volatile__ (
598
+    "1: sbic  %[uartPin],%[uartBit]\n"  // Wait for start edge
599
+    "   rjmp  1b\n"
600
+    "   rcall uartDelay\n"          // Get to middle of start bit
601
+    "2: rcall uartDelay\n"              // Wait 1 bit period
602
+    "   rcall uartDelay\n"              // Wait 1 bit period
603
+    "   clc\n"
604
+    "   sbic  %[uartPin],%[uartBit]\n"
605
+    "   sec\n"
606
+    "   dec   %[bitCnt]\n"
607
+    "   breq  3f\n"
608
+    "   ror   %[ch]\n"
609
+    "   rjmp  2b\n"
610
+    "3:\n"
611
+    :
612
+      [ch] "=r" (ch)
613
+    :
614
+      [bitCnt] "d" (9),
615
+      [uartPin] "I" (_SFR_IO_ADDR(UART_PIN)),
616
+      [uartBit] "I" (UART_RX_BIT)
617
+    :
618
+      "r25"
619
+);
620
+#else
621
+  while(!(UCSR0A & _BV(RXC0)))
622
+    ;
623
+  if (!(UCSR0A & _BV(FE0))) {
624
+      /*
625
+       * A Framing Error indicates (probably) that something is talking
626
+       * to us at the wrong bit rate.  Assume that this is because it
627
+       * expects to be talking to the application, and DON'T reset the
628
+       * watchdog.  This should cause the bootloader to abort and run
629
+       * the application "soon", if it keeps happening.  (Note that we
630
+       * don't care that an invalid char is returned...)
631
+       */
632
+    watchdogReset();
633
+  }
634
+  
635
+  ch = UDR0;
636
+#endif
637
+
638
+#ifdef LED_DATA_FLASH
639
+#ifdef __AVR_ATmega8__
640
+  LED_PORT ^= _BV(LED);
641
+#else
642
+  LED_PIN |= _BV(LED);
643
+#endif
644
+#endif
645
+
646
+  return ch;
647
+}
648
+
649
+#ifdef SOFT_UART
650
+// AVR305 equation: #define UART_B_VALUE (((F_CPU/BAUD_RATE)-23)/6)
651
+// Adding 3 to numerator simulates nearest rounding for more accurate baud rates
652
+#define UART_B_VALUE (((F_CPU/BAUD_RATE)-20)/6)
653
+#if UART_B_VALUE > 255
654
+#error Baud rate too slow for soft UART
655
+#endif
656
+
657
+void uartDelay() {
658
+  __asm__ __volatile__ (
659
+    "ldi r25,%[count]\n"
660
+    "1:dec r25\n"
661
+    "brne 1b\n"
662
+    "ret\n"
663
+    ::[count] "M" (UART_B_VALUE)
664
+  );
665
+}
666
+#endif
667
+
668
+void getNch(uint8_t count) {
669
+  do getch(); while (--count);
670
+  verifySpace();
671
+}
672
+
673
+void verifySpace() {
674
+  if (getch() != CRC_EOP) {
675
+    watchdogConfig(WATCHDOG_16MS);    // shorten WD timeout
676
+    while (1)                         // and busy-loop so that WD causes
677
+      ;                               //  a reset and app start.
678
+  }
679
+  putch(STK_INSYNC);
680
+}
681
+
682
+#if LED_START_FLASHES > 0
683
+void flash_led(uint8_t count) {
684
+  do {
685
+    TCNT1 = -(F_CPU/(1024*16));
686
+    TIFR1 = _BV(TOV1);
687
+    while(!(TIFR1 & _BV(TOV1)));
688
+#ifdef __AVR_ATmega8__
689
+    LED_PORT ^= _BV(LED);
690
+#else
691
+    LED_PIN |= _BV(LED);
692
+#endif
693
+    watchdogReset();
694
+  } while (--count);
695
+}
696
+#endif
697
+
698
+// Watchdog functions. These are only safe with interrupts turned off.
699
+void watchdogReset() {
700
+  __asm__ __volatile__ (
701
+    "wdr\n"
702
+  );
703
+}
704
+
705
+void watchdogConfig(uint8_t x) {
706
+  WDTCSR = _BV(WDCE) | _BV(WDE);
707
+  WDTCSR = x;
708
+}
709
+
710
+void appStart() {
711
+  watchdogConfig(WATCHDOG_OFF);
712
+  __asm__ __volatile__ (
713
+#ifdef VIRTUAL_BOOT_PARTITION
714
+    // Jump to WDT vector
715
+    "ldi r30,4\n"
716
+    "clr r31\n"
717
+#else
718
+    // Jump to RST vector
719
+    "clr r30\n"
720
+    "clr r31\n"
721
+#endif
722
+    "ijmp\n"
723
+  );
724
+}

+ 33
- 0
ArduinoAddons/Arduino_0.xx/Sanguino/bootloaders/atmega1284p/optiboot_1284P_20MHz_57k6_baud.hex View File

@@ -0,0 +1,33 @@
1
+:020000021000EC
2
+:10FE00000F92CDB7DEB7112484B714BE81FFDFD0C7
3
+:10FE100082E08093C00088E18093C10086E08093F7
4
+:10FE2000C2008AE28093C4008EE0BBD0209A00E03A
5
+:10FE300010E0EE24E394E1E1DE2EF3E0FF2EA5D006
6
+:10FE4000813471F4A2D08983B2D08981823809F4D7
7
+:10FE50008BC0813811F484E001C083E08FD08BC067
8
+:10FE6000823411F484E103C0853419F485E0A7D00D
9
+:10FE700082C0853591F489D0A82EBB2486D0082F66
10
+:10FE800010E0102F00270A291B29812F881F88279F
11
+:10FE9000881F8BBF000F111F6DC0863521F484E0D1
12
+:10FEA0008ED080E0DBCF843609F040C06ED06DD0BC
13
+:10FEB000C82E6BD080EE0030180718F4F801F7BE9A
14
+:10FEC000E895A12C51E0B52E60D0F50181935F013A
15
+:10FED000CE16D1F7F0EE00301F0718F0F801F7BE8C
16
+:10FEE000E89565D007B600FCFDCFF801A0E0B1E0D1
17
+:10FEF0002C9130E011968C91119790E0982F8827E3
18
+:10FF0000822B932B12960C01E7BEE89511243296B2
19
+:10FF100082E0A030B80761F785E0F80187BFE89577
20
+:10FF200007B600FCFDCFD7BEE89525C08437A9F4FD
21
+:10FF30002CD02BD0B82E29D03AD0CB2C4801F401AC
22
+:10FF400086911CD00894811C911CCA94C1F70F5F44
23
+:10FF50001F4FBA940B0D111D0EC0853739F427D0F1
24
+:10FF60008EE10CD087E90AD085E078CF813511F495
25
+:10FF700088E017D01CD080E101D061CF9091C00003
26
+:10FF800095FFFCCF8093C60008958091C00087FF45
27
+:10FF9000FCCF8091C00084FD01C0A8958091C6006F
28
+:10FFA0000895E0E6F0E098E1908380830895EDDF26
29
+:10FFB000803219F088E0F5DFFFCF84E1DFCFCF9307
30
+:10FFC000C82FE3DFC150E9F7F2DFCF91089580E059
31
+:08FFD000E8DFEE27FF2709948A
32
+:040000031000FE00EB
33
+:00000001FF

+ 81
- 0
ArduinoAddons/Arduino_0.xx/Sanguino/bootloaders/atmega1284p/pin_defs.h View File

@@ -0,0 +1,81 @@
1
+#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega88) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__)
2
+/* Onboard LED is connected to pin PB5 in Arduino NG, Diecimila, and Duemilanove */
3
+#define LED_DDR     DDRB
4
+#define LED_PORT    PORTB
5
+#define LED_PIN     PINB
6
+#define LED         PINB5
7
+
8
+/* Ports for soft UART */
9
+#ifdef SOFT_UART
10
+#define UART_PORT   PORTD
11
+#define UART_PIN    PIND
12
+#define UART_DDR    DDRD
13
+#define UART_TX_BIT 1
14
+#define UART_RX_BIT 0
15
+#endif
16
+#endif
17
+
18
+#if defined(__AVR_ATmega8__)
19
+  //Name conversion R.Wiersma
20
+  #define UCSR0A        UCSRA
21
+  #define UDR0          UDR
22
+  #define UDRE0         UDRE
23
+  #define RXC0          RXC
24
+  #define FE0           FE
25
+  #define TIFR1         TIFR
26
+  #define WDTCSR        WDTCR
27
+#endif
28
+
29
+/* Luminet support */
30
+#if defined(__AVR_ATtiny84__)
31
+/* Red LED is connected to pin PA4 */
32
+#define LED_DDR     DDRA
33
+#define LED_PORT    PORTA
34
+#define LED_PIN     PINA
35
+#define LED         PINA4
36
+/* Ports for soft UART - left port only for now. TX/RX on PA2/PA3 */
37
+#ifdef SOFT_UART
38
+#define UART_PORT   PORTA
39
+#define UART_PIN    PINA
40
+#define UART_DDR    DDRA
41
+#define UART_TX_BIT 2
42
+#define UART_RX_BIT 3
43
+#endif
44
+#endif
45
+
46
+/* Sanguino support */
47
+#if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)
48
+/* Onboard LED is connected to pin PB0 on Sanguino */
49
+#define LED_DDR     DDRB
50
+#define LED_PORT    PORTB
51
+#define LED_PIN     PINB
52
+#define LED         PINB0
53
+
54
+/* Ports for soft UART */
55
+#ifdef SOFT_UART
56
+#define UART_PORT   PORTD
57
+#define UART_PIN    PIND
58
+#define UART_DDR    DDRD
59
+#define UART_TX_BIT 1
60
+#define UART_RX_BIT 0
61
+#endif
62
+#endif
63
+
64
+/* Mega support */
65
+#if defined(__AVR_ATmega1280__)
66
+/* Onboard LED is connected to pin PB7 on Arduino Mega */
67
+#define LED_DDR     DDRB
68
+#define LED_PORT    PORTB
69
+#define LED_PIN     PINB
70
+#define LED         PINB7
71
+
72
+/* Ports for soft UART */
73
+#ifdef SOFT_UART
74
+#define UART_PORT   PORTE
75
+#define UART_PIN    PINE
76
+#define UART_DDR    DDRE
77
+#define UART_TX_BIT 1
78
+#define UART_RX_BIT 0
79
+#endif
80
+#endif
81
+

+ 39
- 0
ArduinoAddons/Arduino_0.xx/Sanguino/bootloaders/atmega1284p/stk500.h View File

@@ -0,0 +1,39 @@
1
+/* STK500 constants list, from AVRDUDE */
2
+#define STK_OK              0x10
3
+#define STK_FAILED          0x11  // Not used
4
+#define STK_UNKNOWN         0x12  // Not used
5
+#define STK_NODEVICE        0x13  // Not used
6
+#define STK_INSYNC          0x14  // ' '
7
+#define STK_NOSYNC          0x15  // Not used
8
+#define ADC_CHANNEL_ERROR   0x16  // Not used
9
+#define ADC_MEASURE_OK      0x17  // Not used
10
+#define PWM_CHANNEL_ERROR   0x18  // Not used
11
+#define PWM_ADJUST_OK       0x19  // Not used
12
+#define CRC_EOP             0x20  // 'SPACE'
13
+#define STK_GET_SYNC        0x30  // '0'
14
+#define STK_GET_SIGN_ON     0x31  // '1'
15
+#define STK_SET_PARAMETER   0x40  // '@'
16
+#define STK_GET_PARAMETER   0x41  // 'A'
17
+#define STK_SET_DEVICE      0x42  // 'B'
18
+#define STK_SET_DEVICE_EXT  0x45  // 'E'
19
+#define STK_ENTER_PROGMODE  0x50  // 'P'
20
+#define STK_LEAVE_PROGMODE  0x51  // 'Q'
21
+#define STK_CHIP_ERASE      0x52  // 'R'
22
+#define STK_CHECK_AUTOINC   0x53  // 'S'
23
+#define STK_LOAD_ADDRESS    0x55  // 'U'
24
+#define STK_UNIVERSAL       0x56  // 'V'
25
+#define STK_PROG_FLASH      0x60  // '`'
26
+#define STK_PROG_DATA       0x61  // 'a'
27
+#define STK_PROG_FUSE       0x62  // 'b'
28
+#define STK_PROG_LOCK       0x63  // 'c'
29
+#define STK_PROG_PAGE       0x64  // 'd'
30
+#define STK_PROG_FUSE_EXT   0x65  // 'e'
31
+#define STK_READ_FLASH      0x70  // 'p'
32
+#define STK_READ_DATA       0x71  // 'q'
33
+#define STK_READ_FUSE       0x72  // 'r'
34
+#define STK_READ_LOCK       0x73  // 's'
35
+#define STK_READ_PAGE       0x74  // 't'
36
+#define STK_READ_SIGN       0x75  // 'u'
37
+#define STK_READ_OSCCAL     0x76  // 'v'
38
+#define STK_READ_FUSE_EXT   0x77  // 'w'
39
+#define STK_READ_OSCCAL_EXT 0x78  // 'x'

Loading…
Cancel
Save