S3C2440移植uboot过程全解+移植记录精要.docx

上传人:b****9 文档编号:23425122 上传时间:2023-05-17 格式:DOCX 页数:71 大小:51.54KB
下载 相关 举报
S3C2440移植uboot过程全解+移植记录精要.docx_第1页
第1页 / 共71页
S3C2440移植uboot过程全解+移植记录精要.docx_第2页
第2页 / 共71页
S3C2440移植uboot过程全解+移植记录精要.docx_第3页
第3页 / 共71页
S3C2440移植uboot过程全解+移植记录精要.docx_第4页
第4页 / 共71页
S3C2440移植uboot过程全解+移植记录精要.docx_第5页
第5页 / 共71页
点击查看更多>>
下载资源
资源描述

S3C2440移植uboot过程全解+移植记录精要.docx

《S3C2440移植uboot过程全解+移植记录精要.docx》由会员分享,可在线阅读,更多相关《S3C2440移植uboot过程全解+移植记录精要.docx(71页珍藏版)》请在冰豆网上搜索。

S3C2440移植uboot过程全解+移植记录精要.docx

S3C2440移植uboot过程全解+移植记录精要

一、Uboot移植前的准备

1、修改makefile、配置文件

在配置文件之前,需要修改makeflie相关内容:

修改如下:

(1)修改编译器,这里我们的makefile已经设置为arm-linux-无需再修改,如下所示:

ifeq($(ARCH),arm)

CROSS_COMPILE=arm-linux-

Endif

(2)添加fl2440的配置项,如下所示:

fl2440_config:

unconfig

@$(MKCONFIG) $(@:

_config=) arm arm920t  fl2440 step s3c24x0

注意:

在添加的fl2440_config的第二行,必须以Table开头,不能有任何多余的符号,否则极易导致编译错误。

Uboot支持多种处理器和平台,在编译uboot之前需要对其进行配置,使其支持我们自己的开发平台。

在执行编译make之前,需要进行配置即makefl2440_config。

通过查看顶层目录的makeflie文件,通过以下语句:

MKCONFIG:

=$(SRCTREE)/mkconfig得出实际执行的命令为:

./mkconfigfl2440armarm920tfl2440steps3c24x0

执行完这句后,产生如下结果:

(1)开发板名称为fl2440;

(2)将include中的头文件连接到同平台相关的头文件中,这里的连接为:

asm->asm-arm

arch->arch-s3c24x0

proc->proc-armv

(3)创建顶层Makefile包含的文件inclued/config.mk,该文件内容如下

ARCH=arm

CPU=arm920t

BOARD=fl2440

VENDOR=step

SOC=s3c24x0

(4)创建开发板相关头文件include/config.h,该文件中包含了对开发板的相关配置,如下所示:

#include

从上面可以知道,在将uboot配置为适合自己的平台的时候,需要在路径/include/configs下添加配置头文件fl2440.h。

这里我们修改/include/configs/sbc2410x.h的文件名为fl2440.h,并在头文件中加入以下内容:

#defineCONFIG_FL24401/*onaFL2440Board*/

#defineCONFIG_S3C24401/*specificallyaSAMSUNGS3C2440SoC*/

打开fl2440.h,里面有两类宏,一类前缀应该是CONFIG_,这类宏用于选择CPU、SOC、系统时钟、选择设备驱动等;另一类前缀是CFG_,这类宏用于设置参数,例如malloc大小等。

2、创建board级文件

在Board目录中添加step目录,注意此step目录要和Makefile的fl2440_config下的step名字保持一致。

在step中建立fl2440目录,并将Board目录中的sbc2410x目录中的所有文件复制到fl2440目录中。

修改fl2440目录中sbc2410x.c为fl2440.c.

修改fl2440目录下的Makefile文件,将

COBJS:

= sbc2410x.o flash.o

修改为:

COBJS:

= fl2440.o flash.o

至此,配置过程完成。

配置的目的是通过设置相关参数、链接相关头文件,使得uboot适合我们的开发平台。

3、uboot编译、链接过程

Uboot的编译最终生成的u-boot.bin二进制文件,生成u-boot.bin的依赖关系由makefile指定,通过分析makefile可以得到两点:

(1)u-boot第一个执行的文件是start.s;

(2)如何链接各个文件生成的.o文件,由/board/step/fls2240中的U-boot.lds和config.mk决定。

U-Boot的编译流程为:

首先编译cpu/$(CPU)/start.S,对于不同的CPU,还可能编译cpu/$(CPU)下的其他文件。

然后,对于平台/开发板相关的每个目录、每个通用目录都使用它们各自的Makefile生成相应的库。

