Programming boot loader, app and fuses all in one fell swoop

Go To Last Post
16 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi All...

I did some googleing and searching, but have not been able to figure this out. Is it possible to program a boot loader, an application and set fuses all using an AVR ISP mkII or similar programmer?

Thanks...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes.

Start by combining the two .hex files for app.hex and boot.hex in to a combined.hex

Then use AS4 (probably best!) ability to combine fuse settings and combined.hex into a composite "production.elf" file.

Then use ELF file programming on the production line.

For the first step see the bootloader FAQ for details of using srec_cat to combine Intel hex files.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Great, thanks!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So how do i install the elf file on to the uC?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

stk500.exe should be able to program .elf files.

EDIT:

E:\Program Files\Atmel\AVR Tools\STK500>stk500 -h | grep -i elf
    STK500.EXE -dATmega128 -e -ipmyfile.elf -pa -va
ip  Name of ELF input file. Required for programming or verification
    of ALL memory types. The file format is AVR-8 bit ELF.

Use "-cUSB" when stk500.exe wants to talk to an AVRISPmkII over USB.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for your help, I'm back to this project after a while...

I figured out srec_cat, sort of. Its emitting some errors that can't be good:

srec_cat.exe: rp4n_app.hex: 4096: warning: multiple 0001FDF4 values (previous = 80, this one = 09)
srec_cat.exe: rp4n_app.hex: 4096: warning: multiple 0001FDF5 values (previous = E0, this one = F0)
srec_cat.exe: rp4n_app.hex: 4096: warning: multiple 0001FDF6 values (previous = E8, this one = 4E)
srec_cat.exe: rp4n_app.hex: 4096: warning: multiple 0001FDF7 values (previous = DF, this one = C0)

And so on...

Here is how I am invoking srec_cat:

srec_cat.exe -mult bldr.hex -intel app.hex -intel -offset 0xFE00 -O combined.hex -intel

The uC is an ATMega1284P, and the BOOTSZ fuse is set to 512W_FE00, which I think means a 1024 byte area reserved for the boot loader at 0000 and then a start vector that points to 0xFE00. So that's why I set the offset for the app.hex file to 0xFE00.

When I try to program this in using AS5, AS5 complains that it is too big to fit into flash. But, I can program the boot loader in fine, then upload my app fine.

I went through the options for srec_cat but can't seem to find anything that rings a bell... Can you help?

Thanks..

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why are you even using "-mult". As the srecord manual says:

Quote:
There is a new --multiple option to the commands, which permits an input file to contain multiple (contradictory) values for some memory locations. The last value in the file will be used.

So that looks like a "papering over the cracks" solution. More fundamentally I'd be looking at how come the .hex happens to have multiple values for those locations in the first place. This should never occur in a properly built .hex and I'm surprised you didn't get prior errors from the linker telling you that there were section overlaps?

Also I guess it doesn't matter but I'd always specify the bootloader.hex after the app.hex as it is the order they appear in memory - I know Srecord probably doesn't care but even so.

Also why are you using -offset. That adds an offset to the addresses in the second .hex file but it should already be based at the BLS address. Surely when you built it you used -Ttext=0xNNNN (or maybe --section-start=.text=0xNNNN) so you don't want to specify that based address offset a second time.

In fact a simple file joining should be as simple as:

E:\avr>type app.hex
:100000000C942A000C943F000C943F000C943F0089
:100010000C943F000C943F000C943F000C943F0064
:100020000C943F000C943F000C943F000C943F0054
:100030000C943F000C943F000C943F000C943F0044
:100040000C943F000C943F000C943F000C943F0034
:100050000C943F0011241FBECFE5D4E0DEBFCDBF1E
:1000600010E0A0E6B0E0EAE9F0E002C005900D92F1
:10007000A236B107D9F70E9441000C944B000C94B2
:100080000000E0916000F091610009950C94001E61
:0A00900080E090E00895F894FFCF9F
:02009A00003C28
:00000001FF

