接着上一节,板子开始做前期初始化工作。

8.1 board_init_f

  board_f.c (common)

 /* 板子初次初始化。boot_flags = 0 */
void board_init_f(ulong boot_flags)
{
gd->flags = boot_flags;
gd->have_console = ; if (initcall_run_list(init_sequence_f))
hang(); #if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) && \
!defined(CONFIG_EFI_APP) && !CONFIG_IS_ENABLED(X86_64)
/* NOTREACHED - jump_to_copy() does not return */
hang();
#endif
}

  boot_flags 标志位0,且终端标志位也为0,在 initcall_run_list(init_sequence_f) 链表中执行板子初始化过程

8.2 init_sequence_f 函数数组

 static init_fnc_t init_sequence_f[] = {
setup_mon_len, ///< 设置gd->mon_len为编译出来的u-boot.bin+bss段的大小
initf_malloc, ///< 设置内存池的大小 gd->malloc_limit = 0x400, gd->malloc_ptr = 0
initf_console_record, ///< 为空,直接返回 0
arch_cpu_init, ///< 基本arch cpu相关设置, 未做初始化
mach_cpu_init, ///< SoC/machine 相关CPU设置, 未作设置
initf_dm, ///< 驱动模型的初始化, 未开宏
arch_cpu_init_dm, ///< 驱动模型相关的 CPU 初始化, 未开宏
mark_bootstage, /* need timer, go after init dm */
#if defined(CONFIG_BOARD_EARLY_INIT_F)
board_early_init_f, ///< 时钟和 GPIO 的初始化
#endif #if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || \
defined(CONFIG_BLACKFIN) || defined(CONFIG_NDS32) || \
defined(CONFIG_SH) || defined(CONFIG_SPARC)
timer_init, ///< 定时器初始化
#endif env_init, ///< initialize environment, 初始化环境变量结构体 default_environment
///< env_dataflash.c 中是此时的实际调用
init_baud_rate, /* 波特率设置 */
serial_init, /* 串行通信初始化 */
console_init_f, /* 在重定位之前使能串口功能 */
display_options, /* 打印 uboot 版本信息 */
display_text_info, /* 打印 uboot 配置信息 */
print_cpuinfo, /* 显示 CPU 信息 */
#if defined(CONFIG_DISPLAY_BOARDINFO)
show_board_info, ///< 显示板子信息,需要复写函数
#endif
announce_dram_init, ///< 打印了一个 DRAM: 字符串
/* TODO: unify all these dram functions? */
#if defined(CONFIG_ARM) || defined(CONFIG_X86) || defined(CONFIG_NDS32) || \
defined(CONFIG_MICROBLAZE) || defined(CONFIG_AVR32) || \
defined(CONFIG_SH)
dram_init, /* 配置 DRAM 大小, gd->ram_size = 0x04000000 , 即 64MB*/
#endif
/*
* Now that we have DRAM mapped and working, we can
* relocate the code and continue running from DRAM.
*
* Reserve memory at end of RAM for (top down in that order):
* - area that won't get touched by U-Boot and Linux (optional)
* - kernel log buffer
* - protected RAM
* - LCD framebuffer
* - monitor code
* - board info struct
*/
setup_dest_addr, ///< 重定位地址设置 gd->relocaddr = gd->ram_top = 0x3400 0000
reserve_round_4k,
reserve_trace, ///< trace 设置,移动gd->relocaddr,未配置,不动
#if !defined(CONFIG_BLACKFIN) && !defined(CONFIG_XTENSA)
reserve_uboot, ///< 留出 uboot.bin 的空间 gd->relocaddr 下移后, gd->start_addr_sp = gd->relocaddr
#endif
#ifndef CONFIG_SPL_BUILD
reserve_malloc,
reserve_board,
#endif
setup_machine, ///< 不做初始化
reserve_global_data, ///< 初始化 global_data 的空间,gd->start_addr_sp -= sizeof(gd_t);
reserve_fdt, ///< 未开特性
reserve_arch, ///< 未做任务
reserve_stacks, ///< gd->start_addr_sp 16字节对齐
setup_dram_config, ///< DRAM配置前面已经做了
show_dram_config, ///< 显示 DRAM 的大小 64M
display_new_sp, ///< 打印当前栈
reloc_fdt, ///< 未作配置
setup_reloc, ///< gd->reloc_off = gd->relocaddr reloc_off 设置为栈顶
NULL,
};

8.2.1 setup_mon_len

 /* 设置gd->mon_len为编译出来的u-boot.bin+bss段的大小 */
static int setup_mon_len(void)
{
gd->mon_len = (ulong)&__bss_end - (ulong)_start;
return ;
}

  _start 的地址为 0

8.2.2 initf_malloc

 /* 设置内存池的大小 */
