首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

U-Boot启动过程完全分析(7)

U-Boot启动过程完全分析(7)

完整代码见board/samsung/mini2440/nand_read.c中的nand_read_ll函数,这里给出伪代码:
int nand_read_ll(unsigned char *buf,unsigned long start_addr, int size)
{
//根据NFCONF寄存器的Bit3来区分2NAND Flash

if(NFCONF & 0x8 )

/* Bit1,表示是2KB/pageNAND Flash */

{

////////////////////////////////////

读取2K block NAND Flash

////////////////////////////////////



}

else
/* Bit0,表示是512B/pageNAND Flash */

{

/////////////////////////////////////

读取512B block NAND Flash

/////////////////////////////////////



}

return 0;
}
10)设置堆栈


/*
设置堆栈*/
stack_setup:

ldr
r0, _TEXT_BASE
/* upper 128 KiB: relocated uboot
*/

sub
r0, r0, #CONFIG_SYS_MALLOC_LEN
/* malloc area
*/

sub
r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /*
跳过全局数据区
*/
#ifdef CONFIG_USE_IRQ

sub
r0, r0,#(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif

sub
sp, r0, #12
/*leave 3 words for abort-stack
*/

只要将sp指针指向一段没有被使用的内存就完成栈的设置了。根据上面的代码可以知道U-Boot内存使用情况了,如下图所示:



2.2 U-Boot内存使用情况



11)清除BSS

clear_bss:

ldr
r0, _bss_start
/* BSS段开始地址,在u-boot.lds中指定*/

ldr
r1, _bss_end
/*BSS段结束地址,在u-boot.lds中指定*/

mov
r2, #0x00000000

clbss_l:str
r2, [r0]
/* bss段清零*/

add
r0, r0, #4

cmp
r0, r1

ble
clbss_l

初始值为0,无初始值的全局变量,静态变量将自动被放在BSS段。应该将这些变量的初始值赋为0,否则这些变量的初始值将是一个随机的值,若有些程序直接使用这些没有初始化的变量将引起未知的后果。

12)跳转到第二阶段代码入口


ldr
pc, _start_armboot


_start_armboot:
.word
start_armboot

跳转到第二阶段代码入口start_armboot处。

1.1.2
U-Boot启动第二阶段代码分析

start_armboot函数在lib_arm/board.c中定义,是U-Boot第二阶段代码的入口。U-Boot启动第二阶段流程如下:


2.3 U-Boot第二阶段执行流程


在分析start_armboot函数前先来看看一些重要的数据结构:

1gd_t结构体


U-Boot使用了一个结构体gd_t来存储全局数据区的数据,这个结构体在include/asm-arm/global_data.h中定义如下:

typedef
struct
global_data {

bd_t
*bd;

unsignedlong
flags;

unsignedlong
baudrate;

unsignedlong
have_console;
/* serial_init() was called */

unsignedlong
env_addr;
/* Address
of Environmentstruct */

unsignedlong
env_valid;
/* Checksum of Environment valid? */

unsignedlong
fb_base;
/* base address of frame buffer */

void
**jt;
/* jump table */
} gd_t;

U-Boot使用了一个存储在寄存器中的指针gd来记录全局数据区的地址:

#define DECLARE_GLOBAL_DATA_PTR
register volatile gd_t *gd asm("r8")

DECLARE_GLOBAL_DATA_PTR
定义一个gd_t全局数据结构的指针,这个指针存放在指定的寄存器r8中。这个声明也避免编译器把r8分配给其它的变量。任何想要访问全局数据区的代码,只要代码开头加入“DECLARE_GLOBAL_DATA_PTR”一行代码,然后就可以使用gd指针来访问全局数据区了。


根据U-Boot内存使用图中可以计算gd的值:

gd = TEXT_BASE CONFIG_SYS_MALLOC_LEN sizeof(gd_t)
继承事业,薪火相传
返回列表