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币”即可。

  • 相关阅读:
    【Collect】免费图片库网站推荐(国外高清可商用)
    "One or more types required to compile a dynamic expression cannot be found. Are you missing references to Microsoft.CSharp.dll and System.Core.dll?"的解决方法
    "从客户端中检测到有潜在危险的 Request.Form 值"的解决方案汇总
    Fira Code:适合程序员的编程字体
    【Notepad++】notepad++主题和字体设置(非常好看舒服的)
    【sql server】"已更新或删除的行值要么不能使该行成为唯一行,要么改变了多个行" 解决方案
    【SQL】sql update 多表关联更新方法总结
    【C#】 List按指定字段的给出的自定义顺序进行排序
    3 常量与变量
    2 go语言的基础
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/3055294.html
Copyright © 2011-2022 走看看