int initf_malloc(void)
{
#if CONFIG_VAL(SYS_MALLOC_F_LEN)
assert(gd->malloc_base); /* Set up by crt0.S */
gd->malloc_limit = CONFIG_VAL(SYS_MALLOC_F_LEN);
gd->malloc_ptr = ;
#endif return ;
}

8.2.3 设置重定位地址---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);
#ifdef CONFIG_SYS_SDRAM_BASE /* JZ2440 = CONFIG_SYS_SDRAM_BASE = 0x30000000 */
gd->ram_top = CONFIG_SYS_SDRAM_BASE;
#endif
gd->ram_top += get_effective_memsize(); /* gd->ram_top = 0x30000000 + 0x400 0000 = 0x3400 0000 */
/* 此段依然返回 SDRAM 顶端地址 0x3400 0000 */
gd->ram_top = board_get_usable_ram_top(gd->mon_len);
gd->relocaddr = gd->ram_top; /* 重定位地址为 0x3400 0000 */
debug("Ram top: %08lX\n", (ulong)gd->ram_top);
return ;
}

  gd->relocaddr = 0x34000000 指向 SDRAM 的顶端

8.2.4 uboot 和 bss段---reserve_uboot

 /* 预留 uboot 区,gd->start_addr_sp = gd->relocaddr -= gd->mon_len  */
static int reserve_uboot(void)
{
/*
* reserve memory for U-Boot code, data & bss
* round down to next 4 kB limit
*/
gd->relocaddr -= gd->mon_len;
gd->relocaddr &= ~( - );
#if defined(CONFIG_E500) || defined(CONFIG_MIPS)
/* round down to next 64 kB limit so that IVPR stays aligned */
gd->relocaddr &= ~( - );
#endif debug("Reserving %ldk for U-Boot at: %08lx\n", gd->mon_len >> ,
gd->relocaddr); gd->start_addr_sp = gd->relocaddr; return ;
}

  栈 gd->start_addr_sp 指向 uboot 段 基地址

8.2.5 堆区---reserve_malloc

 /* malloc 堆区预留大小 */
static int reserve_malloc(void)
{
/* PHYS_FLASH_1 = 0x00000000
CONFIG_SYS_FLASH_BASE = PHYS_FLASH_1
CONFIG_ENV_ADDR = CONFIG_SYS_FLASH_BASE + 0x070000 = 0x070000
CONFIG_ENV_IS_IN_FLASH
CONFIG_ENV_SIZE = 0x10000 */
/* CONFIG_SYS_MALLOC_LEN = 4 * 1024 * 1024 = 0x40 0000 */
/* TOTAL_MALLOC_LEN = CONFIG_SYS_MALLOC_LEN */
gd->start_addr_sp = gd->start_addr_sp - TOTAL_MALLOC_LEN;
debug("Reserving %dk for malloc() at: %08lx\n",
TOTAL_MALLOC_LEN >> , gd->start_addr_sp);
return ;
}

  栈 gd->start_addr_sp 指向 malloc 段 基地址

8.2.6 预留 bd 区域 --- reserve_board

 /* board 信息结构体分配区域 */
static int reserve_board(void)
{
if (!gd->bd) {
gd->start_addr_sp -= sizeof(bd_t);
gd->bd = (bd_t *)map_sysmem(gd->start_addr_sp, sizeof(bd_t));
memset(gd->bd, '\0', sizeof(bd_t));
debug("Reserving %zu Bytes for Board Info at: %08lx\n",
sizeof(bd_t), gd->start_addr_sp);
}
return ;
}

  栈 gd->start_addr_sp 指向 bd 段 基地址

8.2.7 预留全局数据区域---reserve_global_data

 /* 预留 GD 区域 */
static int reserve_global_data(void)
{
gd->start_addr_sp -= sizeof(gd_t);
gd->new_gd = (gd_t *)map_sysmem(gd->start_addr_sp, sizeof(gd_t));
debug("Reserving %zu Bytes for Global Data at: %08lx\n",
sizeof(gd_t), gd->start_addr_sp);
return ;
}

  栈 gd->start_addr_sp 指向 gd 段 基地址

8.2.8 栈区预留区---reserve_stacks

 /* 栈区预留区,gd->start_addr_sp 指向 栈底基地址 */
static int reserve_stacks(void)
{
/* make stack pointer 16-byte aligned */
gd->start_addr_sp -= ;
gd->start_addr_sp &= ~0xf; /*
* let the architecture-specific code tailor gd->start_addr_sp and
* gd->irq_sp
*/
return arch_reserve_stacks();
}

  gd->start_addr_sp 指向 栈底基地址

8.3 小节

  代码执行完后,则返回,当前栈地址指向栈处,依然有大部分区域未分配。

  当前分配的区域如下:

  

