|
U-boot配置及启动流程
发表于 2014-11-12 18:01:13
浏览:40275
|
回复: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配置,只有如下代码:- # 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按键的识别就在这个函数中。
|
|