U-Boot学习-第二阶段代码分析
来源:互联网 发布:ppt全屏快捷键 mac 编辑:程序博客网 时间:2024/06/04 19:27
U-Boot在完成stage1的工作后会跳转到第一个c语言函数start_armboot()函数中
1 在介绍该函数之前,我们需要看一看几个数据结构,这些是u-boot中几个重要的数据结构:
1)、gd_t该数据结构保存了u-boot 需要的配置信息,注释简单明了
typedef struct global_data {
bd_t *bd; //与板子相关的结构,见下面
unsigned long flags;
unsigned long baudrate;
unsigned long have_console; /* serial_init() was called */
unsigned long reloc_off; /* Relocation Offset */
unsigned long env_addr; /* Address of Environment struct */
unsigned long env_valid; /* Checksum of Environment valid? */
#ifdef CONFIG_VFD //我们一般没有配置这个,这个是frame buffer的首地址
unsigned long fb_base; /* base address of frame buffer */
#endif
} gd_t;
2)、bd_t 保存与板子相关的配置参数
typedef struct bd_info {
int bi_baudrate; /* serial console baudrate */
unsigned long bi_ip_addr; /* IP Address */
unsigned char bi_enetaddr[6]; /* Ethernet adress */
struct environment_s *bi_env;
ulong bi_arch_number; /* unique id for this board */
ulong bi_boot_params; /* where this board expects params */
struct /* RAM configuration */
{
ulong start;
ulong size;
} bi_dram[CONFIG_NR_DRAM_BANKS];//在我的板子上是1个
} bd_t;
3). 初始化函数列表(以数组的形式)
init_fnc_t **init_fnc_ptr;//其中init_fnc_ptr指向一个数组指针:
init_fnc_t *init_sequence[] = {
cpu_init,//初始化IRQ/FIQ模式的栈;
board_init, //这个是对板子的初始化,设置MPLL,改变系统时钟,它是开发板相关的函数,比如2410是在:board/smdk2410/smdk2410.c中实现
interrupt_init, /* set up exceptions || cpu/arm920t,s3c24x0/interrupts.c */初始化定时器
env_init, /* initialize environment */检查flash上的环境变量是否有效
init_baudrate, /* initialze baudrate settings */
serial_init, /* serial communications setup || cpu/arm920t/s3c24x0/serial.c */
//串口初始化后我们就可以打印信息了
console_init_f, /* stage 1 init of console */
display_banner, /* say that we are here */
#if defined(CONFIG_DISPLAY_CPUINFO)
print_cpuinfo, /* display cpu info (and speed) */
#endif
#if defined(CONFIG_DISPLAY_BOARDINFO)
checkboard, /* display board info */
#endif
dram_init, /* configure available RAM banks */检测系统内存映射,设置内存的起始地址和大小
display_dram_config,
NULL,
};
4) u-boot的命令格式:
U_BOOT_CMD(name,maxargs,repeatable,command,”usage”,"help")
name:命令的名字,不是一个字符串;
maxargs:最大的参数个数;
repeatable:命令是可重复的;
command:对应的函数指针
内核的复制和启动,可以通过如下命令来完成:bootm从内存、ROM、NOR Flash中启动内核,bootp则通过网络来启动,而nboot从NAND Flash启动内核。他们是先将内核映像从各种媒介中读出,存放在指定的位置;然后设置标记列表以给内核传递参数;最后跳到内核的入口点去执行。
2 U-Boot第二阶段流程图:
3 star_armboot()源码分析:
=============================================================
void start_armboot (void)
{
init_fnc_t **init_fnc_ptr;//指向初始化函数列表
char *s;
#ifndef CFG_NO_FLASH
ulong size;
#endif
#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 - CFG_MALLOC_LEN - sizeof(gd_t));//为数据结构分配空间_armboot_start
=0x33f880000
/* compiler optimization barrier needed for GCC >= 3.4 */
__asm__ __volatile__("": : :"memory");
memset ((void*)gd, 0, sizeof (gd_t));//初始化全局数据区为0;
gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));//为bd_t分配空间,并赋值到gd
memset (gd->bd, 0, sizeof (bd_t));
monitor_flash_len = _bss_start - _armboot_start; //代码段的大小
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {//依次调用初始化函数
if ((*init_fnc_ptr)() != 0) {
hang ();
}
}
//CFG_NO_FLASH 表示没有flash,如果没定义该常量则表示板子上有flash,此时调用flash_init()对其进行初始化.
#ifndef CFG_NO_FLASH
/* configure available FLASH banks */
size = flash_init ();
display_flash_config (size); //打印flash的信息,仅是其大小;
#endif /* CFG_NO_FLASH */
#ifdef CONFIG_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);
size = vfd_setmem (addr);
gd->fb_base = addr;
#endif /* CONFIG_VFD */
#ifdef CONFIG_LCD
# 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);
size = lcd_setmem (addr);
gd->fb_base = addr;
#endif /* CONFIG_LCD */
/* armboot_start is defined in the board-specific linker script */
mem_malloc_init (_armboot_start - CFG_MALLOC_LEN); //初始化malloc区域
#if (CONFIG_COMMANDS & CFG_CMD_NAND) //如果定义了命令和NAND命令,初始化nand
puts ("NAND: ");
nand_init(); /* go init the NAND */
#endif
#ifdef CONFIG_HAS_DATAFLASH
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 */
/* IP Address */ //初始化网络设备
gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr"); //传递IP地址
/* MAC Address */
{
int i;
ulong reg;
char *s, *e;
char tmp[64];
i = getenv_r ("ethaddr", tmp, sizeof (tmp)); //从环境变量获取网卡的MAC地址并填充gd结构体变量
s = (i > 0) ? tmp : NULL;
for (reg = 0; reg < 6; ++reg) {
gd->bd->bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0;
if (s)
s = (*e) ? e + 1 : e;
}
#ifdef CONFIG_HAS_ETH1
i = getenv_r ("eth1addr", tmp, sizeof (tmp));
s = (i > 0) ? tmp : NULL;
for (reg = 0; reg < 6; ++reg) {
gd->bd->bi_enet1addr[reg] = s ? simple_strtoul (s, &e, 16) : 0;
if (s)
s = (*e) ? e + 1 : e;
}
#endif
}
devices_init (); /* get the devices list going. */ //对设备初始化,在common/devices.c文件中,会根据配置来完成各个设备的初始化,其中会调用函数drv_system_init(),这个函数对串口设备初始化,然后注册串口设备
#ifdef CONFIG_CMC_PU2
load_sernum_ethaddr ();
#endif /* CONFIG_CMC_PU2 */
jumptable_init (); //跳转表初始化
console_init_r (); /* fully init console as a device */
#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_CS8900
cs8900_get_enetaddr (gd->bd->bi_enetaddr); //获取网卡的MAC地址
#endif
#if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96)//没有定义
if (getenv ("ethaddr")) {
smc_set_mac_addr(gd->bd->bi_enetaddr);
}
#endif /* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */
/* Initialize from environment */
if ((s = getenv ("loadaddr")) != NULL) {
load_addr = simple_strtoul (s, NULL, 16);
}
#if (CONFIG_COMMANDS & CFG_CMD_NET)
if ((s = getenv ("bootfile")) != NULL) {
copy_filename (BootFile, s, sizeof (BootFile));
}
#endif /* CFG_CMD_NET */
#ifdef BOARD_LATE_INIT
board_late_init ();
#endif
#if (CONFIG_COMMANDS & CFG_CMD_NET)
#if defined(CONFIG_NET_MULTI)
puts ("Net: ");
#endif
eth_initialize(gd->bd);
#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 */
}
main_loop函数在common/main.c中定义
4 U-Boot内存使用情况:
参考文献:
1 http://6xudonghai.blog.163.com/blog/static/33640629200911364735696/
2 http://hi.baidu.com/yeanleo/blog/item/88d9ed5871e8cf222934f0a6.html
3 http://blog.chinaunix.net/u3/114171/showart_2426405.html
4 http://www.cnblogs.com/heaad/archive/2010/07/17/1779829.html
- U-Boot学习-第二阶段代码分析
- U-boot第二阶段代码分析
- U-Boot 第二阶段代码分析
- U-Boot -第二阶段代码分析
- U-Boot启动第二阶段代码分析
- U-Boot启动第二阶段代码分析
- U-Boot启动第二阶段代码分析
- U-Boot启动第二阶段代码分析
- U-Boot启动第二阶段代码分析
- U-boot第二阶段分析
- U-boot第二阶段分析
- U-Boot启动第二阶段代码
- u-boot第二阶段源码分析
- u-boot第二阶段代码(4)
- u-boot源码分析 --- 启动第二阶段001
- u-boot源码分析 --- 启动第二阶段002
- u-boot源码分析 --- 启动第二阶段003
- u-boot源码分析 --- 启动第二阶段004
- uboot分析之u-boot.lds
- 从新做人么
- 你不知道的21个Qt隐藏功能和技巧
- 下载Android源代码
- DWR
- U-Boot学习-第二阶段代码分析
- JS属性 ClientTop,scrollTop,offsetWidth,ClientWidth,clientLeft,padding,border,top,margin区别
- 请帮助和关心Unix-Center
- 【Android游戏开发之九】(细节处理)触屏事件中的Bug解决方案以及禁止横屏和竖屏切换!
- vi 技巧和诀窍:令人刮目相看的 10 个超酷命令
- IPPBX系统组成原理及其应用
- 国外的开源的CMS系统(ASP.Net-C#)
- 读书摘要——《C++ GUI Programming with Qt4》
- Qt Moblity API 需要的能力