当前位置:   article > 正文

u-boot第二阶段board.c分析_内核board.c

内核board.c

针对s3c2440 u-boot-1.1.6

u-boot第一阶段主要就是:关闭看门狗,关中断,初始化存储器,初始化nand,u-boot代码的重定位。

u-boot第二阶段的主要任务:初始化网口、nor、LCD等外设,初始化u-boot全局变量,初始化u-boot传递给内核参数,循环等待用户输入,它的位置在/lib_arm/board.c下面。

#include <common.h>
#include <command.h>
#include <malloc.h>
#include <devices.h>
#include <version.h>
#include <net.h>

#ifdef CONFIG_DRIVER_SMC91111                     //宏开关
#include "../drivers/smc91111.h"                            
#endif
#ifdef CONFIG_DRIVER_LAN91C96      
#include "../drivers/lan91c96.h"
#endif
DECLARE_GLOBAL_DATA_PTR;                          
#if (CONFIG_COMMANDS & CFG_CMD_NAND)   //u-boot很多重要的宏开关定义在/include/configs/smdk2410.h在u-boot配置时起作用
void nand_init (void);                                                   // 点击访问u-boot配置过程
#endif
ulong monitor_flash_len;                                           //u-boot代码长度
#ifdef CONFIG_HAS_DATAFLASH
extern int  AT91F_DataflashInit(void);
extern void dataflash_print_info(void);
#endif
#ifndef CONFIG_IDENT_STRING
#define CONFIG_IDENT_STRING ""
#endif
const char version_string[] =U_BOOT_VERSION" (" __DATE__ " - " __TIME__ ")"CONFIG_IDENT_STRING;
#ifdef CONFIG_DRIVER_CS8900     //网卡CS8900开关,每个开发板的网卡可能会不同,此处有链接
extern void cs8900_get_enetaddr (uchar * addr);
#endif
#ifdef CONFIG_DRIVER_RTL8019
extern void rtl8019_get_enetaddr (uchar * addr);
#endif
static ulong mem_malloc_start = 0;                         //malloc可分配的开始地址
static ulong mem_malloc_end = 0;                          //malloc可分配的结束地址
static ulong mem_malloc_brk = 0;
static   void mem_malloc_init (ulong dest_addr)   //malloc区域初始化
{
  mem_malloc_start = dest_addr;
  mem_malloc_end = dest_addr + CFG_MALLOC_LEN;//CFG_MALLOC_LEN在/include/configs/xxxx.h中定义
  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);
}
/************************************************************************
 * 初始化函数,根据情况选择合适的编译进u-boot*
 ************************************************************************
static int init_baudrate (void)                                                            //波特率初始化函数
{
   char tmp[64]; /* long enough for environment variables */
   int i = getenv_r ("baudrate", tmp, sizeof (tmp));
   gd->bd->bi_baudrate = gd->baudrate = (i > 0)? (int) simple_strtoul (tmp, NULL, 10): CONFIG_BAUDRATE;
   return (0);
}
static int display_banner (void)//显示打印基本信息
{
  printf ("\n\n%s\n\n", version_string);
  debug ("U-Boot code: %08lX -> %08lX  BSS: -> %08lX\n", _armboot_start, _bss_start, _bss_end);
  #ifdef CONFIG_MODEM_SUPPORT
     debug ("Modem Support enabled\n");
  #endif
  #ifdef CONFIG_USE_IRQ
     debug ("IRQ Stack: %08lx\n", IRQ_STACK_START);
     debug ("FIQ Stack: %08lx\n", FIQ_STACK_START);
   #endif
  return (0);
}
static int display_dram_config (void)//显示dram的信息
{
int i;
#ifdef DEBUG
   puts ("RAM Configuration:\n");
   for(i=0; i<CONFIG_NR_DRAM_BANKS; i++) {
      printf ("Bank #%d: %08lx ", i, gd->bd->bi_dram[i].start);
      print_size (gd->bd->bi_dram[i].size, "\n");}
#else
    ulong size = 0;
    for (i=0; i<CONFIG_NR_DRAM_BANKS; i++) {
      size += gd->bd->bi_dram[i].size;}
    puts("DRAM:  ");
    print_size(size, "\n");
#endif
return (0);
}
#ifndef CFG_NO_FLASH
static void display_flash_config (ulong size)//显示nor  flash 的大小
{
  puts ("Flash: ");
  print_size (size, "\n");
}
#endif /* CFG_NO_FLASH */
typedef int (init_fnc_t) (void);//定义一个函数类型,原型为 int  f(void)
int print_cpuinfo (void); //打印CPU信息,仅作测试用
i nit_fnc_t *init_sequence[] = {    //定义一个函数指针数组
cpu_init,                                         //cpu初始化代码
board_init,                                     //开发板相关的初始化代码
interrupt_init,                                 //中断设置代码
env_init,                                         //uboot环境变量设置
init_baudrate,                               //设置波特率
serial_init,                                     //串口通信设置     u-boot一般都是通过串口来作为标准输入出, 点击访问串口初始化全过程
console_init_f,                             //控制台初始化
display_banner,                          //打印信息
#if defined(CONFIG_DISPLAY_CPUINFO)
print_cpuinfo,                               //打印cpu信息
#endif
#if defined(CONFIG_DISPLAY_BOARDINFO)
checkboard,                                  //显示板子信息
#endif
dram_init,                                      //初始化bank信息
display_dram_config,                 //显示bank信息
NULL,
};
void start_armboot (void)//uboot第一阶段跳转的的位置,uboot第二阶段的第一句
{
init_fnc_t **init_fnc_ptr;
char *s;
#ifndef CFG_NO_FLASH
ulong size;
#endif
#if defined(CONFIG_VFD) || defined(CONFIG_LCD)
unsigned long addr;
#endif
gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
__asm__ __volatile__("": : :"memory");                                                  
memset ((void*)gd, 0, sizeof (gd_t));
gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
memset (gd->bd, 0, sizeof (bd_t));
monitor_flash_len = _bss_start - _armboot_start;

for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {//调用初始化函数进行初始化
   if ((*init_fnc_ptr)() != 0)
        {hang ();}  }
#ifndef CFG_NO_FLASH
size = flash_init ();                                  //获得可用的flash的大小
display_flash_config (size);                 //打印flash信息
#endif /* CFG_NO_FLASH */
#ifdef CONFIG_VFD
#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif
addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);//配置虚拟的显存,必须页对齐,_bss_end 在链接脚本u-boot.lds中定义
size = vfd_setmem (addr);
gd->fb_base = addr;
#endif /* CONFIG_VFD */
#ifdef CONFIG_LCD
#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif
addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); //配置显存,必须页对齐,_bss_end 在链接脚本u-boot.lds中定义
size = lcd_setmem (addr);
gd->fb_base = addr;

