原创 深入剖析barebox(U-BOOT-II)在i.MX27上的移植

2011-10-31 11:24 2487 13 13 分类: 消费电子

深入剖析barebox(U-BOOT-II)在i.MX27上的移植

 

                              

Barebox是一个在uboot的基础上发展起来的一个新的功能强大的bootloader,它有着非常直观的设备模型和友好的编程接口,使用方便、功能强大。以下使用平台为成都莱得科技的i.MX27开发板上,平台稳定并应用到数十个客户的产品中。以下是详细的移植步骤。

文章版权属于成都莱得科技有限责任公司所有,转载请注明出处。

网址:www.nidetech.com,联系电话:18080873876,邮箱:nidetech@163.com,技术交流QQ:1460879610

 

1、barebox的特色和亮点

1.1POSIX File API

barebox使用open/close/read/write/lseek 函数,并且提供了设备文件的模型,可以通过使用像linux下被人熟知的这些API函数来操作设备。

1.2Shell

提供了标准的shell 命令,例如 cd/ls/cat/echo …等等

1.3Envionment Filesystem

barebox可以像操作文件一样的将环境变量保存在一个flash中,并且可以加载到ram中来。环境变量被模拟成了一个文件,可以通过barebox下简单的文本编辑器来编辑和保存环境变量文件。

1.4Filesystem Support

当barebox启动后,环境变量被挂载到/env/目录下,所有的设备被挂载到/dev目录下,我们可以通过标准的API函数来操作这些设备文件,就像在linux下一样。并且还可以通过mount指令挂载其他文件系统

1.5Driver Model(borrowed from Linux)

提供了像linux一样的驱动开发模型,在板级支持文件中定义所有的设备名,然后在驱动中通过相同的名字负责探测和管理这些设备。

1.6Clocksource

提供了在linux下熟知的clocksource函数,来用统一的管理时钟,例如clk_get,clk_enable等

1.7Sandbox

你可以通过将barebox选择成为sandbox来方便的进行barebox开发,他会将barebox编译成为在linux用户空间上的一个POSIX应用程序。方便开发和调试。

1.8Device Parameters

barebox提供了一个参数模型,每个设备都可以指定他们自己的参数,可以通过<devid>.<param> = “….”这样的方式来修改设备的参数,例如可以通过eth0.ipaddr=xxx.xxx.xxx.xxx来修改第一块网卡的ip地址。

1.9Getopt

barebox实现了一个简单的getopt,提供了一种比通过位置来传递参数更方便的模式。

1.10Integrated Editor

内部集成了一个文本编辑器

1.11集成了许多方便调试的命令和功能

  • md –s /dev/mem  [寄存器的物理地址]  可以查看任意寄存器和物理地址空间中的值。
  • mw 可以设置某个寄存器或者物理内存地址的值。
  • gpio_set_value/gpio_get_value 可以设置某个gpio的输出。

1.12支持网络更新自身、内核、文件系统、环境变量。

       1. 可以支持通过串口或者网络更新barebox自身

       2. 可以通过网络下载zImage,uImage,raw格式的内核

       3. 支持jffs2,ubifs等格式的文件系统映像

2、barebox的目录结构和移植相关文件

arch/*/                  -> contains architecture specific parts

arch/*/mach-*/           -> SoC specific code

drivers/serial           -> drivers

drivers/net

drivers/...

include/asm-*            -> architecture specific includes

include/asm-*/arch-*     -> SoC specific includes

fs/                      -> filesystem support and filesystem drivers

lib/                     -> generic library functions (getopt, readline and the

                            like)

common/                  -> common stuff

commands/                -> many things previously in common/cmd_*, one command

                           per file

net/                     -> Networking stuff

scripts/                 -> Kconfig system

Documentation/           -> Parts of the documentation, also doxygen

 

移植相关的文件:按启动顺序

arch/arm/lib/barebox.lds.S ->  针对arm体系下,Barebox的链接脚本,定义了barebox映像在内存中的布局

arch/arm/cpu/start.c  -> arm体系,barebox针对arm体系的入口函数,负责arm体系的初始化

arch/arm/boards/xxx/ lowlevel_init.[c/S] -> 针对某个具体ARM芯片的低层初始化文件,板级初始化文件

common/startup.c  -> 与体系架构无关的 barebox 启动代码,加载各个驱动,并且启动barebox的shell,等待用户输入。

3、barebox的详细启动流程

  • i.MX27冷启动后,nand flash控制器中有2K 的SRAM会被用作boot ram,根据硬件设计如果支持从nandflash启动的话,mx27会将NAND FLASH中的前2K的数据自动拷贝到NAND FLASH 控制器中的 RAM中,并且自动跳转到该2K RAM的开始地址 0xD8000000开始执行。因为我们的barebox是被atk烧写工具烧写到nandflash的0地址处,所以barebox的前2K代码会被拷贝到0xD8000000,barebox从而获得被调用的机会。
  • 那么barebox中首先得以执行的函数或者文件在什么地方啦?这就要查看barebox的链接脚本了,对于每种cpu架构,barebox在其架构名所在的文件夹中都有一个针对该架构的链接文件,对于arm来说,就是arch/arm/lib/barebox.lds.S文件,我们来详细分析一下该文件,弄清楚barebox在运行时候的映像分布情况

 

arch/arm/lib/barebox.lds.S

该头文件中定义了一些节的定义宏,方便barebox来定义输出节名

#include <asm-generic/barebox.lds.h>

 

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")

OUTPUT_ARCH(arm)

ENTRY指示出了Barebox的入口点,也就是在barebox被执行的第一条指令的地方。

ENTRY(exception_vectors)

以下描述了barebox中各个代码和数据的分布情况

SECTIONS

{

定义了barebox最终需要重定位的地址,在我们的开发板中定义为0xa7f00000,也就是硬件上设计的SDRAM的最后1M地址处,这里说的地址都是物理地址,没有经过mmu转化的。

. = TEXT_BASE;

这个是对于支持内部启动的imx系列cpu才支持的flash header比如mx51/53等,对于mx27来说,这个宏是个空的,也就是没有定义,所以我们不需要去管

PRE_IMAGE  

代码段需要以4字节对齐,以便取指令

. = ALIGN(4);

定义了代码段,对于mx27来说代码段的地址等于TEXT_BASE

.text      :

{

        _stext = .;  将代码段和只读数据段的起始处 == TEXT_BASE

        _text = .;   和上面的_stext一样

        *(.text_entry*)  所有的代码段

#ifdef CONFIG_ARCH_EP93XX

        /* the EP93xx expects to find the pattern 'CRUS' at 0x1000 */

  . = 0x1000;

  LONG(0x53555243) /* 'CRUS' */

#endif

        *(.text_bare_init*)

        *(.text*)

}

 

. = ALIGN(4);

.rodata : { *(.rodata*) }

 

#ifdef CONFIG_ARM_UNWIND

/*

 * Stack unwinding tables

 */

. = ALIGN(8);

.ARM.unwind_idx : {

        __start_unwind_idx = .;

        *(.ARM.exidx*)

        __stop_unwind_idx = .;

}

.ARM.unwind_tab : {

        __start_unwind_tab = .;

        *(.ARM.extab*)

        __stop_unwind_tab = .;

}

#endif

_etext = .;                   /* End of text and rodata section */

 

. = ALIGN(4);

.data : { *(.data*) }

 

. = ALIGN(4);

.got : { *(.got*) }

文章评论0条评论)

登录后参与讨论
我要评论
0
13
关闭 站长推荐上一条 /2 下一条