Embedded 为嵌入式系统开发一个简单的引导加载程序

Embedded 为嵌入式系统开发一个简单的引导加载程序,embedded,boot,bootstrapping,Embedded,Boot,Bootstrapping,我的任务是为嵌入式系统开发一个简单的引导程序。我们没有运行任何操作系统或实时操作系统,所以我希望它非常简单 该代码将存储在ROM中,处理器将在通电时开始执行 我的目标是用ASM编写第一部分,它将负责以下操作: 初始化处理器 将.data段从ROM复制到RAM 清除RAM中的.bss段 呼叫总管 Main显然是用C编写的,并执行更高级别的操作,如自检等 现在我真的不知道如何把这两个程序合并成一个程序。我发现了一个蹩脚的工具,它基本上使用objcopy从可执行文件中收集.text和.data部分

我的任务是为嵌入式系统开发一个简单的引导程序。我们没有运行任何操作系统或实时操作系统,所以我希望它非常简单

该代码将存储在ROM中,处理器将在通电时开始执行

我的目标是用ASM编写第一部分,它将负责以下操作:

  • 初始化处理器
  • 将.data段从ROM复制到RAM
  • 清除RAM中的.bss段
  • 呼叫总管
Main显然是用C编写的,并执行更高级别的操作,如自检等

现在我真的不知道如何把这两个程序合并成一个程序。我发现了一个蹩脚的工具,它基本上使用objcopy从可执行文件中收集.text和.data部分,并在前面附加了一些asm,但这似乎是一个非常丑陋的方法,我想知道是否有人能给我指出正确的方向?

你可以(原则上)链接从汇编代码生成的对象文件,就像链接程序中的任何对象一样

关键在于,您需要安排生成的可执行文件,以便启动代码位于开头。如果您使用GNULD,那么实现这一点的方法是

基本设置(未检查语法错误):

基本思想是让链接器大致了解内存映射,然后将输入文件中的部分分配给最终程序中的部分

链接器保持每个输出部分的“虚拟”和“加载”地址之间的区别,因此您可以告诉它生成一个二进制文件,其中代码被重新定位为最终地址,但可执行文件中的布局不同(在这里,我告诉它将.data部分放在RAM中,但将其附加到flash中的.text部分)

然后,引导加载程序可以使用提供的符号(
\u sdata
\u edata
\u sdata\u load
)在RAM和闪存中查找数据节,并复制它


最后一点警告:如果您的程序使用静态构造函数,那么您还需要一个构造函数表,引导加载程序需要调用静态构造函数。

Simon正确。有比这更简单的链接器脚本,可以很好地用于您正在做的事情,但底线是,是链接器获取对象并生成二进制文件,因此根据您正在使用的链接器,您必须了解您可以告诉该链接器做事情,然后让它做事情的方式。不幸的是,我不认为这有一个行业标准,你必须去一个接一个的链接,并了解他们。当然,GNULD有很多非常复杂的链接器脚本,有些人活着就是为了解决链接器中的问题

非常感谢您的解释,这非常有帮助。github.com/dwelch67/raspberrypi我有一个datass或其他目录,其中包含一些文本,可以通过gnu ld进行实验,您可以尝试自己编写所需的链接器脚本,然后从中复制变量。数据,零。bss和任何你可能感兴趣的东西。非常感谢。我来看看。我家里也有覆盆子皮,所以它会派上用场:)
MEMORY
{
    FLASH (RX) : ORIGIN = 0,          LENGTH = 256K
    RAM (RWX)  : ORIGIN = 0x40000000, LENGTH = 4M
}

SECTIONS
{
   .bootloader 0 : AT(0) { bootloader.o(.text) } >FLASH AT>FLASH
   .text : { _stext = .; *(.text .text.* .rodata .rodata.*); _etext = . } >FLASH AT>FLASH
   .data : { _sdata = .; *(.data .data.*); _edata = .; _sdata_load = LOADADDR(.data) } >RAM AT>FLASH
   .bss (NOLOAD) { _sbss = .; *(.bss .bss.*); _ebss = . } >RAM
}