zoukankan      html  css  js  c++  java
  • 地址代码uboot之start.S源码分析

    每日一贴,今天的容内关键字为地址代码

        /arch/arm920t/cpu/start.s件文就是uboot的第一阶段,uboot的前4K容内,即nandflash中的前4K容内会被拷贝到cpu中的SRAM中运行,这一小段代码担任初始化硬件环境,并将残余的Uboot代码加载到内存中去。从而跳到转第二阶段,在第二阶段运行之前要需建立栈堆。

        IRQ_STACK_START    .word 0x0badc0de

        FRQ_STACK_START    .word 0x0badc0de

        /*

     *  armboot - Startup Code for ARM920 CPU-core

     *

      */

        #include <config.h>

        #include <version.h>

        /*

     *************************************************************************

     *

     * Jump vector table as in table 3.1 in [1]

     *

     *************************************************************************

     */

        .globl _start

        _start:  b       reset        //b是跳转指令,即跳到转reset标签处。接着返回到此处。

         ldr  pc, _undefined_instruction置设断中向量表 0x0 0x4.....0x8 0xc

         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来在以后位置放置一个值,这个值实际上就用对应的断中理处函数的地址
    ;.word的义意为在以后地址处放入一个16bits值

         .balignl 16,0xdeadbeef

        /*

     *************************************************************************

     *

     * Startup Code (reset vector)

     *

     * do important init only if we don't start from memory!

     * relocate armboot to ram

     * setup stack

     * jump to second stage //从英文注释中可以看出starts.o的作用。

     *

     *************************************************************************

     */

        _TEXT_BASE:

         .word    TEXT_BASE

        .globl _armboot_start

        _armboot_start:

         .word _start

        /*

     * These are defined in the board-specific linker script. 针对不同板类型的链接脚本中经已义定过了,体具的脚本??

     */

        .globl _bss_start   //未初始化的数据段开始地址

        _bss_start:

         .word __bss_start

        .globl _bss_end  //结束地址

        _bss_end:

         .word _end

        #ifdef CONFIG_USE_IRQ   //断中是不是经已置配。

        /* IRQ stack memory (calculated at run-time) */

        .globl IRQ_STACK_START

        IRQ_STACK_START:

         .word    0x0badc0de  //栈堆的始起地址。

        /* IRQ stack memory (calculated at run-time) */

        .globl FIQ_STACK_START

        FIQ_STACK_START:

         .word 0x0badc0de

        #endif

        /*

     * the actual reset code

     */

        _start:入口处,马上跳到转reset处,在SVC状态下要关闭有所断中。

        reset:

         /*

          * set the cpu to SVC32 mode //超等用户态,操纵统系用使的保护模式。统系复位和软件断中时进入该模式。

          */

         mrs  r0,cpsr   //将以后cpsr的状态为保存到r0中。

         bic  r0,r0,#0x1f  //bic,位清零指令。0x1f=00011111,相当于清除低5位。刚好是模式位。

         orr  r0,r0,#0xd3  //或指令。很明显是置模式位。0xd3=11010011以及置设5,6,7位的状态位。制止FIQ,IRQ,处于arm状态。低5位为10011,则对应超等用户态。

         msr  cpsr,r0  //在将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)我们的是2410,如果移植其它的,则可以添加关相的基地址

        # define pWTCON        0x53000000  //pWTCON 看门狗寄存器的基地址,手册上就是WTCON,这里多一个p

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

        # define INTSUBMSK 0x4A00001C 断中子掩码寄存器

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

        #endif

        将看门狗寄存器清空,其各位含意为,第0位为1则当看门狗定时器溢出时重启,为0则不重启,初始值为1

        第2位为断中使能位,初值为0

        第3,4位为时钟频分银子,初值为00

        第5位为看门狗的使能位,初值为1

        第8~15位为比例因子,初值为0x80

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

         ldr     r0, =pWTCON //将pWTCON寄存器的地址赋给r0

         mov     r1, #0x0

         str     r1, [r0]  //将pWTCON有所位置为0,就关闭看门狗了,实际上只要将第5位置0可即。

         /*

          * 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, =0x7ff   011111111111,很多料资上是0x3ff。手册上定规有13位可用

         ldr  r0, =INTSUBMSK如果是2410,这个寄存器也要蔽屏

         str  r1, [r0] //将低13位全都置1 13位可用 而不是12位

        # endif

         /* FCLK:HCLK:PCLK = 1:2:4 */

         /* default FCLK is 120 MHz ! */时钟置设

         ldr  r0, =CLKDIVN

         mov  r1, #3

         str  r1, [r0]

        #endif   /* CONFIG_S3C2400 || CONFIG_S3C2410 */

         /*

          * we do sys-critical inits only at reboot,

          * not when booting from ram!

          */

        #ifndef CONFIG_SKIP_LOWLEVEL_INIT 避免重复用引cpu_init_crit函数。

         bl   cpu_init_crit

        #endif

         

        橙色的分部代码,是针对从nor flash中启动的设备。对于不是从nandflash中启动的设备,没什么用。这一段似乎也能行执代码制复.

        #ifndef CONFIG_SKIP_RELOCATE_UBOOT 

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

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

        查看以后代码的地址信息,若从ram中运行,则_start=_TEXT_BASE,否则_start = 0x00000000

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

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

             beq     stack_setup 若相称,则建立栈堆

         

             ldr  r2, _armboot_start     若不等,则表现从flash中运行,重定向代码

             ldr  r3, _bss_start         获得未初始化数据段地址

             sub  r2, r3, r2         /* r2 <- size of armboot            */代码段的度长

             add  r2, r0, r2         /* r2 <- source end address         */代码的度长

         

        copy_loop:

        制复代码,r0为代码的始起地址,r1为ram中地址,r2为代码的终止地址,每次copy后将r0的值递增同r2较比来判断是不是制复成完。

             ldmia    r0!, {r3-r10}      /* copy from source address [r0]    */

             stmia    r1!, {r3-r10}      /* copy to   target address [r1]    */

             cmp  r0, r2             /* until source end addreee [r2]    */

             ble  copy_loop

        #endif   /* CONFIG_SKIP_RELOCATE_UBOOT */

             /* Set up the stack                                */

        stack_setup:

             ldr  r0, _TEXT_BASE         /* upper 128 KiB: relocated uboot   */

             sub  r0, r0, #CFG_MALLOC_LEN /* malloc area  192K                    */

             sub  r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo 配分128节字来存储开发板信息        */

        #ifdef CONFIG_USE_IRQ

             sub  r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)

        #endif再减去12节字用于栈点起

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

         

        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

        #if 0

             /* try doing this stuff after the relocation */

             ldr     r0, =pWTCON

             mov     r1, #0x0

             str     r1, [r0]

         

             /*

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

              */

             mov  r1, #0xffffffff

             ldr  r0, =INTMR

             str  r1, [r0]

         

             /* FCLK:HCLK:PCLK = 1:2:4 */

             /* default FCLK is 120 MHz ! */

             ldr  r0, =CLKDIVN

             mov  r1, #3

             str  r1, [r0]

             /* END stuff after relocation */

        #endif

        当初的设别,大都是利用SDRAM与NANDFLASH独特作用,因此为了支撑能从nand_flash中启动,要需添加面下的红色代码。

         

        #ifdef CONFIG_S3C2410_NAND_BOOT

        bl copy_myself

         

        @jump to ram

        ldr r1,=on_the_ram

        add pc,r1,#0

        nop

        nop

        1:

        b 1b

        on_the_ram

        #endif

         ldr  pc, _start_armboot

        _start_armboot:    .word start_armboot

        #ifdef CONFIG_S3C2410_NAND_BOOT

        copy_myself:

        mov r10.lr  将以后的lr保存到r10中,保存断点地址

        @reset nand

        mov r1,#NAND_CTL_BASE nandflash基地址

        ldr r2,0xf830 r2 = 1111,1000,0011,0000 第15位为nandflash控制器使能位,第12位初始化ECC,第11位nFCE使能?????有问题

        str r2,[r1,#oNFCONF]

        每日一道理
    冰心说道:“爱在左,同情在右,走在生命的两旁,随时撒种,随时开花,将这一径长途,点缀得香花弥漫,使穿枝拂叶的行人,踏着荆棘,不觉得痛苦,有泪可落,却不是悲凉。”

        ldr r2,[r1,#oNFCONF]

         

        bic r2,r2,#0x800   将第11位清零指令,使能片芯

        str r2,[r1,#oNFCONF]

        写入令命

        mov r2,#0xff   @reset command

        strb r2,[r1,#oNFCMD]

         

        mov r3,#0 

        1:
      add r3, r3, #0x1     //循环等待  

        cmp r3, #0xa
      blt 1b

    2:利用状态寄存器试测flash部内操纵是不是成完,如果成完则状态寄存器将返回1.NFSTAT最后位一为0时,表现正在忙,为1表现闲暇
      ldr r2, [r1, #oNFSTAT] @ wait ready
      tst r2, #0x1 //tst位试测指令
      beq 2b

      ldr r2, [r1, #oNFCONF] 制止片芯
      orr r2, r2, #0x800 @ disable chip
      str r2, [r1, #oNFCONF]

    @ get read to call C functions (for nand_read()) 建立栈堆,栈点起0x33f00000,巨细为0x8000
      ldr sp, DW_STACK_START         @ setup stack pointer
      mov fp, #0                     @ no previous frame, so fp=0


         

         

        @ copy U-Boot to RAM。r0 r1 r2为传入到Nand_read_ll中的三个参数,nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)

        可知,
      ldr r0, =UBOOT_RAM_BASE 
      mov r1, #0x0
      //mov r2, #0x20000  //UBOOT巨细为128K 这三个参数传入到nand_read_ll中

        mov r2. #0x30000 //置设为192k
      bl nand_read_ll
      tst r0, #0x0     r0为返回值nand_read_ll的返回值
      beq ok_nand_read

    bad_nand_read:
    loop2: b loop2 @ infinite loop


    ok_nand_read: nand_flash通过ecc验校来保障拷贝到SDRAM中的容内是确正的
    @ verify
      mov r0, #0
      ldr r1, =TEXT_BASE
      mov r2, #0x400 @ 4 bytes * 1024 = 4K-bytes,每条指令占4个节字,共挪动0x400即1024次,加起来就挪动了4*1024即4K的巨细
    go_next:
      ldr r3, [r0], #4
      ldr r4, [r1], #4
      teq r3, r4
      bne notmatch
      subs r2, r2, #4
      beq stack_setup
      bne go_next

    notmatch:
    loop3: b loop3 @ infinite loop

    #endif @ CONFIG_S3C2410_NAND_BOOT

        /*

     *************************************************************************

     *

     * CPU_init_critical registers

     *

     * setup important registers

     * setup memory timing

     *

     *************************************************************************

     */

        #ifndef CONFIG_SKIP_LOWLEVEL_INIT  cpu的置设,楚清I/D cache,清除TLB

        cpu_init_crit:

         /*

          * flush v4 I/D caches

          */

         mov  r0, #0

         mcr  p15, 0, r0, c7, c7, 0  /* flush v3/v4 cache */

         mcr  p15, 0, r0, c8, c7, 0  /* flush v4 TLB */

         /*

          * 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        //返回到reset

         bl   lowlevel_init

         mov  lr, ip

         mov  pc, lr        //从lowlevel_init中,返回到reset

        #endif /* CONFIG_SKIP_LOWLEVEL_INIT */

        /*

     *************************************************************************

     *

     * Interrupt handling 断中函数的理处。义定各种常异指令。

     *

     *************************************************************************

     */

        @

        @ IRQ stack frame.

        @

        #define S_FRAME_SIZE   72

        #define S_OLD_R0   68

        #define S_PSR      64

        #define S_PC       60

        #define S_LR       56

        #define S_SP       52

        #define S_IP       48

        #define S_FP       44

        #define S_R10      40

        #define S_R9       36

        #define S_R8       32

        #define S_R7       28

        #define S_R6       24

        #define S_R5       20

        #define S_R4       16

        #define S_R3       12

        #define S_R2       8

        #define S_R1       4

        #define S_R0       0

        #define MODE_SVC 0x13

        #define I_BIT 0x80

        /*

     * use bad_save_user_regs for abort/prefetch/undef/swi ...

     * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling

     */

         .macro   bad_save_user_regs

         sub  sp, sp, #S_FRAME_SIZE

         stmia    sp, {r0 - r12}              @ Calling r0-r12

         ldr  r2, _armboot_start

         sub  r2, r2, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)

         sub  r2, r2, #(CFG_GBL_DATA_SIZE+8)  @ set base 2 words into abort stack

         ldmia    r2, {r2 - r3}          @ get pc, cpsr

         add  r0, sp, #S_FRAME_SIZE       @ restore sp_SVC

         add  r5, sp, #S_SP

         mov  r1, lr

         stmia    r5, {r0 - r3}          @ save sp_SVC, lr_SVC, pc, cpsr

         mov  r0, sp

         .endm

         .macro   irq_save_user_regs

         sub  sp, sp, #S_FRAME_SIZE

         stmia    sp, {r0 - r12}              @ Calling r0-r12

         add     r8, sp, #S_PC

         stmdb   r8, {sp, lr}^                   @ Calling SP, LR

         str     lr, [r8, #0]                    @ Save calling PC

         mrs     r6, spsr

         str     r6, [r8, #4]                    @ Save CPSR

         str     r0, [r8, #8]                    @ Save OLD_R0

         mov  r0, sp

         .endm

         .macro   irq_restore_user_regs

         ldmia    sp, {r0 - lr}^              @ Calling r0 - lr

         mov  r0, r0

         ldr  lr, [sp, #S_PC]             @ Get PC

         add  sp, sp, #S_FRAME_SIZE

         subs pc, lr, #4             @ return & move spsr_svc into cpsr

         .endm

         .macro get_bad_stack

         ldr  r13, _armboot_start         @ setup our mode stack

         sub  r13, r13, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)

         sub  r13, r13, #(CFG_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack

         str  lr, [r13]          @ save caller lr / spsr

         mrs  lr, spsr

         str     lr, [r13, #4]

                     

         mov  r13, #MODE_SVC              @ prepare SVC-Mode

         @ msr    spsr_c, r13

         msr  spsr, r13

         mov  lr, pc

         movs pc, lr

         .endm

         .macro get_irq_stack             @ setup IRQ stack

         ldr  sp, IRQ_STACK_START

         .endm

         .macro get_fiq_stack             @ setup FIQ stack

         ldr  sp, FIQ_STACK_START

         .endm

        /*

     * exception handlers

     */

         .align  5

        undefined_instruction:

         get_bad_stack

         bad_save_user_regs

         bl   do_undefined_instruction

         .align   5

        software_interrupt:

         get_bad_stack

         bad_save_user_regs

         bl   do_software_interrupt

         .align   5

        prefetch_abort:

         get_bad_stack

         bad_save_user_regs

         bl   do_prefetch_abort

         .align   5

        data_abort:

         get_bad_stack

         bad_save_user_regs

         bl   do_data_abort

         .align   5

        not_used:

         get_bad_stack

         bad_save_user_regs

         bl   do_not_used

        #ifdef CONFIG_USE_IRQ

         .align   5

        irq:

         get_irq_stack

         irq_save_user_regs

         bl   do_irq

         irq_restore_user_regs

         .align   5

        fiq:

         get_fiq_stack

         /* someone ought to write a more effiction fiq_save_user_regs */

         irq_save_user_regs

         bl   do_fiq

         irq_restore_user_regs

        #else

         .align   5

        irq:

         get_bad_stack

         bad_save_user_regs

         bl   do_irq

         .align   5

        fiq:

         get_bad_stack

         bad_save_user_regs

         bl   do_fiq

        #endif

    文章结束给大家分享下程序员的一些笑话语录: 腾讯总舵主马化腾,有人曾经戏称如果在Z国选举总统,马化腾一定当选,因为只要QQ来一个弹窗”投马总,送Q币”即可。

  • 相关阅读:
    高级特性(4)- 数据库编程
    UVA Jin Ge Jin Qu hao 12563
    UVA 116 Unidirectional TSP
    HDU 2224 The shortest path
    poj 2677 Tour
    【算法学习】双调欧几里得旅行商问题(动态规划)
    南洋理工大学 ACM 在线评测系统 矩形嵌套
    UVA The Tower of Babylon
    uva A Spy in the Metro(洛谷 P2583 地铁间谍)
    洛谷 P1095 守望者的逃离
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/3055294.html
Copyright © 2011-2022 走看看