Uboot源码.docx

上传人:b****1 文档编号:29123389 上传时间:2023-07-20 格式:DOCX 页数:38 大小:27.18KB
下载 相关 举报
Uboot源码.docx_第1页
第1页 / 共38页
Uboot源码.docx_第2页
第2页 / 共38页
Uboot源码.docx_第3页
第3页 / 共38页
Uboot源码.docx_第4页
第4页 / 共38页
Uboot源码.docx_第5页
第5页 / 共38页
点击查看更多>>
下载资源
资源描述

Uboot源码.docx

《Uboot源码.docx》由会员分享,可在线阅读,更多相关《Uboot源码.docx(38页珍藏版)》请在冰豆网上搜索。

Uboot源码.docx

Uboot源码

uboot源码阅读

这篇文章属于转载

cpu/arm920t/start.S

在开始处首先定义了一个全局的标签,

.globl_start

这个是整个uboot程序的入口,可在链接脚本board/s3c2410/u-boot.lds中找到。

这个标签所指的地址处就是一跳转指令

_start:

breset

开始复位。

reset:

/*

*setthecputoSVC32mode

*/

mrsr0,cpsr

bicr0,r0,#0x1f

/*disableIRQandFIQ,ARMinstructset,supervisormode.addedbyBoySKung*/

orrr0,r0,#0xd3

msrcpsr,r0

首先将cpu设置为supervisor模式。

通过设置cpsr的低5位为10011实现,并禁止IRQ、FIQ。

即cpsr的第七第六位设置为11.

接着关闭看门狗定时器

ldrr0,=pWTCON

movr1,#0x0

strr1,[r0]

将看门狗定时器控制寄存器置0。

ldrr0,=CLKDIVN

movr1,#3

strr1,[r0]

设置FCLK:

HCLK:

PCLK为1:

2:

4,通过设置CLKDIVN控制寄存器的HDIVN、PDIVN值实现不同的

比例

00(1:

1:

1)

01(1:

1:

2)

10(1:

2:

2)

11(1:

2:

4)

这些然后开初始化cpu

cpu_init_crit:

/*

*flushv4I/Dcaches

*/

movr0,#0

mcrp15,0,r0,c7,c7,0/*flushv3/v4cache*/

mcrp15,0,r0,c8,c7,0/*flushv4TLB*/

首先关闭ICache和DCache.

/*

*disableMMUstuffandcaches

*/

mrcp15,0,r0,c1,c0,0

bicr0,r0,#0x00002300@clearbits13,9:

8(--V---RS)

bicr0,r0,#0x00000087@clearbits7,2:

0(B----CAM)

orrr0,r0,#0x00000002@setbit2(A)Align

orrr0,r0,#0x00001000@setbit12(I)I-Cache

mcrp15,0,r0,c1,c0,0

关闭MMU,数据存储格式为小端。

开启数据地址对齐错误检测,使能ICACHE。

/*

*beforerelocating,wehavetosetupRAMtiming

*becausememorytimingisboard-dependend,youwill

*findamemsetup.Sinyourboarddirectory.

*/

movip,lr

blmemsetup

movlr,ip

movpc,lr

还要对内存时序进行设置,因为内存时序是依赖于开发板的。

Cpu初始化结束后,开始初始化串口uart

@InitializeUART

@

@r0=numberofUARTport

InitUART:

ldrr1,=0x

movr2,#0x0

