1。第二阶段的主线函数位于u-boot-2010.06/arch/arm/lib/board.c。


第二阶段的功能:

<1>
初始化本阶段要使用到的硬件设备。

设置时钟、初始化串口。

board_init函数设置MPLL、改变系统时钟,它是开发板相关的函数,在board/samsung/smdk2440/smdk2440.c中实现。值得注意的是board_init函数还保存了机器类型ID,这将在调用内核的时候传递给内核。代码如下:

gd->bd->bi_arch_number = MACH_TYPE_S3C2440;
//值为362

串口的初始化函数主要是serial_init,它设置UART控制器,是CPU相关的函数。

<2>检测系统内存映射(memory
map)。

对于smdk2440的开发板,其内存分布是明确的,一般内存起始地址为0x3000
0000,大小为64M = 0x0400 0000。代码如下:

int dram_init(void)

{

gd->bd->bi_dram[0] .
start = PHYS_SDRAM_1; //即0x3000 0000

gd->bd->bi_dram[0].size =
PHYS_SDRAM_1_SIZE; //即0x0400 0000

//这两个值都定义在include/configs/smdk2440.h中

}

<3>将内核映像和根文件系统映像从Flash上读到RAM空间中。

<4>为内核设置启动参数。

U-Boot 是通过标记列表向内核传递参数。

setup_memory_tags

setup_commandline_tag

这两个标记列表定义在arch/arm/lib/bootm.c中,需要在定义命令的文件include/configs/smdk2440.h中定义两个命令

#define CONFIG_SETUP_MEMORY_TAGS
1

#define CONFIG_CMDLINE_TAG 1

对于ARM构架的CPU来说,都是通过arch/arm/lib/bootm.c中的do_bootm_linux函数来启动内核的。这个函数中,设置标记列表,最后通过
theKernel
= (void (星)(int, int, uint))images->ep;
调用内核。其中,theKernel
指向内核存放的地址(对于ARM构架的CPU,通常这个地址是0x3000 8000)。传递的3个参数如下:void
(星theKernel)(int zero, int arch,
uint
params
);

R0:
0

R1:
机器类型ID -- gd->bd->bi_arch_number = MACH_TYPE_S3C2440;
//值为362

R2:
启动参数标记列表在RAM中的起始地址 0x3000 0100

2。源码解析。

arch/arm/lib/board.c

void
start_armboot (void)
{
init_fnc_t **init_fnc_ptr;
//定义二级函数指针
char *s;

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

unsigned
long env_addr;
unsigned
long env_valid;
unsigned
long fb_base;
#ifdef CONFIG_VFD
unsigned char vfd_type;
#endif
#ifdef CONFIG_FSL_ESDHC
unsigned long sdhc_clk;
#endif
#if 0
unsigned long cpu_clk;
unsigned long bus_clk;
phys_size_t ram_size;
unsigned long reset_status;
#endif
void
**jt;
} gd_t;

sizeof(gd_t)=4 + 4 * 6 + 4 = 32 =
0x20。

故gd所指向地址 0x3ff80000 - 0x40000 - 0x20为 0x3FF3
FFE0


#define GD_FLG_RELOC 0x00001
#define GD_FLG_DEVINIT 0x00002
#define GD_FLG_SILENT 0x00004
#define GD_FLG_POSTFAIL 0x00008
#define GD_FLG_POSTSTOP 0x00010
#define GD_FLG_LOGINIT 0x00020
#define GD_FLG_DISABLE_CONSOLE 0x00040

#define DECLARE_GLOBAL_DATA_PTR
register volatile gd_t *gd asm ("r8")

__asm__ __volatile__("": : :"memory"); //分配一个存储全局数据的区域,地址给指针
gd

memset
((void*)gd, 0, sizeof (gd_t));
//分配空间并清0
gd->bd =
(bd_t*)((char*)gd - sizeof(bd_t));


unsigned
long bi_ip_addr;
struct
environment_s *bi_env;
ulong
bi_arch_number;
ulong
bi_boot_params;
struct
{
ulong
start;
ulong
size;
} bi_dram[CONFIG_NR_DRAM_BANKS];
} bd_t;

#define bi_env_data bi_env->data
#define bi_env_crc bi_env->crc

#endif

****************************************************************************************************************/
memset (gd->bd, 0, sizeof (bd_t));
//分配空间并清0

gd->flags |= GD_FLG_RELOC;
//设置当前uboot标志位已经重定位

monitor_flash_len = _bss_start -
_armboot_start;
//uboot镜像文件大小

//初始化函数循环

for
(init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr)
{
if ((*init_fnc_ptr)() != 0)

{
hang ();
}
}