将前面两步生成的.o、.a文件按照board/$(BOARDDIR)/config.mk文件中指定的代码段起始地址、board/$(BOARDDIR)/U-Boot.lds连接脚本进行连接得到ELF格式的U-Boot,后面Makefile还会将它转换为二进制格式、S-Record格式。

这部分具体可以参考《嵌入式linux应用开发完全手册》第十五章内容15.2.3。

到此修改构成一个段落,此处的修改只是构建了fl2440开发板的框架,其核心的东西还是sbc2410x的,下文会进行深层次的修改。

不过在这里,要首先,测试配置和编译一下,检测我们的框架是否搭建合理。

# make fl2440_config

Configuring for FL2440 board...

# make

如果没有错误,则执行make distclean 和make clean将编译的文件清空。

如果有错误,则查看上面的步骤,是否处理正确

二、Uboot第一阶段分析

1、uboot第一阶段作用

Uboot第一阶段主要完成硬件设备初始化、为加载Bootloader的第二阶段代码准备RAM空间、代码重定向、为调用C语言准备好堆栈空间。

硬件设备初始化依次完成如下设置:

将CPU的工作模式设为管理模式(svc),关闭WATCHDOG,设置FCLK、HCLK、PCLK的比例(即设置CLKDIVN寄存器),关闭MMU、CACHE,代码都在cpu/arm920t/start.S中。

所谓准备RAM空间,就是初始化内存芯片,使它可用。

对于S3C2410/S3C2440,通过在start.S中调用lowlevel_init函数来设置存储控制器,使得外接的SDRAM可用,代码在board/step/fl2440/lowlevel_init.S中。

代码重定向是将bootloader代码从nandflash中读取出来放到sdram的指定地址中,这里指定的地址为0x33f80000。

准备堆栈空间实际就是设置全局参数空间、malloc空间、指定堆栈指针,清空bss段等内容

2、第一阶段代码分析

.globl_start//声明全局变量_start,就是相当于C语言中的Extern

_start:

breset

_start后面加上一个冒号’:

’,表示其是一个标号Label,类似于C语言goto后面的标号。

而同时,_start的值,也就是这个代码的位置了,此处即为代码的最开始,相对的0的位置。

而此处最开始的相对的0位置,在程序开始运行的时候,如果是从NorFlash启动,那么其地址是0,_stat=0如果是重新relocate代码之后,就是我们定义的值了,即,在board\step\f24440\config.mk中的:

TEXT_BASE=0x33D00000表示是代码段的基地址,即_start=TEXT_BASE=0x33D00000.而_start标号后面的:

breset

就是跳转到对应的标号为reset的位置,即复位后要执行的第一条指令。

ldrpc,_undefined_instruction

ldrpc,_software_interrupt

ldrpc,_prefetch_abort

ldrpc,_data_abort

ldrpc,_not_used

ldrpc,_irq

ldrpc,_fiq

这些都是跳转向量表,和芯片体系结构有关,以第一个_undefined_instruction为例,就是将地址为_undefined_instruction中的一个word的值,赋值给pc

_undefined_instruction:

.wordundefined_instruction

_software_interrupt:

.wordsoftware_interrupt

_prefetch_abort:

.wordprefetch_abort

_data_abort:

.worddata_abort

_not_used:

.wordnot_used

_irq:

.wordirq

_fiq:

.wordfiq

.word.wordexpr{,expr}…分配一段字内存单元,并用expr初始化字内存单元(32bit)。

所以上面的含义,以_undefined_instruction为例,就是,此处分配了一个word=32bit=4字节的地址空间,里面存放的值是undefined_instruction。

而此处_undefined_instruction也就是该地址空间的地址了。

undefined_instruction也是一个标号,即一个地址值,对应着就是在发生“未定义指令”的时候,系统所要去执行的代码。

其他几个对应的“软件中断”,“预取指错误”,“数据错误”,“未定义”,“(普通)中断”,“快速中断”,也是同样的做法,跳转到对应的位置执行对应的代码。

所以:

ldrpc,标号1

......

标号1:

.word标号2

......

标号2:

......(具体要执行的代码)

的意思就是,将地址为标号1中内容载入到pc,而地址为标号1中的内容,正好装的是标号2。

用C语言表达其实很简单:

PC=*(标号1)=标号2

对PC赋值,即是实现代码跳转,所以整个这段汇编代码的意思就是:

跳转到标号2的位置,执行对应的代码。

.balignl16,0xdeadbeef

上面的意思是,接下来的代码,都要16字节对齐,不足之处,用0xdeadbeef填充

