Merging two .elf files into a single .hex file

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

I am using avr-gcc version 4.8.2 with avr-libc from the command line in Arch Linux.

I would like my firmware to contain a self-update capability.

This means that I need to write a self-contained program that is put in the bootloader section (byte address 0x7800- for an Atmega328.)

I can write the bootloader program just fine; it's small, self-contained, runs with interrupts disabled; etc.

If I mark all the bootloader program functions (all four of them) with BOOTLOADER_SECTION, and link with the .bootloader section mapped to 0x7800, my executable code symbols do in fact get put in the right place, but the libc seems to insist to include interrupt vectors and data for short string symbols starting at address 0x0000. This is not what I want!

Here's my link command:

avr-gcc -o bld/boot.elf bld/boot.o -Wl,--gc-sections -Wl,--section-start=.bootloader=0x7800 -mmcu=atmega328

There are two things I'd like to know here:

1) How should I build/link my bootloader-section program such that jumping to address 0x7800 (or 0x3C00 in page terms) will just "do the right thing," by virtue of the linker putting the right functions and their explicit dependencies in the bootloader section, yet the linker excluding interrupt vectors?

2) How should I combine the two .elf files (for my main program, and the bootloader) to one .hex file that I can write using a single avrdude command?

Note that just linking the bootloader and the main program together gives me a duplicate-symbols error on main, and it still puts the string constants in program-global data, not the bootloader section.

Here's the "nm" output of what I have:

[jwatte@robot1 Fire]$ nm bld/boot.elf 
000078a2 T _Z10write_pagetPKh
0000788a T _Z13bootload_readv
0000784c T _Z14bootload_writePKch
00007800 t _Z14bootload_writePKch.part.0
0000783e T _Z17bootload_readmodev
0000003e a __SP_H__
0000003d a __SP_L__
0000003f a __SREG__
00000092 T __bad_interrupt
00000068 T __ctors_end
00000068 T __ctors_start
00800118 D __data_end
000000e8 A __data_load_end
000000d0 A __data_load_start
00800100 D __data_start
00000074 T __do_copy_data
00000068 T __dtors_end
00000068 T __dtors_start
00810000 T __eeprom_end
00000096 T __epilogue_restores__
00000000 W __heap_end
00000068 W __init
000008ff W __stack
000000ce t __stop_program
00000000 a __tmp_reg__
00000068 T __trampolines_end
00000068 T __trampolines_start
00000092 W __vector_1
00000092 W __vector_10
00000092 W __vector_11
00000092 W __vector_12
00000092 W __vector_13
00000092 W __vector_14
00000092 W __vector_15
00000092 W __vector_16
00000092 W __vector_17
00000092 W __vector_18
00000092 W __vector_19
00000092 W __vector_2
00000092 W __vector_20
00000092 W __vector_21
00000092 W __vector_22
00000092 W __vector_23
00000092 W __vector_24
00000092 W __vector_25
00000092 W __vector_3
00000092 W __vector_4
00000092 W __vector_5
00000092 W __vector_6
00000092 W __vector_7
00000092 W __vector_8
00000092 W __vector_9
00000000 W __vector_default
00000000 T __vectors
00000001 a __zero_reg__
00800118 D _edata
00800118 T _end
000000d0 T _etext
000000cc T _exit
000000cc W exit
00007924 T main
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I answered question 1 myself by reading the bootloader FAQ PDF document found through some more Googling.
The answer is that the ".bootloader" section name is dumb; instead just build a regular .elf with the .text section re-mapped to address 0x7800 or wherever your bootloader starts.

The question, then, is how to get two .elf files, relocated at different positions, into a single .hex file, using avr-objcopy. The PDF recommends srec_cat, which I presume would work if I wanted to get and install it for my current system, but it seems like the objcopy tool ought to be able to do the same thing?

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

jwatte wrote:
The question, then, is how to get two .elf files, relocated at different positions, into a single .hex file, using avr-objcopy. The PDF recommends srec_cat, which I presume would work if I wanted to get and install it for my current system, but it seems like the objcopy tool ought to be able to do the same thing?
objcopy seems to be designed to manipulate things with symbol tables.
Once one has a file without a symbol table one should be pretty much done with manipulations.
That said, objcopy has some ability to handle binary inputs.
objcopy --gap-fill 0xff --add-section .one=one.bin --change-section-lma .one=0 --add-section .two=two.bin --change-section-lma .two=0xwhatever  empty.elf  tmp.elf
objcopy -O ihex tmp.elf  fred.hex

