第一阶段:

1.硬件设备初始化:将CPU设为SVC模式,关闭开门狗,设置时钟,关闭MMU,Cache(在u-boot-1.1.6/cpu/arm920t/start.s中定义)

2.准备ram:设置存储控制器(在u-boot-1.1.6/board/100ask24x0/lowlevel.s中实现)

#include <config.h>
#include <version.h>

#define BWSCON    0x48000000

/* BWSCON */
#define DW8             (0x0)
#define DW16             (0x1)
#define DW32             (0x2)
#define WAIT             (0x1<<2)
#define UBLB             (0x1<<3)

#define B1_BWSCON          (DW16)
#define B2_BWSCON          (DW16)
//#define B3_BWSCON          (DW16 + WAIT + UBLB)
#define B3_BWSCON          (DW16 + UBLB)
#define B4_BWSCON          (DW16 + WAIT + UBLB)
#define B5_BWSCON          (DW8)
#define B6_BWSCON          (DW32)
#define B7_BWSCON          (DW32)

/* BANK0CON */
#define B0_Tacs             0x0    /*  0clk */
#define B0_Tcos             0x0    /*  0clk */
#define B0_Tacc             0x7    /* 14clk */
#define B0_Tcoh             0x0    /*  0clk */
#define B0_Tah             0x0    /*  0clk */
#define B0_Tacp             0x0
#define B0_PMC             0x0    /* normal */

/* BANK1CON */
#define B1_Tacs             0x0    /*  0clk */
#define B1_Tcos             0x0    /*  0clk */
#define B1_Tacc             0x7    /* 14clk */
#define B1_Tcoh             0x0    /*  0clk */
#define B1_Tah             0x0    /*  0clk */
#define B1_Tacp             0x0
#define B1_PMC             0x0

#define B2_Tacs             0x0
#define B2_Tcos             0x0
#define B2_Tacc             0x7
#define B2_Tcoh             0x0
#define B2_Tah             0x0
#define B2_Tacp             0x0
#define B2_PMC             0x0

#define B3_Tacs             0x0    /*  0clk */
#define B3_Tcos             0x3    /*  4clk */
#define B3_Tacc             0x7    /* 14clk */
#define B3_Tcoh             0x1    /*  1clk */
#define B3_Tah             0x0    /*  0clk */
#define B3_Tacp             0x3     /*  6clk */
#define B3_PMC             0x0    /* normal */

#define B4_Tacs             0x0    /*  0clk */
#define B4_Tcos             0x3    /*  4clk */
#define B4_Tacc             0x7    /* 14clk */
#define B4_Tcoh             0x1    /*  1clk */
#define B4_Tah             0x3    /*  4clk */
#define B4_Tacp             0x6 /*  6clk */
#define B4_PMC             0x0    /* normal */

#define B5_Tacs             0x0    /*  0clk */
#define B5_Tcos             0x0    /*  0clk */
#define B5_Tacc             0x7    /* 14clk */
#define B5_Tcoh             0x0    /*  0clk */
#define B5_Tah             0x0    /*  0clk */
#define B5_Tacp             0x0
#define B5_PMC             0x0    /* normal */

#define B6_MT             0x3    /* SDRAM */
#define B6_Trcd              0x1
#define B6_SCAN             0x1    /* 9bit */

#define B7_MT             0x3    /* SDRAM */
#define B7_Trcd             0x1    /* 3clk */
#define B7_SCAN             0x1    /* 9bit */

/* REFRESH parameter */
#define REFEN             0x1    /* Refresh enable */
#define TREFMD             0x0    /* CBR(CAS before RAS)/Auto refresh */
#define Trp                 0x0    /* 2clk */
#define Trc                0x3    /* 7clk */
#define Tchr             0x2    /* 3clk */
#define REFCNT             0x4f4    /* period=7.8125us, HCLK=100Mhz, (2048+1-7.8125*100) */
/**************************************/

_TEXT_BASE:
    .word    TEXT_BASE

.globl lowlevel_init
lowlevel_init:
    ldr     r0, =SMRDATA  /* 使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

    .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

 

3.复制boot的第二阶段的代码到ram

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 */
#if 1
bl CopyCode2Ram /* r0: source, r1: dest, r2: size */
#else
add r2, r0, r2 /* r2 <- source end address */

copy_loop:
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

4.设置好栈

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

#ifdef CONFIG_USE_IRQ
    sub    r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
    sub    sp, r0, #12        /* leave 3 words for abort-stack    */

 

5.跳转到第二阶段的C入口:先清理bss段,再调用arm_lib/board.c的start_armboot函数进入第二阶段

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
void start_armboot (void)
{
    init_fnc_t **init_fnc_ptr;
    char *s;
#ifndef CFG_NO_FLASH
    ulong size;
#endif
#if defined(CONFIG_VFD) || defined(CONFIG_LCD)
    unsigned long addr;
#endif

    /* Pointer is writable since we allocated a register for it */
    gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
    /* compiler optimization barrier needed for GCC >= 3.4 */
    __asm__ __volatile__("": : :"memory");

    memset ((void*)gd, 0, sizeof (gd_t));
    gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
    memset (gd->bd, 0, sizeof (bd_t));

    monitor_flash_len = _bss_start - _armboot_start;

    for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
        if ((*init_fnc_ptr)() != 0) {
            hang ();
        }
    }

#ifndef CFG_NO_FLASH
    /* configure available FLASH banks */
    size = flash_init ();
    display_flash_config (size);
#endif /* CFG_NO_FLASH */