#endif /* CONFIG_LCD */
mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);//初始化malloc区域,_armboot_start 在u-boot.lds中有定义
#if (CONFIG_COMMANDS & CFG_CMD_NAND)//nand宏开关,因为板子使用的nand各不相同,需要移植,此处有链接
  puts ("NAND:  ");                                                     
  nand_init();     //点击访问nand层次化分析                                                      

#endif
#ifdef CONFIG_HAS_DATAFLASH
  AT91F_DataflashInit();
  dataflash_print_info();
#endif
env_relocate (); //点击访问u-boot环境变量初始化全过程
#ifdef CONFIG_VFD
drv_vfd_init();/* must do this after the framebuffer is allocated */
#endif /* CONFIG_VFD */
gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");   //获得u-boot的ip地址
{      //获得u-boot的MAC地址
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
}
devices_init (); /* get the devices list going. */
#ifdef CONFIG_CMC_PU2
   load_sernum_ethaddr ();
#endif /* CONFIG_CMC_PU2 */
jumptable_init ();
console_init_r (); /* fully init console as a device */
#if defined(CONFIG_MISC_INIT_R)
/* miscellaneous platform dependent initialisations */
misc_init_r ();
#endif
enable_interrupts ();//使能中断
#ifdef CONFIG_DRIVER_CS8900//宏开关,网卡初始化
  cs8900_get_enetaddr (gd->bd->bi_enetaddr);
#endif
#if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96)
  if (getenv ("ethaddr")) {smc_set_mac_addr(gd->bd->bi_enetaddr);}
#endif /* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */
if ((s = getenv ("loadaddr")) != NULL) {load_addr = simple_strtoul (s, NULL, 16);}//获得加载地址
#if (CONFIG_COMMANDS & CFG_CMD_NET)
  if ((s = getenv ("bootfile")) != NULL) {
     copy_filename (BootFile, s, sizeof (BootFile));}
#endif /* CFG_CMD_NET */
#ifdef BOARD_LATE_INIT
  board_late_init ();//board进一步初始化
#endif
#if (CONFIG_COMMANDS & CFG_CMD_NET)
    #if defined(CONFIG_NET_MULTI)
         puts ("Net:   ");
    #endif
    eth_initialize(gd->bd);
#endif
//u-boot主循环,除了boot启动内核没有其他方式跳出该循环,在里面可以执行很多的命令,而这些命令也是u-boot的精华

for (;;) {

     main_loop ();  }//点击查看main_loop分析
} //end start_armboot
void hang (void)
{
  puts ("### ERROR ### Please RESET the board ###\n");
  for (;;);

}

u-boot有两大功能:启动内核,调试功能。这两种功能都是在main_loop中通过不同的命令来实现的。

启动内核:1,传递芯片的机器码

                  2,传递内核需要的参数到默认位置

                  3,拷贝内核到内存,并跳转到内核处

调试功能:1,读写nand

                  2,tftp下载支持

                  3,读写sdram

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号