44b0启动代码详细解析文档格式.docx

上传人:b****6 文档编号:17347397 上传时间:2022-12-01 格式:DOCX 页数:13 大小:23.80KB
下载 相关 举报
44b0启动代码详细解析文档格式.docx_第1页
第1页 / 共13页
44b0启动代码详细解析文档格式.docx_第2页
第2页 / 共13页
44b0启动代码详细解析文档格式.docx_第3页
第3页 / 共13页
44b0启动代码详细解析文档格式.docx_第4页
第4页 / 共13页
44b0启动代码详细解析文档格式.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

44b0启动代码详细解析文档格式.docx

《44b0启动代码详细解析文档格式.docx》由会员分享,可在线阅读,更多相关《44b0启动代码详细解析文档格式.docx(13页珍藏版)》请在冰豆网上搜索。

44b0启动代码详细解析文档格式.docx

FIQMODEEQU0x11

IRQMODEEQU0x12

SVCMODEEQU0x13

ABORTMODEEQU0x17

UNDEFMODEEQU0x1b

MODEMASKEQU0x1f

NOINTEQU0xc0;

IRQ、FIQ中断禁止《田凯文》

用来判断是用16位指令集还是32位指令集《田凯文》

GBLLTHUMBCODE

[{CONFIG}=16

THUMBCODESETL{TRUE}

CODE32

|

THUMBCODESETL{FALSE}

]

