Home > database >  How to embed a bin file in a C program
How to embed a bin file in a C program

Time:12-11

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 (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 };

CodePudding user response:

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_BOOTLOADER_H
#define SRC_BOOTLOADER_H

extern const unsigned long bin_bootloader_termination;
extern const unsigned long bin_bootloader_start;
extern const unsigned long bin_bootloader_finish;
extern const unsigned long bin_bootloader_length;
extern const unsigned char bin_bootloader[];

#endif /* SRC_BOOTLOADER_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 as a specific location and you should let the linker locate it for portability between toolchains and runtime environments.

  • Related