【问题标题】:How to embed a bin file in a C program如何在 C 程序中嵌入 bin 文件
【发布时间】:2022-01-14 02:47:09
【问题描述】:

我正在尝试在 C 程序中的特定闪存地址处嵌入一个 .bin 文件(我正在使用 IAR IDE)。我找到了一个指南,它为如何在 C 代码 (http://elm-chan.org/junk/32bit/binclude.html) 中使用 .incbin 以及 Git Hub (https://github.com/kuopinghsu/incbin) 上的示例提供了一些帮助,但是它们的解释有点稀疏,我真的想要一个分步指南,因为我是新手。

我已经完成了彻底的谷歌搜索,但我找不到任何这样做的东西。 如果有人能指出我错过的指南的方向或发布简短摘要,我将不胜感激。

【问题讨论】:

  • This question 会有所帮助(针对文本文件,但许多方法可以调整甚至不加改变地使用)。
  • 我会在 asm 源文件中使用 .incbin(在 thefile: 这样的标签之后,以便 C 可以将其声明为 extern char thefile[])并将其与编译器生成的 .o 文件链接。

标签: c assembly embedded bin iar


【解决方案1】:

如果您进入链接器选项对话框(项目>选项>链接器>输入)中的输入选项卡,您可以添加原始图像输入文件。对于每个文件,您可以指定一个开始符号(在您的 C 代码中引用)、一个 elf 部分名称(在您的链接器配置中引用)和任何对齐要求。为了确保图像包含在最终应用程序中,即使您的 C 代码没有按名称引用它,您还需要在保留框中添加开始符号。一个例子如下所示。

要将图像放置在闪存中的特定位置,您需要编辑链接器配置文件以将部分的内容(在我的示例中为.mybin)放置在所需的地址。例如,如果您想将其放在地址 0x9000 中,则将以下行添加到您的 .icf 文件中。

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

【讨论】:

  • 非常感谢 Johan,我会试试看的。
  • 嗨,Johan,我听从了您的建议,我正在使用 STM32407 开发板,我正在尝试闪存到扇区 5(0x802 0000 到 0x0802 FFFF)。构建项目后现在是 30 KB,包含之前是 15 KB,但是当我使用 STM32 ST-LINK 实用程序查看内存位置 0x0802 0000 时,它是空白的(即所有 Fs)。我究竟做错了什么?我在地址 mem:0x08020000 { readwrite section .mybin } 处添加了这个地方;到 stm32f407xx_flash.icf 文件。链接器选项与您指定的一样,但文件中的目标文件夹除外:您知道我哪里出错了吗?
  • @stephenbates1971 因为它在闪存中,我认为您需要指定readonly 而不是readwrite
【解决方案2】:

简单且独立于工具链的方法是从二进制数据生成一个 C 代码(或程序集)数组,然后以正常方式编译并链接到您的代码。

编写自己的工具来做这件事是微不足道的,但已经有工具可以为你做这件事。例如,SRecord 工具套件包含此功能:

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

将生成两个包含格式代码的文件(省略的示例 - 您的输出会有所不同):

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*/

SRecord 工具复杂而神秘,但非常强大,可用于各种二进制文件和目标文件的转换和操作。如果您更喜欢只做这一项工作的更简单的东西,那么 "binary to C code" 是一个合适的搜索词。我过去专门用过的例子:

它们都生成与上述大致相似的代码。

如果您需要在特定位置定位二进制文​​件,则需要使用工具链特定方法修改生成的代码。以 IAR 为例:

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

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

同样,您可以在用户定义的链接器部分中定位数据 - 允许链接器确定位置:

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

跨工具链的语法不同。我还没有尝试过,但是 SRecord -C-Array 过滤器具有 −POSTfix string−PREfix string 修饰符,可用于在生成中添加特定于工具链的扩展(如果经常修改二进制文件,这很方便)。但是 IAR 语法没有很好的定义,所有的例子都是这样的:

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

所以“中缀”不是前缀或后缀。可能是这样的:

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

是有效的,但据我所知,手册并没有正式指定语法,而且我没有工具可以测试。如果这确实有效,那么:

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

对于链接器部分的位置:

-POSTfix `@ "BIN_SECTION"`

如果此语法不起作用,您可以编写自己的工具来修改生成的代码并作为自定义构建步骤运行以实现自动化,或者使用文本处理工具(例如 sed)插入位置信息。例如:

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

在 mybinary.c 中用 char mybinary[] @ 0x8020000 = 替换 char mybinary[] =

一般情况下,除非数据要被一些独立链接的代码代码访问,或者独立于代码进行修补/更新,否则没有必要将数据定位在特定位置,您应该让链接器定位它以实现可移植性在工具链和运行时环境之间。

【讨论】:

  • 非常感谢 Clifford 提供了非常完整且内容丰富的答案。
  • @stephenbates1971 欢迎您。请注意,我已经更正了生成的 srec 头文件 - 它是从现有应用程序复制和粘贴的,我没有更改符号名称作为示例。
猜你喜欢
  • 2020-01-06
  • 1970-01-01
  • 2012-03-04
  • 2020-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-19
相关资源
最近更新 更多