stephenbates1971
stephenbates1971

Reputation: 13

How to embed a bin file in a C program

I am trying to embed a .bin file at a specific flash memory address in a C program (I am using the IAR IDE). I have found a guide that gives some help on how to do this using .incbin in C code (http://elm-chan.org/junk/32bit/binclude.html) and also an example on Git Hub (https://github.com/kuopinghsu/incbin) however they a bit sparse on explanation and I would really like a step by step guide as I am new to this.

I have done a thorough google search but I can't find anything that does this. I would be very grateful if someone could either point me in the direction of a guide that I've missed or post a short summary.

Upvotes: 1

Views: 3437

Answers (2)

Clifford
Clifford

Reputation: 93446

The simple and toolchain-independent method is to generate a C code (or assembly) array from the binary data, then compile and link that to your code in the normal manner.

Writing your own tool to do that is trivial, but there are tools already that will do it for you. For example the SRecord tool suite includes this capability:

 srec_cat mybinary.bin -binary -o mybinary.c -C-Array mybinary -INClude

will generate two files containing code of the form (elided example - your output will differ):

mybinary.c

/* http://srecord.sourceforge.net/ */
const unsigned char mybinary[] =
{
0xC0, 0x91, 0x00, 0x20, 0xA5, 0x01, 0x00, 0x08, 0xB1, 0x11, 0x00, 0x08,
...
0x31, 0x31, 0x30, 0x31, 0x30, 0x30, 0x2E, 0x30, 0x31, 0x2E, 0x30, 0x35,
0x2E, 0x30, 0x30, 0x00,
};
const unsigned long mybinary_termination = 0x00000185;
const unsigned long mybinary_start       = 0x00000000;
const unsigned long mybinary_finish      = 0x00004000;
const unsigned long mybinary_length      = 0x00004000;

#define MYBINARY_TERMINATION 0x00000185
#define MYBINARY_START       0x00000000
#define MYBINARY_FINISH      0x00004000
#define MYBINARY_LENGTH      0x00004000

mybinary.h

#ifndef SRC_MYBINARY_H
#define SRC_MYBINARY_H

extern const unsigned long mybinary_termination;
extern const unsigned long mybinary_start;
extern const unsigned long mybinary_finish;
extern const unsigned long mybinary_length;
extern const unsigned char mybinary[];

#endif /* SRC_MYBINARY_H*/

The SRecord tools are complex and arcane but very powerful and can be used for all sorts of binary and object file conversion and manipulation. If you'd prefer something simpler that does just this one job then "binary to C code" is a suitable search term. Examples I have specifically used in the past:

They both generate code broadly similar to the above.

If you need to locate the binary at a specific location you will need to modify the generated code with your toolchain specific method. For example for IAR:

#pragma location=0x8020000 
const unsigned char mybinary[] =
{...} ;

or

const unsigned char mybinary[] @ 0x8020000 =
{...} ;

Similarly you can locate the data in a user defined linker section - allowing the linker to determine where:

const unsigned char mybinary[] @ "BIN_SECTION" =
{...} ;

The syntax differs between across toolchains. I have not tried it but the SRecord -C-Array filter has −POSTfix string and −PREfix string modifiers which can be used to add toolchain specific extensions in the generation (which is convenient if the binary will be modified frequently). However the IAR syntax is not well defined and all the examples are of the form:

<type> <symbol> @<location> = <initialiser> ;

so is "infix" not prefix or postfix. It may be that:

<type> <symbol> = <initialiser> @<location> ;

is valid, but the manual does not formally specify the syntax as far as I can tell, and I do not have the tool to test. If that does work then:

 srec_cat mybinary.bin -binary -o mybinary.c -C-Array mybinary -INClude -POSTfix "@ 0x8020000"
const unsigned char mybinary[] =
{...} @ 0x8020000 ;

For linker-section location:

-POSTfix `@ "BIN_SECTION"`

If this syntax does not work you could write your own tool to modify the generated code and run both as a custom build step to automate, or use a text processing tool such as sed to insert the location information. e.g.:

sed 's/mybinary\[\] =/mybinary\[\] @ 0x8020000 =/' mybinary.c

to replace char mybinary[] = with char mybinary[] @ 0x8020000 = in mybinary.c

Generally unless the data is to be accessed by some independently linked code code, or will be patched/updated independently of the code, it is unnecessary to locate the data at a specific location and you should let the linker locate it for portability between toolchains and runtime environments.

Upvotes: 2

Johan
Johan

Reputation: 3871

If you go to input tab in the linker options dialog (Project>Options>Linker>Input) you can add raw image input files. For each file you can specify a start symbol (to refer to in your C-code), an elf section name (to refer to in your linker configuration) and any alignment requirements. To ensure the the image is included in the final application even if your C-code doesn't refer to it by name you need to add the start symbol in the keep box as well. An example is shown below. Linker configuration dialog

To place image at a specific location in your flash you need to edit your linker configuration file to place the content of the section (.mybin in my example) at the required address. For instance, if you want to place it at address 0x9000 you add the following line to your .icf-file.

place at address mem:0x9000 { ro section .mybin };

Upvotes: 1

Related Questions