E:\avr>type boot.hex
:103C00000C942A1E0C94341E0C94341E0C94341EF6
:103C10000C94341E0C94341E0C94341E0C94341EDC
:103C20000C94341E0C94341E0C94341E0C94341ECC
:103C30000C94341E0C94341E0C94341E0C94341EBC
:103C40000C94341E0C94341E0C94341E0C94341EAC
:103C50000C94341E11241FBECFE5D4E0DEBFCDBFCF
:103C60000E94361E0C943C1E0C94001E8FEF87BBE6
:0C3C700088B3809588BBFCCFF894FFCF90
:0400000300003C00BD
:00000001FF

E:\avr>srec_cat app.hex -intel boot.hex -intel -o combined.hex -intel

E:\avr>type combined.hex
:020000040000FA
:200000000C942A000C943F000C943F000C943F000C943F000C943F000C943F000C943F00FD
:200020000C943F000C943F000C943F000C943F000C943F000C943F000C943F000C943F00C8
:200040000C943F000C943F000C943F000C943F000C943F0011241FBECFE5D4E0DEBFCDBFA2
:2000600010E0A0E6B0E0EAE9F0E002C005900D92A236B107D9F70E9441000C944B000C9413
:1C0080000000E0916000F091610009950C94001E80E090E00895F894FFCF003C52
:203C00000C942A1E0C94341E0C94341E0C94341E0C94341E0C94341E0C94341E0C94341E1E
:203C20000C94341E0C94341E0C94341E0C94341E0C94341E0C94341E0C94341E0C94341EF4
:203C40000C94341E0C94341E0C94341E0C94341E0C94341E11241FBECFE5D4E0DEBFCDBF07
:1C3C60000E94361E0C943C1E0C94001E8FEF87BB88B3809588BBFCCFF894FFCF22
:0400000500003C00BB
:00000001FF

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Clawson, thanks again. I am going to have to review my linker options to see if I used those options. I don't know if I did. I thought the offset switch was absolute, not relative so if ti is adding to an existing offset, then I see what you mean.

I don't know why I got the multiple value errors. After reading some more it seems this is related to linking. But the app works. Is it possible that I linked it wrong to cause these errors yet it would still run correctly?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Okay, so I checked my make file and yes, I am building the boot loader with the address specified. So i removed that from my srec_cat command, and still had one "contradictory value" error:

srec_cat.exe bldr.hex -intel app.hex -intel -O combined.hex -intel
srec_cat: rp4n_app.hex: 1: contradictory 00000000 value (previous = 05, this one = 0C)

Interesting that its at address 0. When I use the -mult option to treat those as warnings, I get only two of them, at address 0 and 1:

srec_cat.exe -mult bldr.hex -intel app.hex -intel -O combined.hex -intel
srec_cat: rp4n_app.hex: 1: warning: multiple 00000000 values (previous = 05, this one = 0C)
srec_cat: rp4n_app.hex: 1: warning: multiple 00000001 values (previous = 04, this one = 94)

A quick, but not complete, test shows that the boot loader appears to work, and the app appears to work after I program the combined.hex file in using the AVR ISP MKii programmer and AS5.

But I am concerned about these address conflicts. Is this a linker issue?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

But I am concerned about these address conflicts. Is this a linker issue?

You should be very concerned. The two .hex files should have no overlaps and -mult is a VERY dangerous option to use as it's just papering over the cracks. Maybe post the two .hex files you are trying to join - it sounds like the boot.hex one may have some records located at 0x0000.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I just looked up the intel hex for mat and yes, both HEX files do have a record at address 0000. I am guessing from your last post that the boot loader should not.

I attached both hex files and also the make file for the boot loader.

But why would the boot loader not have code at 0000? I was under the impression - probably wrongly - that the ARV would start to execute code at 0000, so wouldn't the boot loader have code that started there?

Thanks again...

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hm, it looks like the makefile didn't make it into that last post, so here it is... My target is abcd

# Makefile for ATmegaBOOT
# E.Lins, 18.7.2005
# $Id$
#
# Instructions
#
# To make bootloader .hex file:
# make diecimila
# make lilypad
# make ng
# etc...
#
# To burn bootloader .hex file:
# make diecimila_isp
# make lilypad_isp
# make ng_isp
# etc...