strr2,[r1,#0x8]

strr2,[r1,#0xc]

movr2,#0x3

strr2,[r1,#0x0]

ldrr2,=0x245

strr2,[r1,#0x4]

/*=PCLK=202.8/4=50.7whenFCLKat202.8*/

#defineUART_BRD((/(115200*16))-1)

movr2,#UART_BRD

strr2,[r1,#0x28]

这里主要对uart的一些控制寄存器进行了设置,并设置了串口的波特率

movr3,#100

movr2,#0x0

1:

subr3,r3,#0x1

tstr2,r3

bne1b

movpc,lr

这里是一段延时,具体起什么作用还不清楚。

这些初始化都结束后开始代码重定位

relocate:

/*relocateU-BoottoRAM*/

adrr0,_start/*r0<-currentpositionofcode*/

ldrr1,_TEXT_BASE/*testifwerunfromflashorRAM*/

cmpr0,r1/*don'trelocduringdebug*/

beqstack_setup

ldrr2,_armboot_start

ldrr3,_bss_start

subr2,r3,r2/*r2<-sizeofarmboot*/

addr2,r0,r2/*r2<-sourceendaddress*/

copy_loop:

ldmiar0!

{r3-r10}/*copyfromsourceaddress[r0]*/

stmiar1!

{r3-r10}/*copytotargetaddress[r1]*/

cmpr0,r2/*untilsourceendaddreee[r2]*/

blecopy_loop

重定位时,首先检查当前是不是在ram中运行,若是则不需重定位

紧接着设置堆栈

stack_setup:

@ldrr1,=0x

@ldrr0,[r1]

@blPrintHexWord

/*enteransynchronous,whencpuat202.8MHZ,itmustintoasynchronousmode*/

mrcp15,0,r1,c1,c0,0@readctrlregister

orrr1,r1,#0xc0000000@Asynchronous

mcrp15,0,r1,c1,c0,0@writectrlregister

ldrr0,_TEXT_BASE/*upper128KiB:

relocateduboot*/

subr0,r0,#CFG_MALLOC_LEN/*mallocarea*/

subr0,r0,#CFG_GBL_DATA_SIZE/*bdinfo*/

#ifdefCONFIG_USE_IRQ

subr0,r0,#(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)

#endif

subsp,r0,#12/*leave3wordsforabort-stack*/

清除bss段

clear_bss:

ldrr0,_bss_start/*findstartofbsssegment*/

addr0,r0,#4/*startatfirstbyteofbss*/

ldrr1,_bss_end/*stophere*/

movr2,#0x00000000/*clear*/

clbss_l:

strr2,[r0]/*clearloop...*/

addr0,r0,#4

cmpr0,r1

bneclbss_l

就是将bss段全部置0

最后

ldrpc,_start_armboot

开始进入c的世界,uboot启动的stage2

Lib_arm/board.c

当第一阶段的汇编部分执行完,跳到stage2时,开始执行c函数start_armboot

开头首先声明一个全局指针变量DECLARE_GLOBAL_DATA_PTR;这个宏定义在头文件

include/asm-arm/global_data.h中

#defineDECLARE_GLOBAL_DATA_PTRregistervolatilegd_t*gdasm("r8")

typedefstructglobal_data{

bd_t*bd;

unsignedlongflags;

unsignedlongbaudrate;

unsignedlonghave_console;/*serial_init()wascalled*/

unsignedlongreloc_off;/*RelocationOffset*/

unsignedlongenv_addr;/*AddressofEnvironmentstruct*/

unsignedlongenv_valid;/*ChecksumofEnvironmentvalid?

*/

unsignedlongfb_base;/*baseaddressofframebuffer*/

#ifdefCONFIG_VFD

unsignedcharvfd_type;/*displaytype*/

#endif

#if0

unsignedlongcpu_clk;/*CPUclockinHz!

*/

unsignedlongbus_clk;

unsignedlongram_size;/*RAMsize*/

unsignedlongreset_status;/*resetstatusregisteratboot*/

#endif

void**jt;/*jumptable*/

}gd_t;

在这个结构中存放一些全局数据。

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

这行是对指针的初始化。

接下来通过一个循环,执行初始化序列中的一些函数

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

if((*init_fnc_ptr)()!

=0){

hang();

}

}

初始化序列的定义如下:

init_fnc_t*init_sequence[]={

cpu_init,//初始化cpu,主要是设置FIQ和IRQ的堆栈起始地址

board_init,//开发板初始化,设置电源、时钟、I/O端口及全能I/DCache

interrupt_init,//中断初始化,设置PWM时钟

env_init,//环境变量初始化,检测环境变量是否有效,并初始化相全局变

init_baudrate,//初始化波特率,设置板子通信时的波特率

serial_init,//初始化串口,设置串口和通信时数据结构,包括起始/停止位等

console_init_f,//控制台初始化,将控制台设置为silent模式

display_banner,//打印板子相关信息

dram_init,//内存初始化,设置内存的起始地址和大小

display_dram_config,//显示内存配置信息

#ifdefined(CONFIG_VCMA9)

checkboard,

#endif

NULL,

};

这些初始化都完成后开始初始化flash

unsignedlongflash_init(void)

{

unsignedlongsize_b0;

inti;

/*Init:

noFLASHesknown*/

for(i=0;i

flash_info[i].flash_id=FLASH_UNKNOWN;

}

/*StaticFLASHBankconfigurationhere-FIXMEXXX*/

#if1

debug("\n##Getflashbank1size@0x%08x\n",CFG_FLASH_BASE);

#endif

//根据flash的基地址CFG_FLASH_BASE,获得flash的大小,

size_b0=flash_get_size((vu_short*)CFG_FLASH_BASE,&flash_info[0]);

if(flash_info[0].flash_id==FLASH_UNKNOWN){

printf("##UnknownFLASHonBank0:

"

"ID0x%lx,Size=0x%08lx=%ldMB\n",

flash_info[0].flash_id,

size_b0,size_b0<<20);

}

//获得并保存flash各块的起始地址

flash_get_offsets(CFG_FLASH_BASE,&flash_info[0]);

//保存flash的大小

flash_info[0].size=size_b0;

//下面是根据配置,对flash中相应块进行保护,以免数据丢失。

#ifCFG_MONITOR_BASE>=CFG_FLASH_BASE

/*monitorprotectionONbydefault*/

flash_protect(FLAG_PROTECT_SET,

CFG_MONITOR_BASE,

CFG_MONITOR_BASE+monitor_flash_len-1,

&flash_info[0]);

#endif

#ifdefCFG_ENV_IS_IN_FLASH

/*ENVprotectionONbydefault*/

flash_protect(FLAG_PROTECT_SET,

CFG_ENV_ADDR,

CFG_ENV_ADDR+CFG_ENV_SECT_SIZE-1,

&flash_info[0]);

#endif

returnsize_b0;

}

然后是初始内存堆

static

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

}

之后要进行环境变量重定位,把环境变量放到内存当中

env_relocate();

还要设置网卡的ip地址和mac地址

/*IPAddress*/

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

/*MACAddress*/

{

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;

}

}

设备初始化

intdevices_init(void)

{

char*s;

#ifndefCONFIG_ARM/*alreadyrelocatedforcurrentARMimplementation*/

DECLARE_GLOBAL_DATA_PTR;

ulongrelocation_offset=gd->reloc_off;

inti;

/*relocatedevicenamepointers*/

for(i=0;i<(sizeof(stdio_names)/sizeof(char*));++i){

stdio_names[i]=(char*)(((ulong)stdio_names[i])+

relocation_offset);

}

#endif

/*Initializethelist*/

devlist=ListCreate(sizeof(device_t));

if(devlist==NULL){

eputs("Cannotinitializethelistofdevices!

\n");

return-1;

}

#ifdefined(CONFIG_HARD_I2C)||defined(CONFIG_SOFT_I2C)

i2c_init(CFG_I2C_SPEED,CFG_I2C_SLAVE);

#endif

#ifdefCONFIG_LCD

drv_lcd_init();

#endif

#ifdefined(CONFIG_VIDEO)||defined(CONFIG_CFB_CONSOLE)

if((s=getenv("sm501mode"))!

=NULL)

{

sm501mode=simple_strtoul(s,NULL,10);

if(!

(sm501mode>=1&&sm501mode<=13))

{

printf("sm501modeerror,setsm501modeto1!

\n");

sm501mode=1;

}

}

if((s=getenv("sm501bpp"))!

=NULL)

{

sm501bpp=simple_strtoul(s,NULL,10);

if(sm501mode!

=16)

{

printf("sm501bpperror,only16bppvalid,setsm501bppto16!

\n");

sm501bpp=16;

}

}

drv_video_init();

#endif

#ifdefCONFIG_KEYBOARD

//drv_keyboard_init();

#endif

#ifdefCONFIG_LOGBUFFER

drv_logbuff_init();

#endif

drv_system_init();

return(0);

}

这里要创建一个设备列表,把一些设备放入这个表中,初始化i2c总线,设置sm501显卡,

初始化视频设备,初始化并注册个别系统设备。

voidjumptable_init(void)

{

DECLARE_GLOBAL_DATA_PTR;

inti;

gd->jt=(void**)malloc(XF_MAX*sizeof(void*));

for(i=0;i

gd->jt[i]=(void*)dummy;

gd->jt[XF_get_version]=(void*)get_version;

gd->jt[XF_malloc]=(void*)malloc;

gd->jt[XF_free]=(void*)free;

gd->jt[XF_get_timer]=(void*)get_timer;

gd->jt[XF_udelay]=(void*)udelay;

#ifdefined(CONFIG_I386)||defined(CONFIG_PPC)

gd->jt[XF_install_hdlr]=(void*)irq_install_handler;

gd->jt[XF_free_hdlr]=(void*)irq_free_handler;

#endif/*I386||PPC*/

#if(CONFIG_COMMANDS&CFG_CMD_I2C)

gd->jt[XF_i2c_write]=(void*)i2c_write;

gd->jt[XF_i2c_read]=(void*)i2c_read;

#endif/*CFG_CMD_I2C*/

}

初始化跳转表,主要是保存了一些系统函数的指针。

便于以后引用

然后对控制台进行全面的初始化

console_init_r();/*fullyinitconsoleasadevice*/

主要是初始化控制台输入输出设备

接下来开中断

/*enableexceptions*/

enable_interrupts();

初始化网卡设备等

/*Performnetworkcardinitialisationifnecessary*/

#ifdefCONFIG_DRIVER_DM9000

DM9000_get_enetaddr(gd->bd->bi_enetaddr);

#endif

最后进入主循环

/*main_loop()canreturntoretryautoboot,ifsojustrunitagain.*/

for(;;){

main_loop();

}

在这个循环中,将检测是自动启动还是命令行起动。

起动后,uboot的stage2也就结束了

Uboot中的每一个命令都由一个宏进行声明,这宏在文件include/command.h中定义

#defineU_BOOT_CMD(name,maxargs,rep,cmd,usage,help)\

cmd_tbl_t__u_boot_cmd_##nameStruct_Section={#name,maxargs,rep,cmd,usage,help}

如i2c设备操作中的某个命令的声明如下

U_BOOT_CMD(

imd,4,1,do_i2c_md,\

"imd-i2cmemorydisplay\n",\

"chipaddress[.0,.1,.2][#ofobjects]\n-i2cmemorydisplay\n"\

);

这个声明里初始化了cmd_tbl_t结构

structcmd_tbl_s{

char*name;/*CommandName*/

intmaxargs;/*maximumnumber

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案 > 营销活动策划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1