zoukankan      html  css  js  c++  java
  • 一,移植uboot-分析uboot启动流程

    文档时间:2018-08-08

    交叉编译器:arm-linux-gcc-4.3.2

    Ubuntu版本:16.04

    uboot版本:2013.10

    uboot启动流程简要如下:

        a,设置CPU为管理模式

        b,关闭看门狗

        c,关闭中断

        d,设置时钟频率

        e,进入lowlevel_init.S,初始化各个bank

        f,进入board_init_f()函数

        h,代码重定位,清除bss

        i,跳转到board_init_r(),进入第二阶段

    1,进入https://www.amazon.com/clouddrive/share/HtTEzbceyJDyHv7anDLboEjTe0OkFbYReMxRp3CF20n下载uboot源码

    1.1,在Windows下解压uboot源码,建立source insight工程

      可以选择将uboot文件夹下所有文件添加到source insight工程中,也可以选择添加,本工程在arch/arm/cpu目录下只添加:

    arch/arm/cpu/arm920t        //只添加这个目录下的所有文件

      在board目录下只添加

    board/samsung/smdk2410        //只添加2410单板

    2,通过FileZilla将Windows下的uboot压缩文件传到Ubuntu /home/aaron/work/u-boot目录下,然后编译,烧写

    2.1,编译,烧写uboot

      由于本工程中所用开发本为JZ2440,单板和SMDK2410很像,所以我们选择编译smdk2410,在Ubuntu中输入命令

    cd work/u-boot
    tar xjf u-boot-2013.10.tar.bz2
    cd u-boot-2013.10
    make smdk2410_config            //配置单板SMDK2410
    make                            //编译生成u-boot.bin

      将生成的u-boot.bin通过j-link烧写到JZ2440开发板上(开发板选择nor启动,否则无法烧写,烧写完成发现串口无任何输出,接下来分析uboot启动代码

    3,首先查看archarmcpu目录下的u-boot.lds链接文件

    ENTRY(_start)       //入口地址
    SECTIONS
    {
        . = 0x00000000;  //链接地址
    
        . = ALIGN(4);
        .text :

       u-boot最开始会进入到_start的位置,而_start的位置在arch/arm/cpu/arm920t/文件夹下

    4,分析arch/arm/cpu/arm920t/start.S文件

    .globl _start                        //声明_start全局符号
    _start:    b    start_code                //跳转到start_code处
        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
    
        .balignl 16,0xdeadbeef
    
    
    /*
     *************************************************************************
     *
     * Startup Code (called from the ARM reset exception vector)
     *
     * do important init only if we don't start from memory!
     * relocate armboot to ram
     * setup stack
     * jump to second stage
     *
     *************************************************************************
     */
    
    .globl _TEXT_BASE
    _TEXT_BASE:
    #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_TEXT_BASE)
        .word    CONFIG_SPL_TEXT_BASE
    #else
        .word    CONFIG_SYS_TEXT_BASE
    #endif
    
    /*
     * These are defined in the board-specific linker script.
     * Subtracting _start from them lets the linker put their
     * relative position in the executable instead of leaving
     * them null.
     */
    .globl _bss_start_ofs
    _bss_start_ofs:
        .word __bss_start - _start
    
    .globl _bss_end_ofs
    _bss_end_ofs:
        .word __bss_end - _start
    
    .globl _end_ofs
    _end_ofs:
        .word _end - _start
    
    #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
    
    /* IRQ stack memory (calculated at run-time) + 8 bytes */
    .globl IRQ_STACK_START_IN
    IRQ_STACK_START_IN:
        .word    0x0badc0de
    
    /*
     * the actual start code
     */
    
    start_code:              //设置cpsr寄存器,让CPU处于管理模式
        /*
         * set the cpu to SVC32 mode
         */
        mrs    r0, cpsr
        bic    r0, r0, #0x1f
        orr    r0, r0, #0xd3
        msr    cpsr, r0
    
    #if    defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK)
        /*
         * relocate exception table
         */
        ldr    r0, =_start
        ldr    r1, =0x0
        mov    r2, #16
    copyex:
        subs    r2, r2, #1
        ldr    r3, [r0], #4
        str    r3, [r1], #4
        bne    copyex
    #endif
    
    #ifdef CONFIG_S3C24X0
        /* turn off the watchdog */
    
    # 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]
    
        /*
         * 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
    
        /* FCLK:HCLK:PCLK = 1:2:4 */
        /* default FCLK is 120 MHz ! */    //设置时钟
        ldr    r0, =CLKDIVN
        mov    r1, #3
        str    r1, [r0]
    #endif    /* CONFIG_S3C24X0 */
    
        /*
         * we do sys-critical inits only at reboot,
         * not when booting from ram!
         */
    #ifndef CONFIG_SKIP_LOWLEVEL_INIT
        bl    cpu_init_crit            //跳转到lowlevel_init.S,初始化各个bank
    #endif
    
        bl    _main                 //跳转到_main
    
    /*------------------------------------------------------------------------------*/
    
        .globl    c_runtime_cpu_setup
    c_runtime_cpu_setup:
    
        mov    pc, lr
    
    /*
     *************************************************************************
     *
     * CPU_init_critical registers
     *
     * setup important registers
     * setup memory timing
     *
     *************************************************************************
     */
    
    
    #ifndef CONFIG_SKIP_LOWLEVEL_INIT
    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
    
        bl    lowlevel_init    //初始化blank
    
        mov    lr, ip
        mov    pc, lr
    #endif /* CONFIG_SKIP_LOWLEVEL_INIT */

      可以看出start.S里主要工作是:初始化异常向量表,设置SVC模式,关闭看门狗,关闭中断,设置时钟

      SDRAM的设置在lowlevel_init.S(board/samsung/smdk2410)中 ,start.S工作完成之后,接下来就是调用_main了

    5,分析/arch/arm/lib/crt0.S文件

    ENTRY(_main)        //_main入口位置
    
    /*
     * Set up initial C runtime environment and call board_init_f(0).
     */
    
    #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
        ldr    sp, =(CONFIG_SPL_STACK)
    #else
        ldr    sp, =(CONFIG_SYS_INIT_SP_ADDR)
    #endif
        bic    sp, sp, #7    /* 8-byte alignment for ABI compliance */
        sub    sp, #GD_SIZE    /* allocate one GD above SP */
        bic    sp, sp, #7    /* 8-byte alignment for ABI compliance */  //设置栈
        mov    r9, sp        /* GD is above SP */
        mov    r0, #0
        bl    board_init_f    //进入第一个C函数
    
    #if ! defined(CONFIG_SPL_BUILD)
    
    /*
     * Set up intermediate environment (new sp and gd) and call
     * relocate_code(addr_moni). Trick here is that we'll return
     * 'here' but relocated.
     */
    
        ldr    sp, [r9, #GD_START_ADDR_SP]    /* sp = gd->start_addr_sp */  
        bic    sp, sp, #7    /* 8-byte alignment for ABI compliance */
        ldr    r9, [r9, #GD_BD]        /* r9 = gd->bd */
        sub    r9, r9, #GD_SIZE        /* new GD is below bd */
    
        adr    lr, here
        ldr    r0, [r9, #GD_RELOC_OFF]        /* r0 = gd->reloc_off */
        add    lr, lr, r0
        ldr    r0, [r9, #GD_RELOCADDR]        /* r0 = gd->relocaddr */
        b    relocate_code        //跳转到relocate_code进行代码重定位
    here:
    
    /* Set up final (full) environment */
    
        bl    c_runtime_cpu_setup    /* we still call old routine here */
    
        ldr    r0, =__bss_start    /* this is auto-relocated! */  
        ldr    r1, =__bss_end        /* this is auto-relocated! */
    
        mov    r2, #0x00000000        /* prepare zero to clear BSS */
    
    clbss_l:cmp    r0, r1            /* while not at end of BSS */    //清除BSS段
        strlo    r2, [r0]        /* clear 32-bit BSS word */
        addlo    r0, r0, #4        /* move to next */
        blo    clbss_l
    
        bl coloured_LED_init
        bl red_led_on          //这两行是跳转到与底层led控制有关的c函数
    
        /* call board_init_r(gd_t *id, ulong dest_addr) */
        mov     r0, r9                  /* gd_t */
        ldr    r1, [r9, #GD_RELOCADDR]    /* dest_addr */
        /* call board_init_r */
        ldr    pc, =board_init_r    /* this is auto-relocated! */  //跳转到第二阶段的c函数
    
        /* we should not return here. */
    
    #endif
    
    ENDPROC(_main)
        
      
      relocate_code在arch/arm/lib/relocate.S里,主要讲的是代码的拷贝,这里不再详说  
      board_init_f()函数在arch/arm/lib/board.c里,board_init_f函数主要是根据配置对全局信息结构体gd和init_sequence中的函数进行初始化,init_sequence中函数包括
    init_fnc_t *init_sequence[] = {
        arch_cpu_init,        /* basic arch cpu dependent setup */
        mark_bootstage,
    #ifdef CONFIG_OF_CONTROL
        fdtdec_check_fdt,
    #endif
    #if defined(CONFIG_BOARD_EARLY_INIT_F)
        board_early_init_f,    //在board/samsung/smdk2410/smdk2410.c中定义,主要设置时钟和GPIO
    #endif
        timer_init,        /* initialize timer */
    #ifdef CONFIG_BOARD_POSTCLK_INIT
        board_postclk_init,
    #endif
    #ifdef CONFIG_FSL_ESDHC
        get_clocks,
    #endif
        env_init,        /* initialize environment */
        init_baudrate,        /* initialze baudrate settings */
        serial_init,        /* serial communications setup */
        console_init_f,        /* stage 1 init of console */
        display_banner,        /* say that we are here */
    #if defined(CONFIG_DISPLAY_CPUINFO)
        print_cpuinfo,        /* display cpu info (and speed) */
    #endif
    #if defined(CONFIG_DISPLAY_BOARDINFO)
        checkboard,        /* display board info */
    #endif
    #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C)
        init_func_i2c,
    #endif
        dram_init,        /* configure available RAM banks */
        NULL,
    };
      board_init_r()函数在arch/arm/lib/board.c里,该函数会对各个外设初始化、环境变量初始化等
      在board_init_r函数里首先会执行board_init(); /* Setup chipselects */函数,在这个函数里会设置机器id和传给内核的入口参数地址
        /* arch number of SMDK2410-Board */
        gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;
    
        /* adress of boot parameters */
        gd->bd->bi_boot_params = 0x30000100;

    uboot启动过程到此就结束了
        
  • 相关阅读:
    实验2:Mininet实验——拓扑的命令脚本生成
    实验1:Mininet源码安装和可视化拓扑工具
    第一次博客作业
    数据采集第四次作业
    第7组(69)团队展示
    数据采集第三次作业
    结对作业
    数据采集第二次作业
    数据采集第一次作业
    第一次个人编程作业
  • 原文地址:https://www.cnblogs.com/zhyy-mango/p/9446006.html
Copyright © 2011-2022 走看看