# program name should not be changed...
PROGRAM    = optiboot

# The default behavior is to build using tools that are in the users
# current path variables, but we can also build using an installed
# Arduino user IDE setup, or the Arduino source tree.
# Uncomment this next lines to build within the arduino environment,
# using the arduino-included avrgcc toolset (mac and pc)
# ENV ?= arduino
# ENV ?= arduinodev
# OS ?= macosx
# OS ?= windows


# enter the parameters for the avrdude isp tool
ISPTOOL	   = stk500v2
ISPPORT	   = usb
ISPSPEED   = -b 115200

MCU_TARGET = atmega168
LDSECTIONS  = -Wl,--section-start=.text=0x3e00 -Wl,--section-start=.version=0x3ffe

# Build environments
# Start of some ugly makefile-isms to allow optiboot to be built
# in several different environments.  See the README.TXT file for
# details.

# default
fixpath = $(1)

ifeq ($(ENV), arduino)
# For Arduino, we assume that we're connected to the optiboot directory
# included with the arduino distribution, which means that the full set
# of avr-tools are "right up there" in standard places.
TOOLROOT = ../../../tools
GCCROOT = $(TOOLROOT)/avr/bin/
AVRDUDE_CONF = -C$(TOOLROOT)/avr/etc/avrdude.conf

ifeq ($(OS), windows)
# On windows, SOME of the tool paths will need to have backslashes instead
# of forward slashes (because they use windows cmd.exe for execution instead
# of a unix/mingw shell?)  We also have to ensure that a consistent shell
# is used even if a unix shell is installed (ie as part of WINAVR)
fixpath = $(subst /,\,$1)
SHELL = cmd.exe
endif

else ifeq ($(ENV), arduinodev)
# Arduino IDE source code environment.  Use the unpacked compilers created
# by the build (you'll need to do "ant build" first.)
ifeq ($(OS), macosx)
TOOLROOT = ../../../../build/macosx/work/Arduino.app/Contents/Resources/Java/hardware/tools
endif
ifeq ($(OS), windows)
TOOLROOT = ../../../../build/windows/work/hardware/tools
endif

GCCROOT = $(TOOLROOT)/avr/bin/
AVRDUDE_CONF = -C$(TOOLROOT)/avr/etc/avrdude.conf

else
GCCROOT =
AVRDUDE_CONF =
endif
#
# End of build environment code.


# the efuse should really be 0xf8; since, however, only the lower
# three bits of that byte are used on the atmega168, avrdude gets
# confused if you specify 1's for the higher bits, see:
# http://tinker.it/now/2007/02/24/the-tale-of-avrdude-atmega168-and-extended-bits-fuses/
#
# similarly, the lock bits should be 0xff instead of 0x3f (to
# unlock the bootloader section) and 0xcf instead of 0x2f (to
# lock it), but since the high two bits of the lock byte are
# unused, avrdude would get confused.

ISPFUSES    = $(GCCROOT)avrdude $(AVRDUDE_CONF) -c $(ISPTOOL) \
              -p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \
              -e -u -U lock:w:0x3f:m -U efuse:w:0x$(EFUSE):m \
              -U hfuse:w:0x$(HFUSE):m -U lfuse:w:0x$(LFUSE):m
ISPFLASH    = $(GCCROOT)avrdude $(AVRDUDE_CONF) -c $(ISPTOOL) \
              -p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \
              -U flash:w:$(PROGRAM)_$(TARGET).hex -U lock:w:0x2f:m

STK500 = "C:\Program Files\Atmel\AVR Tools\STK500\Stk500.exe"
STK500-1 = $(STK500) -e -d$(MCU_TARGET) -pf -vf -if$(PROGRAM)_$(TARGET).hex \
-lFF -LFF -f$(HFUSE)$(LFUSE) -EF8 -ms -q -cUSB -I200kHz -s -wt
STK500-2 = $(STK500) -d$(MCU_TARGET) -ms -q -lCF -LCF -cUSB -I200kHz -s -wt

OBJ        = $(PROGRAM).o
OPTIMIZE = -Os -fno-inline-small-functions -fno-split-wide-types -mshort-calls

