u-boot的重要细节

主要分析流程中各函数的功能。按启动顺序罗列一下启动函数执行细节。按照函数start_armboot流程进行分析:

    1)DECLARE_GLOBAL_DATA_PTR;

     这个宏定义在include/global_data.h中:

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

     声明一个寄存器变量 gd 占用r8。这个宏在所有需要引用全局数据指针gd_t *gd的源码中都有申明。

     这个申明也避免编译器把r8分配给其它的变量. 所以gd就是r8,这个指针变量不占用内存。

    2gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));

    对全局数据区进行地址分配,_armboot_start0x3f000000,CFG_MALLOC_LEN是堆大小+环境数据区大小config/smdk2410.hCFG_MALLOC_LEN大小定义为192KB.

    3)gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));

    分配板子数据区bd首地址。

    这样结合start.s中栈的分配,

    stack_setup

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

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

     sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfoCFG_GBL_DATA_SIZE =128B */

     #ifdef CONFIG_USE_IRQ

     sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)

     #endif

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

  4)cpu_init();定义于cpu/arm920t/cpu.c 

   分配IRQFIQ栈底地址,由于没有定义CONFIG_USE_IRQ,所以相当于空实现。

  5)board_init;极级初始化,定义于board/smdk2410/smdk2410.c

    设置PLL时钟,GPIO,使能I/D cache.

    设置bd信息:gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;//板子的ID,没啥意义。

            gd->bd->bi_boot_params = 0x30000100;//内核启动参数存放地址

   6)interrupt_init;定义于cpu/arm920t/s3c24x0/interrupt.c 

     初始化2410PWM timer 4,使其能自动装载计数值,恒定的产生时间中断信号,但是中断被屏蔽了用不上。

   7)env_init;定义于common/env_flash.c

   功能:指定环境区的地址。default_environment是默认的环境参数设置。

    gd->env_addr = (ulong)&default_environment[0];

    gd->env_valid = 0;

   8)init_baudrate;初始化全局数据区中波特率的值

   gd->bd->bi_baudrate = gd->baudrate =(i > 0)

    ? (int) simple_strtoul (tmp, NULL, 10)

    : CONFIG_BAUDRATE;

   9)serial_init; 串口通讯设置 定义于cpu/arm920t/s3c24x0/serial.c 

     根据bd中波特率值和pclk,设置串口寄存器。

   10)console_init_f;控制台前期初始化common/console.c

    由于标准设备还没有初始化(gd->flags & GD_FLG_DEVINIT=0),这时控制台使用串口作为控制台

    函数只有一句:gd->have_console = 1;

   11)dram_init,初始化内存RAM信息。board/smdk2410/smdk2410.c

    其实就是给gd->bd中内存信息表赋值而已。

    gd->bd->bi_dram[0].start = PHYS_SDRAM_1;

 gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;

 初始化序列表init_sequence[]主要函数分析结束。

12)flash_init;定义在board/smdk2410/flash.c

   这个文件与具体平台关系密切,smdk2410使用的flashFS2410不一样,所以移植时这个程序就得重写。

   flash_init()是必须重写的函数,它做哪些操作呢?

   首先是有一个变量flash_info_t flash_info[CFG_MAX_FLASH_BANKS]来记录flash的信息。flash_info_t定义:

   typedef struct {

     ulong size;    /* 总大小BYTE   */

     ushort sector_count;   /* 总的sector*/

     ulong flash_id;   /* combined device & manufacturer code */

     ulong start[CFG_MAX_FLASH_SECT];   /* 每个sector的起始物理地址。 */

     uchar protect[CFG_MAX_FLASH_SECT]; /* 每个sector的保护状态,如果置1,在执行erase操作的时候将跳过对应sector*/

     #ifdef CFG_FLASH_CFI //我不管CFI接口。

     .....

     #endif

    } flash_info_t;

    flash_init()的操作就是读取ID号,ID号指明了生产商和设备号,根据这些信息设置size,sector_count,flash_id.以及start[]protect[]

 13)把视频帧缓冲区设置在bss_end后面

     addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);

    size = vfd_setmem (addr);

    gd->fb_base = addr;

  14)mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);

   设置heap区,供malloc使用。下面的变量和函数定义在lib_arm/board.c

   malloc可用内存由mem_malloc_startmem_malloc_end指定。而当前分配的位置则是mem_malloc_brk

   mem_malloc_init负责初始化这三个变量。malloc则通过sbrk函数来使用和管理这片内存。

     static ulong mem_malloc_start = 0;

     static ulong mem_malloc_end = 0;

     static ulong mem_malloc_brk = 0;

     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);

     }

     void *sbrk (ptrdiff_t increment)

     {

      ulong old = mem_malloc_brk;

      ulong new = old + increment;

    

      if ((new < mem_malloc_start) || (new > mem_malloc_end)) {

       return (NULL);

      }

      mem_malloc_brk = new;

      return ((void *) old);

     }

15)env_relocate() 环境参数区重定位

   由于初始化了heap区,所以可以通过malloc()重新分配一块环境参数区,

   但是没有必要,因为默认的环境参数已经重定位到RAM中了。

   /**这里发现个问题,ENV_IS_EMBEDDED是否有定义还没搞清楚,而且CFG_MALLOC_LEN也没有定义,也就是说如果ENV_IS_EMBEDDED没有定义则执行malloc,是不是应该有问题?**/

  16)IPMAC地址的初始化。主要是从环境中读,然后赋给gd->bd对应域就OK

  17devices_init ();定义于common/devices.c

   int devices_init (void)//我去掉了编译选项,注释掉的是因为对应的编译选项没有定义。

    {

     devlist = ListCreate (sizeof (device_t));//创建设备列表

     i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);//初始化i2c接口,i2c没有注册到devlist中去。

     //drv_lcd_init ();

     //drv_video_init ();

     //drv_keyboard_init ();

     //drv_logbuff_init ();

     drv_system_init ();  //这里其实是定义了一个串口设备,并且注册到devlist中。

     //serial_devices_init ();

     //drv_usbtty_init ();

     //drv_nc_init ();

    }

经过devices_init(),创建了devlist,但是只有一个串口设备注册在内。显然,devlist中的设备都是可以做为console的。

   18设置CS8900MAC地址

   cs8900_get_enetaddr (gd->bd->bi_enetaddr);  

  19初始化以太网

   eth_initialize(gd->bd);//bd中已经IPMAC已经初始化

   20main_loop ();定义于common/main.c

   至此所有初始化工作已经完毕。main_loop在标准转入设备中接受命令行,然后分析,查找,执行。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值