实验一 ARM汇编程序的编写以及启动代码的分析.docx
《实验一 ARM汇编程序的编写以及启动代码的分析.docx》由会员分享,可在线阅读,更多相关《实验一 ARM汇编程序的编写以及启动代码的分析.docx(24页珍藏版)》请在冰豆网上搜索。
![实验一 ARM汇编程序的编写以及启动代码的分析.docx](https://file1.bdocx.com/fileroot1/2023-1/26/94cd4adf-4ae9-4400-8018-cec641498b91/94cd4adf-4ae9-4400-8018-cec641498b911.gif)
实验一ARM汇编程序的编写以及启动代码的分析
实验ARM汇编程序的编写以及启动代码的分析
一、实验目的:
练习ARM汇编程序的编写,对提供的程序的启动代码进行分析,了解S3C2410初始化过程,初始化代码主要是包含在start.s中。
二、实验原理:
启动程序要完成的任务包括:
硬件初始化,系统存储系统的配置,复制二级中断向量表。
启动程序过程
●系统硬件初始化
系统上电或复位后,程序从位于地址0x0的ResetExceptionVector处开始执行,因此需要在这里放置Bootloader的第一条指令:
bResetHandler,跳转到标号为ResetHandler处进行第一阶段的硬件初始化,执行完,系统进行堆栈和存储器的初始化。
使用了外设,则需要设置相关的寄存器,确定其刷新频率、总线宽度等信息。
●代码段复制到RAM中运行
需要把系统的代码复制到RAM中运行。
映像文件内部共有三种输出段:
RO段、RW段和ZI段。
ARMLink同时还产生了这三种输出段的起始和终止定位信息:
Image$$RO$$Base、Image$$RO$$Limit、Image$$RW$$Base、Image$RW$Limit、Image$ZI$Base和Image$$ZI$$Limit。
可以在程序中使用这些定位信息。
将ROM中的代码和数据搬移到RAM中。
●建立二级中断向量表
在ARM系统中,中断向量表位于0X0开始的地址处,意味着无论运行什么样的上层软件,一旦发生中断,程序就得到Flash存储器中的中断向量表里去,降低系统的运行效率。
因此在RAM中建立自己的二级中断向量表,当中断发生后,程序直接从RAM中取中断向量进入中断子程序。
尤其是在中断频繁发生的系统里,这种方法可以大大提高系统的运行效率。
三、实验内容:
1.运行一个简单的串口程序,单步执行初始化代码,观察寄存器变化。
2.分析系统上电后的初始化工作包括哪些内容。
3.分析中断的处理过程,包括中断向量表的建立、中断源的识别及中断IRQ服务程序是如何进入的。
4.分析应用程序的结构。
四、实验代码:
在系统上电后,初始化部分的工作注意包含以下部分:
1、关看门狗定时器
2、屏蔽所有中断
3、设置CPU时钟频率。
4、设置存储器控制寄存器,对外部存储器的参数进行设置。
5、初始化各模式下的堆栈
6、建立IRQ中断的总的入口地址
7、初始化应用程序的执行环境
8、跳入Main函数,进入C程序
;=========================================
;NAME:
2410INIT.S
;DESC:
Cstartupcodes
;Configurememory,ISR,stacks
;InitializeC-variables
;HISTORY:
;2002.02.25:
kwtark:
ver0.0
;2002.03.20:
purnnamu:
AddsomefunctionsfortestingSTOP,POWER_OFFmode
;=========================================
GEToption.s;GET相当INCLUDE将一个源文件包含到当前源文件,这里表示包含option.s,并在当前位置进行汇编
GETmemcfg.s
GET2410addr.s
BIT_SELFREFRESHEQU(1<<22);定义了一些符号常量
;ARM异常模式的定义
;SDRAM/DRAM刷新控制器bit22REFMD位0:
CBR/AUTOREFRESH1:
SHIFREFRESH
;下面是对arm处理器模式寄存器对应值的常数定义,arm处理器中有一个CPSR程序状
;态寄存器,CPSR后五位决定目前的处理器模式。
;Pre-definedconstants
USERMODEEQU0x10;用户模式
FIQMODEEQU0x11;FIQ快速中断模式
IRQMODEEQU0x12;中断模式
SVCMODEEQU0x13;管理模式
ABORTMODEEQU0x17;中止模式
UNDEFMODEEQU0x1b;未定义指令模式
MODEMASKEQU0x1f;系统模式
NOINTEQU0xc0;禁止IRQ和FIQ中断
;ARM各异常模式堆栈,定义各模式堆栈地址
;_STACK_BASEADDRESS在option.s中,
;Thelocationofstacks
_STACK_BASEADDRESSEQU(SDRAM_END-0x8000);0x33ff8000
UserStackEQU(_STACK_BASEADDRESS-0x3800);0x33ff4800~;用户模式堆栈
SVCStackEQU(_STACK_BASEADDRESS-0x2800);0x33ff5800~0x3ff47ff;管理模式堆栈4k
UndefStackEQU(_STACK_BASEADDRESS-0x2400);0x33ff5c00~0x3ff57ff;未定义指令模式堆栈1k
AbortStackEQU(_STACK_BASEADDRESS-0x2000);0x33ff6000~0x3ff5bff;中止模式堆栈1k
IRQStackEQU(_STACK_BASEADDRESS-0x1000);0x33ff7000~0x3ff5fff;中断模式堆栈4k
FIQStackEQU(_STACK_BASEADDRESS-0x0);0x33ff8000~0x33ff6fff;快速中断模式堆栈4k
;arm处理器有两种工作状态
;1.arm:
32位这种工作状态下执行字对齐的arm指令
;2.Thumb:
16位这种工作状;态执行半字对齐的Thumb指令
;因为处理器分为16位32位两种工作状态程序的编译器也是分16位和32两种编译方式
;所以下面的程序用于根据处理器工作状态确定编译器编译方式
;code16伪指令指示汇编编译器,后面的指令为16位的thumb指令
;code32伪指令指示汇编编译器,后面的指令为32位的arm指令
;这段是为了统一目前的处理器工作状态和软件编译方式(16位编译环境使用tasm.exe编译)
;Checkiftasm.exe(armasm-16...@ADS1.0)isused.检查是否是用tasm.exe进行16位编译
GBLLTHUMBCODE;声明一个全局变量并初始化为{FALSE}
[{CONFIG}=16;ifconfig=16这里表示用16位编译方式
THUMBCODESETL{TRUE};SETL给全局变量赋值,设置THUMBCODE为true
CODE32;CODE32表明一下操作都在ARM状态,转入32位编译模式
|;|=ELSE|等同ELSE
THUMBCODESETL{FALSE};设置THUMBCODE为false,THUMBCODE=FALSE
];endif]等同ENDIF
;宏定义MOV_PC_LR
MACRO;MACRO定义宏,宏定义开始
MOV_PC_LR;宏将被下面定义部分展开,宏名MOV_PC_LR
[THUMBCODE;ifTHUMBCODE=true
bxlr;THUMBCODE模式上返回ARM状态
|;else
movpc,lr;ARM状态下返回
];endif
MEND;宏结束
MACRO;宏定义开始
MOVEQ_PC_LR;宏名为MOVEQ_PC_LR,与上面部分相同
[THUMBCODE;ifTHUMBCODE=true
bxeqlr;EQ相等则跳转回ARM状态
|;else
moveqpc,lr;同上位置相同部分,不同的是如果相等才跳回ARM状态
];endif
MEND;宏结束
;宏定义-进入异常流程
;HANDLER-宏的名称
;$HandleLabel-宏的参数
;这个宏的作用是把各个中断程序的地址装入当前的PC,2410有两种装断模式:
一种是没有
;中断向量表,一种是使用中断向量表的
;使用中断向量表只能是IRQ方式,当使用中断向量表的时候,中断发生时由2410的中断控
;制器自动跳转到
;相应的位置。
;注意下面这段宏定义程序
;下面包含的HandlerXXXHANDLERHandleXXX将都被下面这段程序展开
;本初始化程序定义了一个数据区(在文件最后),34个字空间,存放相应中断服务程序的首
;地址。
每个字,即4字节
;空间都有一个标号,以Handle***命名。
;在向量中断模式下使用“加载程序”来执行中断服务程序。
;向量中断模式和非向量中断模式的区别是:
向量中断模式是当cpu读取位于0x18处的IR
;Q中断指令的时候,系统自动读取对应于该中断源确定地址上的指令取代0x18处的指令,
;通过跳转指令系统就直接跳转到对应地址
;函数中节省了中断处理时间提高了中断处理速度标例如ADC中断的向量地址为0xC0,
;在0xC0处放如下代码:
;ldrPC,=HandlerADC当ADC中断产生的时候系统会自动跳转到HandlerADC函数中
;非向量中断模式处理方式是一种传统的中断处理方法,当系统产生中断的时候,系统将int
;erruptpending寄存器中对应标志位置位
;然后跳转到位于0x18处的统一中断;函数中
;该函数通过读取interruptpending寄存器中对应标志位来判断中断源,并根据优先级关系
;再跳到;对应中断源的处理代码中
;大致作用是把宏的第一个参数$HandlerLabel转变为一个标号,然后让程序跳转到第二个参
;数$HandleLabel(为一个地址)对应的值的地址去。
;所以,通过上面的分析可以看出,$HandlerLabelHANDLER$HandleLabel是让PC跳转到$H
;andleLabel中存放的地址执行。
MACRO;宏定义
$HandlerLabelHANDLER$HandleLabel;宏名字叫HANDLER,$HandleLabel是
;行参,定义了一个标号$HandlerLabel,展开时可替换成相应的符号
$HandlerLabel
subsp,sp,#4;sp-sp-4,空出的空间用于存放跳转地址
stmfdsp!
{r0};sp=sp-4,并将r0入栈
ldrr0,=$HandleLabel;获取存放跳转地址的标号HandleLabel到r0
ldrr0,[r0];将HandleLabel中存放的跳转地址送给r0
strr0,[sp,#4];将r0存放到sp+4的地方,
ldmfdsp!
{r0,pc};弹出栈顶2个字,分别保存到r0和pc中,系统将跳
;转到对应中断处理函数,由上r0和pc都没变,但程序已跳转
MEND;宏定义结束
;连接器生成的输出段相关的符号
;引入连接器生成的映象文件的各个部分地址。
;OR-只读区域、RW-读写区域、ZI-初始化为0的区域。
IMPORT|Image$$RO$$Limit|;EndofROMcode(=startofROMdata),RO结束
;地址+1
IMPORT|Image$$RW$$Base|;BaseofRAMtoinitialise,RW起始
IMPORT|Image$$ZI$$Base|;Baseandlimitofarea,RW段结束+1
IMPORT|Image$$ZI$$Limit|;tozeroinitialise,ZI段起始地址
;引入外部函数Main,进入C程序。
IMPORTMain;Themainentryofmonprogram
;IMPORTLEDTEST
;定义ARM汇编程序段,段名为SelfBoot,程序段为只读的代码段。
AREASelfBoot,CODE,READONLY;Selfboot初始化程序
;板子上电和复位后程序开始从位于0x0处开始执行,硬件刚刚上电复位后程序从这里开始
;执行跳转到标为ResetHandler处执行
;DCD用于分配一段字内存单片,并用后面的伪指令初始化,分配字节由expr个数决定
;程序入口地址
ENTRY
ResetEntry
;1)Thecode,whichconvertstoBig-endian,shouldbeinlittleendiancode.
;2)ThefollowinglittleendiancodewillbecompiledinBig-Endianmode.Thecodebyteordershouldbechangedasthememorybuswidth.
;3)Thepseudoinstruction,DCDcan'tbeusedherebecausethelinkergenerateserror.
ASSERT:
DEF:
ENDIAN_CHANGE;ASSERT断言错误伪指令,这里表示是否定义过ENDIAN_CHANGE
[ENDIAN_CHANGE;如果定义了ENDIAN_CHANGE
ASSERT:
DEF:
ENTRY_BUS_WIDTH;这里表示是否定义过ENTRY_BUS_WIDTH
[ENTRY_BUS_WIDTH=32;ifENTRY_BUS_WIDTH=32
bChangeBigEndian;DCD0xea000007,跳转到ChangeBigEndian,
;执行DCD0xea000007改变大小端数据模式
];endif
[ENTRY_BUS_WIDTH=16;ifENTRY_BUS_WIDTH=16
andeqr14,r7,r0,lsl#20;DCD0x0007ea00,标志状态寄存器CPSR的Z
;=1时,r14=r7+r0逻辑左移20位,执行DCD0x0007ea00改变大小端模式
];endif
[ENTRY_BUS_WIDTH=8;ifENTRY_BUS_WIDTH=8
streqr0,[r0,-r10,ror#1];DCD0x070000e,当标志状态寄存器CPSR的Z
;=1时…,执行DCD0x070000ea改变大小端模式
];endif
|;ELSE即如果没定义ENDIAN_CHANGE
bResetHandler;复位处理模式
]
bHandlerUndef;handlerforUndefinedmode处理为定义模式
bHandlerSWI;handlerforSWIinterrupt处理软中断模式
bHandlerPabort;handlerforPAbort处理终止程序访问终止模式
bHandlerDabort;handlerforDAbort处理数据访问终止模式
b.;reserved保留,"."代表指令的地址,即表示进行死循环
bHandlerIRQ;handlerforIRQinterrupt处理中断模式
bHandlerFIQ;handlerforFIQinterrupt处理快速中断模式
;@0x20"@"存储区位置计数器的当前值
bEnterPWDN;进入掉电模式,见下面的标号
ChangeBigEndian;上面提到的ChangeBigEndian,改变大小端数据模式
;@0x24
[ENTRY_BUS_WIDTH=32;ifENTRY_BUS_WIDTH=32
DCD0xee110f10;0xee110f10=>mrcp15,0,r0,c1,c0,0
DCD0xe3800080;0xe3800080=>orrr0,r0,#0x80;//Big-endian
DCD0xee010f10;0xee010f10=>mcrp15,0,r0,c1,c0,0
]
[ENTRY_BUS_WIDTH=16;ifENTRY_BUS_WIDTH=16
DCD0x0f10ee11
DCD0x0080e380
DCD0x0f10ee01
]
[ENTRY_BUS_WIDTH=8;ifENTRY_BUS_WIDTH=8
DCD0x100f11ee
DCD0x800080e3
DCD0x100f01ee
]
DCD0xffffffff;swinv0xffffffissimilarwithNOPandrunwellinbothendianmode.
DCD0xffffffff
DCD0xffffffff
DCD0xffffffff
DCD0xffffffff
bResetHandler;复位处理程式
;Functionforenteringpowerdownmode
;1.SDRAMshouldbeinself-refreshmode.
;2.AllinterruptshouldbemakskedforSDRAM/DRAMself-refresh.
;3.LCDcontrollershouldbedisabledforSDRAM/DRAMself-refresh.
;4.TheI-cachemayhavetobeturnedon.
;5.Thelocationofthefollowingcodemayhavenottobechanged.
;进入掉电模式功能
;1.SDRAM必须在自刷新模式.
;2.所有中断必须屏蔽forSDRAM/DRAMself-refresh.
;3.LCD关闭forSDRAM/DRAMself-refresh.
;4.TheI-cache可能需要开启.
;5.Thelocationofthefollowingcodemayhavenottobechanged.
;voidEnterPWDN(intCLKCON);;进入掉电模式
EnterPWDN
movr2,r0;r2=rCLKCONCLKCON[3]掉电模式控制位0:
关闭1:
进入掉电模式
tstr0,#0x8;POWER_OFFmode?
判断POWER_OFF是否为0。
r0和
#0X8相与,更新CPSR位
bneENTER_POWER_OFF;NE不相等(则表示power_off不为O)标志位Z=0
ENTER_STOP;不进入掉电模式
ldrr0,=REFRESH;0x48000024;DRAM/SDRAMrefreshDRAM/SDRAM刷新控制器,刷新DRAM/SDRAM
ldrr3,[r0];r3=rREFRESH
movr1,r3;r1=r3
orrr1,r1,#BIT_SELFREFRESH;BIT_SELFREFRESHEQU(1<<22)bit22TREFMD位
0:
CBR/AUTOREFRESH1:
SHIFREFRESH
strr1,[r0];R1->[R0]EnableSDRAMself-refresh
;%B是向后搜索局部标号,%F是向前搜索局部标号。
movr1,#16;延时waituntilself-refreshisissued.maynotbeneeded.
0subsr1,r1,#1;0为局部标号(延时)
bne%B0
ldrr0,=CLKCON;enterSTOPmode.CLKCON;Clockgeneratorcontrol
strr2,[r0]
movr1,#32
0subsr1,r1,#1;1)延时waituntiltheSTOPmodeisineffect.
bne%B0;2)OrwaithereuntiltheCPU&Peripheralswillbeturned-off
;EnteringPOWER_OFFmode,onlytheresetbywake-upisavailable.
ldrr0,=REFRESH;exitfromSDRAMselfrefreshmode.
strr3,[r0]
MOV_PC_LR;调用宏MOV_PC_LR
ENTER_POWER_OFF;进入掉电模式
;NOTE.
;1)rGSTATUS3shouldhavethereturnaddressafterwake-upfromPOWER_OFFmode.
ldrr0,=REFRESH
ldrr1,[r0];r1=rREFRESH
orrr1,r1,#BIT_SELFREFRESH
strr1,[r0];EnableSDRAMself-refresh
movr1,#16;Waituntilself-refreshisissued,whichmaynotbeneeded.
0subsr1,r1,#1;延时
bne%B0
ldrr1,=MISCCR;;Miscellaneouscontrol,混杂控制模式
ldrr0,[r1]
orrr0,r0,#(7<<17);MakesurethatSCLK0:
SCLK->0,SCL