U-boot分析与移植(3)----U-boot stage2分析 .

原创 2012年03月27日 19:28:51

 .


一来到void start_armboot (void)函数,马上出现两个很重要的数据结构gd_t和bd_t

1、gd_t : global data数据结构定义,位于文件 include/asm-arm/global_data.h。其成员主要是一些全局的系统初始化参数。

   1. typedef struct  global_data {  
   2.     bd_t        *bd;      // struct board_info<span style="font-family:宋体;">指针,保存板子信息</span>  
   3.     unsigned long   flags;     // <span style="font-family:宋体;">指示标志,如设备已经初始化标志等</span>  
   4.     unsigned long   baudrate;  
   5.     unsigned long   have_console;   /* serial_init() was called */  
   6.     unsigned long   reloc_off;  /* Relocation Offset */  
   7.     unsigned long   env_addr;   /* Address  of Environment struct 环境参数地址*/  
   8.     unsigned long   env_valid;  /* Checksum of Environment valid? */  
   9.     unsigned long   fb_base;    /* base address of frame buffer */  
  10. #ifdef CONFIG_VFD  
  11.     unsigned char   vfd_type;   /* display type */  
  12. #endif  
  13. #if 0  
  14.     unsigned long   cpu_clk;    /* CPU clock in Hz!     */  
  15.     unsigned long   bus_clk;  
  16.     unsigned long   ram_size;   /* RAM size */  
  17.     unsigned long   reset_status;   /* reset status register at boot */  
  18. #endif  
  19.     void        **jt;       /* jump table */  
  20. } gd_t;  

2.、bd_t :board info数据结构定义,位于文件 include/asm-arm/u-boot.h。保存板子参数。

   1. typedef struct bd_info {  
   2.     int         bi_baudrate;    /* serial console baudrate */  
   3.     unsigned long   bi_ip_addr; /* IP Address */  
   4.     unsigned char   bi_enetaddr[6]; /* Ethernet adress */  
   5.     struct environment_s           *bi_env;  
   6.     ulong           bi_arch_number; /* unique id for this board  <span style="font- family:宋体;">板子</span><span style="font- family:Times New Roman;">ID</span><span style="font-family:宋体;">号</span>*/  
   7.     ulong           bi_boot_params; /* where this board expects params */  
   8.     struct              /* RAM configuration */  
   9.     {  
  10.     ulong start;  
  11.     ulong size;  
  12.     }           bi_dram[CONFIG_NR_DRAM_BANKS];  
  13. #ifdef CONFIG_HAS_ETH1  
  14.     /* second onboard ethernet port */  
  15.     unsigned char   bi_enet1addr[6];  
  16. #endif  
  17. } bd_t;  

分配一个存储全局数据的区域,地 址给指针 gd

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

清0并分配空间

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

在gd前面的位置给 gd->bd赋值地址

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

清0并分配空间

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


执行一系列初始化函数

  1. for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {  
  2.   if ((*init_fnc_ptr)() != 0) {  
  3.    hang ();  
  4.   }  
  5.  }  


假如函数指针指向的函数返回值不为0,那么在hang()里就会死循环,初始化失败

  1. void hang (void)  
  2. {  
  3.  puts ("### ERROR ### Please RESET the board ###\n");  
  4.  for (;;);  
  5. }  


函数列表如下:

每个初始化函数正常情况下返回值是0

# init_fnc_t *init_sequence[] = {  
#  cpu_init,  /* 初始化irq/fiq模式的栈*/  
#  board_init, /* 设置系统时钟*/  
#  interrupt_init, /*初始化定时器*/  
#  env_init,  /* 检查flash上的环境参数是否有效*/  
#  init_baudrate, /* 初始化波特率*/  
#  serial_init, /* 初始化串口*/  
#  console_init_f, /*初始化串口控制台*/  
#  display_banner, /* say that we are here */ 

接着进行一些NOR FLASH,LCD,串口,控制台,sd卡,网卡等初始化,不一一列举了。

终于来到重要的时刻了 - -#

进入一个死循环

  1. for (;;)  
  2. {  
  3.  main_loop ();  
  4. }  


继续跟踪

