vivi bootloader.docx
- 文档编号:12215001
- 上传时间:2023-04-17
- 格式:DOCX
- 页数:37
- 大小:37.94KB
vivi bootloader.docx
《vivi bootloader.docx》由会员分享,可在线阅读,更多相关《vivi bootloader.docx(37页珍藏版)》请在冰豆网上搜索。
vivibootloader
vivibootloader的实现
参考资料:
1. 嵌入式系统BootLoader技术内幕,詹荣开(zhanrk@)
2. GettingstartedwithVIVI, JanhoonLyu,nandy@
3. 嵌入式设备上的Linux系统开发,A.Santhanametc.
4. Linuxsystemdevelopmentonanembeddeddevice,A.Santhanam
5. vivi有关资料
6. smdk2410的硬件和软件/linux相关资料search 2410
说明:
本文文字结构照抄”嵌入式系统BootLoader技术内幕,詹荣开(zhanrk@)”一文,以vivi中head.S作为stage1,main()作为stage2,解释了VIVIforSMDK2410(basedonS3C2410)开发系统的bootloader的实现。
将原文放在这里是为了方便读者。
注意,VIVI的实现并非完全跟原文一致。
多谢原文作者詹大侠的详细解释。
附录有一节__SETUP在kernel的作用来自jeppeter(member)fromhttp:
//
文中对MTDsubsystemlinux没作解释。
Google“MTDlinuxsubsystem文件系统JFSS2”可以获得足够的解释。
Chapter1Bootloader基本结构
由于BootLoader的实现依赖于CPU的体系结构,因此大多数BootLoader都分为stage1和stage2两大部分。
依赖于CPU体系结构的代码,比如设备初始化代码等,通常都放在stage1中,而且通常都用汇编语言来实现,以达到短小精悍的目的。
而stage2则通常用C语言来实现,这样可以实现给复杂的功能,而且代码会具有更好的可读性和可移植性。
BootLoader的stage1通常包括以下步骤(以执行的先后顺序):
硬件设备初始化。
为加载BootLoader的stage2准备RAM空间。
拷贝BootLoader的stage2到RAM空间中。
设置好堆栈。
跳转到stage2的C入口点。
BootLoader的stage2通常包括以下步骤(以执行的先后顺序):
初始化本阶段要使用到的硬件设备。
检测系统内存映射(memorymap)。
将kernel映像和根文件系统映像从flash上读到RAM空间中。
为内核设置启动参数。
调用内核。
1.1BootLoader的stage1
1.1.1基本的硬件初始化
这是BootLoader一开始就执行的操作,其目的是为stage2的执行以及随后的kernel的执行准备好一些基本的硬件环境。
它通常包括以下步骤(以执行的先后顺序):
1.屏蔽所有的中断。
为中断提供服务通常是OS设备驱动程序的责任,因此在BootLoader的执行全过程中可以不必响应任何中断。
中断屏蔽可以通过写CPU的中断屏蔽寄存器或状态寄存器(比如ARM的CPSR寄存器)来完成。
2.设置CPU的速度和时钟频率。
3.RAM初始化。
包括正确地设置系统的内存控制器的功能寄存器以及各内存库控制寄存器等。
4.初始化LED。
典型地,通过GPIO来驱动LED,其目的是表明系统的状态是OK还是Error。
如果板子上没有LED,那么也可以通过初始化UART向串口打印BootLoader的Logo字符信息来完成这一点。
5.关闭CPU内部指令/数据cache。
VIVI在第一阶段完成以下任务
Disablewatchdogtimer; disableallinterrupts ;
initialisesystemclocks;initialisethestaticmemory AllLEDon
setGPIOforUART InitializeUART0 ;
copy_myselftoram; jumptoram
getreadtocallCfunctions setupstackpointer
callmain
1.1.2为加载stage2准备RAM空间
为了获得更快的执行速度,通常把stage2加载到RAM空间中来执行,因此必须为加载BootLoader的stage2准备好一段可用的RAM空间范围。
由于stage2通常是C语言执行代码,因此在考虑空间大小时,除了stage2可执行映象的大小外,还必须把堆栈空间也考虑进来。
此外,空间大小最好是memorypage大小(通常是4KB)的倍数。
一般而言,1M的RAM空间已经足够了。
具体的地址范围可以任意安排,比如blob就将它的stage2可执行映像安排到从系统RAM起始地址0xc0200000开始的1M空间内执行。
但是,将stage2安排到整个RAM空间的最顶1MB(也即(RamEnd-1MB)-RamEnd)是一种值得推荐的方法。
为了后面的叙述方便,这里把所安排的RAM空间范围的大小记为:
stage2_size(字节),把起始地址和终止地址分别记为:
stage2_start和stage2_end(这两个地址均以4字节边界对齐)。
因此:
stage2_end=stage2_start+stage2_size
另外,还必须确保所安排的地址范围的的确确是可读写的RAM空间,因此,必须对你所安排的地址范围进行测试。
具体的测试方法可以采用类似于blob的方法,也即:
以memorypage为被测试单位,测试每个memorypage开始的两个字是否是可读写的。
为了后面叙述的方便,我们记这个检测算法为:
test_mempage,其具体步骤如下:
1.先保存memorypage一开始两个字的内容。
2.向这两个字中写入任意的数字。
比如:
向第一个字写入0x55,第2个字写入0xaa。
3.然后,立即将这两个字的内容读回。
显然,我们读到的内容应该分别是0x55和0xaa。
如果不是,则说明这个memorypage所占据的地址范围不是一段有效的RAM空间。
4.再向这两个字中写入任意的数字。
比如:
向第一个字写入0xaa,第2个字中写入0x55。
5.然后,立即将这两个字的内容立即读回。
显然,我们读到的内容应该分别是0xaa和0x55。
如果不是,则说明这个memorypage所占据的地址范围不是一段有效的RAM空间。
6.恢复这两个字的原始内容。
测试完毕。
为了得到一段干净的RAM空间范围,我们也可以将所安排的RAM空间范围进行清零操作。
1.1.3拷贝stage2到RAM中
拷贝时要确定两点:
(1)stage2的可执行映象在固态存储设备的存放起始地址和终止地址;
(2)RAM空间的起始地址。
1.1.4设置堆栈指针sp
堆栈指针的设置是为了执行C语言代码作好准备。
通常我们可以把sp的值设置为(stage2_end-4),也即在1.1.2节所安排的那个1MB的RAM空间的最顶端(堆栈向下生长)。
此外,在设置堆栈指针sp之前,也可以关闭led灯,以提示用户我们准备跳转到stage2。
经过上述这些执行步骤后,系统的物理内存布局应该如下图2所示。
1.1.5跳转到stage2的C入口点
在上述一切都就绪后,就可以跳转到BootLoader的stage2去执行了。
比如,在ARM系统中,这可以通过修改PC寄存器为合适的地址来实现。
head.S负责完成硬件初始化操作,具体分析见源码注释,汇编差不多忘光了,下面注释中有关汇编的东西多些。
其中"linkage.h"
#defineSYMBOL_NAME_STR(X)#X
#defineSYMBOL_NAME(X)X
#ifdef__STDC__
#defineSYMBOL_NAME_LABEL(X)X##:
#else
#defineSYMBOL_NAME_LABEL(X)X/**/:
#endif
#define__ALIGN.align0
#define__ALIGN_STR".align0"
#ifdef__ASSEMBLY__
#defineALIGN__ALIGN
#defineALIGN_STR__ALIGN_STR
#defineENTRY(name)\
.globlSYMBOL_NAME(name);\
ALIGN;\
SYMBOL_NAME_LABEL(name)
#endif
其中"machine.h"包括了
smdk2410.h(有关开发板的配置),
包括memorymap,Porocessormemorymap,FLASH,ROM,DRAM的物理地址和在VIVI中用的虚拟地址(?
),Architecturemagicandmachinetype,UART,CPU,DRAM的初始化参数等
smdk2410.h进一步包括s3c2410.h,有关CPU的设置,DefinitionofconstantsrelatedtotheS3C2410microprocessor(basedonARM920T).
/*
*vivi/arch/s3c2410/head.S:
* Initialisehardware
*
*Copyright(C)2001MIZIResearch,Inc.
*
*Thisprogramisfreesoftware;youcanredistributeitand/ormodify
*itunderthetermsoftheGNUGeneralPublicLicenseaspublishedby
*theFreeSoftwareFoundation;eitherversion2oftheLicense,or
*(atyouroption)anylaterversion.
*
*Thisprogramisdistributedinthehopethatitwillbeuseful,
*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof
*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE. Seethe
*GNUGeneralPublicLicenseformoredetails.
*
*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense
*alongwiththisprogram;ifnot,writetotheFreeSoftware
*Foundation,Inc.,59TemplePlace,Suite330,Boston,MA 02111-1307 USA
*
*
*Author:
JanghoonLyu
*Date :
$Date:
2003/02/2610:
38:
11$
*
*$Revision:
1.18$
*
*
*History:
*
*2002-05-14:
JanghoonLyu
* -Initialcode
*
*/
autoconf.h空的#include"config.h" //
#include"linkage.h" //定义
#include"machine.h"
@Startofexecutablecode
ENTRY(_start) //入口点
ENTRY(ResetEntryPoint)
@
@Exceptionvectortable(physicaladdress=0x00000000)
@ //异常向量表物理地址0x0000000
@0x00:
Reset //最基本操作:
复位 B是最简单的分支。
一旦遇到一个B指令,ARM处理器将立即跳转到给定的地址,从那里继续执行。
注意存储在分支指令中的实际的值是相对当前的R15的
b Reset
@0x04:
Undefinedinstructionexception //处理未定义的指令
UndefEntryPoint:
b HandleUndef
@0x08:
Softwareinterruptexception //软中断
SWIEntryPoint:
b HandleSWI
@0x0c:
PrefetchAbort(InstructionFetchMemoryAbort)//中文名不知道
PrefetchAbortEnteryPoint:
b HandlePrefetchAbort
@0x10:
DataAccessMemoryAbort //
DataAbortEntryPoint:
b HandleDataAbort
@0x14:
Notused //空
NotUsedEntryPoint:
b HandleNotUsed
@0x18:
IRQ(InterruptRequest)exception //中断(普通)
IRQEntryPoint:
b HandleIRQ
@0x1c:
FIQ(FastInterruptRequest)exception //fast中断处理
FIQEntryPoint:
b HandleFIQ
@
@VIVImagics
@
@0x20:
magicnumbersowecanverifythatweonlyput
.long 0
@0x24:
.long 0
@0x28:
wherethisviviwaslinked,sowecanputitinmemoryintherightplace
.long _start
@0x2C:
thiscontainstheplatform,cpuandmachineid
.long ARCHITECTURE_MAGIC
@0x30:
vivicapabilities
.long 0
#ifdefCONFIG_PM //powermanagement//vivi未用
@0x34:
b SleepRamProc
#endif
#ifdefCONFIG_TEST //testmode vivi未用
@0x38:
b hmi
#endif
@
@StartVIVIhead
@
Reset:
//第一步RESET
@disablewatchdogtimer //disablewatchdog定时器
mov r1,#0x53000000
mov r2,#0x0
str r2,[r1] //add0x5300_0000清0,bit5=0disablethistimer
#ifdefCONFIG_S3C2410_MPORT3 //另一种Platform非SMDK
mov r1,#0x56000000
mov r2,#0x00000005
str r2,[r1,#0x70]
movr2,#0x00000001
str r2,[r1,#0x78]
mov r2,#0x00000001
strr2,[r1,#0x74]
#endif
@disableallinterrupts //禁止所有中断
mov r1,#INT_CTL_BASE //0x4A00_0000sourcependingregister
mov r2,#0xffffffff
str r2,[r1,#oINTMSK] //0x4A00_0008
//0x4A00_0008 INTERRUPTMASKregister=0xFFFFFFFF,disableallint
ldr r2,=0x7ff
str r2,[r1,#oINTSUBMSK] //0x4A00_001C
//Interruptsubmaskregister, bit[10:
0]=1->0x7FF->disableall
@initialisesystemclocks //初始化系统时钟
mov r1,#CLK_CTL_BASE //LOCKTIMECOUNTREGISTER(LOCKTIME)
//0x4c000000
mvn r2,#0xff000000
str r2,[r1,#oLOCKTIME] //0x4C000000->0xFF00_0000;
@ldr r2,mpll_50mhz //CPU定成50Mhz
@str r2,[r1,#oMPLLCON] //
#ifndefCONFIG_S3C2410_MPORT1 //如果未定义成MPORT1(一种platform)
@1:
2:
4
mov r1,#CLK_CTL_BASE
mov r2,#0x3
str r2,[r1,#oCLKDIVN] //
//vCLKDIVN 0x3 /*FCLK:
HCLK:
PCLK=1:
2:
4*/
mrc p15,0,r1,c1,c0,0 @readctrlregister
orr r1,r1,#0xc0000000 @Asynchronous
mcr p15,0,r1,c1,c0,0 @writectrlregister
@now,CPUclockis200Mhz //CPU定成200Mhz
mov r1,#CLK_CTL_BASE
ldr r2,mpll_200mhz
str r2,[r1,#oMPLLCON]
#else //platform=MPORT1,以下不理
@1:
2:
2
movr1,#CLK_CTL_BASE
ldrr2,clock_clkdivn
strr2,[r1,#oCLKDIVN]
mrcp15,0,r1,c1,c0,0 @readctrlregister
orrr1,r1,#0xc0000000 @Asynchronous
mcrp15,0,r1,c1,c0,0 @writectrlregister
@now,CPUclockis100Mhz
movr1,#CLK_CTL_BASE
ldrr2,mpll_100mhz
strr2,[r1,#oMPLLCON]
#endif
bl memsetup //第2步memsetup
#ifdefCONFIG_PM //如果有Powermanagement:
不用
@Checkifthisisawake-upfromsleep
ldr r1,PMST_ADDR
ldr r0,[r1]
tst r0,#(PMST_SMR)
bne WakeupStart
#endif
#ifdefCONFIG_S3C2410_SMDK //SMDKplatform
@AllLEDon //点灯,好歹通知一下外面的同志3
mov r1,#GPIO_CTL_BASE
add r1,r1,#oGPIO_F
ldr r2,=0x55aa
str r2,[r1,#oGPIO_CON]
mov r2,#0xff
str r2,[r1,#oGPIO_UP]
mov r2,#0x00
str r2,[r1,#oGPIO_DAT]
#endif
#if0
@SVC
mrs r0,cpsr
bic r0,r0,#0xdf
orr r1,r0,#0xd3
msr cpsr_all,r1
#endif
//设置串口,内外联络的通道
@setGPIOforUART
mov r1,#GPIO_CTL_BASE //0x5600_0000
add r1,r1,#oGPIO_H
//oGPIO_H0x70PORTHCONTROLREGISTERS
ldr r2,gpio_con_uart //vGPHCON=0x0016faaa
str r2,[r1,#oGPIO_CON] //0101101111101010101010B
//oGPIO_CON=0x0
//GPH0bit[1:
0]=10 nCTS0
//GPH1bit[3:
2]=10 nRTS0
//GPH2bit[5:
4]=10 TXD0
//GPH3bit[7:
6]=10 RXD0
//GPH4bit[9:
8]=10TXD1
//GPH5bit[11:
10]=10RXD1
//GPH6bit[13:
12]=11 nRTS1
//GPH7bit[15:
14]=11nCTS1
//GPH8bit[17:
16]=10UEXTCLK
//GPH9bit[19:
18]=01Output
//GPH10bit[21:
20]=01Output
ldr r2,
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- vivi bootloader
![提示](https://static.bdocx.com/images/bang_tan.gif)