DEFS       = 
LIBS       =

CC         = $(GCCROOT)avr-gcc

# Override is only needed by avr-lib build system.

override CFLAGS        = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) -DF_CPU=$(AVR_FREQ) $(DEFS)
override LDFLAGS       = $(LDSECTIONS) -Wl,--relax -Wl,--gc-sections -nostartfiles -nostdlib

OBJCOPY        = $(GCCROOT)avr-objcopy
OBJDUMP        = $(call fixpath,$(GCCROOT)avr-objdump)

SIZE           = $(GCCROOT)avr-size

# Test platforms
# Virtual boot block test
virboot328: TARGET = atmega328
virboot328: MCU_TARGET = atmega328p
virboot328: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' '-DVIRTUAL_BOOT'
virboot328: AVR_FREQ = 16000000L
virboot328: LDSECTIONS  = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
virboot328: $(PROGRAM)_atmega328.hex
virboot328: $(PROGRAM)_atmega328.lst

# 20MHz clocked platforms
#
# These are capable of 230400 baud, or 115200 baud on PC (Arduino Avrdude issue)
#

pro20: TARGET = pro_20mhz
pro20: MCU_TARGET = atmega168
pro20: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200'
pro20: AVR_FREQ = 20000000L
pro20: $(PROGRAM)_pro_20mhz.hex
pro20: $(PROGRAM)_pro_20mhz.lst

pro20_isp: pro20
pro20_isp: TARGET = pro_20mhz
# 2.7V brownout
pro20_isp: HFUSE = DD
# Full swing xtal (20MHz) 258CK/14CK+4.1ms
pro20_isp: LFUSE = C6
# 512 byte boot
pro20_isp: EFUSE = 04
pro20_isp: isp

# 16MHz clocked platforms
#
# These are capable of 230400 baud, or 115200 baud on PC (Arduino Avrdude issue)
#

pro16: TARGET = pro_16MHz
pro16: MCU_TARGET = atmega168
pro16: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200'
pro16: AVR_FREQ = 16000000L
pro16: $(PROGRAM)_pro_16MHz.hex
pro16: $(PROGRAM)_pro_16MHz.lst

pro16_isp: pro16
pro16_isp: TARGET = pro_16MHz
# 2.7V brownout
pro16_isp: HFUSE = DD
# Full swing xtal (20MHz) 258CK/14CK+4.1ms
pro16_isp: LFUSE = C6
# 512 byte boot
pro16_isp: EFUSE = 04
pro16_isp: isp

# Diecimila, Duemilanove with m168, and NG use identical bootloaders
# Call it "atmega168" for generality and clarity, keep "diecimila" for
# backward compatibility of makefile
#
atmega168: TARGET = atmega168
atmega168: MCU_TARGET = atmega168
atmega168: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200'
atmega168: AVR_FREQ = 16000000L 
atmega168: $(PROGRAM)_atmega168.hex
atmega168: $(PROGRAM)_atmega168.lst

atmega168_isp: atmega168
atmega168_isp: TARGET = atmega168
# 2.7V brownout
atmega168_isp: HFUSE = DD
# Low power xtal (16MHz) 16KCK/14CK+65ms
atmega168_isp: LFUSE = FF
# 512 byte boot
atmega168_isp: EFUSE = 04
atmega168_isp: isp

diecimila: TARGET = diecimila
diecimila: MCU_TARGET = atmega168
diecimila: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200'
diecimila: AVR_FREQ = 16000000L 
diecimila: $(PROGRAM)_diecimila.hex
diecimila: $(PROGRAM)_diecimila.lst

diecimila_isp: diecimila
diecimila_isp: TARGET = diecimila
# 2.7V brownout
diecimila_isp: HFUSE = DD
# Low power xtal (16MHz) 16KCK/14CK+65ms
diecimila_isp: LFUSE = FF
# 512 byte boot
diecimila_isp: EFUSE = 04
diecimila_isp: isp

atmega328: TARGET = atmega328
atmega328: MCU_TARGET = atmega328p
atmega328: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200'
atmega328: AVR_FREQ = 16000000L
atmega328: LDSECTIONS  = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
atmega328: $(PROGRAM)_atmega328.hex
atmega328: $(PROGRAM)_atmega328.lst

