How can I get a bootloader embedded into the HEX/ELF of the main application?

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

Hi Everyone,

 

Using a atmega384c3 with a bootloader at 0x60000.  How can I modify the main project so that it compiles the bootloader in at this address automatically and outputs both HEX/ELF correctly?

 

Thanks,

 

Alan

 

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

I think that is impossible to do, or at least too impractical. The bootloader and application are separate images by design, and the compiler is designed to create a single image.

 

I suspect there is a "hidden requirement" behind the question, what are you actually hoping to achieve? IOW, what is the problem with having a separate HEX file for bootloader and application?

Bob. Engineer and trainee Rocket Scientist.

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

It's not at all impossible - I do this myself. The utility you need is srec_cat which is available in the ever-useful WinAVR-20100110 distribution.

 

I perform this in my Makefile using this recipe:

 

%bl.hex : $(TARGET).hex
    @echo
    srec_cat $(TARGET).hex -intel cipherboot002.hex -intel -o $(TARGET)-bl.hex -intel

Where cipherboot002.hex has been previously built as a separate project.

 

I don't use Atmel Studio but In MS Build (the underlying build system) I'm sure there is a "Post Build" area where this sort of thing can be done.

 

It's an advanced concept but you could put your bootloader project and the application project into the same solution and make one dependent on the other so that both are built together,

 

@dontdespisethesnake

There's nothing sinister going on here. I want a single hex file containing both application code + bootloader for production programming.

 

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

That srec_cat command is just joining two .hex files. All it effectively does is copy the two contents together and remove the :00000001FF in the middle.

 

You cannot produce a combined ELF this easily.

 

To do that you set up a solution to build the two separate programs. For the bootloader one have it use objcopy to extract the load image as a .bin. Perhaps the easiest way to combine this into the app.elf is to then convert that .bin to a C array (.xxd) and assign it to a section (something like __attribute__((section(".bootimage"))) applied to the array), then in the link command apply a -section-start to that array data to position it at the 0x60000 address.

 

Another technique is to output the bootimage.bin but then use objcopy to convert that back to a binary loadable image in ELF format and link with it, once again giving a -section-start to position the base.

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

clawson wrote:
You cannot produce a combined ELF this easily.

Bugger I missed that requirement.

 

@OP

Can we assume it's a valid requirement ?

 

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

N.Winterbottom wrote:

It's not at all impossible - I do this myself. The utility you need is srec_cat which is available in the ever-useful WinAVR-20100110 distribution.

 

Sure, combining SREC or HEX is quite easy, I also do it with our bootloader + applications for production programming. I suspect that is what the OP wants, but it is quite different to what he/she asked! Hence request for clarification.

 

 

 

Bob. Engineer and trainee Rocket Scientist.

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

N.Winterbottom wrote:

Bugger I missed that requirement.

@OP

Can we assume it's a valid requirement ?

 

Yes, I really need both ELF/HEX if possible.

 

Clawson - does your technique involve converting the bootloader to a uint8_t PROGMEM array and then putting it in a section that is assigned 0x60000 for the address?  I think I already have a tool I made to convert it from a flat file to that.  Does srec_cat have the ability to convert it from hex to flat/bin?

 

Thanks,

 

Alan

 

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

alank2 wrote:
Clawson - does your technique involve converting the bootloader to a uint8_t PROGMEM array and then putting it in a section that is assigned 0x60000 for the address?
yes that.
alank2 wrote:
Does srec_cat have the ability to convert it from hex to flat/bin?
Why would you need srec_cat for that. You have two obvious ways. At the moment when you build the way a .hex comes from the .elf is in an avr-objcopy that reads the .elf then uses "-O ihex" to write out in Intel Hex. Either simply change that "-O ihex"to be "-O binary" (and perhaps change the extension on the extracted file from .hex to .bin to avoid confusion?) and you will go straight to binary. Alternatively, if you want the .hex file as well, then allow it to be created as normal but then add an additional command that does:

avr-objcopy -I ihex -O binary boot.hex boot.bin

which will do a hex to bin conversion. For example:

