6410 uboot启动引导分析

来源:互联网 发布:linux vi常用命令 编辑:程序博客网 时间:2024/05/22 09:00

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代码中的一些重要环境变量

 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 蓝牙不小心点到忽略此设备怎么办 千牛工作台无线开店确认不了怎么办 开通诚信通后营业执照注销了怎么办 淘宝标的货跟发的不一样怎么办 wps表格里单元之间重叠了怎么办 淘宝店铺停了一段时间没了怎么办 转转买家收货为敲诈卖家怎么办 淘宝被投诉盗用官网图片怎么办 淘宝订单买下后卖家告知无货怎么办 盗图被删除还是待处理违规该怎么办 如果买家说你们的买家秀一样怎么办 花呗唤起安全核身验证失败怎么办 淘宝买东西花呗分期额度不够怎么办 支付宝余额支付额度已达上限怎么办 我是淘宝卖家遇到无良买家怎么办 我的保证金被淘宝当做违约金怎么办 淘宝顾客不想退货申请仅退款怎么办 被买家提供证明说我卖假货怎么办 淘宝退货快递公司填错了俩次怎么办 淘宝上退货把运单号写错了怎么办? 阿里巴巴发货了快递单号掉了怎么办 淘宝上买东西货物被物流扣留怎么办 淘宝买错了对方已发货怎么办 淘宝卖家发货的时候没货了怎么办 买了球显示未出票中奖了怎么办 点错了允许易企秀获得权限怎么办 淘宝还没发货商家拒绝退款怎么办 买家不补邮费还要你发货怎么办 天猫客服提示获取信息失败怎么办 拼多多下单了商家不发货怎么办 店铺扣2分宝贝降权了怎么办 淘宝店没订单没流量怎么办啊 淘宝id账号登录密码忘记了怎么办 淘宝网店铺授权客服联系不上怎么办 卖家发货买家查不到物流信息怎么办 物流信息到了但东西没到怎么办 淘宝详情已更改对方恶意投诉怎么办 淘宝店写的不给退换怎么办 从饿了么商家借款逾期怎么办 谷歌浏览器网页无法复制文字怎么办 复制粘贴在文件本里找不到了怎么办