uboot原理和移植

原创:http://blog.sina.com.cn/u/2312748742
一、linux系统分为:uboot,linux内核,文件系统,用户应用程序
二、uboot概念:
      uboot就是在内核运行前的一段小程序,用来初始化硬件设备,建立内存空间映射图。从而将系统的软硬件带到合适的状态,主要功能就是为了启动内核,它将内核从flash中拷贝到ddr中,然后跳转到内核入口中,交由内核控制权,uboot严重依赖硬件,因此一个通用的uboot不太可能。
三、存储位置:
    flash一般是依次存储 bootloader,boot启动参数,kernel,文件系统。
四、bootloader启动过程可分单阶段和多阶段。
    多阶段能实现更复杂的功能,可分stage1 和stage2;stage1完成初始化硬件,为stage2准备内存空间。
将stage2复制到内存中,设置堆栈然后跳转到stage2中。主要由汇编实现。start.s函数
      stage2初始化本阶段要使用的硬件设备,检测内存映射,将kernel和根文件系统映像拷贝到内存中,为内核设置启动参数。调用内核。主要由c语音实现。
五、uboot代码架构:
  1)board,和开发板相关的文件,每一个开发板都有自己的目录。
  2)common,实现uboot命令行下支持的命令。每一个命令都一个文件。如bootm,对应cmd_bootm.c
  3) cpu.与cpu架构相关的目录。
  4)disk,对硬盘的支持。比较少用。一般都用flash
  5) doc 文档目录
  6)drivers uboot支持的设备驱动程序。比较重要的有网卡和串口等。
  7)include uboot使用的头文件。还有对各种硬件平台支持的汇编文件,系统配置文件,文件系统支持的文件。还有该目录下的configs目录有与开发板相关的配置头文件。
  8)net 与网络协议栈相关的代码
  9)tools 生产uboot的工具。如mkimage ,crc等
六、u-boot.lds 链接顺序:
 
首先了解uboot 的链接脚本arch/arm/cpu/arm926ejs/u-boot.lds,它定义了目标程序
各部分的链接顺序。
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-
littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{

. = ALIGN(4);
.got : { *(.got) }
. = .;
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;
. = ALIGN(4);
__bss_start = .;
.bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
_end = .;
}
第一个链接的是cpu/board/start.o,也即Uboot 的入口指令在start 中,下面
详细分析程序的跳转和函数调用关系
 
七、stage1,arch/arm/cpu/arm926ejs/start.S
 
这个汇编程序时UBoot 的入口程序,以复位向量开头:
reset

cpu_init_crit

relocate

stack_setup

start_armboot()

init_sequence[]

getenv()

main_loop()
其中前面4步为Stage1,下面来详细分析一下 cpu/arm920t/start.S
这里以ARM9 2410 为例,2440移植时需要修改一些配置,具体的再后面的移植
中介绍.


.globl _start
_start:
b reset
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq
_undefined_instruction:
.word undefined_instruction
_software_interrupt:
.word software_interrupt
_prefetch_abort:
.word prefetch_abort
_data_abort:
.word data_abort
_not_used:
.word not_used
_irq:
.word irq
_fiq:
.word fiq
.balignl 16,0xdeadbeef



_TEXT_BASE:
.word TEXT_BASE ;
定义一个字并分配空间 4bytes
.globl _armboot_start
_armboot_start:
.word _start ;
声明一个全局的,并用 _start 初始化它, 在u-boot.lds 中定义

.globl _bss_start
_bss_start:
.word __bss_start
.globl _bss_end
_bss_end:
.word _end
#ifdef CONFIG_USE_IRQ

.globl IRQ_STACK_START
IRQ_STACK_START:
.word 0x0badc0de

.globl FIQ_STACK_START
FIQ_STACK_START:
.word 0x0badc0de
#endif


reset:
mrs r0,cpsr
bic r0,r0,#0x1f
orr r0,r0,#0xd3
msr cpsr,r0

#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)

//这段是关watchdog
#if defined(CONFIG_S3C2400)
# define pWTCON 0x15300000
# define INTMSK 0x14400008
# define CLKDIVN 0x14800014
#else
# define pWTCON 0x53000000
# define INTMSK 0x4A000008
# define INTSUBMSK 0x4A00001C
# define CLKDIVN 0x4C000014
# endif
ldr r0, =pWTCON //具体可以查看手册
mov r1, #0x0
str r1, [r0]

mov r1, #0xffffffff //禁止所有中断
ldr r0, =INTMSK
str r1, [r0]
# if defined(CONFIG_S3C2410)
ldr r1, =0x3ff
ldr r0, =INTSUBMSK
str r1, [r0]
# endif


ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
#endif

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit ;cpu 初始化,其中会调用lowlevel_init.S
/
*********************************************************************
*********
* BL 为相对寻址,以程序计数器PC 的当前值为基地址,指令中的地址标号作
为偏移量,将两者相加之后得到操作数的有效地址
* ARM 指令集中的4 条跳转指令可以完成从当前指令向前或向后的32MB 的地
址空间的跳转,
* 用的是相对寻址,它们是:B、BL、BLX、BX
*********************************************************************
**********/
#endif
#ifndef CONFIG_SKIP_RELOCATE_UBOOT

relocate:
adr r0, _start
/
*********************************************************************
*****
* 把_start 的相对地址移到r0, 相对寻址以程序计数器PC 的当前值为基地址,
* 指令中的地址标号作为偏移量,将两者相加之后得到操作数的有效地址。
* 它是与位置无关的,主要看Boot 在哪里运行,也就是PC 指针在哪里 (假设
_start 偏移量为0),
* 例如这段代码在 0x05000000 (FLASH 起始地址)运行,即此时
PC=0x05000000,
那么 adr r0, _start 得到 r0 = 0x05000000;
* 如果在地址 0x33008000(Boot 在RAM 中加载地址)运行,即此时
PC=0x33008000,那么r0 就是 0x33008000 了。
*通过adr指令得到当前代码的地址信息:如果U-boot 是从RAM 开始运行,
则从adr,r0,_start 得到的地址信息为
*r0=_start=_TEXT_BASE=TEXT_BASE=0x3ff80000;如果U-boot 从
Flash
开始运行,即从处理器对应的地址运 行,则*r0=0x0000,这时将会执行
copy_loop 标识的那段代码了
*********************************************************************
*****/
ldr r1, _TEXT_BASE

cmp r0, r1

beq stack_setup

ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2
add r2, r0, r2
copy_loop:
ldmia r0!, {r3-r10}
stmia r1!, {r3-r10}
cmp r0, r2
ble copy_loop
#endif


stack_setup:
ldr r0, _TEXT_BASE
sub r0, r0, #CFG_MALLOC_LEN
sub r0, r0, #CFG_GBL_DATA_SIZE
#ifdef CONFIG_USE_IRQ
sub r0, r0,
#(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
sub sp, r0, #12

clear_bss:
ldr r0, _bss_start

ldr r1, _bss_end
mov r2, #0x00000000
clbss_l:
str r2, [r0]
add r0, r0, #4
cmp r0, r1
ble clbss_l
ldr pc, _start_armboot

_start_armboot:
.word start_armboot
/********************************************************************
 
八、stage2;arch/arm/lib/Board.c
  跳转到 board_init_r:
 
 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值