Chinaunix首页 | 论坛 | 博客
  • 博客访问: 242203
  • 博文数量: 181
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 422
  • 用 户 组: 普通用户
  • 注册时间: 2016-06-09 15:34
个人简介

你好 世界

文章分类

全部博文(181)

文章存档

2016年(181)

我的朋友

分类: LINUX

2016-06-10 23:30:32

start_armboot函数在lib_arm/board.c中定义,是U-Boot第二阶段代码的入口。U-Boot启动第二阶段流程如下:

 
                                                    图 2.3 U-Boot第二阶段执行流程

      
在分析start_armboot函数前先来看看一些重要的:


(1)gd_t结构体

       U-Boot使用了一个结构体gd_t来存储全局数据区的数据,这个结构体在include/asm-arm/global_data.h中定义如下:

点击(此处)折叠或打开

  1. typedef struct global_data {

  2.        bd_t *bd;

  3.        unsigned long flags;

  4.        unsigned long baudrate;

  5.        unsigned long have_console; /* serial_init() was called */

  6.        unsigned long env_addr; /* Address of Environment struct */

  7.        unsigned long env_valid; /* Checksum of Environment valid? */

  8.        unsigned long fb_base; /* base address of frame buffer */

  9.        void **jt; /* jump table */

  10. } gd_t;

 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_tinclude/asm-arm.u/u-boot.h中定义如下:

点击(此处)折叠或打开

  1. typedef struct bd_info {

  2.     int bi_baudrate; /* 串口通讯波特率 */

  3.     unsigned long bi_ip_addr; /* IP 地址*/

  4.     struct environment_s *bi_env; /* 环境变量开始地址 */

  5.     ulong bi_arch_number; /* 开发板的机器码 */

  6.     ulong bi_boot_params; /* 内核参数的开始地址 */

  7.     struct /* RAM配置信息 */

  8.     {

  9.               ulong start;

  10.               ulong size;

  11.     }bi_dram[CONFIG_NR_DRAM_BANKS];

  12. } bd_t;
  U-Boot启动内核时要给内核传递参数,这时就要使用gd_tbd_t结构体中的信息来设置标记列表。

3init_sequence数组

       U-Boot使用一个数组init_sequence来存储对于大多数开发板都要执行的初始化函数的函数指针。init_sequence数组中有较多的编译选项,去掉编译选项后init_sequence数组如下所示:

点击(此处)折叠或打开

  1. typedef int (init_fnc_t) (void);

  2.  

  3. init_fnc_t *init_sequence[] = {

  4.        board_init, /*开发板相关的配置--board/samsung/mini2440/mini2440.c */

  5.        timer_init, /* 时钟初始化-- cpu/arm920t/s3c24x0/timer.c */

  6.        env_init, /*初始化环境变量--common/env_flash.c 或common/env_nand.c*/

  7.        init_baudrate, /*初始化波特率-- lib_arm/board.c */

  8.        serial_init, /* 串口初始化-- drivers/serial/serial_s3c24x0.c */

  9.        console_init_f, /* 控制通讯台初始化阶段1-- common/console.c */

  10.        display_banner, /*打印U-Boot版本、编译的时间-- gedit lib_arm/board.c */

  11.        dram_init, /*配置可用的RAM-- board/samsung/mini2440/mini2440.c */

  12.        display_dram_config, /* 显示RAM大小-- lib_arm/board.c */

  13.        NULL,

  14. };
其中的board_init函数在board/samsung/mini2440/mini2440.c中定义,该函数设置了MPLLCOM,UPLLCON,以及一些GPIO寄存器的值,还设置了U-Boot机器码和内核启动参数地址 :

/* MINI2440开发板的机器码 */

gd->bd->bi_arch_number = MACH_TYPE_MINI2440;

 

/* 内核启动参数地址 */

gd->bd->bi_boot_params = 0x30000100;  

       其中的dram_init函数在board/samsung/mini2440/mini2440.c中定义如下:

点击(此处)折叠或打开

  1. int dram_init (void)

  2. {

  3.       /* 由于mini2440只有 */

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

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

  6.  

  7.       return 0;

  8. }

mini2440使用232MBSDRAM组成了64MB的内存,接在存储控制器的BANK6,地址空间是0x30000000~0x34000000

include/configs/mini2440.hPHYS_SDRAM_1PHYS_SDRAM_1_SIZE 分别被定义为0x300000000x0400000064M)。

       分析完上述的数据结构,下面来分析start_armboot函数:

点击(此处)折叠或打开

  1. void start_armboot (void)

  2. {

  3.        init_fnc_t **init_fnc_ptr;

  4.        char *s;

  5.        … …

  6.        /* 计算全局数据结构的地址gd */

  7.        gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));

  8.        … …

  9.        memset ((void*)gd, 0, sizeof (gd_t));

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

  11.        memset (gd->bd, 0, sizeof (bd_t));

  12.        gd->flags |= GD_FLG_RELOC;

  13.  

  14.        monitor_flash_len = _bss_start - _armboot_start;

  15.  

  16. /* 逐个调用init_sequence数组中的初始化函数 */

  17.        for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {

  18.               if ((*init_fnc_ptr)() != 0) {

  19.                      hang ();

  20.               }

  21.        }

  22.  

  23. /* armboot_start 在cpu/arm920t/start.S 中被初始化为u-boot.lds连接脚本中的_start */

  24.        mem_malloc_init (_armboot_start - CONFIG_SYS_MALLOC_LEN,

  25.                      CONFIG_SYS_MALLOC_LEN);

  26.  

  27. /* NOR Flash初始化 */

  28. #ifndef CONFIG_SYS_NO_FLASH

  29.        /* configure available FLASH banks */

  30.        display_flash_config (flash_init ());

  31. #endif /* CONFIG_SYS_NO_FLASH */

  32.  

  33.        … …

  34. /* NAND Flash 初始化*/

  35. #if defined(CONFIG_CMD_NAND)

  36.        puts ("NAND: ");

  37.        nand_init(); /* go init the NAND */

  38. #endif

  39.        … …

  40.        /*配置环境变量,重新定位 */

  41.        env_relocate ();

  42.        … …

  43.        /* 从环境变量中获取IP地址 */

  44.        gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");

  45.        stdio_init (); /* get the devices list going. */

  46.        jumptable_init ();

  47.        … …

  48.        console_init_r (); /* fully init console as a device */

  49.        … …

  50.        /* enable exceptions */

  51.        enable_interrupts ();

  52.  

  53. #ifdef CONFIG_USB_DEVICE

  54.        usb_init_slave();

  55. #endif

  56.  

  57.        /* Initialize from environment */

  58.        if ((s = getenv ("loadaddr")) != NULL) {

  59.               load_addr = simple_strtoul (s, NULL, 16);

  60.        }

  61. #if defined(CONFIG_CMD_NET)

  62.        if ((s = getenv ("bootfile")) != NULL) {

  63.               copy_filename (BootFile, s, sizeof (BootFile));

  64.        }

  65. #endif

  66.        … …

  67.        /* 网卡初始化 */

  68. #if defined(CONFIG_CMD_NET)

  69. #if defined(CONFIG_NET_MULTI)

  70.        puts ("Net: ");

  71. #endif

  72.        eth_initialize(gd->bd);

  73. … …

  74. #endif

  75.  

  76.        /* main_loop() can return to retry autoboot, if so just run it again. */

  77.        for (;;) {

  78.               main_loop ();

  79.        }

  80.        /* NOTREACHED - no way out of command loop except booting */

  81. }
 main_loop函数在common/main.c中定义。一般情况下,进入main_loop函数若干秒内没有

























阅读(827) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~