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. sphinx使用

    一. 1.先得包含下载的文件 include'./sphinx/api/sphinxapi.php'; $sphinx= new SphinxClient(); $sphinx->SetServ ...

  2. File I|O(八)

    1.I/O:input/output 1.1.java.io.File 表示:文件或者文件夹(目录) File f=new File("文件路径") 注意:相对路径:非web项目的 ...

  3. VC6工程因行尾格式无法转换到VS2015

    VC6工程因行尾格式无法转换到VS2015(金庆的专栏 2017.6)参考:https://connect.microsoft.com/VisualStudio/feedback/details/54 ...

  4. HAWQ取代传统数仓实践(十五)——事实表技术之无事实的事实表

    一.无事实事实表简介 在多维数据仓库建模中,有一种事实表叫做"无事实的事实表".普通事实表中,通常会保存若干维度外键和多个数字型度量,度量是事实表的关键所在.然而在无事实的事实表中 ...

  5. RIPng 知识要点

    RIPng  --------------------------------------------------------- UDP:521 多播地址:FF02::9 -------------- ...

  6. jstl错误排除:According to TLD or attribute directive in tag file, attribute value does not accept any expressions

    问题描述: 在 JSP 页面中使用 JSTL 标签库,访问 JSP 页面时抛出了如下异常信息: org.apache.jasper.JasperException: /index.jsp (line: ...

  7. Python sh库学习

    官方文档有句话"allows you to call any program",并且: helps you write shell scripts in Python by giv ...

  8. stp 零部件 转为 装配图

    stp 零部件 转为 装配图 起因 由于收到的 stp 为零件件,这时如果输出 eDrawings 文件时是没有装配结构的. 解决 打开 stp 后在资源管理器中有一个实体的文件夹,点右键保存实体. ...

  9. 浪潮各机型管理芯片BMC IP(智能平台管理接口)设置

    NF5240m3/NF5140m3/NF5280m3/SA5212H2/NP5540M3NF5270M3/NF5170M3/NF8420m3 IPMI主板集成管理芯片BMC IP 设置开机按DEL键进 ...

  10. sqlserver sql语句附加 分离数据库

    当使用 sp_attach_db 系统存储过程附加数据库时- - Tag: 当使用 sp_attach_db 系统存储过程附加数据库时 //附加数据库 sp_attach_db 当使用 sp_atta ...