JZ2440开发板移植u-boot 2015.01----第六篇 uboot代码优化之start.S

从这篇文章开始,我们就来分析uboot的源码,同时来做uboot的优化

首先我们先准备好uboot的反汇编码:

              arm-linux-objdump -D u-boot > uboot.asm

1. 第一步分析链接文件arch/arm/cpu/u-boot.lds:
            . = 0x00000000;               //定义代码段的链接地址为0,考虑到后面代码重定位,可定义为0x34000000 - 0x20000 = 0x33fe0000, 0x20000的空间留给栈
            . = ALIGN(4);                   //当前位置4字节对齐
            .text :
            {
                   *(.__image_copy_start)             //代码段起始位放__image_copy_start,该变量定义在arch/arc/lib/sections.c

                    //char __image_copy_start[0] __attribute__((section(".__image_copy_start")));它只是个占位符,来确定中断向量表的起始位置,在此处定义为空数组,不占空间
                   *(.vectors)         //中断向量表,定义在arch/arm/lib/vectors.S中,定义了异常、中断的处理
                   arch/arm/cpu/arm920t/start.o (.text*) //这里就是我们的第一个代码文件
                  *(.text*)
            }

2. 分析第一个代码文件arch/arm/cpu/arm920t/start.S:

    .globl    reset

     reset:
         mrs    r0, cpsr
         bic    r0, r0, #0x1f
         orr    r0, r0, #0xd3
         msr    cpsr, r0            //进入SVC32模式  ,可参考ARM920T的手册 

        # if defined(CONFIG_S3C2400)
        #  define pWTCON    0x15300000
        #  define INTMSK    0x14400008    /* Interrupt-Controller base addresses */
        #  define CLKDIVN    0x14800014    /* clock divisor register */
        #else
        #  define pWTCON    0x53000000
        #  define INTMSK    0x4A000008    /* Interrupt-Controller base addresses */
        #  define INTSUBMSK    0x4A00001C
        #  define CLKDIVN    0x4C000014    /* clock divisor register */
        # endif

        ldr    r0, =pWTCON
        mov    r1, #0x0
        str    r1, [r0]               //关闭看门狗

        mov    r1, #0xffffffff
        ldr    r0, =INTMSK
        str    r1, [r0]                                     //屏蔽中断
        # if defined(CONFIG_S3C2410) ||defined(CONFIG_JZ2440)   //屏蔽子中断,这里增加对CONFIG_JZ2440的定义
        ldr    r1, =0x3ff
        ldr    r0, =INTSUBMSK
        str    r1, [r0]
        # endif
       ldr r0,=0x4C000014   //设置分频FCLK HCLK PCLK: 1:4:8 
       mov r1,#0x5               //将0x3改为0x5,我们预定义的时钟为FCLK HCLK PCLK:400:100:50M
       str r1,[r0]
       mrc p15,0,r0,c1,c0,0   //当HDIVN不为0时,必须改变总线为异步模式,增加左侧代码
       orr r0,r0,#0xc0000000
       mcr p15,0,r0,c1,c0,0

       bl    cpu_init_crit    //执行cpu_init_crit函数,该函数就在start.S中

       bl    _main            //执行_main函数

3. 分析cpu_init_crit函数:

   cpu_init_crit:
       mov    r0, #0                        //清空I/C cache
       mcr    p15, 0, r0, c7, c7, 0   
       mcr    p15, 0, r0, c8, c7, 0    
       mrc    p15, 0, r0, c1, c0, 0   //关闭mmu 和 I/C cache
       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

       bl    lowlevel_init                 //调到lowlevel_init去执行,该函数在我们board/samsung/jz2440下的lowlevel_init.S中定义

       mov    lr, ip
       mov    pc, lr

4. 分析lowlevel_init函数

.globl lowlevel_init
lowlevel_init:
    ldr     r0, =SMRDATA                                //获取SMRDATA的地址放入r0,SMRDATA存放所有的2400内存控制器的所有配置
    ldr    r1, =CONFIG_SYS_TEXT_BASE    //获取代码段的起始地址放入r1
    sub    r0, r0, r1                                         //将SMRDATA减去代码段的起始地址后放入r0,这里因为我们把代码烧到了NOR Flash中,及起始地址为0的地方,但是在链接文件中u-boot.lds,我们定义的地址为代码的运行地址, ldr     r0, =SMRDATA获取到的是运行地址,所以要减去代码段的起始地址,才是SMRDATA在NOR Flash的实际位置
    ldr    r1, =BWSCON            //将内存控制器的地址放入r1
    add     r2, r0, #13*4            //r2存入的是SMRDATA的结束地址,因为SMRDATA中有13个条目
0:
    ldr     r3, [r0], #4                //将r0存放的值及SMRDATA的首个条目放入r3,然后r0加4,即指向SMRDATA的下一个条目
    str     r3, [r1], #4                //将r3的值写入r1,即将SMRDATA的首个条目存入BWSCON寄存器,r1加4即指向下一个寄存器
    cmp     r2, r0                     //循环写入直到SMRDATA的结束
    bne     0b
    mov    pc, lr

    .ltorg
/* the literal pools origin */

SMRDATA:
    .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
    .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
    .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
    .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
    .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
    .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
    .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
    .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
    .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
    .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
    .word 0xb1
    .word 0x30
    .word 0x30
lowlevel_init的主要作用就是初始化JZ2440的内存控制器

这里可以根据我们的实际硬件进行优化,在JZ2440板子上,根据NOR的手册为了加快Nor的读取速度,需要将B0_Tacc的值从0x7调为0x5,及8个clk就可以了,另外,要将REFCNT从1113调至1269,因为我们的HCLK设置为了100M,由于我们的SDRAM只有64M,所以要将SMRDATA中的倒数第三个word调为0xb1

    

 

你可能感兴趣的:(JZ2440-U-BOOT,U-BOOT,u-boot)