`
isiqi
  • 浏览: 16036476 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

start_armboot

阅读更多

第一个c函数位于arch/arm/lib/board.c

start_armboot会马上申请三块空间,一块用来分配给malloc管理,一份用来存储gd_t,一份用来存储bd_t。

他们在RAM中内存布局如上图所示。

void start_armboot (void)
{
init_fnc_t **init_fnc_ptr;
char *s;
int delay = 100000;
int *p3_output_set, *p3_output_clr;


#if defined(CONFIG_VFD) || defined(CONFIG_LCD)
unsigned long addr;
#endif

/* Pointer is writable since we allocated a register for it */
gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t)); //gd指向uboot之前的地址。
/* compiler optimization barrier needed for GCC >= 3.4 */


__asm__ __volatile__("": : :"memory");

memset ((void*)gd, 0, sizeof (gd_t));
gd->bd = (bd_t*)((char*)gd - sizeof(bd_t)); //gd->bd指向gd之前。


memset (gd->bd, 0, sizeof (bd_t));

gd->flags |= GD_FLG_RELOC;

monitor_flash_len = _bss_start - _armboot_start;


/*循环调用init_sequence的初始化函数*/
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
if ((*init_fnc_ptr)() != 0) {
hang ();

}

}

/* armboot_start is defined in the board-specific linker script */
mem_malloc_init (_armboot_start - CONFIG_SYS_MALLOC_LEN,
CONFIG_SYS_MALLOC_LEN);//初始化用作malloc的内存空间。

#ifndef CONFIG_SYS_NO_FLASH //目前3250不支持nor flash.
/* configure available FLASH banks */
display_flash_config (flash_init ());
#endif /* CONFIG_SYS_NO_FLASH */

#ifdef CONFIG_VFD //3250不支持VFD
#ifndef PAGE_SIZE
# define PAGE_SIZE 4096
#endif


/*
* reserve memory for VFD display (always full pages)
*/
/* bss_end is defined in the board-specific linker script */
addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
vfd_setmem (addr);
gd->fb_base = addr;
#endif /* CONFIG_VFD */

#ifdef CONFIG_LCD//3250不支持LCD
/* board init may have inited fb_base */
if (!gd->fb_base) {
#ifndef PAGE_SIZE
# define PAGE_SIZE 4096
#endif


/*
* reserve memory for LCD display (always full pages)
*/
/* bss_end is defined in the board-specific linker script */
addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
lcd_setmem (addr);
gd->fb_base = addr;
}
#endif /* CONFIG_LCD */

#if defined(CONFIG_CMD_NAND)
puts ("NAND: ");
nand_init();/* go init the NAND */调用driver/mtd/nand/nand.c.打印:NAND: 256 MiB
#endif
//puts("NAND init end \n");
#if defined(CONFIG_CMD_ONENAND) ////3250不支持
onenand_init();
#endif

#ifdef CONFIG_HAS_DATAFLASH////3250不支持
AT91F_DataflashInit();
dataflash_print_info();
#endif

/* initialize environment */
env_relocate (); //祥见下面的分析

#ifdef CONFIG_VFD
/* must do this after the framebuffer is allocated */
drv_vfd_init();
#endif /* CONFIG_VFD */

#ifdef CONFIG_SERIAL_MULTI
serial_initialize();
#endif

/* IP Address */
gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr"); //获取环境变量的ip地址填充gd->bd->bi_ip_addr

stdio_init ();/* get the devices list going. */ //common/stdio.c 初始化stdio设备dev,将串口的接口注册进dev系统。

jumptable_init ();//初始化gd->jt跳转表(common/export.c)。跳转表保存的是stdio的各个函数指针

#if defined(CONFIG_API)
/* Initialize API */
api_init ();
#endif

console_init_r ();/* fully init console as a device *//(common/console.c)初始化stdin\stdout\和stderr,都指向stdio_init注册的stdio dev。gd->flags |= GD_FLG_DEVINIT;
/*输出信息:
In: serial
Out: serial
Err: serial*/
#if defined(CONFIG_ARCH_MISC_INIT)
/* miscellaneous arch dependent initialisations */
arch_misc_init ();
#endif


#if defined(CONFIG_MISC_INIT_R)
/* miscellaneous platform dependent initialisations */
misc_init_r ();
#endif

/* enable exceptions */
enable_interrupts ();

/* Perform network card initialisation if necessary */
#ifdef CONFIG_DRIVER_TI_EMAC
/* XXX: this needs to be moved to board init */
extern void davinci_eth_set_mac_addr (const u_int8_t *addr);
if (getenv ("ethaddr")) {
uchar enetaddr[6];
eth_getenv_enetaddr("ethaddr", enetaddr);
davinci_eth_set_mac_addr(enetaddr);
}
#endif

#if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96)
/* XXX: this needs to be moved to board init */
if (getenv ("ethaddr")) {
uchar enetaddr[6];
eth_getenv_enetaddr("ethaddr", enetaddr);
smc_set_mac_addr(enetaddr);
}
#endif /* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */

/* Initialize from environment */
if ((s = getenv ("loadaddr")) != NULL) { //3250目前不支持
load_addr = simple_strtoul (s, NULL, 16);
}
#if defined(CONFIG_CMD_NET)
if ((s = getenv ("bootfile")) != NULL) {//“uImage”内核镜像名
copy_filename (BootFile, s, sizeof (BootFile));
}
#endif

#ifdef BOARD_LATE_INIT
board_late_init ();
#endif

#ifdef CONFIG_GENERIC_MMC
puts ("MMC: ");
mmc_initialize (gd->bd);
#endif

#ifdef CONFIG_BITBANGMII
bb_miiphy_init();
#endif
#if defined(CONFIG_CMD_NET)
#if defined(CONFIG_NET_MULTI)
puts ("Net: ");
#endif


eth_initialize(gd->bd);
#if defined(CONFIG_RESET_PHY_R)
debug ("Reset Ethernet PHY\n");
reset_phy();
#endif
#endif

/* main_loop() can return to retry autoboot, if so just run it again. */
for (;;) {
main_loop ();
}

/* NOTREACHED - no way out of command loop except booting */

}

void hang (void)
{
puts ("### ERROR ### Please RESET the board ###\n");
for (;;);
}

2.env_relocate ()
void env_relocate (void)
{
。。。。。。。。。。
#ifdef ENV_IS_EMBEDDED
。。。。。。。。。。。。。。。。。。。
#else
/*
* We must allocate a buffer for the environment
*/
env_ptr = (env_t *)malloc (CONFIG_ENV_SIZE); //在内存的malloc区域申请一块内存存放环境变量。
DEBUGF ("%s[%d] malloced ENV at %p\n", __FUNCTION__,__LINE__,env_ptr);
#endif

if (gd->env_valid == 0) {
#if defined(CONFIG_GTH)|| defined(CONFIG_ENV_IS_NOWHERE)/* Environment not changable */
puts ("Using default environment\n\n");
#else
puts ("*** Warning - bad CRC, using default environment\n\n");
show_boot_progress (-60);
#endif
set_default_env();
}
else {
env_relocate_spec (); init_sequence说到了,gd->env_valid 总为1,所以会执行这个路径。
}
gd->env_addr = (ulong)&(env_ptr->data); //初始化gd->env_addr

#ifdef CONFIG_AMIGAONEG3SEs
disable_nvram();
#endif
}
由于smartarm3250中定义了CONFIG_CMD_NAND,common/目录下的makefile会选择性的编译env_nand.c而不是其他的文件。

env_relocate_spec (); 就定义在env_nand.c。
void env_relocate_spec (void)
{
#if !defined(ENV_IS_EMBEDDED)
int ret;

ret = readenv(CONFIG_ENV_OFFSET, (u_char *) env_ptr); //CONFIG_ENV_OFFSET是在smartarm3250.h中定义的表示环境变量在flash中的偏移位置。,env_ptr是本文件内的一个全局指针。
if (ret)
return use_default();

if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc)
return use_default();
#endif /* ! ENV_IS_EMBEDDED */
}
#endif /* CONFIG_ENV_OFFSET_REDUND */

#if !defined(ENV_IS_EMBEDDED)
static void use_default()
{
puts ("*** Warning - bad CRC or NAND, using default environment\n\n");
set_default_env();
}
#endif


readenv函数将从flash中读取环境变量到env_ptr。
如果读取失败或者校验错误,则使用default_environment的内容填充env_ptr->data,并打印以下信息:*** Warning - bad CRC or NAND, using default environment\n\n
无论env_ptr->data指向的内容是从flash读出的,还是填充的default_environment,gd->env_addr = (ulong)&(env_ptr->data);

default_environment是根据宏生成的环境变量,从flash中读出的是用户修改过的环境变量,两者可能不一样。

总结:init_sequence之后的函数基本没有涉及到硬件初始化,大多是进行环境变量和数据结构的初始化。虽然函数很长,但是大部分都没有执行。

对与两个全局结构体的初始化过程如下表所示:

arch/arm/include/asm/global_data.h 意义 赋值顺序 第一次赋值 第二次赋值 第一次赋值函数 第二次
typedef struct global_data { uboot全局信息结构体          
bd_t *bd; 指向板级信息结构体 <0> (bd_t*)((char*)gd - sizeof(bd_t)); arch/arm/lib/board.c/start_armboo
unsigned long flags; 标志变量 <0><13> |= GD_FLG_RELOC |= GD_FLG_DEVINIT arch/arm/lib/board.c/start_armboo common/console.c/console_init_r
unsigned long baudrate; 终端波特率 <5> CONFIG_BAUDRATE(115200) arch/arm/lib/board.c/init_baudrate
unsigned long have_console; 是否已经调用了serial_init() <7> 1 common/console.c/console_init_f
unsigned long env_addr; 环境变量结构体的地址 <3><10> (ulong)&default_environment[0]; (ulong)&(env_ptr->data) common/env_nand.c/env_init common/env_common.c/env_relocate
unsigned long env_valid; 环境变量的校验码是否正确 <4> 1 common/env_nand.c/env_init
unsigned long fb_base; 帧缓冲的基地址
void**jt; stdio函数的指针跳转表 <12> malloc(XF_MAX * sizeof(void *)) common/export.c/jumptable_init
} gd_t;            
typedef struct bd_info { 板级配置信息结构体          
int bi_baudrate; 串口终端波特率 <6> CONFIG_BAUDRATE(115200) arch/arm/lib/board.c/init_baudrate
unsigned long bi_ip_addr; ip地址 <11> getenv_IPaddr ("ipaddr") arch/arm/lib/board.c/start_armboo
struct environment_s *bi_env; 环境变量结构体的地址
ulong bi_arch_number; 板子编号 <1> MACH_TYPE_UBOOTSYS(MACH_TYPE_LPC3XXX) board/zhiyuan/smartarm3250/smart3250.c/board_init
ulong bi_boot_params; 板子启动参数 <2> CFG_ENV_ADDR(0x80000100) board/zhiyuan/smartarm3250/smart3251.c/board_init
struct { RAM描述结构体
ulong start; 开始地址 <8> PHYS_SDRAM_1;在smartarm3250.h中,起始地址 board/zhiyuan/smartarm3250/smart3250.c/dram_init
ulong size; RAM大小 <9> 0x04000000; /* 64M ,RAM大小*/ board/zhiyuan/smartarm3250/smart3250.c/dram_init
}bi_dram[CONFIG_NR_DRAM_BANKS];
} bd_t;            

分析,bd的bi_env因该指向env_ptr的,可是程序中没有给它赋值,也没有使用。

分享到:
评论

相关推荐

    uboot start_armboot分析

    uboot start_armboot分析

    u-boot分析第一阶段和第二阶段流程图:lowlevel_init和start_armboot

    该文件是u-boot分析第一阶段和第二阶段流程图:lowlevel_init和start_armboot,具体分析的文章如下: lowlevel_init:https://blog.csdn.net/zi_yang_/article/details/89182278 start_armboot:...

    U-boot的BL2阶段start_armboot解析

    U-boot的BL2阶段start_armboot解析,U-boot的BL2阶段start_armboot解析

    uboot中C语言代码入口函数(start_armboot)的注释.docx

    uboot中C语言代码入口函数(start_armboot)的注释

    U-Boot启动第二阶段代码分析.rar_U-Boot启动;第二阶段_arm_启动分析

    U-Boot第一阶段的启动流程。(nandflash启动,把nand的4k代码考到... )这个阶段主要是初始化硬件设备,为加载U-Boot的第二阶段代码准备RAM空间最后跳转到lib_arm/board.c中start_armboot函数,这是第二阶段的入口点。

    U-BOOT源码分析及移植

    U-BOOT源码分析及移植,分析uboot的原理,程序执行流程,以及下那个硬的分析2)lib_arm/board.c: ... gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t)); memset ((void*)gd, 0, sizeof (gd_t));

    u-boot移植实验

    2 阶段2是C语言代码,在lib_arm/board.c中的start_armboot是C语言开始的函数,也是整个启动代码中C语言的主函数。这个函数调用一系列的初始化函数,然后进入主UBOOT命令行,进入命令循环(即整个boot的工作循环),...

    ARM中start.s详解

    很不错的底层程序详解。参考了别人的一些资料。 对于初学者学习start很有帮助!

    uboott移植实验手册及技术文档

    (4)在 “ _start_armboot: .word start_armboot ”后加入: .align 2 DW_STACK_START: .word STACK_BASE+STACK_SIZE-4 三、创建 board/fs2410/nand_read.c 文件,加入读 NAND Flash 的操作。 #include ...

    uboot代码详细分析.pdf

    start_armboot浅析 42 1.全局数据结构的初始化 42 2.调用通用初始化函数 43 3.初始化具体设备 44 4.初始化环境变量 44 5.进入主循环 44 u-boot编译过程 44 mkconfig文件的分析 47 从NAND闪存中启动U-BOOT的设计 50 ...

    arm_linux_driver

    _old cs8900 led mmu nand_boot std uart bootl exception_mode mboot nand nand_boot_old ts clock key mem_control nand2 start_main ts_printf

    u-boot开源代码

    ◆ cpu:CPU相关文件,其中的子目录都是以U-BOOT所支持的CPU为名,比如有子目录arm926ejs、mips、mpc8260和nios等,每个特定的子目录中都包括cpu.c和interrupt.c,start.S。其中cpu.c初始化CPU、设置指令Cache和数据...

    ARM_Linux启动分析.pdf

    调用pal_init()初始化PAL代码,调用openboot() 打开引导设备(通过读取Firmware环境),调用load()将核心代码加载到START_ADDR(见 “include/asm-alpha/system.h”),再将Firmware中的核心引导参数加载到ZERO_PAGE...

    ARM Linux 启动过程分析

    本文针对arm linux, 从kernel的第一条指令开始分析,一直分析到进入 start_kernel()函数. 我们当前以linux-2.6.19内核版本作为范例来分析,本文中所有的代码,前面都会加上行号以便于和源码进行对照, 例: 在文件init/...

    arm_now:arm_now是一款qemu强大的工具,它允许在arm cpu,mips,powerpc,nios2,x86等上即时设置虚拟机,以进行反向,利用,模糊测试和编程

    arm_now 1.2 arm_now是一款qemu强大的工具,可以即时在arm cpu,mips,powerpc,nios2,x86等平台上设置虚拟机,以进行...$ arm_now start armv5-eabi Welcome to arm_now buildroot login: root # uname -m armv7l

    dp18_ap6330整理完工20170209_1129.7z

    frameworks/native/data/etc/android.software.verified_boot.xml:system/etc/permissions/android.software.verified_boot.xml frameworks/native/data/etc/android.hardware.ethernet.xml:system/etc/...

    U-boot quick start guide

    该文是在ARM7(LPC2200)平台上应用U-boot的指南

    cpu/arm920/start.S文件注释

    学习start.S的注释。语言是汇编,在u-boot移植中一般不做修改,但是应知道这个文件实现了什么作用。

    U-BOOT启动流程详解

    开发板上电后,执行U-Boot的第一条指令,然后顺序执行U-Boot启动函数。...第一个要链接的是cpu/arm920t/start.o,那么U-Boot的入口指令一定位于这个程序中。下面详细分析一下程序跳转和函数的调用关系以及函数实现。

Global site tag (gtag.js) - Google Analytics