board.c

来源:互联网 发布:无锡经信委 软件产值 编辑:程序博客网 时间:2024/06/04 21:05

/*

 *(C) Copyright 2002

 *Wolfgang Denk, DENX Software Engineering, wd@denx.de.

 *

 *(C) Copyright 2002

 *Sysgo Real-Time Solutions, GmbH <www.elinos.com>

 *Marius Groeger <mgroeger@sysgo.de>

 *

 *See file CREDITS for list of people who contributed to this

 *project.

 *

 *This program is free software; you can redistribute it and/or

 *modify it under the terms of the GNU General Public License as

 *published by the Free Software Foundation; either version 2 of

 *the License, or (at your option) any later version.

 *

 *This program is distributed in the hope that it will be useful,

 *but WITHOUT ANY WARRANTY; without even the implied warranty of

 *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

 *GNU General Public License for more details.

 *

 *You should have received a copy of the GNU General Public License

 *along with this program; if not, write to the Free Software

 *Foundation, Inc., 59 Temple Place, Suite 330, Boston,

 * MA02111-1307 USA

 */

 

#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

 

#if (CONFIG_COMMANDS & CFG_CMD_NAND) //命令选项 & NAND 设置

void nand_init (void);

#endif

 

ulong monitor_flash_len;

 

#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   //添加驱动

extern void cs8900_get_enetaddr (uchar *addr);

#endif

 

#ifdef CONFIG_DRIVER_RTL8019

extern void rtl8019_get_enetaddr (uchar *addr);

#endif

 

/*

 *Begin and End of memory area for malloc(), and current "brk"

 */

static ulong mem_malloc_start = 0;             //MEM显示内存状态

static ulong mem_malloc_end = 0;              //存储器分配 malloc...

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)  /*本函数用于扩展堆空间,用incriment来指定扩展的大小*/

{

       ulongold = mem_malloc_brk;

       ulongnew = old + increment;

 

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

              return(NULL);

       }

       mem_malloc_brk= new;

 

       return((void *) old);

}

 

/************************************************************************

 *Init Utilities                                           *

 ************************************************************************

 *Some of this code should be moved into the core functions,

 * ordropped completely,

 *but let's get it working (again) first...

 */

/*获取环境变量,把波特率值赋给全局gd,若获取为空值,则赋给默认115200*/

static int init_baudrate (void)

{

       DECLARE_GLOBAL_DATA_PTR;

 

       uchartmp[64];       /* long enough forenvironment variables */

/*把环境变量获取到tmp中,i为得到的环境变量的长度*/

       inti = getenv_r ("baudrate", tmp, sizeof (tmp));

/*如果获得了env,则把它赋给gd,否则把115200赋给gd*/

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

/*此函数把字符串转换为ulong型*/

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

                     :CONFIG_BAUDRATE;

       return(0);

}

 

static int display_banner (void)

{

       printf("\n\n%s\n\n", version_string);

       printf("U-Boot code: %08lX -> %08lX BSS: -> %08lX\n",

              _armboot_start,_bss_start, _bss_end);

#ifdef CONFIG_MODEM_SUPPORT

       puts("Modem Support enabled\n");

#endif

#ifdef CONFIG_USE_IRQ

       printf("IRQ Stack: %08lx\n", IRQ_STACK_START);

       printf("FIQ Stack: %08lx\n", FIQ_STACK_START);

#endif

 

       return(0);

}

 

/*

 *WARNING: this code looks "cleaner" than the PowerPC version, but

 *has the disadvantage that you either get nothing, or everything.

 * OnPowerPC, you might see "DRAM: " before the system hangs - which

 * givesa simple yet clear indication which part of the

 *initialization if failing.

 */

static int display_dram_config (void)

{

       DECLARE_GLOBAL_DATA_PTR;

       inti;

 

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

       }

 

       return(0);

}

 

static void display_flash_config (ulongsize)

{

       puts("Flash: ");

       print_size(size, "\n");

}

 

 

