U-Boot 启动第二阶段代码分析 (2012-03-23 15:10)一键转载
标签: 二 分类: uboot
U-Boot 第一阶段的启动流程。(nandflash 启动,把 nand 的4k 代码考到 sram 中,因为 nand
没址线,不能映射到内存,所以通过 sram 进行过度,sram 中4k 代码把整个 uboot 拷贝到
sdram 上,初始化好堆栈,为 c 语言提供条件,进入 uboot 的第二阶段! )这个阶段主要是初
始化硬件设备,为加载 U-Boot 的第二阶段代码准备 RAM 空间最后跳转到 lib_arm/board.c
中 start_armboot 函数,这是第二阶段的入口点。
1、在介绍该函数之前,我们需要看一看几个数据结构,这些是 u-boot 中几个重要的数据结
构:
(1)gd_t 结构体
U-Boot 使 用 了 一 个 结 构 体 gd_t 来 存 储 全 局 数 据 区 的 数 据 , 这 个 结 构 体 在
include/asm-arm/global_data.h 中定义如下:
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? */
unsigned long fb_base; /* base address of frame buffer */
#ifdef CONFIG_VFD //我们一般没有配置这个,这个是 frame buffer 的首地址
unsigned char vfd_type; /* display type */
#endif
#if 0
unsigned long cpu_clk; /* CPU clock in Hz! */
unsigned long bus_clk;
unsigned long ram_size; /* RAM size */
unsigned long reset_status; /* reset status register at boot */
#endif
void **jt; /* jump table */
} gd_t;
/*
* Global Data Flags
*/
#define GD_FLG_RELOC 0x00001 /* Code was relocated to RAM */
#define GD_FLG_DEVINIT 0x00002 /* Devices have been initialized */
#define GD_FLG_SILENT 0x00004 /* Silent mode
*/
#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8")
在 global_data.h 中 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)
2)bd_t 保存与板子相关的配置参数
bd_t 在 include/asm-arm/u-boot.h 中定义如下:
typedef struct bd_info {
int bi_baudrate; /* 串口通讯波特率 */
unsigned long bi_ip_addr; /* IP 地址 */
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 配置信息 */
{
ulong start;
ulong size;
} bi_dram[CONFIG_NR_DRAM_BANKS]; //在我的板子上 DRAM 配置是1个
#ifdef CONFIG_HAS_ETH1
/* second onboard ethernet port */
unsigned char bi_enet1addr[6];
#endif
} bd_t;
#define bi_env_data bi_env->data
#define bi_env_crc bi_env->crc
U-Boot 启动内核时要给内核传递参数,这时就要使用 gd_t,bd_t 结构体中的信息来设置标
记列表。
3). 初始化函数列表(以数组的形式)
相关代码在 lib-arm/board.c 中定义
typedef int (init_fnc_t) (void); /*这是使用 typedef 定义一个 init_fnc_t 为函数类型,该函数返回
int 型,无参数*/
int print_cpuinfo (void); /* test-only */
init_fnc_t *init_sequence[]定义一个 init_fnc_t 指针类型的数组。简单的说就是定义了个函数
指针数组,指向一系列 cpu 初始化函数。
init_fnc_t *init_sequence[] = { /*全局变量 init_sequence 的定义,*/
cpu_init, /* basic cpu dependent setup CPU 的相关配置,如初始化 IRQ/FIQ
模式的栈 cpu/arm920t/cpu.c*/
board_init, /* basic board dependent setup 开发板相关配置,是对板子的
初始化,设置 MPLL,改变系统时钟,以及一些 GPIO 寄存器的值,还设置了 U-Boot 机器码
和内核启动参数地址,它是开发板相关的函数,比如2410是在:board/smdk2410/smdk2410.c
中实现*/
interrupt_init, /* set up exceptions 初 始 化 中 断 , 在
cpu/arm920t/s3c24x0/interrupts.c 实现*/
env_init, /* initialize environment 初始化环境变量,检查 flash 上的环境变
量是否有效 common/env_flash.c 或 common/env_nand.c */
init_baudrate, /* initialze baudrate settings 初始化波特率 lib_arm/board.c */
serial_init, /* serial communications setup 串口初始化串口初始化后我们
就可以打印信息了 cpu/arm920t/s3c24x0/serial.c */
console_init_f, /* stage 1 init of console 控制台初始化第一阶段
common/console.c */
display_banner, /* say that we are here 通知代码已经运行到该处,打印
U-Boot 版本、编译的时间-- lib_arm/board.c */
#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 配置可用的内存区,检测
系统内存映射,设置内存的起始地址和大小 board/smdk2410/smdk2410.c*/
display_dram_config,
NULL,
};
可以看出这里定义了一个指针数组,它的每一个元素都是指针变量,这些指针变量指向的类型
为 init_fnc_t,在 C 语言中函数的入口地址就是函数名,所以这里使用一系列函数名来初始化
这个数组。
现在来看看到底做了哪些初始化工作
int cpu_init (void)
{
/*
* setup up stacks if necessary
评论0