$ avr-objcopy -I ihex -O binary avr.hex avr.bin
$ cat avr.hex
:100000000C942A000C9447000C9447000C94470071
:100010000C9447000C9447000C9447000C94470044
:100020000C9447000C9447000C9447000C94470034
:100030000C9447000C9447000C9447000C94470024
:100040000C9447000C9447000C9447000C94470014
:100050000C94470011241FBECFE5D4E0DEBFCDBF16
:1000600010E0A0E6B0E0ECEBF0E002C005900D92ED
:10007000A236B107D9F710E0A2E6B0E001C01D92A8
:10008000AA36B107E1F70E9449000C945C000C9479
:1000900000008091660090916700A0916800B09187
:1000A00069008F3E2EEB92072DEAA2072EEDB207D4
:0C00B00011F485E588BB0895F894FFCF9B
:0200BC004230D0
:00000001FF
$ hexdump -C avr.bin
00000000  0c 94 2a 00 0c 94 47 00  0c 94 47 00 0c 94 47 00  |..*...G...G...G.|
00000010  0c 94 47 00 0c 94 47 00  0c 94 47 00 0c 94 47 00  |..G...G...G...G.|
*
00000050  0c 94 47 00 11 24 1f be  cf e5 d4 e0 de bf cd bf  |..G..$..........|
00000060  10 e0 a0 e6 b0 e0 ec eb  f0 e0 02 c0 05 90 0d 92  |................|
00000070  a2 36 b1 07 d9 f7 10 e0  a2 e6 b0 e0 01 c0 1d 92  |.6..............|
00000080  aa 36 b1 07 e1 f7 0e 94  49 00 0c 94 5c 00 0c 94  |.6......I...\...|
00000090  00 00 80 91 66 00 90 91  67 00 a0 91 68 00 b0 91  |....f...g...h...|
000000a0  69 00 8f 3e 2e eb 92 07  2d ea a2 07 2e ed b2 07  |i..>....-.......|
000000b0  11 f4 85 e5 88 bb 08 95  f8 94 ff cf 42 30        |............B0|
000000be

(hopefully you can see that is the same binary data in two forms).

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

Excellent; thanks for the help everyone!  I'll give it a try.

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

Alan, (alank)

Would you believe it ! - I now find myself needing to debug the handover from Application to Bootloader and I would like to know how  you eventually solved this.

 

 

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

Do you want to try and do that symbolically so you retain DWARF2 in both boot.elf and app.elf or are you happy for one of them to just exist as a "binary payload" built into the other?

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

Hi N. Winterbottom!  In my case I don't need any debugging info.  I'm going to compile the bootloader and convert it to a binary file and then a C PROGMEM structure and put it in a section that moves it to the correct location for the bootloader.  I haven't done this yet, but I am hopeful it will work.  I should be doing this in a week or two so I'll post how it goes.

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

Thanks for the replies -

Debugging info would be great but I'd be happy to work in assembly for the bootloader. It's only 752 bytes when compiled with full rambo size optimisation. I grew up using assembly so I can debug it no problem working alongside the LSS file.

 

Over the past few hours I've implemented Cliffs suggestion to dump the bootloader binary into a const array of uint8_t and get avr-ld to load it at 0x3c00.

 

Thanks Cliff for the three letter clue xxd. I started off with od and using rectangular column mode in Eclipse to insert commas etc. but xxd is brilliant, it has an option (-i) to output in C include file style.

nigel@COMARK-NIGEL:~/Project/P250W/FW_Bt$ xxd -i P250Boot-1.0.bin 
unsigned char P250Boot_1_0_bin[] = {
  0x08, 0xc0, 0x12, 0xc0, 0x41, 0x54, 0x2b, 0x52, 0x55, 0x4e, 0x20, 0x22,
  0x68, 0x74, 0x73, 0x22, 0x0d, 0x00, 0x8f, 0xef, 0x94, 0xe0, 0x9e, 0xbf,
  ... Snipped ...
  0x06, 0xc0, 0xf0, 0x9b, 0x6b, 0xcf, 0xff, 0xcf, 0x85, 0xe1, 0xaa, 0xde,
  0xfa, 0xcf, 0x86, 0xe0, 0xa7, 0xde, 0xf7, 0xcf
};
unsigned int P250Boot_1_0_bin_len = 752;

 

This becomes bootimage.c: The used attribute is necessary to prevent full rambo size optimisation removing the whole section.

const unsigned char  __attribute__((used, section(".bootimage"))) P250Boot_1_0_bin[] = {
    0x08, 0xc0, 0x12, 0xc0, 0x41, 0x54, 0x2b, 0x52, 0x55, 0x4e, 0x20, 0x22,
    0x68, 0x74, 0x73, 0x22, 0x0d, 0x00, 0x8f, 0xef, 0x94, 0xe0, 0x9e, 0xbf,
    ... Snipped ...
    0xf0, 0x9a, 0x0b, 0xc0, 0x19, 0x34, 0x31, 0xf4, 0x80, 0xe1, 0xb0, 0xde,
    0x06, 0xc0, 0xf0, 0x9b, 0x6b, 0xcf, 0xff, 0xcf, 0x85, 0xe1, 0xaa, 0xde,
    0xfa, 0xcf, 0x86, 0xe0, 0xa7, 0xde, 0xf7, 0xcf
};

 

Linking is done by adding this to my Makefile:

LDFLAGS += -Wl,--section-start=.bootimage=0x3c00

 

Oh --- In case you wondered: I found my bootloader bug - I was doing some "cold-start" initialisation of my Bluetooth module even though I was coming from a "warn-start" with it already connected.

 

 

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

N.Winterbottom wrote:
but xxd is brilliant, it has an option (-i) to output in C include file style
Yup, that's the one I always use (in fact I think that's the only option I've ever used).