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配置,只有如下代码:
# 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按键的识别就在这个函数中。
作者:
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