_TEXT_BASE:

.wordTEXT_BASE

此处和上面的类似,_TEXT_BASE是一个标号地址,此地址中是一个word类型的变量,变量名是TEXT_BASE,此值见名知意,是text的base,即代码的基地址,此处TEXT_BASE为0x33f80000

.globl_armboot_start

_armboot_start:

.word_start

此含义可用C语言表示为:

*(_armboot_start)=_start

.globl_bss_start

_bss_start:

.word__bss_start

.globl_bss_end

_bss_end:

.word_end

_bss_start和_bss_end都只是两个标号,对应着此处的地址。

而两个地址里面分别存放的值是__bss_start和_end,这两个的值,根据注释所说,是定义在开发板相关的链接脚本里面的,在链接脚本中可以找到__bss_start和_end的定义:

__bss_start=.;

.bss:

{*(.bss)}

_end=.;

#ifdefCONFIG_USE_IRQ

/*IRQstackmemory(calculatedatrun-time)*/

.globlIRQ_STACK_START

IRQ_STACK_START:

.word0x0badc0de

/*IRQstackmemory(calculatedatrun-time)*/

.globlFIQ_STACK_START

FIQ_STACK_START:

.word0x0badc0de

#endif

代码真正的开始处:

reset:

/*

*setthecputoSVC32mode

*/

a、硬件初始化

mrsr0,cpsr

bicr0,r0,#0x1f

orrr0,r0,#0xd3

msrcpsr,r0设置CPU为SVC模式

定义寄存器地址:

#ifdefined(CONFIG_S3C2400)//S3C2400寄存器地址

#definepWTCON0x15300000

#defineINTMSK0x14400008/*Interupt-Controllerbaseaddresses*/

#defineCLKDIVN0x14800014/*clockdivisorregister*/

#elifdefined(CONFIG_S3C2410)//S3C2410和2440相同的寄存器地址

#definepWTCON0x53000000

#defineINTMSK0x4A000008/*Interupt-Controllerbaseaddresses*/

#defineINTSUBMSK0x4A00001C

#defineCLKDIVN0x4C000014/*clockdivisorregister*/

#endif

#ifdefined(CONFIG_S3C2440)

#defineCONFIG_UBOOT_SIZE0x60000//UBOOT大小的宏定义

#defineMPLLCON0x4C000004//S3C2440时钟配置

#defineUPLLCON0x4C000008

#defineCLKDIV_VAL5

#defineM_MDIV127

#defineM_PDIV2

#defineM_SDIV1

#defineU_MDIV56

#defineU_PDIV2

#defineU_SDIV2

#endif

#ifdefined(CONFIG_S3C2400)||defined(CONFIG_S3C2410)

ldrr0,=pWTCON

movr1,#0x0

strr1,[r0]//关闭看门狗

movr1,#0xffffffff

ldrr0,=INTMSK

strr1,[r0]//关闭所有中断

#ifdefined(CONFIG_S3C2440)

ldrr1,=0x7fff

ldrr0,=INTSUBMSK

strr1,[r0]//关闭所有中断

#endif

#endif

#ifdefined(CONFIG_S3C2440)

//配置S3C2440的PLL控制器,主要包括CLKDIVN,设置FCLK、HCLK、PCLK的比值,这里设置为1:

4:

8

ldrr0,=CLKDIVN

ldrr1,=CLKDIV_VAL

strr1,[r0]

//mrc和mcr是通用寄存器同协处理器寄存器进行数据交换的指令,关于这两个指令的具体使用参考总结文献,此处访问协处理器的目的是设置总线模式为异步总线模式。

mrcp15,0,r0,c1,c0,0

orrr0,r0,#0xc0000000

mcrp15,0,r0,c1,c0,0

//设置UPLLCON寄存器,设置完UPLL后需要一段延迟时间,大约为7个时钟

ldrr0,=UPLLCON

ldrr1,=((U_MDIV<<12)+(U_PDIV<<4)+U_SDIV)

strr1,[r0]

nop

nop

nop

nop

nop

nop

nop

//设置MPLLCON寄存器,

ldrr0,=MPLLCON

ldrr1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV)

strr1,[r0]

#endif

#ifndefCONFIG_SKIP_LOWLEVEL_INIT

blcpu_init_crit

#endif

cpu_init_crit函数的主要作用是关闭cache、关闭mmu以及调用lowlevel_init初始化BANK0~7的位宽,速度,刷新频率等重要参数。

#ifndefCONFIG_SKIP_LOWLEVEL_INIT

cpu_init_crit:

movr0,#0

mcrp15,0,r0,c7,c7,0