[THUMBCODE

CODE32;

forstart-upcodeforThumbmode

MACRO;

宏定义开始,P128《田凯文》

这个宏的功能就是先将r0寄存器中的值存入栈中,接着又将中断函数的入口地址《田凯文》

以r0为中转,存入数据栈中,再通过栈还原r0的值,接着将存入栈中的中断函数的入口地址《田凯文》

取出,送给PC,以实现中断函数的跳转《田凯文》

如果是IRQ中断并且是非向量中断,就会跳转到标号IsrIRQ处,然后再跳转到中断二级向量表《田凯文》

如果是向量中断则通过这一步,直接跳转到中断二级向量表《田凯文》

非向量中断跳转流程:

bHandlerIRQ->

HandlerIRQHANDLERHandleIRQ->

IsrIRQ->

^_ISR_STARTADDRESS《田凯文》

向量中断跳转流程:

VECTOR_BRANCH->

$HandlerLabelHANDLER$HandleLabel->

^_ISR_STARTADDRESS《田凯文》

向量中断比非向量中断少了一个IsrIRQ《田凯文》

$HandlerLabelHANDLER$HandleLabel;

宏名为HANDLER,参数为$HandleLabel《田凯文》

$HandlerLabel;

这里定义了一个标号HandlerLabel,是伪操作《田凯文》

subsp,sp,#4;

减法指令,sp=sp-4,p66《田凯文》

stmfdsp!

{r0};

这是一个压栈操作,由于它是事先递减方式,所以sp的值先减4,即将r0寄存器中的数据《田凯文》

存入以sp-4的值为地址的内存单元,并且sp的值更新为sp-4《田凯文》

stmfd是对FD类型数据栈操作的指令,因为是FD类型的数据栈《田凯文》

所以栈的地址是递减的,而SP后面的!

号,指的是,是否更新基地址寄存器《田凯文》

如果有!

号,指令编码对应的W位置1,基地址寄存器,即sp更新,sp=sp-4《田凯文》

这条指令的目的是为了存储r0寄存器的值,因为后面要用到《田凯文》

现在存储,是为了后面的还原《田凯文》

这条指令没有目标寄存器,只有基址寄存器,所以sp代表的就是地址《田凯文》

ldrr0,=$HandleLabel;

将标号$HandleLabel的值送给r0,$HandleLabel的值就是存放IsrIRQ的地址,在bResetHandler中已经定义过了《田凯文》

ldrr0,[r0];

将以r0的值为地址的内存单元中的数据取出,存入r0寄存器中,《田凯文》

这条ldr指令中基址寄存器为r0,即第二个操作数的内存地址为0,p34《田凯文》

strr0,[sp,#4];

将r0的值放入地址为sp+4的存储单元中,这就是前面sp-4的原因,《田凯文》

它是为了给这一步预留存储空间《田凯文》

ldmfdsp!

{r0,pc};

这是一个出栈操作,由于它是事后递增方式,即将以sp的值为地址的内存单元中《田凯文》

的值存入r0寄存器中,即还原r0寄存器中值,stmfdsp!

{r0}这条指令,就是为了这一刻《田凯文》

再将以sp+4的值为地址的内存单元中的数据取出,即[r0]里面的值,也就是中断函数的入口地址《田凯文》

送给PC寄存器,并且sp更新为sp+8,即sp=sp+8《田凯文》

MEND;

宏定义结束《田凯文》

IMPORT|Image$$RO$$Limit|;

EndofROMcode(=startofROMdata)

IMPORT|Image$$RW$$Base|;

BaseofRAMtoinitialise

IMPORT|Image$$ZI$$Base|;

Baseandlimitofarea

IMPORT|Image$$ZI$$Limit|;

tozeroinitialise

IMPORTMain;

Themainentryofmonprogram

AREAInit,CODE,READONLY;

定义一个名为Init的代码段,属性为READONLY《田凯文》

ENTRY;

伪操作指定程序的入口点p136《田凯文》

bResetHandler;

fordebug

bHandlerUndef;

handlerUndef

bHandlerSWI;

SWIinterrupthandler

bHandlerPabort;

handlerPAbort

bHandlerDabort;

handlerDAbort

b.;

handlerReserved

bHandlerIRQ;

非向量中断跳转到此处《田凯文》

bHandlerFIQ

***IMPORTANTNOTE***

IftheH/Wvectoredinterrutpmodeisenabled,Theabovetwoinstructionsshould

bechangedlikebelow,towork-aroundwithH/WbugofS3C44B0Xinterruptcontroller.

bHandlerIRQ->

subspc,lr,#4

VECTOR_BRANCH;

这是向量中断的入口地址《田凯文》

ldrpc,=HandlerEINT0;

mGAH/Winterruptvectortable

ldrpc,=HandlerEINT1;

ldrpc,=HandlerEINT2;

ldrpc,=HandlerEINT3;

ldrpc,=HandlerEINT4567;

ldrpc,=HandlerTICK;

mGA

b.

ldrpc,=HandlerZDMA0;

mGB

ldrpc,=HandlerZDMA1;

ldrpc,=HandlerBDMA0;

ldrpc,=HandlerBDMA1;

ldrpc,=HandlerWDT;

ldrpc,=HandlerUERR01;

ldrpc,=HandlerTIMER0;

mGC

ldrpc,=HandlerTIMER1;

ldrpc,=HandlerTIMER2;

ldrpc,=HandlerTIMER3;

ldrpc,=HandlerTIMER4;

ldrpc,=HandlerTIMER5;

ldrpc,=HandlerURXD0;

mGD

ldrpc,=HandlerURXD1;

ldrpc,=HandlerIIC;

ldrpc,=HandlerSIO;

ldrpc,=HandlerUTXD0;

ldrpc,=HandlerUTXD1;

ldrpc,=HandlerRTC;

mGKA

ldrpc,=HandlerADC;

mGKB

mGKB

0xe0=EnterPWDN

ldrpc,=EnterPWDN

LTORG;

声明一个数据缓冲池的开始P120《田凯文》

HandlerFIQHANDLERHandleFIQ

HandlerIRQHANDLERHandleIRQ

HandlerUndefHANDLERHandleUndef

HandlerSWIHANDLERHandleSWI

HandlerDabortHANDLERHandleDabort

HandlerPabortHANDLERHandlePabort

HandlerADCHANDLERHandleADC

HandlerRTCHANDLERHandleRTC

HandlerUTXD1HANDLERHandleUTXD1

HandlerUTXD0HANDLERHandleUTXD0

HandlerSIOHANDLERHandleSIO

HandlerIICHANDLERHandleIIC

HandlerURXD1HANDLERHandleURXD1

HandlerURXD0HANDLERHandleURXD0

HandlerTIMER5HANDLERHandleTIMER5

HandlerTIMER4HANDLERHandleTIMER4

HandlerTIMER3HANDLERHandleTIMER3

HandlerTIMER2HANDLERHandleTIMER2

HandlerTIMER1HANDLERHandleTIMER1

HandlerTIMER0HANDLERHandleTIMER0

HandlerUERR01HANDLERHandleUERR01

HandlerWDTHANDLERHandleWDT

HandlerBDMA1HANDLERHandleBDMA1

HandlerBDMA0HANDLERHandleBDMA0

HandlerZDMA1HANDLERHandleZDMA1

HandlerZDMA0HANDLERHandleZDMA0

HandlerTICKHANDLERHandleTICK

HandlerEINT4567HANDLERHandleEINT4567

HandlerEINT3HANDLERHandleEINT3

HandlerEINT2HANDLERHandleEINT2

HandlerEINT1HANDLERHandleEINT1

HandlerEINT0HANDLERHandleEINT0

Oneofthefollowingtworoutinescanbeusedfornon-vectoredinterrupt.

IsrIRQ;

usingI_ISPRregister.

IsrIRQ的作用是,计算出发生的中断,到底是什么中断《田凯文》

只有这样才能跳转到相应的中断服务子程序《田凯文》

仅当中断的类型为非向量中断时,才会跳转到该标号《田凯文》

而向量中断和非向量中断的根本性区别就在于,非向量中断《田凯文》

需要自己计算出到底是哪个中断源,发生的中断,所以非向量中断《田凯文》

要执行这一句,而向量中断是由硬件直接计算出发生中断的类型《田凯文》

所以就不需要执行这一步,直接跳到下一步《田凯文》

非向量中断是通过这一步,跳转到中断二级向量表《田凯文》

{r8-r9};

这是一个压栈操作,由于它是事先递减方式,所以sp的值先减4,即将r9寄存器中的数据《田凯文》

存入以sp-4的值为地址的内存单元,r8寄存器中的数据,存入以sp-8的值为地址的内存单元《田凯文》

并且sp的值更新为sp-8《田凯文》

号,指令编码对应的W位置1,基地址寄存器,即sp更新,sp=sp-8《田凯文》

这条指令的目的是为了存储r8,r9寄存器的值,因为后面要用到《田凯文》

IMPORTANTCAUTION

ifI_ISPCisn'

'

tusedproperly,I_ISPRcanbe0inthisroutine.

ldrr9,=I_ISPR;

将I_ISPR寄存器的地址赋给r9《田凯文》

I_ISPR是44b0中断标示寄存器,通过它可以知道,什么中断发生了《田凯文》

这个寄存器和ARM的种类有关,如果是2440就不是I_ISPR了《田凯文》

ldrr9,[r9];

将I_ISPR寄存器的值赋给r9《田凯文》

movr8,#0x0;

将r8寄存器清零《田凯文》

0

movsr9,r9,lsr#1;

将r9寄存器的值左移1位,在赋值给r9,即r9=(r9<

<

1)《田凯文》

movs可以分为mov和s,其中mov为传送指令,s指的是《田凯文》

该指令的执行结果会影响CPSR寄存器《田凯文》

由于该指令中包含移位运算,所以移位运算中溢出的值《田凯文》

即为CPSR寄存器中的C位的值,即溢出0,标志位C的值就为0《田凯文》

溢出1,标志位C的值就为1《田凯文》

bcs%F1;

判断条件标志位C的值是否为1,如果为1则执行跳转指令《田凯文》

bcs指令中的cs,是指令执行的条件码,《田凯文》

意思是如果条件标志位C的值是1,则执行跳转指令《田凯文》

addr8,r8,#4;

偏移量加4,执行下一个中断《田凯文》

b%B0;

跳转到标号0处继续执行,直到C值变为1《田凯文》

1

ldrr9,=HandleADC;

将标号HandleADC的地址送给r9《田凯文》

addr9,r9,r8;

再将r9的值加上偏移量r8,将得到的值送给r9《田凯文》

这个值,就是发生中断的服务程序,入口地址存放的地址《田凯文》

将中断服务程序的入口地址,取出送给r9《田凯文》

strr9,[sp,#8];

将r9即中断服务程序的入口地址,送入栈中,[sp,#8]=r9《田凯文》

{r8-r9,pc};

将r8、r9寄存器中的值还原,并且PC指针指向存放中断函数《田凯文》

入口地址的地址《田凯文》

****************************************************

*START*

ResetHandler

ldrr0,=WTCON;

将WTCON这个值送给r0《田凯文》

ldrr1,=0x0;

r1寄存器清零《田凯文》

strr1,[r0];

将r1中得值,赋给存储地址为r0的区域,看门狗禁止《田凯文》

ldr为字数据加载指令《田凯文》

str为字数据存储指令《田凯文》

ldrr0,=INTMSK

ldrr1,=0x07ffffff

禁止所有中断《田凯文》

*Setclockcontrolregisters*

ldrr0,=LOCKTIME

ldrr1,=800;

count=t_lock*Fin(t_lock=200us,Fin=4MHz)=800

strr1,[r0]

[PLLONSTART;

如果PLLONSTART为真《田凯文》

ldrr0,=PLLCON;

temporarysettingofPLL

ldrr1,=((M_DIV<

12)+(P_DIV<

4)+S_DIV);

Fin=10MHz,Fout=66MHz

设定PCLL的输出时钟为66MHz《田凯文》

]

ldrr0,=CLKCON

ldrr1,=0x7ff8;

AllunitblockCLKenable0111111111111000

*Setmemorycontrolregisters*

ldrr0,=SMRDATA

ldmiar0,{r1-r13};

加载R0指向的地址上的多字数据,保存到R1~R13中,R0的值更新(地址加1,即加4个字节)。

《田凯文》

ldrr0,=0x01c80000;

BWSCONAddress《田凯文》

stmiar0,{r1-r13};

将R1~R13的数据存储到R0指向的地址上,R1值更新(地址加1,即加4个字节)《田凯文》

ldmia为多寄存器加载指令《田凯文》

stmia为多寄存器存储指令《田凯文》

*初始化各模式下的栈指针*

ldrsp,=SVCStack;

Why?

blInitStacks;

跳转到标号InitStacks处,同时将当前的PC值保存到R14中《田凯文》

PC即为程序计数器,是R15寄存器的别称《田凯文》

bl指令为带返回的跳转指令,使用BL跳转指令之前会在寄存器R14中保存当前的PC内容《田凯文》

******************************************************************

*将IRQ中断函数的入口地址存取地址HandleIRQ处*

*****************************************************************

ldrr0,=HandleIRQ;

将HandleIRQ存入目标寄存器r0中《田凯文》

ldrr1,=IsrIRQ;

将IsrIRQ存入目标寄存器r1中《田凯文》

将r1的值存入以r0的值为地址的内存单元中《田凯文》

*********************************************************************

*将RW段拷备到RAM中,并建立ZI段即将ZI段清零《田凯文》*

LDRr0,=|Image$$RO$$Limit|;

表示RO断结束地址加1(运行时)《田凯文》

LDRr1,=|Image$$RW$$Base|;

表示RW断起始地址(运行时)《田凯文》

LDRr3,=|Image$$ZI$$Base|;

表示ZI断起始地址(运行时)《田凯文》

Zeroinitbase=>

topofinitialiseddata

加载时地址:

映像文件开始运行之前的地址《田凯文》

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

当前位置:首页 > 高中教育 > 初中教育

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

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