发现在bootdelay时间内按下键进入命令行,用run_command来解析命令

   1. #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)  
   2.     s = getenv ("bootdelay");  
   3.     bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;  
   4.   
   5.     debug ("### main_loop entered: bootdelay=%d\n\n", bootdelay);  

如果CONFIG_BOOTDELAY已经定义,用s得到环境变量bootdelay,然后倒数启动内核
   1. #ifdef CONFIG_BOOTCOUNT_LIMIT  
   2.     if (bootlimit && (bootcount > bootlimit)) {  
   3.         printf ("Warning: Bootlimit (%u) exceeded. Using altbootcmd.\n",  
   4.                 (unsigned)bootlimit);  
   5.         s = getenv ("altbootcmd");  
   6.     }  
   7.     else  
   8. #endif /* CONFIG_BOOTCOUNT_LIMIT */  
   9.         s = getenv ("bootcmd");  

CONFIG_BOOTCOUNT_LIMIT是设置u-boot启动次数的限制

最后s = getenv ("bootcmd");获得启动参数

  1. run_command (s, 0);  

启动命令解析
在run_command 函数里最终执行命令

  1. /* OK - call function to do the command */  
  2. if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0) {  
  3.  rc = -1;  
  4. }  

这是一个命令结构体,原型如下:

  1. struct cmd_tbl_s {  
  2.     char        *name;      /* Command Name         */  
  3.     int     maxargs;             /* 最大的参数个数 */  
  4.     int     repeatable; /* 命令可否重复   */  
  5.     int     (*cmd)(struct cmd_tbl_s *, intintchar *[]);/*对应的函数指针*/  
  6.     char        *usage;     /* Usage message    (short) */  

正常情况下就会执行U_BOOT_CMD命令,U_BOOT_CMD宏定义一个命令,命令宏原型如下:

  1. /*命令宏U_BOOT_CMD*/  
  2. #define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \  
  3. cmd_tbl_t    __u_boot_cmd_##name     Struct_Section = {#name, maxargs, rep, cmd, usage, help}  

假若上面是传入的是一个bootm命令启动内核,将会调用相应的

 U_BOOT_CMD里的do_bootm函数
  1. U_BOOT_CMD(  
  2.     bootm,  CFG_MAXARGS,    1,  do_bootm,  
  3.     "bootm   - boot application image from memory\n",  
  4.     "[addr [arg ...]]\n    - boot application image stored in memory\n"  
  5.     "\tpassing arguments 'arg ...'; when booting a Linux kernel,\n"  
  6.     "\t'arg' can be the address of an initrd image\n"  

在do_bootm函数里,将用switch case检查内核zImage类型,解压方式,操作系统等,因为zImage是自解压的,不用解压

  1. switch (hdr->ih_os) {  
  2.     default:            /* handled by (original) Linux case */  
  3.     case IH_OS_LINUX:  
  4.   
  5.         do_bootm_linux  (cmdtp, flag, argc, argv,  
  6.                  addr, len_ptr, verify);  
  7.         break;    

最后,将进入Armlinux.c的do_bootm_linux函数启动Linux内核

U_Boot也是通过标记列表向内核传递参数的

  1. #ifdef CONFIG_CMDLINE_TAG  
  2.     char *commandline = getenv ("bootargs");  
  3. #endif  

CONFIG_CMDLINE_TAG在smdk2410.h里已经定义了

theKernel指向内核 存放的地址,(对于ARM架构的CPU,通常是0x30008000),

/*声明内核的入口函数指针*/

  1. void (*theKernel)(int zero, int arch, uint params);  

 

/*把内核入口地址赋值给theKernel,hdr是image_header_t结构体,指向uImage头部 ,ih_ep是内核的入口点(Entry Point)*/

  1. theKernel = (void (*)(intint, uint))ntohl(hdr->ih_ep);   

/*最后是对内核入口函数的调用,bd->bi_arch_number是这个板子机器类型ID, bd->bi_boot_params是传给内核的参数,从标记列表地址开始*/

  1. theKernel (0, bd->bi_arch_number, bd->bi_boot_params);  
引导Linux内核启动的必须要满足的几个条件:
   1. * CPU register settings //这里也就是我们的theKernel中的作用  
   2.           o r0 = 0.  
   3.           o r1 = machine type number.  
   4.           o r2 = physical address of tagged list in system RAM.  
   5.     * CPU mode  
   6.           o All forms of interrupts must be disabled (IRQs and FIQs.)  
   7.           o The CPU must be in SVC mode. (A special exception exists for Angel.)  
   8.     * Caches, MMUs  
   9.           o The MMU must be off.  
  10.           o Instruction cache may be on or off.  
  11.           o Data cache must be off and must not contain any stale data.  
  12.     * Devices  
  13.           o DMA to/from devices should be quiesced.  
  14.     * The boot loader is expected to call the kernel image by jumping directly to the first instruction of the kernel image.  



U-boot分析与移植(3)-U-boot stage2分析 .

本文来自:http://blog.csdn.net/jianchi88/article/details/7067260 一来到void start_armboot (void)函数,马上出现两个...
  • dddd0216
  • dddd0216
  • 2016年04月13日 11:05
  • 146

U-boot分析与移植(3)----U-boot stage2分析 .

一来到void start_armboot (void)函数,马上出现两个很重要的数据结构gd_t和bd_t 1、gd_t : global data数据结构定义,位于文件 include/asm-...
  • wuchengsai110
  • wuchengsai110
  • 2014年03月05日 23:31
  • 224

U-boot分析与移植(3)----U-boot stage2分析

一来到void start_armboot (void)函数,马上出现两个很重要的数据结构gd_t和bd_t 1、gd_t : global data数据结构定义,位于文件 include/asm-...
  • asmxpl
  • asmxpl
  • 2014年03月11日 17:00
  • 323

u-boot-2016.09移植(2)-uboot启动简易分析

不管什么版本的uboot都是在arch/arm/cpu/u-boot-spl.lds和arch/arm/cpu/u-boot.lds中制定了入口函数ENTRY(_start),u-boot-2016....
  • keyue123
  • keyue123
  • 2016年11月06日 19:09
  • 850

U-BOOT-2016.07移植 (第二篇) 添加单板

U-BOOT-201607移植 第二篇 添加单板 1. 在board中创建单板目录 2. 创建单板相关头文件 3. 创建defconfig文件 4. 修改arch/arm/Kconfig文件 5. 尝...
  • funkunho
  • funkunho
  • 2016年09月08日 01:46
  • 2260

U-BOOT-2016.07移植 (第一篇) 初步分析

U-BOOT-2016.07移植 (第一篇) 初步分析 U-BOOT-2016.07移植 (第二篇) 添加单板 U-BOOT-2016.07移植 (第三篇) 代码重定位 U-BOOT...
  • RRR_obben
  • RRR_obben
  • 2017年04月14日 20:59
  • 356

U-boot主Makefile分析

主Makefile位于uboot源码的根目录下,其内容主要结构为: 1. 确定版本号及主机信息 2. 实现静默编译功能 3. 设置各种路径 4. 设置编译工具链 5. 设置规则 6. 设置...
  • qq_28992301
  • qq_28992301
  • 2016年07月01日 16:53
  • 1931

u-boot分析 二 (u-boot目录结构)

u-boot分析 二继前一启动篇,此博文目的:学习u-boot的目录结构,从code架构上对u-boot有一个整体的把握和了解。一、学习u-boot,得问,什么是u-boot?u-boot是一段开源的...
  • itxiebo
  • itxiebo
  • 2016年03月20日 09:31
  • 4067

移植u-boot学习笔记3-----分析启动过程之重定位

1、重定位的实现 (1)代码原型(C语言调用汇编代码) 参数addr_sp存在r0里 参数id存在r1里 参数addr存在r2里 (2)里面的addr参数 a、addr的地址是0x33ff00...
  • qingkongyeyue
  • qingkongyeyue
  • 2016年09月04日 20:11
  • 736

U-boot分析与移植(5)----U-boot移植

网上很多很好很详细的手册可以参考如: mini2440之U-boot移植详细手册-20100419.pdf 移植u-boot-1.1.6到TQ2440文档.pdf 移植u-boot-1.3.4到...
  • wuchengsai110
  • wuchengsai110
  • 2014年03月05日 23:37
  • 271
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:U-boot分析与移植(3)----U-boot stage2分析 .
举报原因:
原因补充:

(最多只允许输入30个字)