基于TQ2440开发板的U-boot-1.1.6的start.S代码分析

start.S汇编源文件是U-boot执行的起始代码文件,也是不容易理解的实现部分。执行流程如下:

.globl _start  //定义_start是全局标签,其他文件也可以使用。.globlGNU汇编语法。

_start:     b       reset  //跳转到reset标签出执行,由于reset操作是在MMU工作之前/之后都有可能使用,所以这里用b来跳转。

       /*下面定义ARM异常向量表对应的跳转代码*/

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

/*其中.word的语法是用来指定该变量可以被C语言直接引用*/

       .balignl 16,0xdeadbeef /* 这个指令用来填写一个长字,即内容长度为长字,即4个字节的长度,填写内容为0xdeadbeef */

当一个异常出现以后,ARM会自动执行以下几个步骤:

1)把下一条指令的地址放到连接寄存器LR(通常是R14),这样就能够在处理异常返回时从正确的位置继续执行。

2)将相应CPSR(当前程序状态寄存器)复制到SPSR(备份的程序状态寄存器)中。从异常退出的时候,就可以由SPSR来恢复CPSR

3)根据异常类型,强制设置CPSR的运行模式位。

4)强制PC(程序计数器)从相关异常向量地址取出下一条指令执行,从而跳转到相应的异常处理程序中。

reset:

       /*

        * set the cpu to SVC32 mode

        */

       mrs  r0,cpsr   /*传送CPSR的内容到通用寄存器指令*/

       bic   r0,r0,#0x1f    /*位清除指令,即=r0&(~0x1f)*/

       orr   r0,r0,#0xd3   /*逻辑或指令,即=r0|0xd3*/

       msr  cpsr,r0   /*传送通用寄存器到CPSR指令*/

 

/* turn off the watchdog */

#if defined(CONFIG_S3C2400)

# define pWTCON        0x15300000

# define INTMSK          0x14400008    /* Interupt-Controller base addresses */

# define CLKDIVN 0x14800014    /* clock divisor register */

#elif defined(CONFIG_S3C2410)

# define pWTCON        0x53000000

# define INTMOD     0X4A000004

# define INTMSK          0x4A000008   /* Interupt-Controller base addresses */

# define INTSUBMSK   0x4A00001C

# define CLKDIVN 0x4C000014   /* clock divisor register */

#endif

 

#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)

       ldr     r0, =pWTCON

       mov     r1, #0x0  /*0x0值传入r1寄存器*/

       str     /*r1, [r0] r1种的内容写入到r0*/

 

       /*

        * mask all IRQs by setting all bits in the INTMR - default

        */

       mov r1, #0xffffffff

       ldr   r0, =INTMSK

       str   r1, [r0]

# if defined(CONFIG_S3C2410)

       ldr   r1, =0x3ff

       ldr   r0, =INTSUBMSK

       str   r1, [r0]

# endif

#endif     /* CONFIG_S3C2400 || CONFIG_S3C2410 */

cpu_init_crit 主要完成内存管理相关的寄存器设置,CP15协处理器,配置内存区控制寄存器。另外这段代码中调用了lowlevel_init 函数,进行寄存器的具体设置,与采用的内存芯片有关。

#ifndef CONFIG_SKIP_LOWLEVEL_INIT

       bl     cpu_init_crit  /*bl是带跳转返回指令*/

#endif

接下来看一下cpu_init_crit标签的实现,如下:

cpu_init_crit:

       /*

        * flush v4 I/D caches

        */

       mov r0, #0

       mcr p15, 0, r0, c7, c7, 0      /* ARM 处理器寄存器到协处理器寄存器的数据传送指令,清除ID cache分支运算缓存(BTB*/

       mcr p15, 0, r0, c8, c7, 0      /* flush v4 TLBTranslation Lookaside Buffers */

 

       /*

        * disable MMU stuff and caches

        */

       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

 

       /*

        * before relocating, we have to setup RAM timing

        * because memory timing is board-dependend, you will

        * find a lowlevel_init.S in your board directory.

        */

       mov ip, lr

       bl     lowlevel_init /*跳转到lowlevel_init,处理完返回*/

       mov lr, ip

       mov pc, lr

lowlevel_init实现是在board/tq2440/ lowlevel_init.S中,主要完成初始化内存控制器,即SDRAM的初始化。

.globl lowlevel_init

lowlevel_init:

       /* memory control configuration */

       /* make r0 relative the current location so that it */

       /* reads SMRDATA out of FLASH rather than memory ! */

       ldr     r0, =SMRDATA

       ldr   r1, _TEXT_BASE

       sub  r0, r0, r1

       ldr   r1, =BWSCON       /* Bus Width Status Controller */

       add     r2, r0, #13*4

0:

       ldr     r3, [r0], #4

       str     r3, [r1], #4

       cmp     r2, r0

       bne     0b

 

       /* everything is fine now */

       mov pc, lr

接下来是设置堆栈,设置后的逻辑位置如下图所示:

 

stack_setup:

       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                        */

       sub  sp, r0, #12             /* leave 3 words for abort-stack    */

接下来调用:bl clock_init 用来完成初始化时钟的目的。

下面的代码是将NandFlash数据搬运到SDRAM的核心实现代码,其最主要由C语言函数CopyCode2Ram函数来完成复制目的,该函数在board/tq2440/boot_init.c中实现。

relocate:                       /* relocate U-Boot to RAM        */

       adr   r0, _start        /* r0 <- current position of code   */

       ldr   r1, _TEXT_BASE         /* test if we run from flash or RAM */

       cmp     r0, r1                  /* don't reloc during debug         */

       beq     clear_bss

 

       ldr   r2, _armboot_start

       ldr   r3, _bss_start

       sub  r2, r3, r2        /* r2 <- size of armboot            */

       bl  CopyCode2Ram      /* r0: source, r1: dest, r2: size */

       接下来就是清除BSS段,并进入C语言阶段的高级初始化过程实现。

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

 

       ldr   pc, _start_armboot

_start_armboot:      .word start_armboot   /*start_armbootC代码函数,在lib_arm/board.c中实现*/

你可能感兴趣的:(技术交流文章,代码分析,translation,c,汇编,语言,flash)