123.rk3399 uboot(2017.09) 源码分析3(2024-09-12)
啃了几天initf_dm,发现啃不动啊,但是后面的函数比这个简单,要不先把简单的做了吧。
本文接上一篇https://blog.csdn.net/zhaozhi0810/article/details/142050827
一、c的入口 board_init_f
1.3.12 arch_cpu_init_dm(common/board_f.c)
空函数返回
1.3.13 board_early_init_f
CONFIG_BOARD_EARLY_INIT_F 配置未被选中。不执行。
1.3.14 get_clocks
配置没有选中,不执行
CONFIG_PPC 对应power pc 架构,rk3399是armv8 架构
CONFIG_M68K 对应M68K架构,不符合
1.3.15 timer_init
配置没有选中,不执行
1.3.16 board_postclk_init
配置没有选中,不执行
1.3.17 env_init (env/env.c)
环境变量的初始化,主要是gd->env_addr和gd->env_valid 被分别赋值。
uboot.map中,实际没有设置环境变量存储位置,CONFIG_ENV_IS_NOWHERE是被定义的。
使用的是nowhere驱动。对应的是nowhere.c文件。
int env_init(void)
{
struct env_driver *drv = env_driver_lookup_default(); //实际返回空
int ret = -ENOENT;
if (!drv)
return -ENODEV;
if (drv->init)
ret = drv->init();
if (ret == -ENOENT) {
gd->env_addr = (ulong)&default_environment[0]; //使用默认环境变量
gd->env_valid = ENV_VALID;
return 0;
} else if (ret) {
debug("%s: Environment failed to init (err=%d)\n", __func__,
ret);
return ret;
}
return 0;
}
nowhere.c
它使用的就是default_environment 默认环境变量
调用init函数之后
gd->env_addr和gd->env_valid 被分别赋值
DECLARE_GLOBAL_DATA_PTR;
/*
* Because we only ever have the default environment available we must mark
* it as invalid.
*/
static int env_nowhere_init(void)
{
gd->env_addr = (ulong)&default_environment[0];
gd->env_valid = ENV_INVALID;
return 0;
}
U_BOOT_ENV_LOCATION(nowhere) = {
.location = ENVL_NOWHERE,
.init = env_nowhere_init,
ENV_NAME("nowhere")
};
这里可以看到,默认环境变量都是通过配置设置的,(env_default.h)
CONFIG开头的都是配置部分。
const uchar default_environment[] = {
#ifdef CONFIG_ENV_CALLBACK_LIST_DEFAULT
ENV_CALLBACK_VAR "=" CONFIG_ENV_CALLBACK_LIST_DEFAULT "\0"
#endif
#ifdef CONFIG_ENV_FLAGS_LIST_DEFAULT
ENV_FLAGS_VAR "=" CONFIG_ENV_FLAGS_LIST_DEFAULT "\0"
#endif
#ifdef CONFIG_USE_BOOTARGS
"bootargs=" CONFIG_BOOTARGS "\0"
#endif
#ifdef CONFIG_BOOTCOMMAND
"bootcmd=" CONFIG_BOOTCOMMAND "\0"
#endif
#ifdef CONFIG_RAMBOOTCOMMAND
"ramboot=" CONFIG_RAMBOOTCOMMAND "\0"
#endif
#ifdef CONFIG_NFSBOOTCOMMAND
"nfsboot=" CONFIG_NFSBOOTCOMMAND "\0"
#endif
#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
"bootdelay=" __stringify(CONFIG_BOOTDELAY) "\0"
#endif
#if defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0)
"baudrate=" __stringify(CONFIG_BAUDRATE) "\0"
#endif
#ifdef CONFIG_LOADS_ECHO
"loads_echo=" __stringify(CONFIG_LOADS_ECHO) "\0"
#endif
#ifdef CONFIG_ETHPRIME
"ethprime=" CONFIG_ETHPRIME "\0"
#endif
#ifdef CONFIG_IPADDR
"ipaddr=" __stringify(CONFIG_IPADDR) "\0"
#endif
#ifdef CONFIG_SERVERIP
"serverip=" __stringify(CONFIG_SERVERIP) "\0"
#endif
#ifdef CONFIG_SYS_AUTOLOAD
"autoload=" CONFIG_SYS_AUTOLOAD "\0"
#endif
#ifdef CONFIG_PREBOOT
"preboot=" CONFIG_PREBOOT "\0"
#endif
#ifdef CONFIG_ROOTPATH
"rootpath=" CONFIG_ROOTPATH "\0"
#endif
#ifdef CONFIG_GATEWAYIP
"gatewayip=" __stringify(CONFIG_GATEWAYIP) "\0"
#endif
#ifdef CONFIG_NETMASK
"netmask=" __stringify(CONFIG_NETMASK) "\0"
#endif
#ifdef CONFIG_HOSTNAME
"hostname=" __stringify(CONFIG_HOSTNAME) "\0"
#endif
#ifdef CONFIG_BOOTFILE
"bootfile=" CONFIG_BOOTFILE "\0"
#endif
#ifdef CONFIG_LOADADDR
"loadaddr=" __stringify(CONFIG_LOADADDR) "\0"
#endif
#ifdef CONFIG_CLOCKS_IN_MHZ
"clocks_in_mhz=1\0"
#endif
#if defined(CONFIG_PCI_BOOTDELAY) && (CONFIG_PCI_BOOTDELAY > 0)
"pcidelay=" __stringify(CONFIG_PCI_BOOTDELAY)"\0"
#endif
#ifdef CONFIG_ENV_VARS_UBOOT_CONFIG
"arch=" CONFIG_SYS_ARCH "\0"
#ifdef CONFIG_SYS_CPU
"cpu=" CONFIG_SYS_CPU "\0"
#endif
#ifdef CONFIG_SYS_BOARD
"board=" CONFIG_SYS_BOARD "\0"
"board_name=" CONFIG_SYS_BOARD "\0"
#endif
#ifdef CONFIG_SYS_VENDOR
"vendor=" CONFIG_SYS_VENDOR "\0"
#endif
#ifdef CONFIG_SYS_SOC
"soc=" CONFIG_SYS_SOC "\0"
#endif
#ifdef CONFIG_SILENT_CONSOLE
"silent=enable\0"
#endif
#endif
#ifdef CONFIG_EXTRA_ENV_SETTINGS
CONFIG_EXTRA_ENV_SETTINGS
#endif
"\0"
#ifdef DEFAULT_ENV_INSTANCE_EMBEDDED
}
#endif
};
rk3399一般都是使用emmc作为存储介质,它也按照一定的方式进行了分区操作。
如果要保存到emmc的话,估计还要对分区进行调整。
所以现在看到的都是环境变量可以通过配置uboot来完成,而实际使用过程中就不能修改了。
除非重新配置并编译uboot。
1.3.18 init_baud_rate(common/board_f.c)
gd->baudrate 赋值波特率。
static int init_baud_rate(void)
{
if (gd && gd->serial.using_pre_serial)
gd->baudrate = env_get_ulong("baudrate", 10, gd->serial.baudrate);
else //波特率可以在配置uboot中设置,应该是走这一条路。
gd->baudrate = env_get_ulong("baudrate", 10, CONFIG_BAUDRATE);
return 0;
}
1.3.19 serial_init (drivers/serial/serial-uclass.c)
a. 主要通过serial_find_console_or_panic(void) 完成设备树中串口的查找,引脚复用的初始化
如果未找到,则初始化卡死panic_str 导致程序打印串口异常并卡死。
(先略过这个部分,后面有机会再把程序的分析补齐)
b.gd->flags 表示console串口可用了。
/* Called prior to relocation */
int serial_init(void)
{
serial_find_console_or_panic();
gd->flags |= GD_FLG_SERIAL_READY;
return 0;
}
1.3.20 console_init_f
实际只有这句生效了:gd->have_console = 1;
/* Called before relocation - use serial functions */
int console_init_f(void)
{
gd->have_console = 1;
console_update_silent(); //宏CONFIG_SILENT_CONSOLE未定义,空函数
print_pre_console_buffer(PRE_CONSOLE_FLUSHPOINT1_SERIAL); //PRE_CONSOLE_BUFFER未定义,空函数
return 0;
}
可以在make menuconfig 中直接搜索PRE_CONSOLE_BUFFER,提示N表示没有配置。
1.3.21 display_options
这个应该就是uboot的第一条串口打印信息。
int display_options(void)
{
char buf[DISPLAY_OPTIONS_BANNER_LENGTH]; //200字节
display_options_get_banner(true, buf, sizeof(buf)); //完成字符串的组合
printf("%s", buf); //串口打印这个字符串
return 0;
}
char *display_options_get_banner(bool newlines, char *buf, int size)
{
//newlines 为ture,BUILD_TAG为NULL,buf即200字节的空间,size是200
return display_options_get_banner_priv(newlines, BUILD_TAG, buf, size); //
}
//version_string[] --》 U_BOOT_VERSION " (" U_BOOT_DATE " - " \
// U_BOOT_TIME " " U_BOOT_TZ ")" CONFIG_IDENT_STRING
//其中这些大写的宏,全部在一个自动生成的h文件中,version_autogenerated.h(include/genarated/)
char *display_options_get_banner_priv(bool newlines, const char *build_tag,
char *buf, int size)
{
int len;
len = snprintf(buf, size, "%s%s", newlines ? "\n\n" : "",
version_string);
if (build_tag && len < size) //build_tag == NULL, 不执行
len += snprintf(buf + len, size - len, ", Build: %s",
build_tag);
if (len > size - 3) //长度最大为197,超过了后面的字节就丢失了
len = size - 3;
strcpy(buf + len, "\n\n"); //末尾加两个换行
return buf;
}
从代码中可以看到:
实际uboot启动时的打印:
因为没有更新到最新编译的,所以就还是用之前的时间吧,格式是一致的。
1.3.22 display_text_info
这个是一段调试信息,因为debug没有开启,实际并未打印
主要的打印信息,代码段的起始地址,bss段的起始地址和结束地址。
static int display_text_info(void)
{
#if !defined(CONFIG_SANDBOX) && !defined(CONFIG_EFI_APP)
ulong bss_start, bss_end, text_base;
bss_start = (ulong)&__bss_start;
bss_end = (ulong)&__bss_end;
#ifdef CONFIG_SYS_TEXT_BASE
text_base = CONFIG_SYS_TEXT_BASE;
#else
text_base = CONFIG_SYS_MONITOR_BASE;
#endif
debug("U-Boot code: %08lX -> %08lX BSS: -> %08lX\n",
text_base, bss_start, bss_end);
#endif
return 0;
}
1.3.23 checkcpu
宏未定义,不执行
1.3.24 print_cpuinfo
宏未定义,不执行
1.3.25 embedded_dtb_select
宏未定义,不执行
1.3.26 show_board_info
打印板级信息
/*
* If the root node of the DTB has a "model" property, show it.
* Then call checkboard().
*/
int __weak show_board_info(void)
{
#ifdef CONFIG_OF_CONTROL //这个宏定义了
DECLARE_GLOBAL_DATA_PTR;
const char *model;
model = fdt_getprop(gd->fdt_blob, 0, "model", NULL); //从设备树中找到model节点
if (model)
printf("Model: %s\n", model); //打印该信息
#endif
#ifdef CONFIG_ARM64_BOOT_AARCH32 //未定义
if (!(gd->flags & GD_FLG_RELOC))
printf("CPU: AArch32\n");
#endif
return checkboard(); //空函数
}
1.3.27 INIT_FUNC_WATCHDOG_INIT
CONFIG_WATCHDOG 和CONFIG_HW_WATCHDOG 均未定义
//两个宏均未定义,所以就是空的
#if defined(CONFIG_WATCHDOG) || defined(CONFIG_HW_WATCHDOG)
#define INIT_FUNC_WATCHDOG_INIT init_func_watchdog_init,
#define INIT_FUNC_WATCHDOG_RESET init_func_watchdog_reset,
#else
#define INIT_FUNC_WATCHDOG_INIT
#define INIT_FUNC_WATCHDOG_RESET
#endif
1.3.28 misc_init_f
宏未定义,不执行该函数
1.3.29 INIT_FUNC_WATCHDOG_RESET
空,不需要执行
1.3.30 init_func_i2c
宏未定义,不执行
1.3.31 init_func_spi
宏未定义,不执行
1.3.32 announce_pre_serial
就是一个打印信息,看样子是串口的编号
rk3399调试串口是串口2(从0开始计数)。
static int announce_pre_serial(void)
{
if (gd && gd->serial.using_pre_serial) //gd->serial.using_pre_serial 不为0
printf("PreSerial: %d\n", gd->serial.id); //打印 2
return 0;
}
1.3.33 announce_dram_init
空函数
static int announce_dram_init(void)
{
#ifndef CONFIG_SUPPORT_USBPLUG //未定义
puts("DRAM: ");
#endif
return 0;
}
1.3.34 dram_init
设置gd->ram_size 内存大小
int dram_init(void)
{
/* Store complete RAM size and return */
gd->ram_size = get_ram_size(PHYS_SDRAM_1, PHYS_SDRAM_1_MAXSIZE);
return 0;
}
1.3.35 post_init_f
宏未定义,不执行
1.3.36 INIT_FUNC_WATCHDOG_RESET
空
1.3.37 testdram
宏未定义,不执行
1.3.38 INIT_FUNC_WATCHDOG_RESET
空
1.3.39 init_post
宏未定义,不执行 (见1.3.35)
1.3.40 INIT_FUNC_WATCHDOG_RESET
空
从这个函数开始,就是uboot的内存规划处理部分。
这里是一环扣一环,我还没有来得及仔细分析。这个坑还有点大!!!(2024-09-12).
干不动了又想休息了。
1.3.41 setup_dest_addr
这个函数应该还比较重要,但是目前几个宏定义不知道是哪个。
先跳过,回来再填坑
static int setup_dest_addr(void)
{
debug("Monitor len: %08lX\n", gd->mon_len);
/*
* Ram is setup, size stored in gd !!
*/
debug("Ram size: %08lX\n", (ulong)gd->ram_size);
#if defined(CONFIG_SYS_MEM_TOP_HIDE)
/*
* Subtract specified amount of memory to hide so that it won't
* get "touched" at all by U-Boot. By fixing up gd->ram_size
* the Linux kernel should now get passed the now "corrected"
* memory size and won't touch it either. This should work
* for arch/ppc and arch/powerpc. Only Linux board ports in
* arch/powerpc with bootwrapper support, that recalculate the
* memory size from the SDRAM controller setup will have to
* get fixed.
*/
gd->ram_size -= CONFIG_SYS_MEM_TOP_HIDE;
#endif
#ifdef CONFIG_SYS_SDRAM_BASE
gd->ram_top = CONFIG_SYS_SDRAM_BASE;
#endif
gd->ram_top += get_effective_memsize();
gd->ram_top = board_get_usable_ram_top(gd->mon_len);
gd->relocaddr = gd->ram_top;
debug("Ram top: %08lX\n", (ulong)gd->ram_top);
#if defined(CONFIG_MP) && (defined(CONFIG_MPC86xx) || defined(CONFIG_E500))
/*
* We need to make sure the location we intend to put secondary core
* boot code is reserved and not used by any part of u-boot
*/
if (gd->relocaddr > determine_mp_bootpg(NULL)) {
gd->relocaddr = determine_mp_bootpg(NULL);
debug("Reserving MP boot page to %08lx\n", gd->relocaddr);
}
#endif
return 0;
}
1.3.42 reserve_pram
宏未定义,不执行
1.3.43 reserve_round_4k
重定位的地址,4k对齐,最低12位清零。
/* Round memory pointer down to next 4 kB limit */
static int reserve_round_4k(void)
{
gd->relocaddr &= ~(4096 - 1);
return 0;
}
1.3.44 reserve_mmu
CONFIG_SYS_ICACHE_OFF 未定义
CONFIG_SYS_DCACHE_OFF 也是未定义
实际这个代码被编译了。(在代码里面加几个字符,编译会报错)。
#ifdef CONFIG_ARM
__weak int reserve_mmu(void)
{
#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))
/* reserve TLB table */
gd->arch.tlb_size = PGTABLE_SIZE;
gd->relocaddr -= gd->arch.tlb_size;
/* round down to next 64 kB limit */
gd->relocaddr &= ~(0x10000 - 1);
gd->arch.tlb_addr = gd->relocaddr;
debug("TLB table from %08lx to %08lx\n", gd->arch.tlb_addr,
gd->arch.tlb_addr + gd->arch.tlb_size);
#ifdef CONFIG_SYS_MEM_RESERVE_SECURE
/*
* Record allocated tlb_addr in case gd->tlb_addr to be overwritten
* with location within secure ram.
*/
gd->arch.tlb_allocated = gd->arch.tlb_addr;
#endif
#endif
return 0;
}
#endif