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

时间:2014-07-02 08:50:26

标签: embedded boot bootstrapping

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

此代码将存储在ROM中,处理器将在开机时开始执行。

我的目标是用ASM编写第一部分来处理以下操作:

  • 初始化处理器
  • 将.data段从ROM复制到RAM
  • 清除RAM中的.bss段
  • 致电主要

Main显然是用C语言编写的,并执行更高级别的操作,如自测等......

现在,我真正不知道如何将这两个程序合并为一个程序。我找到了一个糟糕的工具,基本上使用objcopy从可执行文件中收集.text和.data部分并在前面附加一些asm,但这似乎是一种非常丑陋的方式来做到这一点我想知道是否有人能指出我在右边方向?

2 个答案:

答案 0 :(得分:2)

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

问题是您需要布置生成的可执行文件,以便您的启动代码在开头。如果您使用GNU ld,那么执行此操作的方法是linker script

原始设置(未检查语法错误):

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
}

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

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

然后,您的引导加载程序可以使用提供的符号(_sdata_edata_sdata_load)来查找RAM和闪存中的数据部分,然后复制它。

最后警告:如果你的程序使用静态构造函数,你还需要一个构造函数表,引导程序器需要调用静态构造函数。

答案 1 :(得分:1)

西蒙是对的。有比这更简单的链接器脚本,它们可以很好地处理你正在做的事情,但最重要的是它是接收对象并生成二进制文件的链接器,所以根据你使用的链接器,你必须了解你的方法可以告诉链接器做什么然后让它做。不幸的是,我不认为有一个行业标准,你必须通过链接器链接并理解它们。当然,对于gnu ld,有许多非常复杂的链接描述文件,有些人可以解决链接器中的问题。