在uboot第一阶段引导的最后一步做了一下代码
- ldr pc, _start_armboot
-
33f800f0: e51ff004 ldr pc, [pc, #-4] ; 33f800f4 <_start_armboot>
-
33f800f4 <_start_armboot>:
-
33f800f4: 33f80be0 mvnccs r0, #229376 ; 0x38000
该指令是把当前指令地址+4的内存地址的值赋值为PC,PC=0x33f80be0;
第一阶段的代码是地址无关代码,但是现在PC却指向了0x33f80be0处,此处的代码在uboot(1.1.6)的根目录下/lib_arm/board.c中的start_armboot函数,主要是一些初始化。其中关系到两个数据结构
- 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
-
unsigned char vfd_type; /* display type */
-
#endif
-
void **jt; /* jump table */
-
} gd_t;
#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8")
gd指针的值存放在r8寄存器里,register是将gd指针和r8绑定在一起,volatile关键字的意思是每次使用该变量时都直接存取原始地址,和内核中的task_struct结构中的state变量一样
- 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];
-
#ifdef CONFIG_HAS_ETH1
- /* second onboard ethernet port */
-
unsigned char bi_enet1addr[6];
-
#endif
-
} bd_t;
在start_armboot函数里先是gd的初始化然后再进行系统初始化,在2011.03版本中这两部分的初始化是放在两个函数里,而且gd的初始化是在relocate_code之前进行的。
gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
从这里可以发现gd的数据在内存里存放的地址是位于uboot代码和malloc区域的上方,由于传统栈的生长方向满递减,所以gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
接下来是把初始化队列里的函数按顺序执行下来,如果执行错误,则执行hang(),实际是死循环。
接着是flash的初始化,
malloc区域的初始化,
uboot的环境的初始化先是在malloc区域申请指定大小的内存,再是初始化,并设置好gd结构里相应的标志位,和该区域的地址,
- #ifdef ENV_IS_EMBEDDED
-
/*
-
* The environment buffer is embedded with the text segment,
-
* just relocate the environment pointer
-
*/
-
env_ptr = (env_t *)((ulong)env_ptr + gd->reloc_off);
-
DEBUGF ("%s[%d] embedded ENV at %p\n", __FUNCTION__,__LINE__,env_ptr);
-
#else
-
/*
-
* We must allocate a buffer for the environment
-
*/
-
env_ptr = (env_t *)malloc (CFG_ENV_SIZE);
-
DEBUGF ("%s[%d] malloced ENV at %p\n", __FUNCTION__,__LINE__,env_ptr);
-
#endif
- ......
- ......
-
memset (env_ptr, 0, sizeof(env_t));
-
memcpy (env_ptr->data,
- .....
-
gd->env_valid = 1;
- ......
-
gd->env_addr = (ulong)&(env_ptr->data);
ip地址的配置并将地址放到gd结构里等网卡的初始化时再去读取,
初始化板子上有的设备,例如usb,keyboard,lcd等,
-
/* Initialize the list */
-
devlist = ListCreate (sizeof (device_t));
-
-
if (devlist == NULL) {
-
eputs ("Cannot initialize the list of devices!\n");
-
return -1;
-
}
-
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
-
i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
-
#endif
- ......
- ......
-
return (0);
填充jumptable里的数据
- gd->jt[XF_get_version] = (void *) get_version;
-
gd->jt[XF_malloc] = (void *) malloc;
-
gd->jt[XF_free] = (void *) free;
-
gd->jt[XF_getenv] = (void *) getenv;
-
gd->jt[XF_setenv] = (void *) setenv;
-
gd->jt[XF_get_timer] = (void *) get_timer;
-
gd->jt[XF_simple_strtoul] = (void *) simple_strtoul;
-
gd->jt[XF_udelay] = (void *) udelay;
-
#if defined(CONFIG_I386) || defined(CONFIG_PPC)
-
gd->jt[XF_install_hdlr] = (void *) irq_install_handler;
-
gd->jt[XF_free_hdlr] = (void *) irq_free_handler;
-
#endif /* I386 || PPC */
-
#if (CONFIG_COMMANDS & CFG_CMD_I2C)
-
gd->jt[XF_i2c_write] = (void *) i2c_write;
-
gd->jt[XF_i2c_read] = (void *) i2c_read;
-
#endif /* CFG_CMD_I2C */
再就是控制台的初始化,开启中断,初始化相应的网卡,最后进入了main_loop。
阅读(1449) | 评论(0) | 转发(0) |