atmega328_isp: atmega328
atmega328_isp: TARGET = atmega328
atmega328_isp: MCU_TARGET = atmega328p
# 512 byte boot, SPIEN
atmega328_isp: HFUSE = DE
# Low power xtal (16MHz) 16KCK/14CK+65ms
atmega328_isp: LFUSE = FF
# 2.7V brownout
atmega328_isp: EFUSE = 05
atmega328_isp: isp

atmega1284: TARGET = atmega1284p
atmega1284: MCU_TARGET = atmega1284p
atmega1284: CFLAGS += '-DLED_START_FLASHES=3' '-DLED_DATA_FLASH=3' '-DBAUD_RATE=115200' '-DBIGBOOT'
atmega1284: AVR_FREQ = 16000000L
atmega1284: LDSECTIONS  = -Wl,--section-start=.text=0x1fc00
atmega1284: $(PROGRAM)_atmega1284p.hex
atmega1284: $(PROGRAM)_atmega1284p.lst

# JWA Add support for ABCD
ABCD: TARGET = atmega1284p
ABCD: MCU_TARGET = atmega1284p
ABCD: CFLAGS += '-DABCD=1' '-DLED_START_FLASHES=3' '-DLED_DATA_FLASH=1' '-DBAUD_RATE=115200' '-DBIGBOOT'
ABCD: AVR_FREQ = 16000000L
ABCD: LDSECTIONS  = -Wl,--section-start=.text=0x1fc00
ABCD: ABCD_bldr.hex
ABCD: ABCD_bldr.lst


atmega1284_isp: atmega1284
atmega1284_isp: TARGET = atmega1284p
atmega1284_isp: MCU_TARGET = atmega1284p
# 1024 byte boot
atmega1284_isp: HFUSE = DE
# Low power xtal (16MHz) 16KCK/14CK+65ms
atmega1284_isp: LFUSE = FF
# 2.7V brownout
atmega1284_isp: EFUSE = FD
atmega1284_isp: isp

# Sanguino has a minimum boot size of 1024 bytes, so enable extra functions
#
sanguino: TARGET = atmega644p
sanguino: MCU_TARGET = atmega644p
sanguino: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' '-DBIGBOOT'
sanguino: AVR_FREQ = 16000000L
sanguino: LDSECTIONS  = -Wl,--section-start=.text=0xfc00
sanguino: $(PROGRAM)_atmega644p.hex
sanguino: $(PROGRAM)_atmega644p.lst

sanguino_isp: sanguino
sanguino_isp: TARGET = atmega644p
sanguino_isp: MCU_TARGET = atmega644p
# 1024 byte boot
sanguino_isp: HFUSE = DE
# Low power xtal (16MHz) 16KCK/14CK+65ms
sanguino_isp: LFUSE = FF
# 2.7V brownout
sanguino_isp: EFUSE = 05
sanguino_isp: isp

# Mega has a minimum boot size of 1024 bytes, so enable extra functions
#mega: TARGET = atmega1280
mega: MCU_TARGET = atmega1280
mega: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200' '-DBIGBOOT'
mega: AVR_FREQ = 16000000L
mega: LDSECTIONS  = -Wl,--section-start=.text=0x1fc00
mega: $(PROGRAM)_atmega1280.hex
mega: $(PROGRAM)_atmega1280.lst

mega_isp: mega
mega_isp: TARGET = atmega1280
mega_isp: MCU_TARGET = atmega1280
# 1024 byte boot
mega_isp: HFUSE = DE
# Low power xtal (16MHz) 16KCK/14CK+65ms
mega_isp: LFUSE = FF
# 2.7V brownout
mega_isp: EFUSE = 05
mega_isp: isp

# ATmega8
#
atmega8: TARGET = atmega8
atmega8: MCU_TARGET = atmega8
atmega8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200'
atmega8: AVR_FREQ = 16000000L 
atmega8: LDSECTIONS  = -Wl,--section-start=.text=0x1e00 -Wl,--section-start=.version=0x1ffe
atmega8: $(PROGRAM)_atmega8.hex
atmega8: $(PROGRAM)_atmega8.lst

