1. 首页
  2. 课程学习
  3. 嵌入式
  4. uboot中C语言代码入口函数(start_armboot)

uboot中C语言代码入口函数(start_armboot)

上传者: 2023-01-12 11:09:14上传 RAR文件 42.162 KB 热度 12次

uboot中C语言代码入口函数(start_armboot)的注释

 //打印BANK的相关信息

 display_dram_config,

 NULL, //用以标识列表数组的结束

};

//------------start_armboot--------------------

//功能: 完成uboot第二阶级的一系列的

//  硬件初始化工作, 然后转入main函数.

//备注: 该函数是C程序的入口函数,从汇编语

//  言跳转到此 .

//---------------------------------------------

void start_armboot (void)

{

    init_fnc_t **init_fnc_ptr; //init_fnc_t 是各初始化函数的数组

    char *s;

#ifndef CFG_NO_FLASH

    ulong size;

#endif

#if defined(CONFIG_VFD) || defined(CONFIG_LCD)

    unsigned long addr;

#endif

  /* Pointer is writable since we allocated a register for it

      gd_t: 定义在 /include/asm-arm/Global_data.h中,包含一些全局通用的变量.

    _armboot_start: 代码的起始地址,它定义在start.S中的前几行中,定义为 _start

   当系统第一次加电时,指令是从0x0地址开始执行的,所以此时的 _start值

   应为0x0;而当uboot经过代码重定位后,指令会从 _TEXT_BASE 处开始执行,

   此时的 _start值就成了 _TEXT_BASE的值.

   CFG_MALLOC_LEN: 在/include/configs/smdk2440.h中有定义,该变量表示供

   malloc函数使用的内存池空间,代码中定义值为:0x10000+128*1024

 |-------|<--- _armboot_start基址

 |  4    | 

 |-------|<--- malloc函数池基址

 |  3    |

 |-------|<--- (gd_t)gd(全局变量表)基址

 |  2    |

 |-------|<--- (bt_t)bd(板卡信息表)基址

 |  1    |

  -------

   4 就是为malloc函数预留的数据空间

   3 是全信息表gd的数据区

 2 是板卡信息表bd的数据区

 网上找了个图片,更能反应这个空间的分配关系:

 

 */

     //分配区域 3 给 gd ,gd是一个全局静态变量

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

    /* compiler opTImizaTIon barrier needed for GCC >= 3.4 */

    __asm__ __volaTIle__("": : :"memory");

 //把gd变量的内容填充为0 ,填充 3 区的数据为0 ,即初始化gd表.注意:这里并没有

 //初始化bd表,在gd表中的bd成员只是一个指针,因为对初始化的是个指针地址

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

 /*

  bd_t 结构体在/include/asm-arm/U-boot.h中定义, 定义板子的一些信息,包括:

  波特率,IP地址, 以太网地址, 架构编码,启动参数 ,BANK的起始地址和大小等

 */

 //分配区域 2 给bd, bd的基址 = gd的基址 - bd的尺寸

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

 

 //把区域 2 填充为 0 ,即初始化 bd 表

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

 /*monitor_falsh_len定义在 /lib_arm/Board.c

 

 在bin文件中 BSS 段和 TEXT 段和 DATA 段存放的顺序同前向后依次是:

  TEXT(代码段 RO)    DATA(已初始化数据段 RW)   BSS(未初始化数据段 ZI)

 所以 _bss_start 的基址等于 TEXT的长度加上DATA的长度.

 即: _bss_start(BSS段基址) = 代码段长度+数据段长度

 

 BSS(Block Started by Symbol)段是未被初始化的数据段,是存放程序中

  未被初始化的全局变量的一块内存区域,初始化时应清零;该段只有

  名称和大小却没有值;该段不包含任何数据,只是简单的维护开始和

  结束的地址,以便内存区能在运行时被有效地清零,它在应用程序的

  映像文件(ARM中也即bin文件)中并不存在.

 text :代码段,是包含程序代码的段

 dat  :已经初始化的数据段,保存已经初始化的全局变量.

 

    在嵌入式系统中,bin文件(又称Image文件)中只包含text和data段,

  而bss段不在其中,它是由系统初始化为零.

    */

  //_armboot_start 在start.S中定义为_start,而_start为代码的起始地址

    //只包含 RO(TEXT) 和 RW(DATA) 段.重定位前的值为0x0,此时指向flash,

 //重定位后则指向RAM中的某一地址

 //由此可以知道:  _bss_start - _armboot_start 的值即是在第一阶段从

 //flash中重定位到RAM中的那部分代码的长度,也即可TEXT和DATA数据段,

 //这个值与start.S中的重定位那部分代码所计算的值是相等的

 //所以,monitor_flash_len表示从flash中搬来的代码的长度

    monitor_flash_len = _bss_start - _armboot_start;  //_bss_start 在u-boot.lds中定位

 

 //各设置的初始化.当返回值不为0时表示初始化失败 ,此时会调用 hang()函数

 //打印一错误提示信息,然后进入死循环

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

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

            hang ();

        }

    }