mcrp15,0,r0,c8,c7,0

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

//关闭cache和mmu,在arm中cache是cpu的内部缓存,MMU实现虚拟地址与物理地址的转换。

cache在cpu中用来存放常用的数据和指令,cache开启的情况下,cpu首先在cache中寻找需要的指令或数据,cache中没有再从RAM获取,uboot启动的时候不管cache是否初始化都不会有cpu需要的数据,uboot用来实现简单的初始化和引导操作,关闭cache优化uboot性能。

C语言不能控制cache的开关,但关键字volatile能够避免优化,所谓避免优化实际上就是编译器告诉cpu在获取这个变量时不要从cache中读取,因为这个变量是随时可变的,cache不能实时的反应这些变量的值,cpu每次读取都直接从变量实际地址读取。

同样关闭MMU,在uboot刚启动的时候避免虚拟地址无物理地址的转换。

movip,lr//保存lr的值,以便返回到主函数中

bllowlevel_init//跳到lowlevel_init中执行

movlr,ip

movpc,lr//返回主函数

b、内存初始化

lowlevel_init的作用是通过配置BANK0~7的寄存器,实现对板级外部设备的控制。

这里主要配置了SDRAM(BANK6)和以太网控制器DM9000(BANK4)的相关参数

#defineBWSCON0x48000000//BANK寄存器基地址

//通过宏设置参数

/*BWSCON*/

#defineDW8(0x0)//位宽参数

#defineDW16(0x1)

#defineDW32(0x2)

#defineWAIT(0x1<<2)

#defineUBLB(0x1<<3)

#defineB1_BWSCON(DW16)//给每个BANK设置位宽宏值

#defineB2_BWSCON(DW16)

#defineB3_BWSCON(DW16)

#defineB4_BWSCON(DW16)

#defineB5_BWSCON(DW16)

#defineB6_BWSCON(DW32)

#defineB7_BWSCON(DW32)

#defineB0_Tacs0x0//BANKCON0时序参数

#defineB0_Tcos0x1

#defineB0_Tacc0x7

#defineB0_Tcoh0x1

#defineB0_Tah0x0

#defineB0_Tacp0x0

#defineB0_PMC0x0

#defineB1_Tacs0x0//BANKCON1时序参数

#defineB1_Tcos0x0

#defineB1_Tacc0x7

#defineB1_Tcoh0x0

#defineB1_Tah0x0

#defineB1_Tacp0x0

#defineB1_PMC0x0

#defineB2_Tacs0x0//BANKCON2时序参数

#defineB2_Tcos0x0

#defineB2_Tacc0x7

#defineB2_Tcoh0x0

#defineB2_Tah0x0

#defineB2_Tacp0x0

#defineB2_PMC0x0

#defineB3_Tacs0x1//BANKCON3时序参数

#defineB3_Tcos0x1

#defineB3_Tacc0x6

#defineB3_Tcoh0x1

#defineB3_Tah0x1

#defineB3_Tacp0x0

#defineB3_PMC0x0

#defineB4_Tacs0x0//BANKCON4时序参数

#defineB4_Tcos0x1

#defineB4_Tacc0x7

#defineB4_Tcoh0x1

#defineB4_Tah0x0

#defineB4_Tacp0x0

#defineB4_PMC0x0

#defineB5_Tacs0x1//BANKCON5时序参数

#defineB5_Tcos0x1

#defineB5_Tacc0x6

#defineB5_Tcoh0x1

#defineB5_Tah0x1

#defineB5_Tacp0x0

#defineB5_PMC0x0

#defineB6_MT0x3/*SDRAM*///BANKCON6时序、地址参数

#defineB6_Trcd0x0

#defineB6_SCAN0x1/*9bit*/

#defineB7_MT0x3/*SDRAM*///BANKCON7时序、地址参数

#defineB7_Trcd0x0/*2clk*/

#defineB7_SCAN0x1/*9bit*/

/*REFRESHparameter*/

#defineREFEN0x1/*Refreshenable*///SDR特有的时序参数

#defineTREFMD0x0/*CBR(CASbeforeRAS)/Autorefresh*/

#defineTrp0x1/*3clk*/

#defineTrc0x1/*5clk*/

#defineTchr0x2/*3clk*/

#defineREFCNT0x04f4

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

_TEXT_BASE:

.wordTEXT_BASE

.globllowlevel_init

lowlevel_init:

/*memorycontrolconfiguration*/

/*maker0relativethecurrentlocationsothatit*/

/*readsSMRDAT

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

当前位置:首页 > 经管营销 > 经济市场

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

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