Even if I got both lines right, srec_cat would seem a lot easier to do and to understand.

Iluvatar is the better part of Valar.

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

Quote:

Even if I got both lines right, srec_cat would seem a lot easier to do and to understand.

+1

So just avr-objcopy as usual to extract .text (+.data) from each .elf to app.hex and boot.hex then use srec_cat to join these into a single combined.hex

When using srec_cat you can have it do other useful stuff such as padding the app section then running a CRC over it and finally embedding the result into the output .hex at a known location. You can then add CRC checking to your bootloader that it can use to verify the integrity of the app image using that CRC.

I do that here:

https://spaces.atmel.com/gf/proj...

when CRC_FLASH is #defined in the config header. What may be of interest in that is that my source contains the decode side of the CRC that matches the CRC algorithm srec_cat uses to embed when --l-e-crc16 is used.

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

If you combine two elf files into a hex file, don't you (potentially) loose information?

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

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

Yes,

A .hex file effectively holds one data section while an ELF can hold multiple data sections.

When you objcopy an ELF to a HEX you generally ask for two of the ELF sections (.text and .data) to be combined to form the single section in the HEX. If you have defined your own sections (.mydata, .boot, whatever) that must also reside in flash you would add further -j's to the objcopy command to collect them all together in the HEX.

If you want you can run a second (or even multiple) objcopy commands and also ask for .eeprom (say) to be extracted from the ELF and written to a different Intel Hex file (.eep for argument's sake).

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

Is there a reason they are needed in the same hex file?
Why not just use ISP twice?
Better yet, ISP the bootloader and bootload the main application.

Iluvatar is the better part of Valar.

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

Quote:

Why not just use ISP twice?

ISP does a Chip Erase so you cannot do this. The only way to "part program" an AVR is to use SPM from the bootloader. So everyone who writes boot.hex and app.hex needs some way to combine them into a single "blob" that can be ISP'd in one go. This issue is as old as the hills.
Quote:

Better yet, ISP the bootloader and bootload the main application.

I often wonder if that might not be the better solution but you can see that when boards are being factory/assembled and programmed it would be a right pain to ISP the bootloader first then connect up some other mechanism and deliver a second, different file to deliver app.hex. Folks just want a one shot does it all solution for (a) speed and (b) avoidance of cock-ups.

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

Quote:

Quote:

Why not just use ISP twice?

ISP does a Chip Erase so you cannot do this.


Well, if you do the full, "normal" ISP sequence--then I suppose I have to agree.

But in this context, there is no reason why the "normal" (example below--there can be variations) sequence:
-- Check signature
-- Erase
-- Program flash
-- Verify flash
-- Program EEPROM
-- Verify EEPORM
-- Set fuse bits
-- Verify fuse bits
-- Set lock bits

cannot be done step-by-step

-- Check signature
-- Erase
-- Program flash A
-- Verify flash A
-- Program flash B
-- Verify flash B
-- Program EEPROM A
-- Verify EEPROM A
-- Program EEPROM B
-- Verify EEPROM B
-- Set fuse bits
-- Verify fuse bits
-- Set lock bits

Depending on the particular toolchain used, this might be harder or easier.

BTW, I have production apps that do
...
-- Program EEPROM A
-- Verify EEPROM A
-- Program EEPROM B
-- Verify EEPROM B
...

where EEPROM B is unique serial/ID/address information. This goes into an "erased" (or programmed to 0xff by EEPROM A) memory area.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

What tool allows:

Quote:
-- Program flash B

leaving the result of:
Quote:
-- Program flash A

intact?

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

clawson wrote:
What tool allows:
Quote:
-- Program flash B

leaving the result of:
Quote:
-- Program flash A

intact?

My knee-jerk response is "any"? I know that the CodeVision tools will. My "EEPROM B" work was done with STK500.EXE and a batch file (e.g. DOS .BAT).

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Quote:

I know that the CodeVision tools will.

Where is a picture of that crow I need to eat?

CV 3.x indeed did an erase when I did a little test. I think the last time I did it with CV tools was 1.x. I'd need to dig further. (There are tools, including integrated features in CV, to combine bootloader+application so I don't want to spend a lot of time on it. I did enough of that with the EEPROM "ID" stuff some years ago.)

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

clawson wrote:
What tool allows:
Quote:
-- Program flash B

leaving the result of:
Quote:
-- Program flash A

intact?
avrdude -D .

Iluvatar is the better part of Valar.