#ifdef CONFIG_VFD
#    ifndef PAGE_SIZE
#      define PAGE_SIZE 4096
#    endif
    /*
     * reserve memory for VFD display (always full pages)
     */
    /* bss_end is defined in the board-specific linker script */
    addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
    size = vfd_setmem (addr);
    gd->fb_base = addr;
#endif /* CONFIG_VFD */

#ifdef CONFIG_LCD
#    ifndef PAGE_SIZE
#      define PAGE_SIZE 4096
#    endif
    /*
     * reserve memory for LCD display (always full pages)
     */
    /* bss_end is defined in the board-specific linker script */
    addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
    size = lcd_setmem (addr);
    gd->fb_base = addr;
#endif /* CONFIG_LCD */

    /* armboot_start is defined in the board-specific linker script */
    mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);

#if (CONFIG_COMMANDS & CFG_CMD_NAND)
    puts ("NAND:  ");
    nand_init();        /* go init the NAND */
#endif

#ifdef CONFIG_HAS_DATAFLASH
    AT91F_DataflashInit();
    dataflash_print_info();
#endif

    /* initialize environment */
    env_relocate ();

#ifdef CONFIG_VFD
    /* must do this after the framebuffer is allocated */
    drv_vfd_init();
#endif /* CONFIG_VFD */

    /* IP Address */
    gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");

    /* MAC Address */
    {
        int i;
        ulong reg;
        char *s, *e;
        char tmp[64];

        i = getenv_r ("ethaddr", tmp, sizeof (tmp));
        s = (i > 0) ? tmp : NULL;

        for (reg = 0; reg < 6; ++reg) {
            gd->bd->bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0;
            if (s)
                s = (*e) ? e + 1 : e;
        }

#ifdef CONFIG_HAS_ETH1
        i = getenv_r ("eth1addr", tmp, sizeof (tmp));
        s = (i > 0) ? tmp : NULL;

        for (reg = 0; reg < 6; ++reg) {
            gd->bd->bi_enet1addr[reg] = s ? simple_strtoul (s, &e, 16) : 0;
            if (s)
                s = (*e) ? e + 1 : e;
        }
#endif
    }

    devices_init ();    /* get the devices list going. */

#ifdef CONFIG_CMC_PU2
    load_sernum_ethaddr ();
#endif /* CONFIG_CMC_PU2 */

    jumptable_init ();

    console_init_r ();    /* fully init console as a device */

#if defined(CONFIG_MISC_INIT_R)
    /* miscellaneous platform dependent initialisations */
    misc_init_r ();
#endif

    Port_Init();
    if (!PreLoadedONRAM) {
        /* enable exceptions */
        enable_interrupts ();
        /* add by www.100ask.net */
        usb_init();
    }

    /* Perform network card initialisation if necessary */
#ifdef CONFIG_DRIVER_CS8900
    cs8900_get_enetaddr (gd->bd->bi_enetaddr);
#endif

#if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96)
    if (getenv ("ethaddr")) {
        smc_set_mac_addr(gd->bd->bi_enetaddr);
    }
#endif /* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */

    /* Initialize from environment */
    if ((s = getenv ("loadaddr")) != NULL) {
        load_addr = simple_strtoul (s, NULL, 16);
    }
#if (CONFIG_COMMANDS & CFG_CMD_NET)
    if ((s = getenv ("bootfile")) != NULL) {
        copy_filename (BootFile, s, sizeof (BootFile));
    }
#endif    /* CFG_CMD_NET */

#ifdef BOARD_LATE_INIT
    board_late_init ();
#endif
#if (CONFIG_COMMANDS & CFG_CMD_NET)
#if defined(CONFIG_NET_MULTI)
    puts ("Net:   ");
#endif
    eth_initialize(gd->bd);
#endif
    /* main_loop() can return to retry autoboot, if so just run it again. */
    for (;;) {
        main_loop ();
    }

    /* NOTREACHED - no way out of command loop except booting */
}

 

第二阶段:

1.初始化本阶段用到的硬件:改变时钟,配置串口等

2.检测内存映射:板子的内存其实地址和大小

3.uboot命令的格式

4.为内核设置启动参数:对于arm架构,通过lib_arm/armlinux.c的do_bootm_linux函数来启动内核,这个函数设置标记列表,最后通过

theKernel (0, bd->bi_arch_number, bd->bi_boot_params);调用内核

下图为uboot内存使用情况

 

 

 辨别是否从nor启动:

int bBootFrmNORFlash(void)
{
    volatile unsigned int *pdw = (volatile unsigned int *)0;
    unsigned int dwVal;
    
    /*
     * 无论是从NOR Flash还是从NAND Flash启动,
     * 地址0处为指令"b    Reset", 机器码为0xEA00000B,
     * 对于从NAND Flash启动的情况,其开始4KB的代码会复制到CPU内部4K内存中,
     * 对于从NOR Flash启动的情况,NOR Flash的开始地址即为0。
     * 对于NOR Flash,必须通过一定的命令序列才能写数据,
     * 所以可以根据这点差别来分辨是从NAND Flash还是NOR Flash启动:
     * 向地址0写入一个数据,然后读出来,如果没有改变的话就是NOR Flash
     */

    dwVal = *pdw;       
    *pdw = 0x12345678;
    if (*pdw != 0x12345678)
    {
        return 1;
    }
    else
    {
        *pdw = dwVal;
        return 0;
    }
}

 

posted on 2019-09-18 21:46  lzd626  阅读(292)  评论(0编辑  收藏  举报