#endif
board_init,
#if defined(CONFIG_USE_IRQ)
interrupt_init,
#endif
timer_init,
#ifdef CONFIG_FSL_ESDHC
get_clocks,
#endif
env_init,
init_baudrate,
serial_init,
console_init_f,
display_banner,
#if defined(CONFIG_DISPLAY_CPUINFO)
print_cpuinfo,
#endif
#if defined(CONFIG_DISPLAY_BOARDINFO)
checkboard,
#endif
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
init_func_i2c,
#endif
dram_init,
#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI)
arm_pci_init,
#endif
display_dram_config,
NULL,
};

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


mem_malloc_init (_armboot_start -
CONFIG_SYS_MALLOC_LEN,
CONFIG_SYS_MALLOC_LEN);

#ifndef CONFIG_SYS_NO_FLASH

display_flash_config (flash_init ());
#endif

#if
defined(CONFIG_CMD_NAND)
puts ("NAND: ");
nand_init();
#endif

#if
defined(CONFIG_CMD_ONENAND)
onenand_init();
#endif


env_relocate ();

//多串口配置,跳过。

#ifdef
CONFIG_SERIAL_MULTI
serial_initialize();
#endif

//IP地址获取。


gd->bd->bi_ip_addr = getenv_IPaddr
("ipaddr");

//标准的输入输出

stdio_init ();

//初始化外设列表

jumptable_init ();

//u-boot的应用函数集,跳过

#if
defined(CONFIG_API)

api_init ();
#endif

//初始化控制台(console),平台无关,不一定是串口哦,如果把标准输出设为vga,字符会显示在LCD上。

console_init_r ();

//平台相关的其他设备初始化,这些s3c2440都没有。跳过

#if
defined(CONFIG_ARCH_MISC_INIT)

arch_misc_init ();
#endif

#if
defined(CONFIG_MISC_INIT_R)

misc_init_r ();
#endif

//允许中断,这里还没移植USB下载,所以直接return。


enable_interrupts ();

//TI平台的网卡驱动,直接跳过


#ifdef
CONFIG_DRIVER_TI_EMAC

extern void davinci_eth_set_mac_addr (const u_int8_t *addr);
if (getenv ("ethaddr"))

{
uchar enetaddr[6];
eth_getenv_enetaddr("ethaddr", enetaddr);
davinci_eth_set_mac_addr(enetaddr);
}
#endif

//其他网卡的设置,直接跳过。

#if
defined(CONFIG_DRIVER_SMC91111) || defined
(CONFIG_DRIVER_LAN91C96)

if (getenv ("ethaddr"))

{
uchar enetaddr[6];
eth_getenv_enetaddr("ethaddr", enetaddr);
smc_set_mac_addr(enetaddr);
}
#endif


if ((s = getenv ("loadaddr")) != NULL)

{
load_addr = simple_strtoul (s, NULL, 16);
}

//获取bootfile参数

#if
defined(CONFIG_CMD_NET)
if ((s = getenv ("bootfile")) != NULL)

{
copy_filename (BootFile, s, sizeof (BootFile));
}
#endif

#ifdef
BOARD_LATE_INIT
board_late_init ();
#endif

//MMC卡的控制器初始化

#ifdef
CONFIG_GENERIC_MMC
puts ("MMC: ");
mmc_initialize (gd->bd);
#endif

#ifdef
CONFIG_BITBANGMII
bb_miiphy_init();
#endif

#if
defined(CONFIG_CMD_NET)
//多网卡配置

#if
defined(CONFIG_NET_MULTI)
puts ("Net: ");
#endif

//网卡初始化
eth_initialize(gd->bd);

//允许网卡复位
#if defined(CONFIG_RESET_PHY_R)
debug ("Reset Ethernet PHY\n");
reset_phy();
#endif
#endif

//进入主循环。其中会读取bootdelay和bootcmd。在bootdelay时间内按下键进入命令行,否则执行bootcmd的命令。


for (;;)

{
main_loop ();
}


}

//出错提示

void
hang (void)
{
puts ("### ERROR ### Please RESET the board ###\n");
for (;;);
}

3。初始化列表具体分析。

void jumptable_init(void)
{

//为gd->jt是这个函数指针数组分配空间。

gd->jt = malloc(XF_MAX * sizeof(void *));
#include <_exports.h>
}