atmega8_isp: atmega8
atmega8_isp: TARGET = atmega8
atmega8_isp: MCU_TARGET = atmega8
# SPIEN, CKOPT, Bootsize=512B
atmega8_isp: HFUSE = CC
# 2.7V brownout, Low power xtal (16MHz) 16KCK/14CK+65ms
atmega8_isp: LFUSE = BF
atmega8_isp: isp

# ATmega88
#
atmega88: TARGET = atmega88
atmega88: MCU_TARGET = atmega88
atmega88: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200'
atmega88: AVR_FREQ = 16000000L 
atmega88: LDSECTIONS  = -Wl,--section-start=.text=0x1e00 -Wl,--section-start=.version=0x1ffe
atmega88: $(PROGRAM)_atmega88.hex
atmega88: $(PROGRAM)_atmega88.lst

atmega88_isp: atmega88
atmega88_isp: TARGET = atmega88
atmega88_isp: MCU_TARGET = atmega88
# 2.7V brownout
atmega88_isp: HFUSE = DD
# Low power xtal (16MHz) 16KCK/14CK+65ms
atemga88_isp: LFUSE = FF
# 512 byte boot
atmega88_isp: EFUSE = 04
atmega88_isp: isp


# 8MHz clocked platforms
#
# These are capable of 115200 baud
#

lilypad: TARGET = lilypad
lilypad: MCU_TARGET = atmega168
lilypad: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200'
lilypad: AVR_FREQ = 8000000L
lilypad: $(PROGRAM)_lilypad.hex
lilypad: $(PROGRAM)_lilypad.lst

lilypad_isp: lilypad
lilypad_isp: TARGET = lilypad
# 2.7V brownout
lilypad_isp: HFUSE = DD
# Internal 8MHz osc (8MHz) Slow rising power
lilypad_isp: LFUSE = E2
# 512 byte boot
lilypad_isp: EFUSE = 04
lilypad_isp: isp

lilypad_resonator: TARGET = lilypad_resonator
lilypad_resonator: MCU_TARGET = atmega168
lilypad_resonator: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200'
lilypad_resonator: AVR_FREQ = 8000000L
lilypad_resonator: $(PROGRAM)_lilypad_resonator.hex
lilypad_resonator: $(PROGRAM)_lilypad_resonator.lst

lilypad_resonator_isp: lilypad_resonator
lilypad_resonator_isp: TARGET = lilypad_resonator
# 2.7V brownout
lilypad_resonator_isp: HFUSE = DD
# Full swing xtal (20MHz) 258CK/14CK+4.1ms
lilypad_resonator_isp: LFUSE = C6
# 512 byte boot
lilypad_resonator_isp: EFUSE = 04
lilypad_resonator_isp: isp

pro8: TARGET = pro_8MHz
pro8: MCU_TARGET = atmega168
pro8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200'
pro8: AVR_FREQ = 8000000L
pro8: $(PROGRAM)_pro_8MHz.hex
pro8: $(PROGRAM)_pro_8MHz.lst

pro8_isp: pro8
pro8_isp: TARGET = pro_8MHz
# 2.7V brownout
pro8_isp: HFUSE = DD
# Full swing xtal (20MHz) 258CK/14CK+4.1ms
pro8_isp: LFUSE = C6
# 512 byte boot
pro8_isp: EFUSE = 04
pro8_isp: isp

atmega328_pro8: TARGET = atmega328_pro_8MHz
atmega328_pro8: MCU_TARGET = atmega328p
atmega328_pro8: CFLAGS += '-DLED_START_FLASHES=3' '-DBAUD_RATE=115200'
atmega328_pro8: AVR_FREQ = 8000000L
atmega328_pro8: LDSECTIONS = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
atmega328_pro8: $(PROGRAM)_atmega328_pro_8MHz.hex
atmega328_pro8: $(PROGRAM)_atmega328_pro_8MHz.lst