//CFG_NO_FLASH 表示没有flash,如果没定义该常量则表示板子上有flash,此时调用flash_init()对其进行初始化.

#ifndef CFG_NO_FLASH

    /* configure available FLASH banks */

    size = flash_init ();

    display_flash_config (size); //打印flash的信息,这里仅输出它的大小

#endif /* CFG_NO_FLASH */

#ifdef CONFIG_VFD

#   ifndef PAGE_SIZE

#     define PAGE_SIZE 4096

#   endif

     /*

      * reserve memory for VFD display (always full pages)

      */

    /* bss_end is defined in the board-specific linker script */

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

    size = vfd_setmem (addr);

    gd->fb_base = addr;

#endif /* CONFIG_VFD */

#ifdef CONFIG_LCD

# ifndef PAGE_SIZE

#   define PAGE_SIZE 4096

# endif

     /*

      * reserve memory for LCD display (always full pages)

      *///为LCD分配RAM(内存)空间

     /* bss_end is defined in the board-specific linker script */

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

    size = lcd_setmem (addr);

    gd->fb_base = addr; //为显存缓冲区地址变量赋值

#endif /* CONFIG_LCD */

 /* armboot_start is defined in the board-specific linker script */

 //malloc函数使用缓冲区的初始化

    mem_malloc_init (_armboot_start - CFG_MALLOC_LEN); 

//如果定义了命令和NAND命令,则初始化nand

#if (CONFIG_COMMANDS & CFG_CMD_NAND)

    puts ("NAND:  ");

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

#endif

#ifdef CONFIG_HAS_DATAFLASH

    AT91F_DataflashInit();

    dataflash_print_info();

#endif

     /* iniTIalize environment 环境的初始化,代码在common\env_common.c中 */

    env_relocate ();

#ifdef CONFIG_VFD

     /* must do this after the framebuffer is allocated */

    drv_vfd_init();

#endif /* CONFIG_VFD */

     /* IP Address 为全局变量的成员赋值:IP地址*/

    gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");//ipaddr在smdk2440.h中的CONFIG_IPADDR中出现,应该是该常量

 /* MAC Address *///高处MAC地址 ,并赋给gd的成员变量

 {

    int i;

    ulong reg;

    char *s, *e;

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

}

#ifdef CONFIG_HAS_ETH1

  i = getenv_r ("eth1addr", tmp, sizeof (tmp));

  s = (i > 0) ? tmp : NULL;

  for (reg = 0; reg < 6; ++reg) {

   gd->bd->bi_enet1addr[reg] = s ? simple_strtoul (s, &e, 16) : 0;

   if (s)

    s = (*e) ? e + 1 : e;

  }

#endif

 }

 //这个函数涉及好多,我没深入分析,若哪位分析了希望能分享一下:cczy_english@163.com,将不胜感激

 devices_init (); /* get the devices list going. */

#ifdef CONFIG_CMC_PU2

 load_sernum_ethaddr ();

#endif /* CONFIG_CMC_PU2 */

//初始化跳转表,对gd中的jt(函数跳转表)数组进行初始化,其中保存着一些函数的入口地址

用户评论