您的位置:首页 > 其它

uboot的启动过程

2014-11-23 12:49 141 查看
Time 2014- 10-14

基于S5PV210平台

===============================================================================

uboot启动第一阶段(汇编代码)流程:

1》 设置异常向量表

2》 进入SVC32模式,并禁止中断CPST[I,F]= 1:1

3》 CPU初始化 I/D cache 和 MMU 禁用

4》 关闭看门狗

5》 VIC控制(中断控制器)---可选

6》 串口初始化(调试用)---可选

7》 时钟初始化

8》 内存初始化(为重定位做准备)

9》 栈的初始化 (SP指针的初始化)

10》 重定位代码到内存中

11》 清bss段

12》 跳转到第二阶段(c代码)

代码跟读:

(cpu/arm_cortexa8/start.S)

.word 0x2000 //----->s5pv210平台uboot需要包含16字节的头部信息

.word 0x0

.word 0x0

.word 0x0

_start: b reset //------------------------------------->1.设置异常向量表

ldr pc,_undefined_instruction

ldr pc,_software_interrupt

ldr pc,_prefetch_abort

ldr pc,_data_abort

ldr pc,_not_used

ldr pc,_irq

ldr pc,_fiq

…..

mrs r0, cpsr//------------------------------------>2. set thecpu to SVC32 mode

bic r0,r0, #0x1f

orr r0,r0, #0xd3

msr cpsr,r0

mrc p15, 0, r0, c1, c0, 0//--------------------->3.disable MMU stuff and caches

bic r0,r0, #0x00002000 @ clear bits 13(--V-)

bic r0,r0, #0x00000007 @ clear bits 2:0(-CAM)

orr r0,r0, #0x00000002 @ set bit 1 (--A-)Align

orr r0,r0, #0x00000800 @ set bit 12(Z---) BTB

mcr p15,0, r0, c1, c0, 0

bl lowlevel_init --------------------------->时钟、内存、栈的初始化

ldrsp,=(0x22000000) ---------------------------->重定位代码到内存中

blcopy_uboot_to_ram

clear_bss: ---------------------------->清bss

ldr r0,_bss_start @ find start of bsssegment

ldr r1,_bss_end @ stop here

mov r2,#0x00000000 @ clear value

ldr pc, _start_armboot ----------------------------->跳转到第二阶段

=============================================================================

u-boot启动第二阶段(lib_arm/board.c)

1》 初始化一个全局变量 gd

2》 完成初始化序列

3》 nand flash 初始化(nand 命令:nand write/nand erase; saveenv…)

4》 环境变量的重定位

5》 网卡的初始化(tftp )

6》 进入一个死循环(倒计时 ---->a结束:自动执行bootcmd 中的内容;b
打断:接收用户的输入 。(处理的都是命令))

代码跟读:

void start_armboot(void)

|

//gd指针,指向哪个地方??

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

/* compiler optimization barrier needed forGCC >= 3.4 */

__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)

//执行数组中的所有函数

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

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

hang();

}

}

init_sequence

|

board_init, ------------>boaidid 2456

serial_init, ------------>串口初始化

mem_malloc_init (_armboot_start - CONFIG_SYS_MALLOC_LEN,

CONFIG_SYS_MALLOC_LEN); ------>堆的初始化

nand_init(); ---------------------->nand flash
初始化

env_relocate (); ---------------------->环境变量重定位

#if defined(CONFIG_NET_MULTI) --------------------->网卡的初始化

puts ("Net: ");

#endif

eth_initialize(gd->bd);

eth_init(gd->bd);

for (;;) {

main_loop (); ------------------------>进入死循环

}

============================================================================================

