uboot中C语言代码入口函数(start_armboot)的注释
//打印BANK的相关信息
display_dram_config,
NULL,//用以标识列表数组的结束
};
//------------start_armboot--------------------
//功能:完成uboot第二阶级的一系列的
//硬件初始化工作,
然后转入main函数.
//备注:该函数是C程序的入口函数,从汇编语
//言跳转到此
.
//---------------------------------------------
void
start_armboot (void)
{
init_fnc_t
**init_fnc_ptr;//init_fnc_t 是各初始化函数的数组
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_t:定义在
/include/asm-arm/Global_data.h中,包含一些全局通用的变量.
_armboot_start:代码的起始地址,它定义在start.S中的前几行中,定义为
_start
当系统第一次加电时,指令是从0x0地址开始执行的,所以此时的
_start值
应为0x0;而当uboot经过代码重定位后,指令会从
_TEXT_BASE
处开始执行,
此时的
_start值就成了
_TEXT_BASE的值.
CFG_MALLOC_LEN:在/include/configs/smdk2440.h中有定义,该变量表示供
malloc函数使用的内存池空间,代码中定义值为:0x10000+128*1024
|-------|<---
_armboot_start基址
|
4 |
|-------|<--- malloc函数池基址
|
3 |
|-------|<--- (gd_t)gd(全局变量表)基址
|
2 |
|-------|<---
(bt_t)bd(板卡信息表)基址
|
1 |
-------
4
就是为malloc函数预留的数据空间
3 是全信息表gd的数据区
2
是板卡信息表bd的数据区
网上找了个图片,更能反应这个空间的分配关系:
*/
//分配区域
3
给
gd
,gd是一个全局静态变量
gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
/* compiler optimization barrier needed for GCC >= 3.4 */
__asm__ __volatile__("": : :"memory");
//把gd变量的内容填充为0
,填充
3
区的数据为0
,即初始化gd表.注意:这里并没有
//初始化bd表,在gd表中的bd成员只是一个指针,因为对初始化的是个指针地址
memset ((void*)gd, 0, sizeof (gd_t));
/*
bd_t
结构体在/include/asm-arm/U-boot.h中定义,
定义板子的一些信息,包括:
波特率,IP地址,
以太网地址,
架构编码,启动参数
,BANK的起始地址和大小等
*/
//分配区域
2
给bd,
bd的基址
=
gd的基址
-
bd的尺寸
gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
//把区域
2
填充为
0
,即初始化
bd
表
memset (gd->bd, 0, sizeof (bd_t));
/*monitor_falsh_len定义在
/lib_arm/Board.c
在bin文件中
BSS
段和
TEXT
段和
DATA
段存放的顺序同前向后依次是:
TEXT(代码段
RO)
DATA(已初始化数据段
RW)
BSS(未初始化数据段
ZI)
所以
_bss_start
的基址等于
TEXT的长度加上DATA的长度.
即:
_bss_start(BSS段基址)
= 代码段长度+数据段长度
BSS(Block
Started by
Symbol)段是未被初始化的数据段,是存放程序中
未被初始化的全局变量的一块内存区域,初始化时应清零;该段只有
名称和大小却没有值;该段不包含任何数据,只是简单的维护开始和
结束的地址,以便内存区能在运行时被有效地清零,它在应用程序的
映像文件(ARM中也即bin文件)中并不存在.
text :代码段,是包含程序代码的段
dat
:已经初始化的数据段,保存已经初始化的全局变量.
在嵌入式系统中,bin文件(又称Image文件)中只包含text和data段,
而bss段不在其中,它是由系统初始化为零.
*/
//_armboot_start
在start.S中定义为_start,而_start为代码的起始地址
//只包含
RO(TEXT)
和
RW(DATA)
段.重定位前的值为0x0,此时指向flash,
//重定位后则指向RAM中的某一地址
//由此可以知道:
_bss_start - _armboot_start
的值即是在第一阶段从
//flash中重定位到RAM中的那部分代码的长度,也即可TEXT和DATA数据段,
//这个值与start.S中的重定位那部分代码所计算的值是相等的
//所以,monitor_flash_len表示从flash中搬来的代码的长度
monitor_flash_len = _bss_start - _armboot_start; //_bss_start
在u-boot.lds中定位
//各设置的初始化.当返回值不为0时表示初始化失败
,此时会调用
hang()函数
//打印一错误提示信息,然后进入死循环
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)
*///为LCD分配RAM(内存)空间
/* 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
*/
//malloc函数使用缓冲区的初始化
mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);
//如果定义了命令和NAND命令,则初始化nand
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
puts ("NAND: ");
nand_init();/* go init the NAND */
#endif
#ifdef
CONFIG_HAS_DATAFLASH
AT91F_DataflashInit();
dataflash_print_info();
#endif
/*
initialize environment 环境的初始化,代码在common/env_common.c中
*/
env_relocate ();
#ifdef
CONFIG_VFD
/* must do this after the
framebuffer is allocated */
drv_vfd_init();
#endif /* CONFIG_VFD */
/* IP
Address 为全局变量的成员赋值:IP地址*/
gd->bd->bi_ip_addr = getenv_IPaddr
("ipaddr");//ipaddr在smdk2440.h中的CONFIG_IPADDR中出现,应该是该常量
/*
MAC Address *///高处MAC地址
,并赋给gd的成员变量
{
int i;
ulong reg;
char
*s, *e;
char tmp[64];
i =
getenv_r ("ethaddr", tmp, sizeof (tmp));
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
}
//这个函数涉及好多,我没深入分析,若哪位分析了希望能分享一下:cczy_english@163.com,将不胜感激
devices_init
();/* get the devices list going. */
#ifdef
CONFIG_CMC_PU2
load_sernum_ethaddr ();
#endif /*
CONFIG_CMC_PU2 */
//初始化跳转表,对gd中的jt(函数跳转表)数组进行初始化,其中保存着一些函数的入口地址
分享到:
相关推荐
`start_armboot`函数中,通过`_armboot_start`(代码起始地址)减去预定义的内存分配长度来确定`gd`的基地址,然后对其进行初始化。 #### 板卡信息结构`bd_t` `bd_t`结构体定义于`include/asm-arm/U-boot.h`文件,...
在U-Boot(通用引导加载程序)中,`start_armboot`函数是C语言代码的入口点,负责启动过程中的核心任务。理解`start_armboot`的运作方式,需要先了解一些关键的数据结构,如`gd_t`和`bd_t`,以及初始化函数列表。 1...
U-Boot第一阶段的启动流程。(nandflash启动,把nand的4k代码考到... )这个阶段主要是初始化硬件设备,为加载U-Boot的第二阶段代码准备RAM空间最后跳转到lib_arm/board.c中start_armboot函数,这是第二阶段的入口点。
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));
3. 执行 start_armboot 函数:Uboot 将执行 start_armboot 函数,以便启动 Uboot。 start_armboot 函数是 Uboot 启动的主要入口函数,该函数将执行 Uboot 的主要任务,包括初始化硬件、加载内核等。 Uboot 启动...
* stage2:一般主函数是lib_arm/board.c中的start_armboot。调用一系列的初始化函数,将内核从flash复制到RAM中,进入U-Boot命令行,调用内核。 U-Boot命令行 U-Boot命令行是U-Boot提供的一种交互方式,用于提供...
4. C运行时环境的建立:在完成必要的硬件初始化后,Start.S会跳转到C语言编写的初始化函数中,比如__main或者start_armboot等。这些函数会进一步设置C运行时环境,包括初始化堆栈、设置bss段(未初始化数据区)为零...
关于U-Boot如何从4KB的启动引导区(steppingstone)跳转到RAM中执行,文章指出关键在于ldrpc,_start和_start_armboot:.word start_armboot这两条指令。ldrpc,_start指令将_start_armboot标签所指的位置(即start_arm...
这段代码的作用是将 `_start_armboot` 的地址加载到 PC 寄存器中,然后跳转到 `_start_armboot` 执行。`_start_armboot` 是 U-Boot 的入口函数,它会将 U-Boot 的部分代码复制到 RAM 中,并跳转到 RAM 地址继续执行...
在Uboot启动过程的第二阶段中,Uboot会执行`start_armboot`函数,该函数是Uboot的主要入口点。在这个函数中,Uboot会执行一系列的初始化操作,包括设置堆栈、初始化内存、清零BSS段等。 在`start_armboot`函数中,...
在`start_armboot`函数中,会针对特定的硬件平台进行初始化,包括设置时钟、初始化GPIO、配置串口、设置中断控制器等。 3. **内存管理**: 在这个阶段,U-Boot会进行内存的检测和分区,为后续的系统加载和应用...
通过分析`armboot-1.1.0_project`的源代码,开发者可以了解如何根据实际需求调整uboot的功能,如何编译生成适用于自己硬件的引导加载程序,以及如何利用uboot提供的接口进行设备调试和系统升级。 总结来说,uboot-...
UBoot支持多种处理器架构,如ARM、PowerPC、x86等。 2. **启动流程** - **上电自检(POST)**:系统上电后,UBoot首先执行基本的硬件自检,检查CPU、内存和其他关键硬件设备是否正常。 - **初始化DDR**:对系统的...
最后,Uboot 将控制权交给 `_start_armboot` 函数,接着 Uboot 的主要功能将被执行。 总结 Uboot 启动流程是一个复杂的过程,它涉及到 CPU 的初始化和复位、Uboot 的重定位、堆栈的初始化、内存的分配、BSS 段的...
在第一阶段完成后,U-Boot会跳转到start_armboot函数,这是一个C语言函数,位于lib_arm/board.c文件中。这个函数负责完成系统的初始化工作,包括内存的初始化、硬件的初始化、内核镜像的解压缩等。 在这个阶段中,U...
1. **处理器初始化**:start.S首先会根据目标平台(如ARM、PowerPC等)的特性,将CPU设置到适当的运行模式,例如对于ARM,通常是将处理器从.thumb模式切换到.ARM模式。 2. **堆栈设置**:初始化堆栈,确保程序在...
它支持多种处理器架构,如ARM、PowerPC、MIPS等,适用于各种嵌入式系统,如路由器、手机、工控设备等。 1.2 版本2009.6亮点:此版本包含了多项改进和新特性,包括更完善的硬件驱动、性能优化以及对新平台的支持。...