Firefly开源社区

标题: U-boot配置及启动流程 [打印本页]

作者: Xinxin_2011    时间: 2014-11-12 18:01
标题: 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配置,只有如下代码:
  1. # Read arch specific Makefile to set KBUILD_DEFCONFIG as needed.
  2. # KBUILD_DEFCONFIG may point out an alternative default configuration
  3. # used for 'make defconfig'

  4. %_config:: outputmakefile
  5.         @$(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等
       下面代码比较重要:
  1. if [ \( $# -eq 2 \) -a \( "$1" = "-A" \) ] ; then
  2.        # Automatic mode
  3.        line=`awk '($0 !~ /^#/ && $7 ~ /^'"$2"'$/) { print $1, $2, $3, $4, $5, $6, $7, $8 }' $srctree/boards.cfg`
  4.        if [ -z "$line" ] ; then
  5.               echo "make: *** No rule to make target \`$2_config'.  Stop." >&2
  6.               exit 1
  7.        fi

  8.        set ${line}
  9.        # add default board name if needed
  10.        [ $# = 3 ] && set ${line} ${1}
  11. 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的定义:
  1. #add for rockchip
  2. 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函数会调用初始化队列里面的函数,如下定义:
  1. init_fnc_t *init_sequence[] = {
  2.     arch_cpu_init,                   /* basic arch cpu dependent setup */
  3.     mark_bootstage,
  4. #ifdef CONFIG_OF_CONTROL
  5.     fdtdec_check_fdt,
  6. #endif
  7. #if defined(CONFIG_BOARD_EARLY_INIT_F)
  8.     board_early_init_f,
  9. #endif
  10.     timer_init,                /* initialize timer */
  11. #ifdef CONFIG_BOARD_POSTCLK_INIT
  12.     board_postclk_init,
  13. #endif
  14. #ifdef CONFIG_FSL_ESDHC
  15.    get_clocks,
  16. #endif
  17.     env_init,                    /* initialize environment */
  18.     init_baudrate,                /* initialze baudrate settings */
  19.     serial_init,                    /* serial communications setup */
  20.     console_init_f,                /* stage 1 init of console */
  21.     display_banner,                /* say that we are here */
  22.     print_cpuinfo,                /* display cpu info (and speed) */
  23. #if defined(CONFIG_DISPLAY_BOARDINFO)
  24.     checkboard,                   /* display board info */
  25. #endif
  26. #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C)
  27.     init_func_i2c,
  28. #endif
  29.     dram_init,                  /* configure available RAM banks */
  30.     NULL,
  31. };
复制代码
       这里以第一个函数arch_cpu_init为例分析一下,它也定义在这个文件中:
  1. int __arch_cpu_init(void)
  2. {
  3.     return 0;
  4. }
  5. int arch_cpu_init(void)
  6.     __attribute__((weak, alias("__arch_cpu_init")));
复制代码
      好像什么也没做,但注意这个定义属性有个weak,也就是如果自己实现的话,就不调用此函数了,那具体有实现吗?在u-boot/arch/arm/cpu/armv7/rk32xx/cpu.c文件中:
  1. #ifdef CONFIG_ARCH_CPU_INIT
  2. int arch_cpu_init(void)
  3. {
  4.     gd->arch.chiptype = rk_get_chiptype();  // 定义在其上面
  5.     return 0;
  6. }
  7. #endif
复制代码

        CONFIG_ARCH_CPU_INIT宏在rk32xx.h文件中已然定义,所以实际执行的是这个函数。


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

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

  6.     return 0;
  7. }
复制代码
  1. int board_late_init(void)
  2. {
  3.     debug("board_late_init\n");
  4.     load_disk_partitions();
  5.     prepare_fdt();
  6.     key_init();
  7. #ifdef CONFIG_POWER_RK
  8.     pmic_init(0);
  9.     fg_init(0); /*fuel gauge init*/
  10. #endif
  11.     SecureBootCheck();

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

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

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

  19.     char tmp_buf[30];
  20.     if (getSn(tmp_buf)) {
  21.         tmp_buf[sizeof(tmp_buf)-1] = 0;
  22.         setenv("fbt_sn#", tmp_buf);
  23.     }

  24. #ifdef CONFIG_CMD_FASTBOOT
  25.     fbt_preboot();
  26. #else
  27.     rk_preboot();
  28. #endif
  29.     return 0;
  30. }
复制代码
       可见board_late_init函数里完成开发板按键等功能的初始化,key_init()函数在u-boot/board/rockchip/common/rkloader目录下的key.c文件中实现:
  1. void key_init(void)
  2. {
  3. #if (CONFIG_RKCHIPTYPE == CONFIG_RK3036)
  4.     RockusbKeyInit(&key_rockusb);
  5.     RemotectlInit();
  6. #else
  7.     charge_state_gpio.name = "charge_state";
  8.     charge_state_gpio.flags = 0;
  9.     charge_state_gpio.gpio = ((GPIO_BANK0 << RK_GPIO_BANK_OFFSET) | GPIO_B0);
  10.     gpio_direction_input(charge_state_gpio.gpio);

  11.         //power_hold_gpio.name

  12.     RockusbKeyInit(&key_rockusb);
  13.     FastbootKeyInit(&key_fastboot);
  14.     RecoveryKeyInit(&key_recovery);
  15.     PowerKeyInit();
  16. #endif
  17. }
复制代码
       文件中还实现按键检测函数checkKey():
  1. int checkKey(uint32* boot_rockusb, uint32* boot_recovery, uint32* boot_fastboot)
  2. {
  3.     *boot_rockusb = 0;
  4.     *boot_recovery = 0;
  5.     *boot_fastboot = 0;

  6.     printf("checkKey\n");

  7.     if(GetPortState(&key_rockusb))
  8.     {
  9.         *boot_rockusb = 1;
  10.         //printf("rockusb key is pressed\n");
  11.     }
  12.     if(GetPortState(&key_recovery))
  13.     {
  14.         *boot_recovery = 1;
  15.         //printf("recovery key is pressed\n");
  16.     }
  17.     if(GetPortState(&key_fastboot))
  18.     {
  19.         *boot_fastboot = 1;
  20.         //printf("fastboot key is pressed\n");
  21.     }

  22.     return 0;
  23. }
复制代码
       系统上电时对于recovery按键的识别就在这个函数中。







作者: ZZP    时间: 2014-11-12 18:06
Xinxin很赞哦,此文不错。
作者: zhansb    时间: 2014-11-13 09:19
写的不错,支持原创帖子{:3_48:}
作者: hoh    时间: 2015-10-31 10:09
支持楼主
作者: Jesdy0813    时间: 2016-3-14 17:31

写的不错,支持
作者: biaoun    时间: 2016-3-17 22:56
DDR如何完成初始化的????
作者: qbasicbirthday    时间: 2016-5-14 01:13
学习了,谢谢
作者: samuel0755    时间: 2016-5-15 19:33
此文不错。
作者: qbasicbirthday    时间: 2016-5-16 00:24
在那里开始 ram 的拷贝 并且跳转啊
作者: gyj82117    时间: 2016-6-27 18:27
支持一个
作者: zzyzjdy    时间: 2016-6-29 09:54
qdqqfw
作者: gyj82117    时间: 2016-7-2 22:13

写的不错,支持原创帖子
作者: luminmin882001    时间: 2016-8-26 14:05
楼主下面还有吗,我还是等你继续更新吧,这个蛮重要的。
作者: sghmy    时间: 2016-8-27 13:47
学习了,支持。。
作者: ldqmoon    时间: 2017-2-10 17:36
在rockchip的UBOOT文档中, 他里面定义了很多命令,像IIC, SPI等, 为啥我编译出来的只有简单的几个命令?
我看了common/Makefile里,里面也有的,
要怎样做才能把那些命令加进去?

我试了二级BOOTLOADER, 不过也没用,命令还是没变
作者: kevin6861    时间: 2017-2-22 23:47
学习了,谢谢
作者: jacky_shen    时间: 2017-5-9 16:26
你好,楼主能给出UBOOT的源码吗?
作者: 沙漠狼    时间: 2018-7-10 15:35
还是这些比较有实质性收获,毕竟搞嵌入式的




欢迎光临 Firefly开源社区 (https://dev.t-firefly.com/) Powered by Discuz! X3.1