S3C2440移植uboot过程全解+移植记录精要.docx
- 文档编号:23425122
- 上传时间:2023-05-17
- 格式:DOCX
- 页数:71
- 大小:51.54KB
S3C2440移植uboot过程全解+移植记录精要.docx
《S3C2440移植uboot过程全解+移植记录精要.docx》由会员分享,可在线阅读,更多相关《S3C2440移植uboot过程全解+移植记录精要.docx(71页珍藏版)》请在冰豆网上搜索。
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
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- S3C2440 移植 uboot 过程 记录 精要