/*

 *Breathe some life into the board...

 *

 *Initialize a serial port as console, and carry out some hardware

 *tests.

 *

 *The first part of initialization is running from Flash memory;

 *its main purpose is to initialize the RAM so that we

 *can relocate the monitor code to RAM.

 */

 

/*

 *All attempts to come up with a "common" initialization sequence

 *that works for all boards and architectures failed: some of the

 *requirements are just _too_ different. To get rid of the resulting

 *mess of board dependent #ifdef'ed code we now make the whole

 *initialization sequence configurable to the user.

 *

 *The requirements for any new initalization function is simple: it

 *receives a pointer to the "global data" structure as it's only

 *argument, and returns an integer return code, where 0 means

 *"continue" and != 0 means "fatal error, hang the system".

 */

typedef int (init_fnc_t) (void);

 

init_fnc_t *init_sequence[] = {

       cpu_init,         /* basic cpu dependent setup 基本处理器相关配置*/

       board_init,             /* basic board dependent setup 基本的开发板相关配置*/

       interrupt_init,         /* set up exceptions 初始化例外处理*/

       env_init,         /* initialize environment 初始化环境变量*/

       init_baudrate,         /* initialze baudrate settings 初始化波特率设置*/

       serial_init,              /* serial communications setup 串口通讯设置*/

       console_init_f,              /* stage 1 init of console 控制台初始化阶段1*/

       display_banner,             /* say that we are here 打印 u-boot信息*/

       dram_init,              /* configure available RAM banks 配置可用的RAM*/

       display_dram_config,  //显示 RAM的配置大小

#if defined(CONFIG_VCMA9)

       checkboard,

#endif

       NULL,

};

/*start_armboot是U-Boot执行的第一个C语言函数,完成系统初始化工作,进入主循环,处理用户输入的命令。*/

void start_armboot (void)

{

       DECLARE_GLOBAL_DATA_PTR;

 

       ulongsize;

       init_fnc_t**init_fnc_ptr;

       char*s;

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

       unsignedlong addr;

#endif

 

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

/*****************全局数据结构的初始化*******************/

/*gd_t结构的初始化:

*/

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

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

       __asm____volatile__("": : :"memory");

 

       memset((void*)gd, 0, sizeof (gd_t)); //用0填充全局数据表gd

       gd->bd= (bd_t*)((char*)gd - sizeof(bd_t)); //bd_t结构的初始化:

       memset(gd->bd, 0, sizeof (bd_t)); //用0填充(初始化)*gd->bd

 

       monitor_flash_len= _bss_start - _armboot_start; //取u-boot的 长度

/****************调用通用初始化函数***********/

/* 顺序执行init_sequence数组中的初始化函数 */

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

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

                     hang(); //打印错误信息并死锁

              }

       }

/*init_sequence[]init_fnc_t函数指针数组,这个数组包含了众多初始化函数,比如cpu_initboard_init等。*/

    /* configure available FLASH banks */  /*配置可用的Flash */

       size= flash_init ();         //初始化 flash

       display_flash_config(size);  //显示 flash 大小

 

#ifdef CONFIG_VFD

#     ifndefPAGE_SIZE

#       define PAGE_SIZE 4096

#     endif

       /*

        * reserve memory for VFD display (always fullpages)为VFD显示预留内存(整个页面)

        */

    /* bss_end is defined in the board-specificlinker script *//* _armboot_startu-boot.lds链接脚本中定义 */

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

       size= vfd_setmem (addr);

       gd->fb_base= addr;   

#endif /* CONFIG_VFD */ //进入下一个界面

 

#ifdef CONFIG_LCD

#     ifndefPAGE_SIZE

#       define PAGE_SIZE 4096

#     endif

       /*

        * reserve memory for LCD display (always fullpages)

        */

       /*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 */

       mem_malloc_init(_armboot_start - CFG_MALLOC_LEN);/*将CFG_MALLOC_LEN 区域用memset清0(直接往目的地址写0)*/

/****************初始化具体设备*************/