atmega328_pro8_isp: atmega328_pro8
atmega328_pro8_isp: TARGET = atmega328_pro_8MHz
atmega328_pro8_isp: MCU_TARGET = atmega328p
# 512 byte boot, SPIEN
atmega328_pro8_isp: HFUSE = DE
# Low power xtal (16MHz) 16KCK/14CK+65ms
atmega328_pro8_isp: LFUSE = FF
# 2.7V brownout
atmega328_pro8_isp: EFUSE = 05
atmega328_pro8_isp: isp

# 1MHz clocked platforms
#
# These are capable of 9600 baud
#

luminet: TARGET = luminet
luminet: MCU_TARGET = attiny84
luminet: CFLAGS += '-DLED_START_FLASHES=3' '-DSOFT_UART' '-DBAUD_RATE=9600'
luminet: CFLAGS += '-DVIRTUAL_BOOT_PARTITION'
luminet: AVR_FREQ = 1000000L
luminet: LDSECTIONS = -Wl,--section-start=.text=0x1d00 -Wl,--section-start=.version=0x1efe
luminet: $(PROGRAM)_luminet.hex
luminet: $(PROGRAM)_luminet.lst

luminet_isp: luminet
luminet_isp: TARGET = luminet
luminet_isp: MCU_TARGET = attiny84
# Brownout disabled
luminet_isp: HFUSE = DF
# 1MHz internal oscillator, slowly rising power
luminet_isp: LFUSE = 62
# Self-programming enable
luminet_isp: EFUSE = FE
luminet_isp: isp

#
# Generic build instructions
#
#

isp: $(TARGET)
	$(ISPFUSES)
	$(ISPFLASH)

isp-stk500: $(PROGRAM)_$(TARGET).hex
	$(STK500-1)
	$(STK500-2)

%.elf: $(OBJ)
	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
	$(SIZE) $@

clean:
	rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex

%.lst: %.elf
	$(OBJDUMP) -h -S $< > $@

%.hex: %.elf
	$(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O ihex $< $@

%.srec: %.elf
	$(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O srec $< $@

%.bin: %.elf
	$(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O binary $< $@
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I read an Atmel app note, and I did misunderstand. Apparently, the boot loader lives at the top of the flash memory, and the boot reset vector fuse causes the uC to execute code at the address selected in boot size fuse, in my case, FE00.

My boot loader HEX file has 4 records at address 0, two at the top and two at the bottom.

The second one is an "extended segment address record" for which the address is always 0000. It appears that this is caused by this in the linker:

atmega1284: LDSECTIONS = -Wl,--section-start=.text=0x1fc00

Since the addresses of the rest of the hex file all start with FC00 and the extended segment is 1000, so the addresses are all converted to 1FCxx.

The second to last is a linear address type record, which contains the start address of the application:

1000FC00

I'm not sure why its 1000 FC00, but the address field is always 0000 for this record type.

The very last one is an end of file record.

The first one is a data record with the data being 05 and 04. This one seems to be the problem, because the entire complaint from srec_cat is:

srec_cat: blink.hex: 1: warning: multiple 00000000 values (previous = 05, this one = 0C)
srec_cat: blink.hex: 1: warning: multiple 00000001 values (previous = 04, this one = 94)

So I have to figure out why the boot loader starts with a 2 byte data record. It seems that if I can solve that, I can solve the conflict.

Am I on the right track?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I got this fixed now. Turns out the two bytes of data were the version number. Modifying the linker instructions put it at the top of the flash instead of the bottom.

Thanks Cliff!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

The second one is an "extended segment address record" for which the address is always 0000. It appears that this is caused by this in the linker:

The other one is how a .hex file with a 16bit (0..64K) address field can be used to program beyond 64K. the Extended address record itself does not actually output any data just says "from here on add "this" to the address records"

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Quote:

The second one is an "extended segment address record" for which the address is always 0000. It appears that this is caused by this in the linker:

The other one is how a .hex file with a 16bit (0..64K) address field can be used to program beyond 64K. the Extended address record itself does not actually output any data just says "from here on add "this" to the address records"

Thanks again Cliff, this was all very educational. Somehow, I'm not getting notices of replies from this board, otherwise I would have replied sooner :-(