smdkc100之u-boot 2010.03代码的分析1
来源:互联网 发布:vscode配置go 编辑:程序博客网 时间:2024/06/11 10:03
以下用以记录uboot 2010.03代码的分析过程,目标是smdkc100,本文参考了网上有关s3c6410开发板有关源码的分析,在此感谢无私奉献,如有错误,欢迎指正。
强调,内容与三星原厂提供的uboot-2010.03有更改的地方,因为外接外设的区别,特别是nand_flash、外接网卡芯片和LCD芯片
以下纯代码情景分析,请结合uboot的功能结构图和内存分布图查看代码,这样会更加容易理解。
功能结构图(上图)
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
_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
--------------------
/* 当发生中断异常时,pc会跳转到.word的后面地址处处理异常,
undefined异常由arm核译码单元检测,并触发未定义指令异常请求,硬件设置pc的值为0x4,强制程序从内存0x4地址执行指令;
0x8存放软件中断处理指令,arm中使用swi指令时触发软件中断,硬件设置PC的值为0x8,同时进入系统模式,多用在系统库的编写;
prefetch异常,预取指中止异常,导致正在取的指令无法正常取出,这里需要注意流水线造成的pc值 ;
data中止,无法获取数据,产生的原因有可能是内存未准备好、内存无读或写权限等一些原因产生的异常;
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
--------------------
/* u-boot 执行总共需要二次搬移,第一次是 iROM 固化的代码搬移 nand flash 的前 16k 到 iRAM 中去运行,第二次是iRAM 中 16K 代码执行会把 nand flash 中的 u-boot 搬移到链接地址也就是 0x34800000 .
_TEXT_BASE标号所代表的是uboot代码的运行地址,对于FS_S5PC100系统来说,如果nand flash启动方式,系统会把nand flash里面前16KB的内容映射到引导镜像区,即0x0地址,但是我们需要把uboot代码放到我们的SDRAM,原因是我们代码里面需要对变量做更改并且增加代码执行效率等
下面代码的含义是定义uboot程序执行的运行地址,值为0x34800000,.word后面的值TEXT_BASE在编译的时候,
通过向编译器传递参数获得,-DTEXT_BASE方式向编译器传递宏参,在编译的时候可以注意下编译的时候都会指定它的值,值得定义在
config.mk中,Makefile会包含它。
*/
--------------------
_TEXT_BASE:
.word TEXT_BASE
--------------------
/*
在uboot里面会开启MMU,下面是在MMU开启前uboot在内存存放的真实物理地址,值为0x34800000。强调一下,我们做的开发板的SDRAM在DMC1上,即访问物理内存的实际物理地址从0x30000000开始,SDRAM的大小为256M,正好是一个DMC1,所以内存的访问地址就是0x30000000-0x40000000之间了。
*/
--------------------
.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的模式为管理模式,如果想使得为cpu为管理模式,需要保证cpsr寄存器的最低5位为10011,下面是把0xd3的值赋值给cpsr,0xd3即1101 0011,最高两位置1的意思为关闭中断和快中断,这是为了防止代码正在执行时,产生外部中断,导致程序跳转到异常向量表而无法正常按顺序执行。5位为0的意思是cpu的状态为arm状态,如果是1则cpu进入thumb态,thumb态处理16位指令代码和数据。
*/
--------------------
reset:
mrs r0,cpsr
bic r0,r0,#0x1f
orr r0,r0,#0xd3
msr cpsr,r0
--------------------
/*下面宏没有定义,所以代码不执行*/
#if (CONFIG_OMAP34XX)
/* Copy vectors to mask ROM indirect addr */
adrr0, _start@ r0 <- current position of code
addr0, r0, #4@ skip reset vector
movr2, #64@ r2 <- size to copy
addr2, r0, r2@ r2 <- source end address
movr1, #SRAM_OFFSET0@ build vect addr
movr3, #SRAM_OFFSET1
addr1, r1, r3
movr3, #SRAM_OFFSET2
addr1, r1, r3
next:
ldmiar0!, {r3 - r10}@ copy from source address [r0]
stmiar1!, {r3 - r10}@ copy to target address [r1]
cmpr0, r2@ until source end address [r2]
bnenext@ loop until equal */
#if !defined(CONFIG_SYS_NAND_BOOT) && !defined(CONFIG_SYS_ONENAND_BOOT)
/* No need to copy/exec the clock code - DPLL adjust already done
* in NAND/oneNAND Boot.
*/
blcpy_clk_code@ put dpll adjust code behind vectors
#endif /* NAND Boot */
#endif
/* 以下标号所在处的代码比较多,将做逐步分析,这段代码主要的工作也就是改了一些硬件寄存器和内存初始化工作 */
--------------------
cpu_init_crit:
--------------------
/*
指令的含义为刷新指令和数据缓存。mcr的意思是把arm寄存器的值赋值给coprocesser寄存器,拿第一条指令来说,p15代表协处理器,0为一定的值,指令中0b0000四位来表示,现在无具体作用,如果不是0则结果未知,后面的r0是即将写入c7目标寄存器中的值,后面还有个c7所代表的意思为额外操作码,如果不是c0,则表示的是同一个寄存器的不同物理寄存器,因为同一个寄存器的名字并不代码通一个物理内存,我们在学rpsr的时候应该知道这点,最后的0提供附加信息,用于区分同一寄存器的不同物理寄存器,如无附加信息,请保持为0值,否则结果不可预测
下面三行代码不难看出,c7、c8的值被清为0,为什么要清为零呢,你需要去看Cortex-A8_Technical_Reference_Manual_r3p2.pdf芯片手册了,其中是有说明的,不再累述,如下图:
*/
--------------------
/*
* Invalidate L1 I/D
*/
movr0, #0@ set up for MCR
mcrp15, 0, r0, c8, c7, 0@ invalidate TLBs
mcrp15, 0, r0, c7, c5, 0@ invalidate icache
--------------------
/*
查看芯片手册,因为以下改的内容是协处理器c1,那么你就该去查c1是用来干什么的。查看得知,是控制寄存器,查看手册Cortex-A8_Technical_Reference_Manual_r3p2.pdf,其中13,0:2位为 V、CAM:V位是对高端异常向量表的支持,如果选择0异常向量表为0x00000000-0x0000001c,如果选择1异常向量表就是FFFF0000-FFFF001c;接下来再分析下下面的指令含义bic r0, r0, #0x00000007 @ 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的含义将会打开指令缓存
*/
--------------------
/*
* disable MMU stuff and caches
*/
mrcp15, 0, r0, c1, c0, 0
bicr0, r0, #0x00002000@ clear bits 13 (--V-)
bicr0, r0, #0x00000007@ clear bits 2:0 (-CAM)
orrr0, r0, #0x00000002@ set bit 1 (--A-) Align
orrr0, r0, #0x00000800@ set bit 12 (Z---) BTB
mcrp15, 0, r0, c1, c0, 0
--------------------
/*
寄存器C1详细信息如下:
********************************我是分割线11月28*******************************
代码较多,后续我会跟进,敬请期待- smdkc100之u-boot 2010.03代码的分析1
- smdkc100之u-boot 2010.03代码的分析2
- smdkc100之u-boot 2010.03代码的分析3
- u-boot代码分析
- u-boot代码分析
- u-boot代码分析
- u-boot代码分析
- u-boot代码分析
- 对U-BOOT的第1阶段代码的分析
- 对U-BOOT的第1阶段代码的分析
- 对U-BOOT的第1阶段代码的分析
- u-boot启动代码分析
- U-Boot关键代码分析
- u-boot启动代码分析
- U-Boot关键代码分析
- U-boot第二阶段代码分析
- U-boot汇编代码分析
- U-Boot 第一阶段代码分析
- Bilateral Filtering(双边滤波)
- oracle学习笔记-序列
- asp.net中通过ashx转换,把代码写入.cs文件的2种方法(Ajax中应用)
- 无法识别的属性“targetFramework”---解决之道
- 第十四周上机项目4:数组的排序
- smdkc100之u-boot 2010.03代码的分析1
- Struts2之我见系列总结----开发流程(2012.11.29)
- java判断一个字符串在另一个字符串里的个数
- fibnacci数列
- C++: undefined reference to vtable
- 第14周项目一——数组大乐斗!
- 算法·杂烩
- Windows线程生灭 (一)
- 实现linux的互斥量c++封装