八、uboot 代码流程分析---board_init_f的更多相关文章

  1. 六、uboot 代码流程分析---start.S

    6.1 _start 入口函数 6.1.1 vectors.S (arch\arm\lib) 从上一节可以知道,uboot 的入口函数为 _start .此 函数定义在 vectors.S (arch ...

  2. 七、uboot 代码流程分析---C环境建立

    7.1 start.S 修改 在上一节中的流程中,发现初始化的过程并没由设置看门狗,也未进行中断屏蔽 如果看门狗不禁用,会导致系统反复重启,因此需要在初始化的时候禁用看门狗:中断屏蔽保证启动过程中不出 ...

  3. 十、uboot 代码流程分析---run_main_loop

    调用 board_init_r,传入全局 GD 和 SDRAM 中的目的地址 gd->rellocaddr void board_init_r(gd_t *new_gd, ulong dest_ ...

  4. 九、uboot 代码流程分析---relloc_code

    执行完 board_init_f 后,重新跳转回 _main 中执行. 9.1 relloc_code 前 9.1.1 gd 设置 在调用board_init_f()完成板卡与全局结构体变量 gd 的 ...

  5. u-boot启动流程分析(2)_板级(board)部分

    转自:http://www.wowotech.net/u-boot/boot_flow_2.html 目录: 1. 前言 2. Generic Board 3. _main 4. global dat ...

  6. imx6 uboot启动流程分析

    参考http://blog.csdn.net/skyflying2012/article/details/25804209 这里以imx6平台为例,分析uboot启动流程对于任何程序,入口函数是在链接 ...

  7. Uboot启动流程分析(三)

    1.前言 在前面的文章Uboot启动流程分析(二)中,链接如下: https://www.cnblogs.com/Cqlismy/p/12002764.html 已经对_main函数的整个大体调用流程 ...

  8. Uboot启动流程分析(二)

    1.前言 在前面的文章Uboot启动流程分析(一)中,链接如下: https://www.cnblogs.com/Cqlismy/p/12000889.html 已经简单地分析了low_level_i ...

  9. Uboot启动流程分析(一)

    1.前言 Linux系统的启动需要一个bootloader程序,该bootloader程序会先初始化DDR等外设,然后将Linux内核从flash中拷贝到DDR中,最后启动Linux内核,uboot的 ...

随机推荐

  1. Angular $interval

    <!DOCTYPE html><html ng-app="myApp"><head lang="en"> <meta ...

  2. 微信小程序的界面下拉刷新

    小程序的下拉刷新的值设置:需要设置app.json的window中 "navigationBarTextStyle":true  

  3. BZOJ2017[USACO 2009 Nov Silver 1.A Coin Game]——DP+博弈论

    题目描述 农夫约翰的奶牛喜欢玩硬币游戏,因此他发明了一种称为“Xoinc”的两人硬币游戏. 初始时,一个有N(5 <= N <= 2,000)枚硬币的堆栈放在地上,从堆顶数起的第I枚硬币的 ...

  4. BZOJ5251 八省联考2018劈配(网络流)

    劈配,匹配,网络流.那么考虑怎么跑网络流. 先看第一问.首先套路的建出超源超汇.不用想也知道导师向汇连容量为战队人数上限的边.特别地,给出局也建一个点,向汇连容量inf的边(似乎没有必要).对于一个新 ...

  5. 睡前小dp-poj1276-多重背包+二进制优化

    http://poj.org/problem?id=1276 简单的多重背包,不过需要优化一下才能过.网上还有暴力的做法. 二进制优化在背包九讲里讲的比较清楚.对于多重背包的每一件物品,使用二进制的形 ...

  6. Java中如何输出对勾,ASCII编码与字符串相互转换

    Java中如何输出对勾? 最简单的方法是,从那个地方拷贝一个对勾的字符,然后System.out.println("√"); 但是心里总会担心,万一机器不认这个字符该怎么办?(可能 ...

  7. nagios 配置 check_traffic 流量监控模块(Server 端)

    安装软件包yum -y install net-snmp*chkconfig nrpe onchkconfig snmpd onchkconfig nagios on 修改snmp参数,vi /etc ...

  8. Nginx多进程高并发、低时延、高可靠机制在缓存(redis、memcache)twemproxy代理中的应用

    1. 开发背景 现有开源缓存代理中间件有twemproxy.codis等,其中twemproxy为单进程单线程模型,只支持memcache单机版和redis单机版,都不支持集群版功能. 由于twemp ...

  9. 08 Zabbix Item类型之Zabbix agent类型

    点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 08 Zabbix Item类型之Zabbix agent类型 Zabbix agent类型的item是使用部署在服务器端的age ...

  10. BZOJ 4499: 线性函数

    4499: 线性函数 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 177  Solved: 127[Submit][Status][Discuss] ...