2.6.1、start_armboot函数简介
2.6.1.1、一个很长的函数

2.6.1.2、一个函数组成uboot第二阶段
2.6.1.3、宏观分析:uboot第二阶段应该做什么

2.6.1.4、思考:uboot第二阶段完结于何处?

/* main_loop() can return to retry autoboot, if so just run it again. */
//main_loop()可以返回重试自动引导,如果是这样,就再次运行它
for (;;) {
main_loop (); //接收命令、解析命令、执行命令的死循环
}
2.6.2.start_armboot解析1
2.6.2.1、init_fnc_t

//init_fnc_t:是一个函数类型
//其是用typedef给该函数重命名为init_fnc_t,该函数没有参数,其返回值为int类型
typedef int (init_fnc_t) (void);


//init_fnc_ptr:二重指针
//typedef int (init_fnc_t) (void); 是一个函数类型
init_fnc_t **init_fnc_ptr;
2.6.2.DECLARE_GLOBAL_DATA_PTR

//gd:全局变量,为指针类型
//volatile:表示其是可变的
//register:表示其放在寄存器中
//asm("r8"):gcc支持的一种语法,意思就是要把gd放到寄存器r8中
//gd_t:是一个结构体;gd是一个结构体指针,其指向gd_t。
#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8")

#ifndef __ASM_GBL_DATA_H
#define __ASM_GBL_DATA_H
/*
* The following data structure is placed in some memory wich is
* available very early after boot (like DPRAM on MPC8xx/MPC82xx, or
* some locked parts of the data cache) to allow for a minimum set of
* global variables during system initialization (until we have set
* up the memory controller so that we can use RAM).
*
* Keep it *SMALL* and remember to set CFG_GBL_DATA_SIZE > sizeof(gd_t)
*下面的数据结构放在内存中
*启动后很早就可用(如MPC8xx/MPC82xx上的DPRAM,或数据缓存的一些锁定部分),
*以便在系统初始化期间允许最小的全局变量集(直到我们设置了内存控制器,以便可以使用RAM)。
*保持*小*并且记得设置CFG _ GBL _数据_大小>大小of(gd_t)
*/
typedef struct global_data {
bd_t *bd; //bd_t:存放开发板的硬件信息的结构体
unsigned long flags; //标志位
unsigned long baudrate; //波特率
unsigned long have_console;/* serial_init() was called;serial_init()被调用*/
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
unsigned char vfd_type; /* display type */
#endif
#if 0
unsigned long cpu_clk; /* CPU clock in Hz! */
unsigned long bus_clk;
phys_size_t ram_size; /* RAM size */
unsigned long reset_status; /* reset status register at boot */
#endif
void **jt; /* jump table 跳转表*/
} gd_t;
********************************************************************
* NOTE: This header file defines an interface to U-Boot. Including
* this (unmodified) header file in another file is considered normal
* use of U-Boot, and does *not* fall under the heading of "derived
* work".
* 注意:这个头文件定义了一个U-Boot盘接口。将这个(未修改的)头文件包含在另一个
* 文件中被认为是U-Boot的正常使用,并且不*属于“衍生作品”的标题。
********************************************************************
*/
#ifndef _U_BOOT_H_
#define _U_BOOT_H_ 1
typedef struct bd_info {
int bi_baudrate; /* 串口控制台波特率*/
unsigned long bi_ip_addr; /* IP Address 开发板的IP地址*/
unsigned char bi_enetaddr[6]; /* Ethernet adress 开发板的MAC地址*/
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]; //开发板的DDR
#ifdef CONFIG_HAS_ETH1
/* second onboard ethernet port */
unsigned char bi_enet1addr[6];
#endif
} bd_t;
2.6.3、内存使用排布
2.6.3.1、为什么要分配内存

2.6.3.2、内存排布



