Firefly开源社区

12
发表新贴
打印 上一主题 下一主题

U-boot配置及启动流程

37

积分

0

威望

0

贡献

技术小白

积分
37

U-boot配置及启动流程

发表于 2014-11-12 18:01:13      浏览:40286 | 回复:17        打印      只看该作者   [复制链接] 楼主
本帖最后由 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按键的识别就在这个函数中。






回复

使用道具 举报

279

积分

10

威望

9

贡献

社区版主

Rank: 7Rank: 7Rank: 7

积分
279
QQ
发表于 2014-11-12 18:06:16        只看该作者  沙发
Xinxin很赞哦,此文不错。
回复

使用道具 举报

2918

积分

56

威望

46

贡献

高级创客

Rank: 6Rank: 6

积分
2918

优秀版主论坛元老

发表于 2014-11-13 09:19:44        只看该作者  板凳
写的不错,支持原创帖子{:3_48:}
回复

使用道具 举报

10

积分

0

威望

0

贡献

技术小白

积分
10
发表于 2015-10-31 10:09:17        只看该作者  地板
支持楼主
回复

使用道具 举报

47

积分

0

威望

0

贡献

技术小白

积分
47
发表于 2016-3-14 17:31:22        只看该作者  5#

写的不错,支持
回复

使用道具 举报

60

积分

0

威望

0

贡献

游客

积分
60
发表于 2016-3-17 22:56:15        只看该作者  6#
DDR如何完成初始化的????
回复

使用道具 举报

94

积分

0

威望

0

贡献

技术小白

积分
94
发表于 2016-5-14 01:13:08        只看该作者  7#
学习了,谢谢
回复

使用道具 举报

21

积分

0

威望

0

贡献

技术小白

积分
21
发表于 2016-5-15 19:33:18        只看该作者  8#
此文不错。
回复

使用道具 举报

94

积分

0

威望

0

贡献

技术小白

积分
94
发表于 2016-5-16 00:24:38        只看该作者  9#
在那里开始 ram 的拷贝 并且跳转啊
回复

使用道具 举报

133

积分

0

威望

0

贡献

技术小白

积分
133
发表于 2016-6-27 18:27:30        只看该作者  10#
支持一个
回复

使用道具 举报

返回列表
12
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

友情链接 : 爱板网 电子发烧友论坛 云汉电子社区 粤ICP备14022046号-2
快速回复 返回顶部 返回列表