#if (CONFIG_COMMANDS & CFG_CMD_NAND)

       puts("NAND:");

       nand_init();            /* go init the NAND  nand初始化*/

#endif

 

#ifdef CONFIG_HAS_DATAFLASH

       AT91F_DataflashInit();

       dataflash_print_info();

#endif

 

       /*initialize environment 初始化环境*/

       env_relocate();//函数作用将环境变量从flash到RAM的拷贝

 

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

 

    /* MAC Address *//* 以太网接口MAC 地址 */

       {

              inti;

              ulongreg;

              char*s, *e;

              uchartmp[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;

              }

       }

 

    devices_init ();  /* get the devices list going. *//*获取列表中的设备(外围设备初始化) */

       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 exceptions *//*启用异常处理 */

       enable_interrupts();

 

       /*Perform network card initialisation if necessary */

#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 */

    /* Initialize from environment *//*通过环境变量初始化 */

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

#endif

 

    /* main_loop() can return to retry autoboot,if so just run it again. *//* main_loop()总是试图自动启动,循环不断执行 */

       for(;;) {

       main_loop ();/* 主循环函数处理执行用户命令 --common/main.c */

       }

 

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

}

 

void hang (void)

{

       puts("### ERROR ### Please RESET the board ###\n");

       for(;;);

}

 

#ifdef CONFIG_MODEM_SUPPORT

/* called from main loop (common/main.c) */

extern void dbg(const char *fmt, ...);

int mdm_init (void)

{

       charenv_str[16];

       char*init_str;

       inti;

       externchar console_buffer[];

       staticinline void mdm_readline(char *buf, int bufsiz);

       externvoid enable_putc(void);

       externint hwflow_onoff(int);

 

       enable_putc();/* enable serial_putc() */

 

#ifdef CONFIG_HWFLOW

       init_str= getenv("mdm_flow_control");

       if(init_str && (strcmp(init_str, "rts/cts") == 0))

              hwflow_onoff(1);

       else

              hwflow_onoff(-1);

#endif

 

       for(i = 1;;i++) {

              sprintf(env_str,"mdm_init%d", i);

              if((init_str = getenv(env_str)) != NULL) {

                     serial_puts(init_str);

                     serial_puts("\n");

                     for(;;){

                            mdm_readline(console_buffer,CFG_CBSIZE);

                            dbg("ini%d:[%s]", i, console_buffer);

 

                            if((strcmp(console_buffer, "OK") == 0) ||

                                   (strcmp(console_buffer,"ERROR") == 0)) {

                                   dbg("ini%d:cmd done", i);

                                   break;

                            }else /* in case we are originating call ... */

                                   if(strncmp(console_buffer, "CONNECT", 7) == 0) {

                                          dbg("ini%d:connect", i);

                                          return0;

                                   }

                     }

              }else

                     break;/* no init string - stop modem init */

 

              udelay(100000);

       }

 

       udelay(100000);

 

       /*final stage - wait for connect */

       for(;i> 1;) { /* if 'i' > 1 - wait for connection

                              message from modem */

              mdm_readline(console_buffer,CFG_CBSIZE);

              dbg("ini_f:[%s]", console_buffer);

              if(strncmp(console_buffer, "CONNECT", 7) == 0) {

                     dbg("ini_f:connected");

                     return0;

              }

       }

 

       return0;

}

 

/* 'inline' - We have to do it fast */

static inline void mdm_readline(char *buf,int bufsiz)

{

       charc;

       char*p;

       intn;

 

       n= 0;

       p= buf;

       for(;;){

              c= serial_getc();

 

              /*           dbg("(%c)", c); */

 

              switch(c){

              case'\r':

                     break;

              case'\n':

                     *p= '\0';

                     return;

 

              default:

                     if(n++> bufsiz) {

                            *p= '\0';

                            return;/* sanity check */

                     }

                     *p= c;

                     p++;

                     break;

              }

       }

}

#endif     /*CONFIG_MODEM_SUPPORT */


原创粉丝点击