下面展示一些 内联代码片。
/* Pointer is writable since we allocated a register for it */
//指针是可写的,因为我们为它分配了一个寄存器
#ifdef CONFIG_MEMORY_UPPER_CODE //此处定义了
ulong gd_base; //定义了gd_base变量,gd是DDR中内存分配的起始地址
//CFG_UBOOT_BASE:33E00000,uboot的基地址;CFG_UBOOT_SIZE:2MB;
//CFG_MALLOC_LEN:堆区;CFG_STACK_SIZE:栈区;gd_t:结构体
//#define CFG_UBOOT_BASE 0x33e00000 uboot的基地址
/* total memory required by uboot;uboot所需的总内存 */
//#define CFG_UBOOT_SIZE (2*1024*1024) 2MB
//#define CFG_ENV_SIZE 0x4000 /* Total Size of Environment Sector 环境变量的总大小16KB*/
//#define CFG_MALLOC_LEN (CFG_ENV_SIZE + 896*1024) 912KB
//#define CFG_STACK_SIZE 512*1024 512KB
gd_base = CFG_UBOOT_BASE + CFG_UBOOT_SIZE - CFG_MALLOC_LEN - CFG_STACK_SIZE - sizeof(gd_t); //gd在DDR中内存分配的 起始地址
#ifdef CONFIG_USE_IRQ //CONFIG_USE_IRQ没有定义,如果定义的话;gd_base需重新计算
gd_base -= (CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ);
#endif
gd = (gd_t*)gd_base; //强制类型转换。gd就指向了gd_base地址指向的地方
#else
gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
#endif
/* compiler optimization barrier needed for GCC >= 3.4 */
//GCC需要编译器优化屏障
__asm__ __volatile__("": : :"memory");
//将gd内存处清0,将环境变量内存处清0
memset ((void*)gd, 0, sizeof (gd_t));
gd->bd = (bd_t*)((char*)gd - sizeof(bd_t)); //gd->bd指针指向存放开发板的硬件信息的结构体的地址
memset (gd->bd, 0, sizeof (bd_t)); //将bd内存处清0
2.6.4、start_armboot解析2
2.6.4.1、for循环执行init_sequence


函数名其实就是一个函数指针。
//Board.c
////typedef int (init_fnc_t) (void); init_fnc_t是一个函数类型
//函数指针数组。其是一个数组,该数组存放的元素是指针,该指针指向类型是一个函数。
init_fnc_t *init_sequence[] = {
cpu_init, /* 基本cpu相关设置 */
#if defined(CONFIG_SKIP_RELOCATE_UBOOT) //CONFIG_SKIP_RELOCATE_UBOOT没定义
reloc_init, //设置重定位完成标志,必须在cpu_init()之后完成,但要尽快*/
#endif
board_init, /* 基本板相关设置*/
interrupt_init, /* 设置中断*/
env_init, /* i 初始化环境*/
init_baudrate, /* 初始化波特率*/
serial_init, /* 串行通信设置*/
console_init_f, /* 控制台的第1阶段初始化*/
display_banner, /* say that we are here */
#if defined(CONFIG_DISPLAY_CPUINFO) //CONFIG_DISPLAY_CPUINFO定义
print_cpuinfo, /* 显示cpu信息(和速度)*/
#endif
#if defined(CONFIG_DISPLAY_BOARDINFO) //CONFIG_DISPLAY_BOARDINFO定义
checkboard, /*显示板信息*/
#endif
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C) //CONFIG_HARD_I2C定义
init_func_i2c,
#endif
dram_init, /*配置可用内存库*/
display_dram_config,
NULL,
};

//typedef int (init_fnc_t) (void); 是一个函数类型
//init_fnc_t **init_fnc_ptr; 二重指针,
//init_sequence是一个函数指针数组名,二重指针可以指向它
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
if ((*init_fnc_ptr)() != 0) {
//如果返回不是0
hang (); //死循环,挂起
}
}
void hang (void)
{
while (1) ;
}
2.6.4.2、cpu_init

//Cpu.c
int cpu_init (void)
{
/*
* 如有必要,设置堆栈
*/
#ifdef CONFIG_USE_IRQ //CONFIG_USE_IRQ没定义
IRQ_STACK_START = _armboot_start - CFG_MALLOC_LEN - CFG_GBL_DATA_SIZE - 4;
FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ;
#endif
return 0;
}
2.6.4.3、board_init

//X210.c
int board_init(void) //开发板初始化
{
//#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8")
DECLARE_GLOBAL_DATA_PTR; //声明全局变量
#ifdef CONFIG_DRIVER_SMC911X //CONFIG_DRIVER_SMC911X没定义
smc9115_pre_init(); //网卡初始化,不使用
#endif
#ifdef CONFIG_DRIVER_DM9000 //CONFIG_DRIVER_DM9000定义
dm9000_pre_init(); //网卡初始化,使用
#endif
gd->bd->bi_arch_number = MACH_TYPE;
gd->bd->bi_boot_params = (PHYS_SDRAM_1+0x100);
return 0;
}
//X210_sd.h
#define CONFIG_DRIVER_DM9000 1 //DM9000网卡初始化

//X210_sd.h
#define CONFIG_DRIVER_DM9000 1 //DM9000网卡初始化
//X210.c
/*
* Miscellaneous platform dependent initialisations
* 网卡平台相关初始化
*/
static void dm9000_pre_init(void) //网卡初始化,主要是网卡的GPIO和端口的配置
{
unsigned int tmp;
#if defined(DM9000_16BIT_DATA)
SROM_BW_REG &= ~(0xf << 4);
SROM_BW_REG |= (1<<7) | (1<<6) |

最低0.47元/天 解锁文章
287

被折叠的 条评论
为什么被折叠?



