没有合适的资源?快使用搜索试试~ 我知道了~
U-Boot 源码分析(u-boot-2009.03)
需积分: 0 3 下载量 120 浏览量
2015-08-29
09:50:44
上传
评论
收藏 567KB PDF 举报
温馨提示
试读
22页
U-Boot 源码分析(u-boot-2009.03),后续会有移植详细教程。
资源推荐
资源详情
资源评论
U-Boot 源码分析(u-boot-2009.03)
hzb
我们开始学习 uboot,对于 linux 我还是个新手,在这只是对学习 uboot 做下笔记,文中错误之处请谅解。
UBoot
下载 :
ftp://ftp.denx.de/pub/u-boot/
一、
cpu/arm920t/start.S
分析
#include <config.h>
@该文件是第二步中 mkconfig 文件执行时创建的。include/config.h
#include <version.h>
@global 声明一个符号可被其他文档引用,相当于声明了一个全局变量。
@该部分为处理器的异常处理向量表。地址范围为 0x0000 0000 ~ 0x0000 0020,刚好 8 条指令。
.globl _start
_start: b reset
@ uboot 的主入口,跳到后面的标号 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
@ .word 为定义一个 4 字节的空间
_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
@ 由链接器脚本决定,在/borad/samsung/smdk2410/config.mk
.globl _armboot_start
_armboot_start:
.word _start
@ _start 是在起始代码处定义的标号,当跳到_armboot_start 后还是会跳转到_start
.globl _bss_start
_bss_start:
.word __bss_start
@ 在 board/samsung/smdk2410/u-boot.lds 中定义了__bss_start
.globl _bss_end
_bss_end:
.word _end
@ 在 board/samsung/smdk2410/u-boot.lds 中定义了__bss_start
#ifdef CONFIG_USE_IRQ
@ 这个宏在 include/configs/smdk2410.h 中定义,可以取消。
.globl IRQ_STACK_START
IRQ_STACK_START:
.word 0x0badc0de
.globl FIQ_STACK_START
@ 同样在 include/configs/smdk2410.h 中定义,可以取消。
FIQ_STACK_START:
.word 0x0badc0de
#endif
@ “mrs, msr”使用这两条指令将状态寄存器传送到一般寄存器,只修改必要的位,再将结果传送回状态寄存器,这样能够
@ 最好地完成对 CRSP 或 SPSR 的修改。
reset:
mrs r0,cpsr
@ 设置为 SVC 模式
bic r0,r0,#0x1f
orr r0,r0,#0xd3
msr cpsr,r0
bl coloured_LED_init
bl red_LED_on
@ CONFIG_AT91RM9200DK , CONFIG_AT91RM9200EK 在 include/configs/smdk2410.h 中定义
#if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK)
ldr r0, =_start
ldr r1, =0x0
mov r2, #16
copyex:
subs r2, r2, #1
ldr r3, [r0], #4
str r3, [r1], #4
bne copyex
#endif
@ CONFIG_S3C2400 或 CONFIG_S3C2410 在文件 include/configs/smdk2410.h 中定义
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
# 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
@ 关闭看门狗,将寄存器 WTCON 全部置 0。
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
@ 设置分频比为 1:2:4 , FCLK = 120MHz.
@ 在 uboot 启动的第二阶段 start_armboot()函数里调用 board_init()函数也重置 CPU 时钟。
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
#endif
@如果没有定义 CONFIG_SKIP_LOWLEVEL_INIT,就进行严格的初始化,调用 lowlevel_init 函数
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif
@ 判断是否为 norflash 启动
@ 调试阶段的代码是直接在 RAM 中运行的,而最后需要把这些代码固化到 Flash 中,因此 U-Boot 需要自己从 Flash 转移
@ 到 RAM 中运行,这也是重定向的目的所在。通过 adr 指令得到当前代码的地址信息:假如 U-boot 是从 RAM 开始运行,
@ 则从 adr,r0,_start 得到的地址信息为 r0=_start=_TEXT_BASE=TEXT_BASE=0xa3000000;假如 U-boot 从 Flash 开
@ 始运行,即从处理器对应的地址运行,则 r0=0x0000,这时将会执行 copy_loop 标识的那段代码了。
@ _TEXT_BASE 定义在 board/smdk2410/config.mk 中
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate:
@ 判断当前代码是在 norflash 还是在 RAM 中
adr r0, _start
@ 如果_start 与_TEXT_BASE 相等,就直接跳去 stack_setup 进行栈的设置,
ldr r1, _TEXT_BASE
@ 否则就要进行代码的拷贝,把代码拷贝到内存中
cmp r0, r1
@ 两个地址比较,相同说明在 RAM 中运行,不同说明在 FLASH 中运行。
beq stack_setup
@ 说明在 RAM 中运行
@ 如果是在 FLASH 中的话,就把代码拷贝到 RAM 中运行,即重新定位代码。
@ 声明_bss_start 并用__bss_start 来初始化,其中__bss_start 定义在和板相关的 u-boot.lds 中
ldr r2, _armboot_start
ldr r3, _bss_start
@ 计算代码段大小=_bss_start - _armboot_start
sub r2, r3, r2
@ 计算引导代码大小,并保存到 r2 中。
add r2, r0, r2 @ 计算引导代码最后相对地址并存入 r2
@ r2 = _start 的地址+代码段大小
copy_loop:
@ 将 flash 中的代码拷贝到 RAM 中
ldmia r0!, {r3-r10} @ 从源地址[r0]读取 32 个字节到寄存器,并更新 r0
stmia r1!, {r3-r10} @ 拷贝寄存器 r3-r10 的 32 个字节值保存到 [r1]指明的地址,并更新 r1 的值
cmpr0, r2 @ 循环拷贝,直到把所有引导代码都移到内存
ble copy_loop
#endif /* CONFIG_SKIP_RELOCATE_UBOOT */
stack_setup:
ldr r0, _TEXT_BASE
@ r0 = _TEXT_BASE=0x33F8 0000
sub r0, r0, #CONFIG_SYS_MALLOC_LEN
@ malloc area 堆区,r0=0x33F80000 - malloc area
sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE
@ r0=0x33F80000 - malloc area - bdinfo
#ifdef CONFIG_USE_IRQ
@如果定义了 IRQ,就要为 IRQ,FIQ 分配中断栈。
@ r0=0x33F80000 - malloc area - bdinfo - IRQ -FIQ
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
@ 此时堆栈指针的值 sp=0x33F80000 - malloc area - bdinfo - IRQ -FIQ - 12
sub sp, r0, #12
@ leave 3 words for abort-stack
@ 清除 bss 段,_bss_start 和_bss_end 就是 u-boot.lds 脚本传入的变量
clear_bss:
@ 将_bss_start 到_bss_start 之间的数据清 0.
ldr r0, _bss_start @ 把_bss_start 地址处存储的绝对地址移到 r0
ldr r1, _bss_end @ 把_bss_end 地址处存储的绝对地址移到 r1
mov r2, #0x00000000
@ clear
clbss_l:str r2, [r0]
@
add r0, r0, #4
cmpr0, r1
ble clbss_l @ 小于或等于跳转
ldr pc, _start_armboot
_start_armboot: .word start_armboot
@ 进入 uboot 第二阶段,跳转到 start_armboot 函数入口,_start_armboot 字保存函数入口指针 , start_armboot 函
数在 lib_arm/board.c 中实现 。
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
cpu_init_crit:
@ 进行严格的初始化,关闭 I/D caches,MMU,
mov r0, #0
@ 下面几段代码是芯片手册给出的,个人觉得不必深究。
mcr p15, 0, r0, c7, c7, 0
@ flush v3/v4 cache
mcr p15, 0, r0, c8, c7, 0
@ flush v4 TLB
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002300
@ clear bits 13, 9:8 (--V- --RS)
bic r0, r0, #0x00000087
@ clear bits 7, 2:0 (B--- -CAM)
orr r0, r0, #0x00000002
@ set bit 2 (A) Align
orr r0, r0, #0x00001000
@ set bit 12 (I) I-Cache
mcr p15, 0, r0, c1, c0, 0
mov ip, lr
#if defined(CONFIG_AT91RM9200EK)
#else
bl lowlevel_ini
@ 初始化 SDRAM,在 board/samsung/smdk2410/lowlevel_init.S
#endif
@ 初始化 SDRAM,其实就是配置 13 个寄存器,这里就不展开了。
mov lr, ip
mov pc, lr
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
Uboot
第一阶段
start.S
文件就分析到这里,现在我们总结一下第一阶段做的事情。
接下来分析下链接文件
u-boot.lds (board/samsung/smdk2410/u-boot.lds)
uboot.lds
是告诉编译器这些段改怎么划分,
GUN
编译过的段,最基本的三个段是
RO
,
RW
,
ZI
,
RO
表示只读,对应于具体的指代码段,
RW
是数据段,
ZI
是归零段,就是全局变量的那段。
Uboot
代码这么多,如何保证
start.s
会第一个执行,编译在最开始呢?就是通过
uboot.lds
链接
文件进行。
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
@ 指定输出可执行文件是 elf 格式,32 位 ARM 指令,小端
OUTPUT_ARCH(arm)
@ 指定输出可执行文件的平台为 ARM
ENTRY(_start)
@ 指定函数入口点为_start。cpu/arm920t/start.S 中定义。
SECTIONS
{
@ 指定可执行 image 文件的全局入口点,通常这个地址都放在 ROM(flash)0x0 位置。必须使编译器知道这个地址,通常都是修
@ 改此处来完成。
. = 0x00000000;
@ 从 0x0 位置开始
. = ALIGN(4);
@ 代码以 4 字节对齐
.text :
{
cpu/arm920t/start.o (.text)
@ 代码的第一个代码部分
*(.text)
@ 其它代码部分
}
剩余21页未读,继续阅读
资源评论
Neil_hzb
- 粉丝: 8
- 资源: 13
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- MyBatis动态SQL是一种强大的特性,它允许我们在SQL语句中根据条件动态地添加或删除某些部分,从而实现更加灵活和高效的数据
- MyBatis动态SQL是一种强大的特性,它允许我们在SQL语句中根据条件动态地添加或删除某些部分,从而实现更加灵活和高效的数据
- MyBatis动态SQL是一种强大的特性,它允许我们在SQL语句中根据条件动态地添加或删除某些部分,从而实现更加灵活和高效的数据
- MyBatis动态SQL是一种强大的特性,它允许我们在SQL语句中根据条件动态地添加或删除某些部分,从而实现更加灵活和高效的数据
- 文件批量改名神器10.0一款简单易用的批量文件重命名工具(已注册PRO版本).rar
- MyBatis动态SQL是一种强大的特性,它允许我们在SQL语句中根据条件动态地添加或删除某些部分,从而实现更加灵活和高效的数据
- MyBatis动态SQL是一种强大的特性,它允许我们在SQL语句中根据条件动态地添加或删除某些部分,从而实现更加灵活和高效的数据
- MyBatis动态SQL是一种强大的特性,它允许我们在SQL语句中根据条件动态地添加或删除某些部分,从而实现更加灵活和高效的数据
- MyBatis动态SQL是一种强大的特性,它允许我们在SQL语句中根据条件动态地添加或删除某些部分,从而实现更加灵活和高效的数据
- MyBatis动态SQL是一种强大的特性,它允许我们在SQL语句中根据条件动态地添加或删除某些部分,从而实现更加灵活和高效的数据
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功