6410 uboot启动引导分析
2012-08-22 13:47
369 查看
http://keyewan.blog.163.com/blog/static/1898272332011763164586/
以下用以记录分析过程,如有错误,欢迎指正。
强调,内容与三星提供的uboot有更改的地方,因为外接外设的区别。
纯代码分析,以后会传上uboot的内存分布图和功能结构图。
代码可以在arm9网站下载,mini6410的,本代码也是基于它的改的。
本文章将分析介绍uboot代码的第一阶段和第二阶段。
1.start.s代码分析(第一阶段)
/* 以下是具有arm特色的异常向量表,为使能中断异常的时候处理用 */
--------------------
.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
--------------------
/* 当发生中断异常时,跳转到pc会跳转到.word的后面地址处 处理异常,
undefined异常由arm核译码单元检测,并触发未定义指令异常请求;
软中断放在0x8地址,arm中使用swi指令时触发,多用在系统库的编写;
prefetch异常,预取指中止异常,产生的原因未知,导致正在取的指令无法正常取出,这里需要注意流水线造成的pc值 ;
data中止,无法获取数据,产生的原因有可能是内存未准备好,或是cache未命中等一些原因产生的异常;
0x14暂时未使用;
0x18地址存放中断异常,一般我们的处理器都会引出很多的中断线,在这里所要做的就是判断系统中断,注册中断,初始化中断,调用中断函数等等;
0x1c地址为_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
_pad:
.word 0x12345678 /* now 16*4=64 */
.global _end_vect
_end_vect:
.balignl 16,0xdeadbeef
--------------------
/* _TEXT_BASE标号所代表的是uboot代码实际的运行地址,我们的uboot最终不可能运行在s3c6410的引导镜像区,对于s3c6410
系统来说,如果nand flash启动方式,系统会把0xc000000里面前4KB的内容映射到引导镜像区,即0x0地址,但是我们需要把
uboot代码放到我们的SDRAM,原因是我们代码里面需要对变量做更改并且增加代码执行效率
好吧,说多了,上面的看不明白当废话,下面的含义其实就是执行程序的运行地址,.word后面的值TEXT_BASE在编译的时候,
通过向编译器传递参数获得,-DTEXT_BASE方式向编译器传递宏参
*/
--------------------
_TEXT_BASE:
.word TEXT_BASE
--------------------
/* 在uboot里面会开启MMU,使用到虚拟地址 */
--------------------
_TEXT_PHY_BASE:
.word CFG_PHY_UBOOT_BASE
--------------------
/* 这个不解释也是可以的 */
--------------------
.globl _armboot_start
_armboot_start:
.word _start
--------------------
/* 下面的代码__bss_start的值的定义在u-boot.lds脚本里面定义的,虽然没给值,但是你要知道文件的大小和位置是由
编译器指定的,那么还需要我们告诉它值吗?所以没值胜有值啦
*/
--------------------
.globl _bss_start
_bss_start:
.word __bss_start
.globl _bss_end
_bss_end:
.word _end
--------------------
/* uboot开始执行代码处即在这里了,下面的代码在干些事情,使得cpu的模式为管理模式,话又说回来,不是管理模式msr、mrs官方给
的解释也是用不了的,何况,系统上电的时候就是管理模式,CPRS的值也是固定的,模式这部分代码有些小多余。 */
--------------------
reset:
mrs r0,cpsr
bic r0,r0,#0x1f
orr r0,r0,#0xd3
msr cpsr,r0
--------------------
/* 以下标号所在处的代码比较多,将做逐步分析,这段代码主要的工作也就是改了一些硬件寄存器和内存初始化工作 */
--------------------
cpu_init_crit:
--------------------
/*
刷新指令和数据缓存,mcr的意思是把arm寄存器的值赋值给coprocesser寄存器,拿第一条指令来说,
p15代表协处理器,0为一定的值,指令中0b0000四位来表示,现在无具体作用,如果不是0则结果未知,后面的r0是即将写入
c7目标寄存器中的值,后面还有个c7所代表的意思为额外操作码,如果不是c0,则表示的是同一个寄存器的不同物理寄存器,因为
同一个寄存器的名字并不代码通一个物理内存,我们在学rpsr的时候应该知道这点,最后的0提供附加信息,用于区分同一寄存器的
不同物理寄存器,如无附加信息,请保持为0值,否则结果不可预测
下面三行代码不难看出,c7、c8的值被清为0,为什么要清为零呢,你需要去看arm1176jzf-sarm核了,其中是有说明的,不再累述,
arm1176jzf-sarm核芯片手册下载地址httop://www.arm.com
*/
--------------------
mov r0, #0
mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
--------------------
/*
实在不想解释这段,因为以前看过芯片手册的解释,且不止一遍,对于这里面要更改的内容就是不能全部记下来,和工作有关了,
不能全心搞这块内容,最多2个月左右的时间能回来回顾一下了。总之还是去查arm11核芯片手册,因为以下改的内容是协处理器
c1,那么你就该去查c1是用来干什么的。查看得知,是控制寄存器,查看手册是online books12.2.2 Primary register allocation
一节,其中13,9,8位为 V、R、S:V位是对高端异常向量表的支持,如果选择0异常向量表为0x00000000-0x0000001c,如果选择
1异常向量表就是FFFF0000-FFFF001c;R位用于ROM保护的,具体的还要与c5里面的配合,这都是MMU惹的祸,很烦,但是现在
我们还没有讲到MMU,所以为什么这样做,也必须到讲到MMU的时候才见分晓了,S在这里面的意思也是用于系统保护的,和MMU
又是有很大的关系,好吧,后面会找MMU算账的,这里就先不深入了,接下来再分析下下面的指令含义
bic r0, r0, #0x00000087 @ clear bits 7, 2:0(B--- -CAM) 的B位为0表示支持小little-endian,1表示支持big-endian格式的系统内存
CAM为第三位,M为0代表禁止MMU,反之打开,A代表地址对齐检查,0代表禁止,C代表指令数据cache控制,0为禁止
orr r0, r0, #0x00000002 @ set bit 2 (A) Align 这段指令又比较犯贱了,打开地址对齐检查了,这是应该的O(∩_∩)O~,后面又
设置12位为1,含义是如果数据cache和指令cache是分开的话,这里面置1的含义将会打开指令cache*/
--------------------
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
--------------------
/* c15在s3c6410上有特殊作用,它是内存端口映射32位寄存器,MMU在开关的时候发生作用,且优先级最高
这里的0x70000000为peri port的基地址,0x13的二进制为0x10011,0x10011的意思为256M,代表映射的
大小为256M,0x10010为128M。假如你没开MMU,那么下面代码就不需要写了,写了的话PHY和Peri port
映射的地址相同。但是MMU ON,下面代码是一定要写的。
使用C15的方法是:
1.Opcode_1 set to 0
2.CRn set to c15
3.CRm set to c2
4.Opcode_2 set to 4
*/
--------------------
/* Peri port setup */
ldr r0, =0x70000000
orr r0, r0, #0x13
mcr p15,0,r0,c15,c2,4 @ 256M(0x70000000-0x7fffffff)
--------------------
/* 下面是一条跳转指令,代码实在不想贴,因为功能都是老生常谈的,比如说点亮LED灯、关闭watchdog、关闭中断、系统时钟初始
nand flash初始化、内存控制器初始化。不过说实在的,去仔细分析这些初始化的过程,对于你对如何控制硬件有很大的帮助,
对于这个函数,所要说的东西太多,会在后面的文章中单独分析它,现在先知道功能就好。
*/
--------------------
bl lowlevel_init
--------------------
/* 跳转出来以后,继续执行下面的代码,下面的代码是判断程序是否已经在ram中了,在的话就不拷贝,直接跳转到after_copy了,否则
继续执行下面的代码 */
--------------------
ldr r0, =0xff000fff
bic r1, pc, r0 /* r0 <- current base addr of code */
ldr r2, _TEXT_BASE /* r1 <- original base addr in ram */
bic r2, r2, r0 /* r0 <- current base addr of code */
cmp r1, r2 /* compare r0, r1 */
beq after_copy /* r0 == r1 then skip flash copy */
--------------------
/* 判断是否从NAND启动,其实还可以从SD卡启动,onenand,有兴趣自己研究这些启动方式吧 ,下面是通过函数copy_from_nand
拷贝代码到ram中*/
--------------------
#ifdef CONFIG_BOOT_NAND
mov r0, #0x1000
bl copy_from_nand
#endif
--------------------
/* SD卡启动方式 */
--------------------
#ifdef CONFIG_BOOT_MOVINAND
ldr sp, _TEXT_PHY_BASE
bl movi_bl2_copy
b after_copy
#endif
--------------------
/* 点灯 */
--------------------
after_copy:
ldr r0, =ELFIN_GPIO_BASE
ldr r1, =0xC00
str r1, [r0, #GPPDAT_OFFSET]
ldr r1, [r0, #GPFPUD_OFFSET]
bic r1, r1, #0xc0000000
orr r1, r1, #0x80000000
str r1, [r0, #GPFPUD_OFFSET]
ldr r1, [r0, #GPFDAT_OFFSET]
orr r1, r1, #0x8000
str r1, [r0, #GPFDAT_OFFSET]
ldr r1, [r0, #GPFCON_OFFSET]
bic r1, r1, #0xc0000000
orr r1, r1, #0x40000000
str r1, [r0, #GPFCON_OFFSET]
--------------------
/* 打开MMU功能了,下班了,下次再细化介绍吧。 */
--------------------
#ifdef CONFIG_ENABLE_MMU
enable_mmu:
/* enable domain access */
ldr r5, =0x0000ffff
mcr p15, 0, r5, c3, c0, 0 @ load domain access register
/* Set the TTB register */
ldr r0, _mmu_table_base
ldr r1, =CFG_PHY_UBOOT_BASE
ldr r2, =0xfff00000
bic r0, r0, r2
orr r1, r0, r1
mcr p15, 0, r1, c2, c0, 0
/* Enable the MMU */
mmu_on:
mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #1 /* Set CR_M to enable MMU */
mcr p15, 0, r0, c1, c0, 0
nop
nop
nop
nop
#endif
--------------------
/* 堆栈初始化代码,这也是老生常谈的不用说了 */
--------------------
skip_hw_init:
/* Set up the stack */
stack_setup:
#ifdef CONFIG_MEMORY_UPPER_CODE
ldr sp, =(CFG_UBOOT_BASE + CFG_UBOOT_SIZE - 0xc)
#else
ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
sub r0, r0, #CFG_MALLOC_LEN /* malloc area */
sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */
#ifdef CONFIG_USE_IRQ
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
sub sp, r0, #12 /* leave 3 words for abort-stack */
#endif
--------------------
/* 清楚BSS段代码为0 */
--------------------
clear_bss:
ldr r0, _bss_start /* find start of bss segment */
ldr r1, _bss_end /* stop here */
mov r2, #0x00000000 /* clear */
clbss_l:
str r2, [r0] /* clear loop... */
add r0, r0, #4
cmp r0, r1
ble clbss_l
--------------------
/* 跳转到代码的uboot代码的第二个阶段 */
--------------------
ldr pc, _start_armboot
_start_armboot:
.word start_armboot
--------------------
2.第二阶段代码分析(代码在lib_arm目录下的board.c里面,start_armboot函数)
下次分析吧,下班了。。。想想头疼啊,还有前面的VFP、象棋算法没有去研究呢。
好吧,我本来觉得可以继续分析下去,但一看第二阶段代码太多,且不容易理解,所以,再次决定下次单独开辟章节写第二阶段的代码分析。但是,我们首先应该知道的是第二阶段在干什么:
1.硬件初始化
2.网络传输功能
3.命令交互功能
4.环境变量
等有时间,会针对这些问题在新的文章中深入浅出说明以下问题:
1.硬件初始化的详细过程,比如说nand_flash、UART(通过原理图、datasheet、寄存器控制等说明)
2.网络传输功能(将介绍DM9000网卡芯片的驱动程序)
3.命令交互(uboot中是如何添加命令的,如何增加自己的命令调用)
4.环境变量的存储和调用,以及uboot代码中的一些重要环境变量
以下用以记录分析过程,如有错误,欢迎指正。
强调,内容与三星提供的uboot有更改的地方,因为外接外设的区别。
纯代码分析,以后会传上uboot的内存分布图和功能结构图。
代码可以在arm9网站下载,mini6410的,本代码也是基于它的改的。
本文章将分析介绍uboot代码的第一阶段和第二阶段。
1.start.s代码分析(第一阶段)
/* 以下是具有arm特色的异常向量表,为使能中断异常的时候处理用 */
--------------------
.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
--------------------
/* 当发生中断异常时,跳转到pc会跳转到.word的后面地址处 处理异常,
undefined异常由arm核译码单元检测,并触发未定义指令异常请求;
软中断放在0x8地址,arm中使用swi指令时触发,多用在系统库的编写;
prefetch异常,预取指中止异常,产生的原因未知,导致正在取的指令无法正常取出,这里需要注意流水线造成的pc值 ;
data中止,无法获取数据,产生的原因有可能是内存未准备好,或是cache未命中等一些原因产生的异常;
0x14暂时未使用;
0x18地址存放中断异常,一般我们的处理器都会引出很多的中断线,在这里所要做的就是判断系统中断,注册中断,初始化中断,调用中断函数等等;
0x1c地址为_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
_pad:
.word 0x12345678 /* now 16*4=64 */
.global _end_vect
_end_vect:
.balignl 16,0xdeadbeef
--------------------
/* _TEXT_BASE标号所代表的是uboot代码实际的运行地址,我们的uboot最终不可能运行在s3c6410的引导镜像区,对于s3c6410
系统来说,如果nand flash启动方式,系统会把0xc000000里面前4KB的内容映射到引导镜像区,即0x0地址,但是我们需要把
uboot代码放到我们的SDRAM,原因是我们代码里面需要对变量做更改并且增加代码执行效率
好吧,说多了,上面的看不明白当废话,下面的含义其实就是执行程序的运行地址,.word后面的值TEXT_BASE在编译的时候,
通过向编译器传递参数获得,-DTEXT_BASE方式向编译器传递宏参
*/
--------------------
_TEXT_BASE:
.word TEXT_BASE
--------------------
/* 在uboot里面会开启MMU,使用到虚拟地址 */
--------------------
_TEXT_PHY_BASE:
.word CFG_PHY_UBOOT_BASE
--------------------
/* 这个不解释也是可以的 */
--------------------
.globl _armboot_start
_armboot_start:
.word _start
--------------------
/* 下面的代码__bss_start的值的定义在u-boot.lds脚本里面定义的,虽然没给值,但是你要知道文件的大小和位置是由
编译器指定的,那么还需要我们告诉它值吗?所以没值胜有值啦
*/
--------------------
.globl _bss_start
_bss_start:
.word __bss_start
.globl _bss_end
_bss_end:
.word _end
--------------------
/* uboot开始执行代码处即在这里了,下面的代码在干些事情,使得cpu的模式为管理模式,话又说回来,不是管理模式msr、mrs官方给
的解释也是用不了的,何况,系统上电的时候就是管理模式,CPRS的值也是固定的,模式这部分代码有些小多余。 */
--------------------
reset:
mrs r0,cpsr
bic r0,r0,#0x1f
orr r0,r0,#0xd3
msr cpsr,r0
--------------------
/* 以下标号所在处的代码比较多,将做逐步分析,这段代码主要的工作也就是改了一些硬件寄存器和内存初始化工作 */
--------------------
cpu_init_crit:
--------------------
/*
刷新指令和数据缓存,mcr的意思是把arm寄存器的值赋值给coprocesser寄存器,拿第一条指令来说,
p15代表协处理器,0为一定的值,指令中0b0000四位来表示,现在无具体作用,如果不是0则结果未知,后面的r0是即将写入
c7目标寄存器中的值,后面还有个c7所代表的意思为额外操作码,如果不是c0,则表示的是同一个寄存器的不同物理寄存器,因为
同一个寄存器的名字并不代码通一个物理内存,我们在学rpsr的时候应该知道这点,最后的0提供附加信息,用于区分同一寄存器的
不同物理寄存器,如无附加信息,请保持为0值,否则结果不可预测
下面三行代码不难看出,c7、c8的值被清为0,为什么要清为零呢,你需要去看arm1176jzf-sarm核了,其中是有说明的,不再累述,
arm1176jzf-sarm核芯片手册下载地址httop://www.arm.com
*/
--------------------
mov r0, #0
mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
--------------------
/*
实在不想解释这段,因为以前看过芯片手册的解释,且不止一遍,对于这里面要更改的内容就是不能全部记下来,和工作有关了,
不能全心搞这块内容,最多2个月左右的时间能回来回顾一下了。总之还是去查arm11核芯片手册,因为以下改的内容是协处理器
c1,那么你就该去查c1是用来干什么的。查看得知,是控制寄存器,查看手册是online books12.2.2 Primary register allocation
一节,其中13,9,8位为 V、R、S:V位是对高端异常向量表的支持,如果选择0异常向量表为0x00000000-0x0000001c,如果选择
1异常向量表就是FFFF0000-FFFF001c;R位用于ROM保护的,具体的还要与c5里面的配合,这都是MMU惹的祸,很烦,但是现在
我们还没有讲到MMU,所以为什么这样做,也必须到讲到MMU的时候才见分晓了,S在这里面的意思也是用于系统保护的,和MMU
又是有很大的关系,好吧,后面会找MMU算账的,这里就先不深入了,接下来再分析下下面的指令含义
bic r0, r0, #0x00000087 @ clear bits 7, 2:0(B--- -CAM) 的B位为0表示支持小little-endian,1表示支持big-endian格式的系统内存
CAM为第三位,M为0代表禁止MMU,反之打开,A代表地址对齐检查,0代表禁止,C代表指令数据cache控制,0为禁止
orr r0, r0, #0x00000002 @ set bit 2 (A) Align 这段指令又比较犯贱了,打开地址对齐检查了,这是应该的O(∩_∩)O~,后面又
设置12位为1,含义是如果数据cache和指令cache是分开的话,这里面置1的含义将会打开指令cache*/
--------------------
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
--------------------
/* c15在s3c6410上有特殊作用,它是内存端口映射32位寄存器,MMU在开关的时候发生作用,且优先级最高
这里的0x70000000为peri port的基地址,0x13的二进制为0x10011,0x10011的意思为256M,代表映射的
大小为256M,0x10010为128M。假如你没开MMU,那么下面代码就不需要写了,写了的话PHY和Peri port
映射的地址相同。但是MMU ON,下面代码是一定要写的。
使用C15的方法是:
1.Opcode_1 set to 0
2.CRn set to c15
3.CRm set to c2
4.Opcode_2 set to 4
*/
--------------------
/* Peri port setup */
ldr r0, =0x70000000
orr r0, r0, #0x13
mcr p15,0,r0,c15,c2,4 @ 256M(0x70000000-0x7fffffff)
--------------------
/* 下面是一条跳转指令,代码实在不想贴,因为功能都是老生常谈的,比如说点亮LED灯、关闭watchdog、关闭中断、系统时钟初始
nand flash初始化、内存控制器初始化。不过说实在的,去仔细分析这些初始化的过程,对于你对如何控制硬件有很大的帮助,
对于这个函数,所要说的东西太多,会在后面的文章中单独分析它,现在先知道功能就好。
*/
--------------------
bl lowlevel_init
--------------------
/* 跳转出来以后,继续执行下面的代码,下面的代码是判断程序是否已经在ram中了,在的话就不拷贝,直接跳转到after_copy了,否则
继续执行下面的代码 */
--------------------
ldr r0, =0xff000fff
bic r1, pc, r0 /* r0 <- current base addr of code */
ldr r2, _TEXT_BASE /* r1 <- original base addr in ram */
bic r2, r2, r0 /* r0 <- current base addr of code */
cmp r1, r2 /* compare r0, r1 */
beq after_copy /* r0 == r1 then skip flash copy */
--------------------
/* 判断是否从NAND启动,其实还可以从SD卡启动,onenand,有兴趣自己研究这些启动方式吧 ,下面是通过函数copy_from_nand
拷贝代码到ram中*/
--------------------
#ifdef CONFIG_BOOT_NAND
mov r0, #0x1000
bl copy_from_nand
#endif
--------------------
/* SD卡启动方式 */
--------------------
#ifdef CONFIG_BOOT_MOVINAND
ldr sp, _TEXT_PHY_BASE
bl movi_bl2_copy
b after_copy
#endif
--------------------
/* 点灯 */
--------------------
after_copy:
ldr r0, =ELFIN_GPIO_BASE
ldr r1, =0xC00
str r1, [r0, #GPPDAT_OFFSET]
ldr r1, [r0, #GPFPUD_OFFSET]
bic r1, r1, #0xc0000000
orr r1, r1, #0x80000000
str r1, [r0, #GPFPUD_OFFSET]
ldr r1, [r0, #GPFDAT_OFFSET]
orr r1, r1, #0x8000
str r1, [r0, #GPFDAT_OFFSET]
ldr r1, [r0, #GPFCON_OFFSET]
bic r1, r1, #0xc0000000
orr r1, r1, #0x40000000
str r1, [r0, #GPFCON_OFFSET]
--------------------
/* 打开MMU功能了,下班了,下次再细化介绍吧。 */
--------------------
#ifdef CONFIG_ENABLE_MMU
enable_mmu:
/* enable domain access */
ldr r5, =0x0000ffff
mcr p15, 0, r5, c3, c0, 0 @ load domain access register
/* Set the TTB register */
ldr r0, _mmu_table_base
ldr r1, =CFG_PHY_UBOOT_BASE
ldr r2, =0xfff00000
bic r0, r0, r2
orr r1, r0, r1
mcr p15, 0, r1, c2, c0, 0
/* Enable the MMU */
mmu_on:
mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #1 /* Set CR_M to enable MMU */
mcr p15, 0, r0, c1, c0, 0
nop
nop
nop
nop
#endif
--------------------
/* 堆栈初始化代码,这也是老生常谈的不用说了 */
--------------------
skip_hw_init:
/* Set up the stack */
stack_setup:
#ifdef CONFIG_MEMORY_UPPER_CODE
ldr sp, =(CFG_UBOOT_BASE + CFG_UBOOT_SIZE - 0xc)
#else
ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
sub r0, r0, #CFG_MALLOC_LEN /* malloc area */
sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */
#ifdef CONFIG_USE_IRQ
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
sub sp, r0, #12 /* leave 3 words for abort-stack */
#endif
--------------------
/* 清楚BSS段代码为0 */
--------------------
clear_bss:
ldr r0, _bss_start /* find start of bss segment */
ldr r1, _bss_end /* stop here */
mov r2, #0x00000000 /* clear */
clbss_l:
str r2, [r0] /* clear loop... */
add r0, r0, #4
cmp r0, r1
ble clbss_l
--------------------
/* 跳转到代码的uboot代码的第二个阶段 */
--------------------
ldr pc, _start_armboot
_start_armboot:
.word start_armboot
--------------------
2.第二阶段代码分析(代码在lib_arm目录下的board.c里面,start_armboot函数)
下次分析吧,下班了。。。想想头疼啊,还有前面的VFP、象棋算法没有去研究呢。
好吧,我本来觉得可以继续分析下去,但一看第二阶段代码太多,且不容易理解,所以,再次决定下次单独开辟章节写第二阶段的代码分析。但是,我们首先应该知道的是第二阶段在干什么:
1.硬件初始化
2.网络传输功能
3.命令交互功能
4.环境变量
等有时间,会针对这些问题在新的文章中深入浅出说明以下问题:
1.硬件初始化的详细过程,比如说nand_flash、UART(通过原理图、datasheet、寄存器控制等说明)
2.网络传输功能(将介绍DM9000网卡芯片的驱动程序)
3.命令交互(uboot中是如何添加命令的,如何增加自己的命令调用)
4.环境变量的存储和调用,以及uboot代码中的一些重要环境变量
相关文章推荐
- Linux0.11内核--启动引导代码分析bootsect.s
- U-BOOT全线移植分析系列之四——U-boot如何引导Linux内核启动
- U-Boot启动引导内核分析(一)
- U-Boot启动引导内核分析(二)
- U-Boot启动引导内核分析(三)
- linux0.11 引导启动程序目录boot/分析
- 学习笔记--- U-BOOT从启动到引导内核过程分析
- 转: U-Boot启动引导内核分析
- linux0.11 引导启动程序目录boot/分析
- U-BOOT全线移植分析系列之四--U-boot如何引导Linux内核启动?
- OK6410之uboot移植(2)——U-Boot启动过程完全分析
- u-boot2013.01 smdk2410 启动第二阶段分析之引导内核
- Linux0.11内核--启动引导代码分析bootsect.s
- 【嵌入式Linux学习七步曲之第三篇 Linux系统bootlaoder移植】U-BOOT全线移植分析系列之四--U-boot如何引导Linux内核启动?
- u-boot.lds分析(u-boot-1.3.4 nandflash启动 引导linux内核)
- U-Boot启动引导内核分析
- Linux0.11内核--启动引导代码分析bootsect.s
- u-boot.lds分析(u-boot-1.3.4 nandflash启动 引导linux内核)
- U-boot启动第一阶段详细分析
- Linux启动分析(2)— bootsect.S、setup.S、head.S分析