U-boot配置及启动流程

本帖最后由 Xinxin_2011 于 2014-11-24 17:14 编辑

以CONFIG_开头的宏定义的配置文件:
include\configs\rk32xx.h(其中又包含了rk32plat.h文件,在include\configs\rkplat目录)
新版的SDK,配置文件为include\configs\rk32plat.h和rk_default_config.h文件

编译配置:make rk32xx_config
而我们在uboot目录下的Makefile文件中并没有找到rk32xx_config配置,只有如下代码:

# Read arch specific Makefile to set KBUILD_DEFCONFIG as needed.
# KBUILD_DEFCONFIG may point out an alternative default configuration
# used for 'make defconfig'

%_config:: outputmakefile
        @$(MKCONFIG) -A $(@:_config=)
 %_config前面的%是通配符,会匹配所有以_config为后缀的目标,::是 Makefile的中的多目标规则,可以同时跟多个目标,$(MKCONFIG)是顶层目录下的一个可执行shell脚本文件,$(@:_config=)会将所有目标中的后缀_config去掉,得到rk32xx,然后make会执行命令:u-boot/mkconfig –A rk32xx
由此需要分析mkconfig命令脚本,首先定义了几个变量:

BOARD_NAME=“”:开发板名称
TARGETS:Makefile的目标
arch:体系架构,比如 arm、x86、mips等
cpu: cpu类型,比如 arm920t、arm11等
board:单板名称,比如smdk2410、smdkc100等
vendor:厂商名称,比如samsung、freescale等
soc:片上系统,比如s3c2410、s3c2440、s5pv210等
下面代码比较重要:

if [ \( $# -eq 2 \) -a \( "$1" = "-A" \) ] ; then
       # Automatic mode
       line=`awk '($0 !~ /^#/ && $7 ~ /^'"$2"'$/) { print $1, $2, $3, $4, $5, $6, $7, $8 }' $srctree/boards.cfg`
       if [ -z "$line" ] ; then
              echo "make: *** No rule to make target \`$2_config'.  Stop." >&2
              exit 1
       fi

       set ${line}
       # add default board name if needed
       [ $# = 3 ] && set ${line} ${1}
fi
 如果参数个数等于2,而且第1个参数等于“-A”,则执行:line=`awk '($0 !~ /^#/ && $7 ~ /^'"$2"'$/) { print $1, $2, $3, $4, $5, $6, $7, $8 }' $srctree/boards.cfg`
 这里的$srctree变量代表u-boot根目录,可以在根目录下找到boards.cfg文件,boards.cfg保存了各种单板的相关信息,其格式为:

# Status Arch CPU:SPLCPU SoC Vendor Board name Target Options Maintainers
在最后面有rk32xx的定义:

#add for rockchip
Active  arm         armv7          rk32xx      rockchip        rk32xx              rk32xx                               
   从而会得到开头定义各变量的值,如BOARD_NAME= rk32xx

   程序启动是从u-boot/arch/arm/cpu/armv7目录下的start.S文件开始,里面会调用到该目录下的/rk32xx/lowlevel_init.S文件,start.S函数最后调用_main函数,这个在u-boot/arch/arm/lib/crt0.S文件中,里面再调用board_init_f和board_init_r函数,其定义均在u-boot/arch/arm/lib/board.c文件中。
  board_init_f函数会调用初始化队列里面的函数,如下定义:
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,
#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 */
    print_cpuinfo,                /* display cpu info (and speed) */
#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,
};
    这里以第一个函数arch_cpu_init为例分析一下,它也定义在这个文件中:
int __arch_cpu_init(void)
{
    return 0;
}
int arch_cpu_init(void)
    __attribute__((weak, alias("__arch_cpu_init")));
   好像什么也没做,但注意这个定义属性有个weak,也就是如果自己实现的话,就不调用此函数了,那具体有实现吗?在u-boot/arch/arm/cpu/armv7/rk32xx/cpu.c文件中:
#ifdef CONFIG_ARCH_CPU_INIT
int arch_cpu_init(void)
{
    gd->arch.chiptype = rk_get_chiptype();  // 定义在其上面
    return 0;
}
#endif
    CONFIG_ARCH_CPU_INIT宏在rk32xx.h文件中已然定义,所以实际执行的是这个函数。

    board_init_r函数里调用了board_init和board_late_init函数,其均定义在u-boot/board/rockchip/rk32xx/rk32xx.c文件:
int board_init(void)
{
    /* Set Initial global variables */

    gd->bd->bi_arch_number = MACH_TYPE_RK30XX;
    gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x88000;

    return 0;
}
int board_late_init(void)
{
    debug("board_late_init\n");
    load_disk_partitions();
    prepare_fdt();
    key_init();
#ifdef CONFIG_POWER_RK
    pmic_init(0);
    fg_init(0); /*fuel gauge init*/
#endif
    SecureBootCheck();

        //TODO:set those buffers in a better way, and use malloc?
    setup_space(gd->arch.rk_extra_buf_addr);

        /* after setup space, get id block data first */
    get_idblk_data();

    if (get_bootloader_ver() == 0) {
        printf("\n#Boot ver: %s\n", bootloader_ver);
    }

    char tmp_buf[30];
    if (getSn(tmp_buf)) {
        tmp_buf[sizeof(tmp_buf)-1] = 0;
        setenv("fbt_sn#", tmp_buf);
    }

#ifdef CONFIG_CMD_FASTBOOT
    fbt_preboot();
#else
    rk_preboot();
#endif
    return 0;
}
    可见board_late_init函数里完成开发板按键等功能的初始化,key_init()函数在u-boot/board/rockchip/common/rkloader目录下的key.c文件中实现:
void key_init(void)
{
#if (CONFIG_RKCHIPTYPE == CONFIG_RK3036)
    RockusbKeyInit(&key_rockusb);
    RemotectlInit();
#else
    charge_state_gpio.name = "charge_state";
    charge_state_gpio.flags = 0;
    charge_state_gpio.gpio = ((GPIO_BANK0 << RK_GPIO_BANK_OFFSET) | GPIO_B0);
    gpio_direction_input(charge_state_gpio.gpio);

        //power_hold_gpio.name

    RockusbKeyInit(&key_rockusb);
    FastbootKeyInit(&key_fastboot);
    RecoveryKeyInit(&key_recovery);
    PowerKeyInit();
#endif
}
    文件中还实现按键检测函数checkKey():
int checkKey(uint32* boot_rockusb, uint32* boot_recovery, uint32* boot_fastboot)
{
    *boot_rockusb = 0;
    *boot_recovery = 0;
    *boot_fastboot = 0;

    printf("checkKey\n");

    if(GetPortState(&key_rockusb))
    {
        *boot_rockusb = 1;
        //printf("rockusb key is pressed\n");
    }
    if(GetPortState(&key_recovery))
    {
        *boot_recovery = 1;
        //printf("recovery key is pressed\n");
    }
    if(GetPortState(&key_fastboot))
    {
        *boot_fastboot = 1;
        //printf("fastboot key is pressed\n");
    }

    return 0;
}
    系统上电时对于recovery按键的识别就在这个函数中。

Xinxin很赞哦,此文不错。

写的不错,支持原创帖子{:3_48:}

支持楼主

写的不错,支持

DDR如何完成初始化的????

学习了,谢谢

此文不错。

在那里开始 ram 的拷贝 并且跳转啊

支持一个

qdqqfw

写的不错,支持原创帖子

楼主下面还有吗,我还是等你继续更新吧,这个蛮重要的。

学习了,支持。。

在rockchip的UBOOT文档中, 他里面定义了很多命令,像IIC, SPI等, 为啥我编译出来的只有简单的几个命令?
我看了common/Makefile里,里面也有的,
要怎样做才能把那些命令加进去?

我试了二级BOOTLOADER, 不过也没用,命令还是没变

学习了,谢谢

你好,楼主能给出UBOOT的源码吗?

还是这些比较有实质性收获,毕竟搞嵌入式的