Uboot源码阅读笔记2


 
Lib_arm/board.c
 
当第一阶段的汇编部分执行完,跳到stage2时,开始执行c函数start_armboot
 
开头首先声明一个全局指针变量DECLARE_GLOBAL_DATA_PTR;这个宏定义在头文件include/asm-arm/global_data.h中
 
#define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r8")
 
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
#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;
 
在这个结构中存放一些全局数据。
 
       gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
这行是对指针的初始化。
 
接下来通过一个循环,执行初始化序列中的一些函数
 
       for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
              if ((*init_fnc_ptr)() != 0) {
                     hang ();
              }
       }
初始化序列的定义如下:
 
init_fnc_t *init_sequence[] = {
       cpu_init,         //初始化cpu,主要是设置FIQ和IRQ的堆栈起始地址
       board_init,      //开发板初始化,设置电源、时钟、I/O端口及全能I/DCache
       interrupt_init,  //中断初始化,设置PWM时钟
       env_init,         //环境变量初始化,检测环境变量是否有效,并初始化相全局变量
       init_baudrate,  //初始化波特率,设置板子通信时的波特率
       serial_init,       //初始化串口,设置串口和通信时数据结构,包括起始/停止位等
       console_init_f,       //控制台初始化,将控制台设置为silent模式
       display_banner,//打印板子相关信息
       dram_init,       //内存初始化,设置内存的起始地址和大小
       display_dram_config, //显示内存配置信息
#if defined(CONFIG_VCMA9)
       checkboard,
#endif
       NULL,
};
 
这些初始化都完成后开始初始化flash
unsigned long flash_init (void)
{
       unsigned long size_b0;
       int i;
 
       /* Init: no FLASHes known */
       for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
              flash_info[i].flash_id = FLASH_UNKNOWN;
       }
 
       /* Static FLASH Bank configuration here - FIXME XXX */
#if 1
       debug ("/n## Get flash bank 1 size @ 0x%08x/n",CFG_FLASH_BASE);
#endif
 
//根据flash的基地址CFG_FLASH_BASE,获得flash的大小,
       size_b0 = flash_get_size((vu_short *)CFG_FLASH_BASE, &flash_info[0]);
 
       if (flash_info[0].flash_id == FLASH_UNKNOWN) {
              printf ("## Unknown FLASH on Bank 0: "
                     "ID 0x%lx, Size = 0x%08lx = %ld MB/n",
                     flash_info[0].flash_id,
                     size_b0, size_b0<<20);
       }
 
//获得并保存flash各块的起始地址
       flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]);
 
//保存flash的大小
       flash_info[0].size = size_b0;
 
//下面是根据配置,对flash中相应块进行保护,以免数据丢失。
#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
       /* monitor protection ON by default */
       flash_protect(FLAG_PROTECT_SET,
                    CFG_MONITOR_BASE,
                    CFG_MONITOR_BASE+monitor_flash_len-1,
                    &flash_info[0]);
#endif
 
#ifdef      CFG_ENV_IS_IN_FLASH
       /* ENV protection ON by default */
       flash_protect(FLAG_PROTECT_SET,
                    CFG_ENV_ADDR,
                    CFG_ENV_ADDR+CFG_ENV_SECT_SIZE-1,
                    &flash_info[0]);
#endif
 
       return size_b0;
}
 
然后是初始内存堆
static
void mem_malloc_init (ulong dest_addr)
{
       mem_malloc_start = dest_addr;
       mem_malloc_end = dest_addr + CFG_MALLOC_LEN;
       mem_malloc_brk = mem_malloc_start;
 
       memset ((void *) mem_malloc_start, 0,
                     mem_malloc_end - mem_malloc_start);
}
 
之后要进行环境变量重定位,把环境变量放到内存当中
       env_relocate ();
 
还要设置网卡的ip地址和mac地址
 
       /* IP Address */
       gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
 
       /* MAC Address */
       {
              int i;
              ulong reg;
              char *s, *e;
              uchar 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;
              }
       }
 
设备初始化
int devices_init (void)
{
       char *s;
#ifndef CONFIG_ARM     /* already relocated for current ARM implementation */
       DECLARE_GLOBAL_DATA_PTR;
 
       ulong relocation_offset = gd->reloc_off;
       int i;
 
       /* relocate device name pointers */
       for (i = 0; i < (sizeof (stdio_names) / sizeof (char *)); ++i) {
              stdio_names[i] = (char *) (((ulong) stdio_names[i]) +
                                          relocation_offset);
       }
#endif
 
       /* 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
#ifdef CONFIG_LCD
       drv_lcd_init ();
#endif
#if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE)
       if ((s = getenv ("sm501mode")) != NULL)
       {
              sm501mode = simple_strtoul (s, NULL, 10);
              if(!(sm501mode >= 1 && sm501mode <= 13))
              {
                     printf("sm501 mode error, set sm501 mode to 1!/n");
                     sm501mode = 1;
              }
       }    
       if ((s = getenv ("sm501bpp")) != NULL)
       {
              sm501bpp = simple_strtoul (s, NULL, 10);
              if(sm501mode != 16)
              {
                     printf("sm501 bpp error, only 16bpp valid, set sm501 bpp to 16!/n");
                     sm501bpp = 16;
              }
       }
       drv_video_init ();
#endif
#ifdef CONFIG_KEYBOARD
       //drv_keyboard_init ();
#endif
#ifdef CONFIG_LOGBUFFER
       drv_logbuff_init ();
#endif
       drv_system_init ();
 
       return (0);
}
这里要创建一个设备列表,把一些设备放入这个表中,初始化i2c总线,设置sm501显卡,初始化视频设备,初始化并注册个别系统设备。
 
void jumptable_init (void)
{
       DECLARE_GLOBAL_DATA_PTR;
       int i;
 
       gd->jt = (void **) malloc (XF_MAX * sizeof (void *));
       for (i = 0; i < XF_MAX; i++)
              gd->jt[i] = (void *) dummy;
 
       gd->jt[XF_get_version] = (void *) get_version;
       gd->jt[XF_malloc] = (void *) malloc;
       gd->jt[XF_free] = (void *) free;
       gd->jt[XF_get_timer] = (void *)get_timer;
       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 */
}
初始化跳转表,主要是保存了一些系统函数的指针。便于以后引用
 
然后对控制台进行全面的初始化
       console_init_r ();    /* fully init console as a device */
主要是初始化控制台输入输出设备
 
接下来开中断
       /* enable exceptions */
       enable_interrupts ();
初始化网卡设备等
       /* Perform network card initialisation if necessary */
#ifdef CONFIG_DRIVER_DM9000
       DM9000_get_enetaddr (gd->bd->bi_enetaddr);
#endif
 
最后进入主循环
 
       /* main_loop() can return to retry autoboot, if so just run it again. */
       for (;;) {
              main_loop ();
       }
在这个循环中,将检测是自动启动还是命令行起动。起动后,uboot的stage2也就结束了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值