1

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.

  • 1
    [This question](https://stackoverflow.com/q/410980/9952196) will be helpful (Aimed at text files, but many of the approaches can be adapted or even used unchanged). – Shawn Dec 09 '21 at 09:05
  • I'd use `.incbin` in an asm source file (after a label like `thefile:` so C can declare it as `extern char thefile[]`) and link that with compiler-generated `.o` files. – Peter Cordes Dec 09 '21 at 09:57

2 Answers2

1

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 };
Johan
  • 3,667
  • 6
  • 20
  • 25
  • Thank you so much Johan, I will give this a try. – stephenbates1971 Dec 09 '21 at 11:32
  • Hi Johan, I've followed your advice, I'm using a STM32407 board and I am attempting to flash to Sector 5 (0x802 0000 to 0x0802 FFFF). After building the project is now 30 KB and it was 15 KB before the include however when I look at memory location 0x0802 0000 using the STM32 ST-LINK utility it is blank (i.e. all Fs). What am I doing wrong? I have added this place at address mem:0x08020000 { readwrite section .mybin }; to the stm32f407xx_flash.icf file. The Linker options are as you specify except for the target folder in File: Do you know where I am going wrong? – stephenbates1971 Dec 09 '21 at 15:44
  • 1
    @stephenbates1971 Since it is in flash I think you need to specify `readonly` instead of `readwrite` – Johan Dec 10 '21 at 08:40
1

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.

Clifford
  • 88,407
  • 13
  • 85
  • 165
  • Thank you so much Clifford for a very complete and informative answer. – stephenbates1971 Dec 13 '21 at 13:54
  • @stephenbates1971 You are welcome. Note that I have since corrected generated srec header file - it was copy and pasted from an existing application and I did not change the symbol name to serve as an example. – Clifford Dec 14 '21 at 09:15