init_fnc_t *init_sequence[] = {
#if defined(CONFIG_ARCH_CPU_INIT)
arch_cpu_init,
#endif

board_init,

clk_power->LOCKTIME = 0xFFFFFF;

clk_power->MPLLCON = ((M_MDIV << 12) + (M_PDIV << 4)
+ M_SDIV);

delay (4000);

clk_power->UPLLCON = ((U_M_MDIV << 12) + (U_M_PDIV
<< 4) + U_M_SDIV);

delay (8000);

gpio->GPACON = 0x007FFFFF;
gpio->GPBCON = 0x00044555;
gpio->GPBUP = 0x000007FF;
gpio->GPCCON = 0xAAAAAAAA;
gpio->GPCUP = 0x0000FFFF;
gpio->GPDCON = 0xAAAAAAAA;
gpio->GPDUP = 0x0000FFFF;
gpio->GPECON = 0xAAAAAAAA;
gpio->GPEUP = 0x0000FFFF;
gpio->GPFCON = 0x000055AA;
gpio->GPFUP = 0x000000FF;
gpio->GPGCON = 0xFF95FFBA;
gpio->GPGUP = 0x0000FFFF;
gpio->GPHCON = 0x002AFAAA;
gpio->GPHUP = 0x000007FF;

gd->bd->bi_arch_number =
MACH_TYPE_S3C2440;

gd->bd->bi_boot_params =
0x30000100;

icache_enable(); //关闭指令cache
dcache_enable();
//关闭数据cache

return 0;
}
***************************************************************************************************************/

#if defined(CONFIG_USE_IRQ)
interrupt_init,
#endif
timer_init, //定时器初始化

writel(0x0f00, &timers->TCFG0);
if (timer_load_val == 0) {

timer_load_val = get_PCLK() / (2 * 16 * 100);
timer_clk = get_PCLK() / (2 * 16);
}

lastdec = timer_load_val;
writel(timer_load_val, &timers->TCNTB4);

tmr = (readl(&timers->TCON) & ~0x0700000) |
0x0600000;
writel(tmr, &timers->TCON);

tmr = (tmr & ~0x0700000) | 0x0500000;
writel(tmr, &timers->TCON);
timestamp = 0;

return (0);
}

****************************************************************************************************************/
#ifdef CONFIG_FSL_ESDHC
get_clocks,
#endif
env_init, //环境变量

gd->env_addr = (ulong) & default_environment[0];
gd->env_valid = 1;

return 0;
}
****************************************************************************************************************/
init_baudrate, //波特率获取

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

***************************************************************************************************************/
serial_init, //串口设置

int serial_init(void)
{
return serial_init_dev(UART_NR); //UART_NR
就是串口号,在文件drivers/serial/serial_s3c24x0.c中有如下定义:

默认的输出为串口0 即定义在include/configs/smdk2440.h中

#define CONFIG_S3C24X0_SERIAL
#define
CONFIG_SERIAL1 1
}
#endif

|

|

|

static int serial_init_dev(const int dev_index)
{
struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);

#ifdef CONFIG_HWFLOW
hwflow = 0;
#endif

writel(0x07, &uart->UFCON);
writel(0x0, &uart->UMCON);

writel(0x3, &uart->ULCON);

writel(0x245, &uart->UCON);

#ifdef CONFIG_HWFLOW
writel(0x1, &uart->UMCON);
#endif

#if defined(CONFIG_ARCH_GTA02_v1) ||
defined(CONFIG_ARCH_GTA02_v2)

if (dev_index == 0 || dev_index == 1)
writel(0x10, &uart->UMCON);
#endif
_serial_setbrg(dev_index);

return (0);
}

****************************************************************************************************************/
console_init_f,

int console_init_f(void)
{
gd->have_console = 1;

#ifdef
CONFIG_SILENT_CONSOLE
if (getenv("silent") != NULL)
gd->flags |= GD_FLG_SILENT;
#endif

return
0;
}

****************************************************************************************************************/
display_banner,

#if defined(CONFIG_DISPLAY_CPUINFO)
print_cpuinfo,
#endif
#if defined(CONFIG_DISPLAY_BOARDINFO)
checkboard,
#endif
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
init_func_i2c,
#endif
dram_init, //内存初始化

#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI)
arm_pci_init,
#endif
display_dram_config, //显示内存信息

NULL,
};




