当前位置: 首页 > article >正文

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


http://www.kler.cn/a/301668.html

相关文章:

  • 【网络安全面经】OSI七层模型每层都有什么协议
  • 云速搭助力用友 BIP 平台快速接入阿里云产品
  • Day18 Nim游戏
  • MacOS下,如何在Safari浏览器中打开或关闭页面中的图片文字翻译功能
  • c++原型模式(Prototype Pattern)
  • SpringMVC学习笔记(一)
  • CSS中的位置定位总结
  • 《2024中国数据要素产业图谱2.0版》重磅发布
  • Java将Word文档转换为PDF文件常用方法总结
  • Android 系统下:普通应用无缝安装,Launcher 应用安装遭遇罕见障碍解析
  • route-forward springboot实现路由转发程序
  • 【C++开发中XML 文件的妙用】
  • Django+Vue协同过滤算法图书推荐系统的设计与实现
  • 【数字集成电路与系统设计】Chisel/Scala简介与Verilog介绍
  • 【分支-快速排序】
  • Python中如何实现列表的排序
  • 十、组合模式
  • AcWing119 袭击
  • 韩语中的多义词 (치다)柯桥学韩语到蓝天广场附近
  • Python的学习(三十二)---- ctypes库的使用整理
  • LSP协议:打造流动性管理的市场新标杆
  • [前端][js]获取当前正在执行的Javascript脚本文件的路径
  • 项目实现:云备份(一)
  • 【数字集成电路与系统设计】一些Chisel语法的介绍
  • 二、Maven工程的创建--JavaSEJavaEE
  • Element UI按钮组件:构建响应式用户界面的秘诀