赞
踩
/*
*(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_init,board_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_start在u-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 */
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。