Uboot详细解析2的更多相关文章

  1. Uboot详细解析1

    uboot 详细注释讲解 声明:该贴是通过参考其他人的帖子整理出来,从中我加深了对uboot的理解,我知道对其他人一定也是有很大的帮助,不敢私藏,如果里面的注释有什么错误请给我回复,我再加以修改.有些 ...

  2. 【系统移植】uboot详细分析

    uboot使用 uboot控制台,倒计时    命令: 调试,操作一些硬件 setenv printenv saveenv  nand erase  nand write  tftp zImage h ...

  3. java类生命周期详细解析

    (一)详解java类的生命周期 引言 最近有位细心的朋友在阅读笔者的文章时,对java类的生命周期问题有一些疑惑,笔者打开百度搜了一下相关的问题,看到网上的资料很少有把这个问题讲明白的,主要是因为目前 ...

  4. springmvc 项目完整示例06 日志–log4j 参数详细解析 log4j如何配置

    Log4j由三个重要的组件构成: 日志信息的优先级 日志信息的输出目的地 日志信息的输出格式 日志信息的优先级从高到低有ERROR.WARN. INFO.DEBUG,分别用来指定这条日志信息的重要程度 ...

  5. include_path详细解析

    include_path详细解析     原文地址:http://www.laruence.com/2010/05/04/1450.html 1.php默认的包含路径为 .;C:\php\pear 即 ...

  6. Intent的详细解析以及用法

    Intent的详细解析以及用法      Android的四大组件分别为Activity .Service.BroadcastReceiver(广播接收器).ContentProvider(内容提供者 ...

  7. C++多态的实现及原理详细解析

    C++多态的实现及原理详细解析 作者: 字体:[增加 减小] 类型:转载   C++的多态性用一句话概括就是:在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型 ...

  8. 对MySQL DELETE语法的详细解析

    以下的文章主要描述的是MySQL DELETE语法的详细解析,首先我们是从单表语法与多表语法的示例开始的,假如你对MySQL DELETE语法的相关内容十分感兴趣的话,你就可以浏览以下的文章对其有个更 ...

  9. 转:二十一、详细解析Java中抽象类和接口的区别

    转:二十一.详细解析Java中抽象类和接口的区别 http://blog.csdn.net/liujun13579/article/details/7737670 在Java语言中, abstract ...

随机推荐

  1. [置顶] kubernetes1.7新特性:新增StorageOS卷插件和Local持久存储

    背景介绍 在Kubernetes中卷的作用在于提供给POD存储,这些存储可以挂载到POD中的容器上,进而给容器提供存储. 从图中可以看到结构体PodSpec有个属性是Volumes,通过这个Volum ...

  2. 【MFC】VC界面绘制双缓存

    VC界面绘制双缓存 转载请注明原文网址: http://www.cnblogs.com/xianyunhe/archive/2011/11/20/2255811.html 1.闪屏的问题在GDI的绘图 ...

  3. Linux下Apache配置局域网访问出现的问题

    在网站安装好之后,本机可以访问,但是局域网内无法访问,我查看了 /etc/httpd/conf/httpd.conf 看到我的配置如下 <Directory ......> Allow A ...

  4. WCF+上传+大文件处理

    大文件处理的方式拆分读取,此文只为记录文件处理方式,供日后查阅. 源码来自http://blog.csdn.net/lywust/article/details/7009248 经过改编将源码改编为文 ...

  5. 【spring源码学习】spring的IOC容器之BeanFactoryPostProcessor接口学习

    [一]org.springframework.beans.factory.config.BeanFactoryPostProcessor接口==>该接口实现方法的执行时机:该接口void pos ...

  6. ACM学习历程—HDU5701 中位数计数(中位数 && 计数排序)

    http://acm.hdu.edu.cn/showproblem.php?pid=5701 这是这次百度之星初赛2B的第六题.之前白山云做过类似的题,省赛完回来,我看了一下大概就有这样的思路:首先枚 ...

  7. bootstrap table 兼容ie8 -- refreshOptions

    今天项目使用 bootstrap table 在ie8下发现 方法 refreshOptions 报错. 经过调试监控发现错误如下: 153 行 代码 Object.getOwnPropertyNam ...

  8. 使用spring框架的JdbcTemplate实现对Oracle数据库的简单操作实例

    最近实现了一个小功能,针对Oracle数据库两张关联表进行查询和修改,因为比较简单,所以选择了spring框架里的JdbcTemplate.JdbcTemplate算是老古董了,是当年spring为了 ...

  9. 在centos6.6中mysql5.5的编译、安装、配置

    今天根据需求要在centos6.6上编译安装mysql5.5,因为以前编译安装过感觉很简单,但是今天还是出现了点小问题,所以把过安装过程总结了一下: 好像从mysql5.5开始编译安装mysql需要用 ...

  10. 半导体巨头青睐物联网领域 众强联手打造MCU生态系统

    随着万物互联的时代到来,众多半导体巨头纷纷转战物联网领域.早在十年前,意法半导体曾将STM32推向市场,意法半导体对32位MCU在物联网方面的应用在两年前就已展开攻势. 4月25日,历经两届盛况的ST ...