全局的gd数据:(Global_data.h(include\asm)

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

全局:该变量在所有的.c文件中都可以访问---- 需要在.c中声明DECLARE_GLOBAL_DATA_PTR

gd->bd->bi_arch_number = MACH_TYPE_SMDKC100; //开发板的id号码 25260-->在内核中要用到

gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100; //传递数据给内核的位置

gd->bd->bi_baudrate = gd->baudrate = 115200

gd->bd->bi_dram[0].start = PHYS_SDRAM_1; //记录内存的物理地址:0x2000000

gd->bd->bi_dram[0].size = get_ram_size((long *)PHYS_SDRAM_1,

PHYS_SDRAM_1_SIZE);//记录内存大小

gd->have_console = 1;

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

gd->env_valid = 1;

初始化序列 代码跟读:(lib_arm/board.c)

init_sequence[]

|

arch_cpu_init,

|

s5pc1xx_clock_init();

|

if (cpu_is_s5pc110()) { //-------------------------->系统时钟的初始化信息

get_pll_clk = s5pc110_get_pll_clk;

get_arm_clk = s5pc110_get_arm_clk;

get_pclk = s5pc110_get_pclk;

} else {

get_pll_clk =s5pc100_get_pll_clk;

get_arm_clk =s5pc100_get_arm_clk;

get_pclk = s5pc100_get_pclk;

}

board_init,

|

gd->bd->bi_arch_number = MACH_TYPE_SMDKV210; ----->板子id 2456

gd->bd->bi_boot_params = PHYS_SDRAM_1+ 0x100; ----->传递数据给内核的位置

timer_init, //--------------->为uboot提供一个倒计时时间间隔10ms

|

/* count_value / 100 = 20859.375(HZ) (per 10 msec) */ // (cpu/arm_cortexa8/5pcXX/timer.c)

count_value= count_value / 100;

env_init,

|

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

gd->env_valid= 1;
| //----->如果用户没有自定义环境变量,则使用默认值

|

"bootargs=" CONFIG_BOOTARGS

"bootcmd=" CONFIG_BOOTCOMMAND

init_baudrate,

|

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

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

:CONFIG_BAUDRATE;

serial_init,

|

struct serial_device *dev= default_serial_console ();

dram_init,

|

gd->bd->bi_dram[0].start = PHYS_SDRAM_1; ---->记录物理内存地址

gd->bd->bi_dram[0].size =get_ram_size((long *)PHYS_SDRAM_1,

PHYS_SDRAM_1_SIZE); ---->记录物理内存大小

=================================================================================================

环境变量的处理:(lib_arm/board.c)

voidstart_armboot (void)

|

init_fnc_t*init_sequence[]

|

env_init,

| //(common/env_nand.c)

#else /* ENV_IS_EMBEDDED ||CONFIG_NAND_ENV_DST */

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

gd->env_valid= 1;

env_relocate ();

|

env_ptr= (env_t *)malloc (CONFIG_ENV_SIZE);

env_relocate_spec();

| // CONFIG_ENV_OFFSET从nand中的哪个位置读取

ret= readenv(CONFIG_ENV_OFFSET, (u_char *) env_ptr);

if(ret)

returnuse_default(); ------->
如果读取失败,使用默认位置

|

puts ("*** Warning - bad CRC or NAND, using default environment\n\n");

set_default_env();

|

memcpy(env_ptr->data,default_environment, sizeof(default_environment));

gd->env_addr= (ulong)&(env_ptr->data);

================================================================================================

定制默认的环境变量: smdkc100.h(基于S5PC100平台)

#define CONFIG_SERVERIP 192.168.7.2

#define CONFIG_IPADDR 192.168.7.7

#define CONFIG_ETHADDR 00:23:32:34:ee:ab

#define CONFIG_BOOTCOMMAND "tftp0x20800000 uImage35 ; bootm 0x20800000"

#define CONFIG_BOOTARGS "console=ttySAC0,115200 root=/dev/nfsnfsroot=192.168.7.2:/opt/filesystem ip=192.168.7.7 init=/linuxrc"

=================================================================================================

死循环部分代码跟读

main_loop ();

|//(common/main.c)

有两种分析字符串的方式

1, hushparser 类型于shell,复杂, 代码中采用这种方式去分析

CONFIG_SYS_HUSH_PARSER一般都会定义

2, 普通分析方式: 简单

看代码的时候: 看普通分析方法

实际代码 hushparser

s = getenv("bootdelay");

bootdelay = s ?(int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;

if (bootdelay >= 0&& s && !abortboot (bootdelay)) { //abortboot 就是倒计时

run_command(s, 0);

|

cmd_tbl_t*cmdtp;

(argc= parse_line (finaltoken, argv)

(cmdtp=
find_cmd(argv[0])) //argv[0] = “tftp”

|

int len = &__u_boot_cmd_end - &__u_boot_cmd_start;

returnfind_cmd_tbl(cmd, &__u_boot_cmd_start, len);

|

for (cmdtp =table;cmdtp != table + table_len; cmdtp++) {

if(strncmp (cmd, cmdtp->name, len) == 0)

cmdtp_temp= cmdtp; /* abbreviated command

}

if(n_found == 1) {
/* exactly one match */

returncmdtp_temp;

}

}

//执行命令的处理方式

(cmdtp->cmd) (cmdtp, flag, argc, argv)

//倒计时被打断

for (;;) {

len = readline(CONFIG_SYS_PROMPT);

rc = run_command (lastcommand,flag);

}

=============================================================================================

nandflash初始化(lib_arm/board.c)

start_armboot

|

#if defined(CONFIG_CMD_NAND)

puts ("NAND: ");

nand_init();

| 1, 构建一个mtd_info对象

| 2,构建一个nand_chip对象<---------board_nand_init();

for (i = 0; i <CONFIG_SYS_MAX_NAND_DEVICE; i++) {

nand_init_chip(&nand_info[i], &nand_chip[i], base_address[i]);

| (drivers/mtd/nand/nand.c)

mtd->priv = nand;

nand->IO_ADDR_R =nand->IO_ADDR_W = (void __iomem*)base_addr;

board_nand_init(nand) //初始化nand_chip对象

|

nand->IO_ADDR_R = (void __iomem *)(NFDATA);

nand->IO_ADDR_W = (void __iomem *)(NFDATA);

nand->cmd_ctrl = s3c_nand_hwcontrol;

nand->dev_ready = s3c_nand_device_ready;

nand->scan_bbt = s3c_nand_scan_bbt;

nand->options = 0;

nand_scan(mtd, maxchips) //初始化mtd_info对象

(include\linux\mtd\nand.h)

struct nand_chip{

void __iomem *IO_ADDR_R;

void __iomem *IO_ADDR_W;

uint8_t (*read_byte)(structmtd_info *mtd);

u16 (*read_word)(structmtd_info *mtd);

void (*write_buf)(structmtd_info *mtd, const uint8_t *buf, int len);

void (*read_buf)(structmtd_info *mtd, uint8_t *buf, int len);

int (*verify_buf)(structmtd_info *mtd, const uint8_t *buf, int len);

void (*select_chip)(structmtd_info *mtd, int chip);

int (*block_bad)(structmtd_info *mtd, loff_t ofs, int getchip);

int (*block_markbad)(structmtd_info *mtd, loff_t ofs);

void (*cmd_ctrl)(structmtd_info *mtd, int dat,

unsigned int ctrl);

int (*dev_ready)(structmtd_info *mtd);

void (*cmdfunc)(struct mtd_info *mtd, unsignedcommand, int column, int page_addr);

int (*waitfunc)(structmtd_info *mtd, struct nand_chip *this);

void (*erase_cmd)(structmtd_info *mtd, int page);

int (*scan_bbt)(structmtd_info *mtd);

int (*errstat)(structmtd_info *mtd, struct nand_chip *this, int state, int status, int page);

int (*write_page)(struct mtd_info*mtd, struct nand_chip *chip,

const uint8_t *buf, int page, int cached, intraw);

int chip_delay;

unsignedint options;

int page_shift;

int phys_erase_shift;

int bbt_erase_shift;

int chip_shift;

int numchips;

uint64_t chipsize;

int pagemask;

int pagebuf;

int subpagesize;

uint8_t cellinfo;

int badblockpos;

int state;

uint8_t *oob_poi;

structnand_hw_control *controller;

structnand_ecclayout *ecclayout;

structnand_ecc_ctrl ecc;

structnand_buffers *buffers;

structnand_hw_control hwcontrol;

structmtd_oob_ops ops;

uint8_t *bbt;

structnand_bbt_descr *bbt_td;

structnand_bbt_descr *bbt_md;

structnand_bbt_descr *badblock_pattern;

void *priv;

};

(include\linux\mtd\mtd.h)

struct mtd_info{

int (*read) (struct mtd_info *mtd,loff_t from, size_t len, size_t *retlen, u_char *buf);

int (*write) (struct mtd_info*mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);

void *priv;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: