您的位置:首页 > 编程语言

mini2440开发板中启动代码2440INIT.S分析

2011-09-14 20:31 489 查看
声明:文章转自别处,非本人自创

http://hi.baidu.com/haijie0707/blog/item/6ff41a3bff7ccef93a87ced5.html
;=========================================
;NAME:2440INIT.S
;DESC:Cstartupcodes
;Configurememory,ISR,stacks
;InitializeC-variables
;HISTORY:
;2002.02.25:kwtark:ver0.0
;2002.03.20:purnnamu:AddsomesfortestingSTOP,Sleepmode
;2003.03.14:DonGo:Modifiedfor2440.
;=========================================

;首先,启动代码定义了一些常量
;汇编不能使用include包含头文件,所有用Get
;汇编也不认识*.h文件,所有只能用*.inc
GEToption.inc;定义芯片相关的配置
GETmemcfg.inc;定义存储器配置
GET2440addr.inc;定义了寄存器符号
;REFRESH寄存器[22]bit:0-autorefresh;1-selfrefresh
;用于节电模式中,SDRAM自动刷新
BIT_SELFREFRESHEQU(1<<22)


;处理器模式常量:CPSR寄存器的后5位决定目前处理器模式M[4:0]
USERMODEEQU0x10
FIQMODEEQU0x11
IRQMODEEQU0x12
SVCMODEEQU0x13
ABORTMODEEQU0x17
UNDEFMODEEQU0x1b
MODEMASKEQU0x1f
NOINTEQU0xc0

;定义处理器各模式下堆栈地址常量

;_STACK_BASEADDRESS定义在option.inc中
UserStackEQU(_STACK_BASEADDRESS-0x3800);0x33ff4800~
SVCStackEQU(_STACK_BASEADDRESS-0x2800);0x33ff5800~
UndefStackEQU(_STACK_BASEADDRESS-0x2400);0x33ff5c00~
AbortStackEQU(_STACK_BASEADDRESS-0x2000);0x33ff6000~
IRQStackEQU(_STACK_BASEADDRESS-0x1000);0x33ff7000~
FIQStackEQU(_STACK_BASEADDRESS-0x0);0x33ff8000~

;arm处理器有两种工作状态1.arm:32位这种工作状态下执行字对准的arm指令2.Thumb:16位这种工状;态执行半字对准的Thumb指令
;因为处理器分为16位32位两种工作状态程序的编译器也是分16位和32两种编译方式所以下面的程序用
;于根据处理器工作状态确定编译器编译方式
;code16伪指令指示汇编编译器后面的指令为16位的thumb指令
;code32伪指令指示汇编编译器后面的指令为32位的arm指令
;
;Arm上电时处于ARM状态,故无论指令为ARM集或Thumb集,都先强制成ARM集,待init.s初始化完成后
;再根据用户的编译配置转换成相应的指令模式。为此,定义变量THUMBCODE作为指示,跳转到main之前
;根据其值切换指令模式
;
;这段是为了统一目前的处理器工作状态和软件编译方式(16位编译环境使用tasm.exe编译

;检查在tasm.exe里是否设置了采用THUMB(16位)代码(armasm-16...@ADS1.0)

GBLLTHUMBCODE;定义THUMBCODE全局变量
[{CONFIG}=16
;如果发现是在用16位代码的话(编译选项中指定使用thumb指令
THUMBCODESETL{TRUE};把THUMBCODE设置为TURE
CODE32;把处理器从新设置成为ARM模式
|;如果处理器现在就是ARM模式
THUMBCODESETL{FALSE};把THUMBCODE设置为FALSE就行了
]
MACRO
;一个根据THUMBCODE把PC寄存的值保存到LR的宏,宏MOV_PC_LR
MOV_PC_LR[THUMBCODEbxlr;([表示if)

;在ARM模式中要使用BX指令转跳到THUMB指令,并转换模式

|;(|表示else)如果编译选项本来就指定为ARM模式

movpc,lr;如果目标地址也是ARM指令的话就采用这种方式

];(]表示endif)

MEND

MACRO;和上面的宏一样,只是多了一个相等的条件

MOVEQ_PC_LR

[THUMBCODE

bxeqlr

|

moveqpc,lr

]

MEND

;=======================================================================================

;下面这个宏是用于第一次查表过程的实现中断向量的重定向,如果你比较细心的话就是发现

;在_ISR_STARTADDRESS=0x33FF_FF00里定义的第一级中断向量表是采用型如Handle***的方式的.

;而在程序的ENTRY处(程序开始处)采用的是bHandler***的方式.

;在这里Handler***就是通过HANDLER这个宏和Handle***进立联系的.

;这种方式的优点就是正真定义的向量数据在内存空间里,而不是在ENTRY处的ROM(FLASH)空间里,

;这样,我们就可以在程序里灵活的改动向量的数据了.

;========================================================================================

;;这段程序用于把中断服务程序的首地址装载到pc中,有人称之为“加载程序”。

;本初始化程序定义了一个数据区(在文件最后),34个字空间,存放相应中断服务程序的首地址。每个字

;空间都有一个标号,以Handle***命名。

;在向量中断模式下使用“加载程序”来执行中断服务程序。

;这里就必须讲一下向量中断模式和非向量中断模式的概念

;向量中断模式是当cpu读取位于0x18处的IRQ中断指令的时候,系统自动读取对应于该中断源确定地址上的;

;指令取代0x18处的指令,通过跳转指令系统就直接跳转到对应地址

;函数中节省了中断处理时间提高了中断处理速度标例如ADC中断的向量地址为0xC0,则在0xC0处放如下

;代码:ldrPC,=HandlerADC当ADC中断产生的时候系统会

;自动跳转到HandlerADC函数中

;非向量中断模式处理方式是一种传统的中断处理方法,当系统产生中断的时候,系统将interrupt

;pending寄存器中对应标志位置位然后跳转到位于0x18处的统一中断

;函数中该函数通过读取interruptpending寄存器中对应标志位来判断中断源并根据优先级关系再跳到

;对应中断源的处理代码中

;

MACRO

$HandlerLabelHANDLER$HandleLabel

$HandlerLabel;标号

subsp,sp,#4;减少sp(用于存放转跳地址)

stmfdsp!,{r0};把工作寄存器压入栈(lrdoesnotpushbecauseitreturntooriginal
address)

ldrr0,=$HandleLabel;将HandleXXX的址址放入r0

ldrr0,[r0];把HandleXXX所指向的内容(也就是中断程序的入口)放入r0

strr0,[sp,#4];把中断服务程序(ISR)压入栈

ldmfdsp!,{r0,pc};用出栈的方式恢复r0的原值和为pc设定新值(也就完成了到ISR的转跳)

MEND

;=========================================================================================

;在这里用IMPORT伪指令(和c语言的extren一样)引入|Image$$RO$$Base|,|Image$$RO$$Limit|...

;这些变量是通过ADS的工程设置里面设定的ROBase和RWBase设定的,

;最终由编译脚本和连接程序导入程序.

;那为什么要引入这玩意呢,最简单的用处是可以根据它们拷贝自已

;==========================================================================================

IMPORT|Image$$RO$$Base|;ROMcode(也就是代码)的开始地址

IMPORT|Image$$RO$$Limit|;ROMcode的结束地址(=ROMdata的开始地址)

IMPORT|Image$$RW$$Base|;要初始化的RAM的开始地址

IMPORT|Image$$ZI$$Base|;area(需要清零的RAM区域)的开始地址

IMPORT|Image$$ZI$$Limit|;area的结束地址

;这里引入一些在其它文件中实现在函数,包括为我们所熟知的main函数

IMPORTMMU_SetAsyncBusMode

IMPORTMMU_SetFastBusMode;hzh

IMPORTMain

;Themainentryofmonprogram

;从这里开始就是正真的代码入口了!

AREAInit,CODE,READONLY;这表明下面的是一个名为Init的代码段

ENTRY;定义程序的入口(调试用)

EXPORT__ENTRY;导出符号_ENTRY,告知__ENTRY不

是在本源文件中,是在别的中定义的在本源文件中要用到

__ENTRY

ResetEntry

;1)Thecode,whichconvertstoBig-endian,shouldbeinlittleendiancode.

;2)ThefollowinglittleendiancodewillbecompiledinBig-Endianmode.

;Thecodebyteordershouldbechangedasthememorybuswidth.

;3)Thepseudoinstruction,DCDcannotbeusedherebecausethelinkergenerateserror.

;条件编译,在编译成机器码前就设定好

ASSERT:DEF:ENDIAN_CHANGE

[ENDIAN_CHANGE

;下面是大小端的一个判断,在Option.inc里已经设FALSE

ASSERT:DEF:ENTRY_BUS_WIDTH;判断ENTRY_BUS_WIDTH是否已定义

[ENTRY_BUS_WIDTH=32;如果已经定义了ENTRY_BUS_WIDTH,则判断是不是为32

bChangeBigEndian;DCD0xea000007

;在bigendian中,地址为A的字单元包括字节单元A,A+1,A+2,A+3,字节单元由高位到低位为A,A+1,A+2,A+3

;地址为A的字单元包括半字单元A,A+2,半字单元由高位到低位为A,A+2

]

[ENTRY_BUS_WIDTH=16

andeqr14,r7,r0,lsl#20;DCD0x0007ea00

]bChangeBigEndian指令,只是由于总线不一样而取机器码的顺序不一样

[ENTRY_BUS_WIDTH=8

streqr0,[r0,-r10,ror#1];DCD0x070000ea

]

|

bResetHandler;设成FALSE的话就来到这了,转跳到复位程序入口

]

bHandlerUndef;转跳到Undefinedmode程序入口0x04

bHandlerSWI;转跳到SWI中断程序入口0x08

bHandlerPabort;转跳到PAbort(指令异常)程序入口0x0c

bHandlerDabort;转跳到DAbort(数据异常)程序入口0x10

b.;保留0x14

bHandlerIRQ;转跳到IRQ中断程序入口0x18

bHandlerFIQ;转跳到FIQ中断程序入口0x1c

;@0x20

bEnterPWDN;Mustbe@0x20.

;==================================================================================

;下面是改变大小端的程序,这里采用直接定义机器码的方式,至说为什么这么做就得问三星了

;反正我们程序里这段代码也不会去执行,不用去管它

;==================================================================================

ChangeBigEndian

;@0x24

[ENTRY_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

DCD0x0f10ee11

DCD0x0080e380

DCD0x0f10ee01

]

[ENTRY_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.

;voidEnterPWDN(intCLKCON);

EnterPWDN

ldrr0,=rCLKCON

movr2,r0;r2=rCLKCON保存原始数据0x4c00000c使能各模块的时钟输入

tstr0,#0x8;测试bit[3]SLEEPmode?1=>sleep

bneENTER_SLEEP;C=0,即TST结果非0,bit[3]=1

;//进入PWDN后如果不是sleep则进入stop

;//进入Stopmode

ENTER_STOP

ldrr0,=REFRESH;0x48000024DRAM/SDRAMrefreshconfig

ldrr3,[r0];r3=rREFRESH

movr1,r3

orrr1,r1,#BIT_SELFREFRESH;EnableSDRAMself-refresh

strr1,[r0];EnableSDRAMself-refresh

movr1,#16;waituntilself-refreshisissued.maynotbeneeded.

0

subsr1,r1,#1

bne%B0;%B表示向前找到0处

;//wait16fclksforself-refresh

ldrr0,=CLKCON;enterSTOPmode.

strr2,[r0]

movr1,#32

0

subsr1,r1,#1;1)waituntiltheSTOPmodeisineffect.

bne%B0;2)OrwaithereuntiltheCPU&Peripheralswillbeturned-off

;EnteringSLEEPmode,onlytheresetbywake-upisavailable.

ldrr0,=REFRESH;exitfromSDRAMselfrefreshmode.

strr3,[r0]

MOV_PC_LR;backtomainprocess

ENTER_SLEEP

;NOTE.

;1)rGSTATUS3shouldhavethereturnaddressafterwake-upfromSLEEPmode.

ldrr0,=REFRESH

ldrr1,[r0];r1=rREFRESH

orrr1,r1,#BIT_SELFREFRESH

strr1,[r0];EnableSDRAMself-refresh

;//EnableSDRAMself-refresh

movr1,#16;Waituntilself-refreshisissued,whichmaynotbeneeded.

0

subsr1,r1,#1

bne%B0

;//Waituntilself-refreshisissued,whichmaynotbeneeded

ldrr1,=MISCCR;IOregister

ldrr0,[r1]

orrr0,r0,#(7<<17);SetSCLK0=1,SCLK1=1,SCKE=1.

strr0,[r1]

ldrr0,=CLKCON;Entersleepmode

strr2,[r0]

b.;CPUwilldiehere.

;//进入SleepMode,1)设置SDRAM为self-refresh

;//2)设置MISCCRbit[17]1:sclk0=sclk0:sclk0=0

;//bit[18]1:sclk1=sclk0:sclk1=0

;//bit[19]1:Selfrefreshretainenable

;//0:Selfrefreshretaindisable

;//When1,Afterwake-upfromsleep,Theself-refreshwillberetained.

WAKEUP_SLEEP

;ReleaseSCLKnafterwake-upfromtheSLEEPmode.

ldrr1,=MISCCR

ldrr0,[r1]

bicr0,r0,#(7<<17);SCLK0:0->SCLK,SCLK1:0->SCLK,SCKE:0->=SCKE.

strr0,[r1]

;//设置MISCCR

;Setmemorycontrolregisters

;ldrr0,=SMRDATA

adrlr0,SMRDATA

ldrr1,=BWSCON;BWSCONAddress;//总线宽度和等待控制寄存器

addr2,r0,#52;EndaddressofSMRDATA

0

ldrr3,[r0],#4;数据处理后R0自加4,[R0]->R3,R0+4->R0

strr3,[r1],#4

cmpr2,r0

bne%B0

;//设置所有的memorycontrolregister,他的初始地址为BWSCON,初始

;//数据在以SMRDATA为起始的存储区

movr1,#256

0

subsr1,r1,#1;1)waituntiltheSelfRefreshisreleased.

bne%B0

.

ldrr1,=GSTATUS3;GSTATUS3hasthestartaddressjustafterSLEEPwake-up

ldrr0,[r1]

movpc,r0

;//跳出SleepMode,进入Sleep状态前的PC

;如上所说,这里采用HANDLER宏去建立Hander***和Handle***之间的联系

HandlerFIQHANDLERHandleFIQ

HandlerIRQHANDLERHandleIRQ

HandlerUndefHANDLERHandleUndef

HandlerSWIHANDLERHandleSWI

HandlerDabortHANDLERHandleDabort

HandlerPabortHANDLERHandlePabort

;===================================================================================

,这一段程序就是用来进行第二次查表的过程了.

;如果说第一次查表是由硬件来完成的,那这一次查表就是由软件来实现的了.

;为什么要查两次表??

;没有办法,ARM把所有的中断都归纳成一个IRQ中断异常和一个FIRQ中断异常

;第一次查表主要是查出是什么异常,可我们总要知道是这个中断异常中的什么中断;

;===================================================================================

IsrIRQ

subsp,sp,#4;给PC寄存器保留

stmfdsp!,{r8-r9};把r8-r9压入栈

ldrr9,=INTOFFSET;把INTOFFSET的地址装入r9INTOFFSET是一个内部的寄存器,存着中断的偏移

ldrr9,[r9];把INTOFFSET的值装入r9

ldrr8,=HandleEINT0;这就是我们第二个中断向量表的入口的,先装入r8

;===================================================================================

;哈哈,这查表方法够好了吧,r8(入口)+index*4(别望了一条指令是4bytes的喔),

;这不就是我们要找的那一项了吗.找到了表项,下一步做什么?肯定先装入了!

;==================================================================================

addr8,r8,r9,lsl#2;地址对齐,因为每个中断向量占4个字节,即isr=IvectTable+Offeset*4

ldrr8,[r8];装入中断服务程序的入口

strr8,[sp,#8];把入口也入栈,准备用旧招

ldmfdsp!,{r8-r9,pc};施招,弹出栈,哈哈,顺便把r8弹出到PC,O了,跳转成功!

LTORG;声明文字池,因为我们用了ldr伪指令

;==============================================================================

;ENTRY(好了,我们的CPU要在这复位了.)

;==============================================================================

ResetHandler

ldrr0,=WTCON;1.关看门狗

ldrr1,=0x0;bit[5]:0-disable;1-enable(reset默认)

strr1,[r0]

ldrr0,=INTMSK

ldrr1,=0xffffffff;2.关中断

strr1,[r0]

ldrr0,=INTSUBMSK

ldrr1,=0x7fff;3.关子中断

strr1,[r0]

[{FALSE}

;4.得有些表示了,该点点LED灯了,不过被FALSE掉了.

;rGPFDAT=(rGPFDAT&~(0xf<<4))|((~data&0xf)<<4);

;Led_Display

ldrr0,=GPFCON

ldrr1,=0x5500

strr1,[r0]

ldrr0,=GPFDAT

ldrr1,=0x10

strr1,[r0]

]

;5.为了减少PLL的locktime,调整LOCKTIME寄存器.

ldrr0,=LOCKTIME

ldrr1,=0xffffff

strr1,[r0]

;6.下面就来设置PLL了,你的板快不快就看这了!!

;这里介绍一下计算公式

;//Fpllo=(m*Fin)/(p*2^s)

;//m=MDIV+8,p=PDIV+2,s=SDIV

;TheproperrangeofPandM:1<=P<=62,1<=M<=248

;Fpllo必须大于200Mhz小于600Mhz

;Fpllo*2^s必须小于1.2GHz

;如下面的PLLCON设定中的M_DIVP_DIVS_DIV是取自option.h中

;#elif(MCLK==40000000)

;#definePLL_M(0x48)

;#definePLL_P(0x3)

;#definePLL_S(0x2)

;所以m=MDIV+8=80,p=PDIV+2=5,s=SDIV=2

;硬件使用晶振为10Mhz,即Fin=10Mhz

;Fpllo=80*10/5*2^2=40Mhz

[PLL_ON_START

;Addedforconfirmclockdivide.for2440.

;SettingvalueFclk:Hclk:Pclk

ldrr0,=CLKDIVN

ldrr1,=CLKDIV_VAL;0=1:1:1,1=1:1:2,2=1:2:2,3=1:2:4,

strr1,[r0];4=1:4:4,5=1:4:8,6=1:3:3,7=1:3:6.

;//数据表示分频数

;===============================================================================

;MMU_SetAsyncBusMode和MMU_SetFastBusMode都在4K代码以上,

;如果你想你编译出来的程序能在NAND上运行的话,就不要在这调用这两函数了.

;如果你不要求的话,你就用把.啥事没有.

;为什么是4K,问三星吧,就提供4K的内部SRAM,要是提供400K多好呀.

;好了,好了,4K就4K吧,不能用这两函数,自己写还不行吗,下面的代码这这么来了,

;实现和上面两函数一样的功能.

;===============================================================================

;[CLKDIV_VAL>1;意思是Fclk:Hclk不是1:1.

;blMMU_SetAsyncBusMode

;|

;blMMU_SetFastBusMode;defaultvalue.

;]

[CLKDIV_VAL>1;意思是Fclk:Hclk不是1:1.

mrcp15,0,r0,c1,c0,0

orrr0,r0,#0xc0000000;R1_nF:OR:R1_iA

mcrp15,0,r0,c1,c0,0

|

mrcp15,0,r0,c1,c0,0

bicr0,r0,#0xc0000000;R1_iA:OR:R1_nF

mcrp15,0,r0,c1,c0,0

]

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

上接mini2440开发板中启动代码2440INIT.S分析(1)

;配置UPLL

;//ConfigureUPLLFin=12.0MHzUFout=48MHz

ldrr0,=UPLLCON

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

strr1,[r0]

nop;Caution:AfterUPLLsetting,atleast7-clocks

nop;delaymustbeinsertedforsettinghardwarebecompleted.

nop

nop

nop

nop

nop

;配置MPLL

;//ConfigureMPLLFin=12.0MHzMFout=304.8MHz一定要使最后的频率为16.9344MHz,不然你甭想用USB接口了

ldrr0,=MPLLCON

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

strr1,[r0]

]

;检查是否从SLEEP模式中恢复

ldrr1,=GSTATUS2

ldrr0,[r1]

tstr0,#0x2

;如果是从SLEEP模式中恢复,转跳到SLEEP_WAKEUP.

bneWAKEUP_SLEEP

EXPORTStartPointAfterSleepWakeUp;导出符号StartPointAfterSleepWakeUp

StartPointAfterSleepWakeUp

;===============================================================================

;设置内存控制器等寄存器的值,因为这些寄存器是连续排列的,所以采用如下办法对这些

;寄存器进行连续设置.其中用到了SMRDATA的数据,这在代码后面有定义

;===============================================================================

;ldrr0,=SMRDATA

adrlr0,SMRDATA;becareful!,hzh

ldrr1,=BWSCON;BWSCON地址

addr2,r0,#52;
SMRDATA
数据的结束地址,共有52字节的数据

0

ldrr3,[r0],#4

strr3,[r1],#4

cmpr2,r0

bne%B0

;================================================================================

;如果EINT0产生(这中断就是我们按键产生的),就清除SDRAM,不过好像没人会在这个时候按

;================================================================================

;checkifEIN0buttonispressed

ldrr0,=GPFCON

ldrr1,=0x0

strr1,[r0]

ldrr0,=GPFUP

ldrr1,=0xff

strr1,[r0]

ldrr1,=GPFDAT

ldrr0,[r1]

bicr0,r0,#(0x1e<<1);bitclear

tstr0,#0x1

bne%F1;如果没有按,就跳到后面的1标号处

;这就是清零内存的代码

ldrr0,=GPFCON

ldrr1,=0x55aa

strr1,[r0]

;ldrr0,=GPFUP

;ldrr1,=0xff

;strr1,[r0]

ldrr0,=GPFDAT

ldrr1,=0x0

strr1,[r0];LED=****

movr1,#0

movr2,#0

movr3,#0

movr4,#0

movr5,#0

movr6,#0

movr7,#0

movr8,#0

ldrr9,=0x4000000;64MB

ldrr0,=0x30000000

0

stmiar0!,{r1-r8}

subsr9,r9,#32

bne%B0

;到这就结束了.

1

blInitStacks;初始化堆栈

;blLed_Test;又是LED,注掉了

;=======================================================================

;哈哈,下面又有看头了,这个初始化程序好像被名曰hzh的高手改过

;能在NORNAND还有内存中运行,当然了,在内存中运行最简单了.

;在NORNAND中运行的话都要先把自己拷到内存中.

;此外,还记得上面提到的|Image$$RO$$Base|,|Image$$RO$$Limit|...吗?

;这就是拷贝的依据了!!!

;=========================================================================

ldrr0,=BWSCON

ldrr0,[r0]

andsr0,r0,#6;OM[1:0]!=0,从NORFLash启动或直接在内存运行

bnecopy_proc_beg;不读取NANDFLASH

adrr0,ResetEntry;OM[1:0]==0,为从NANDFLash启动

cmpr0,#0;再比较入口是否为0地址处

;==========================================================================

;如果不是,则表示主板设置了从NAND启动,但这个程序由于其它原因,

;并没有从NAND启动,这种情况最有可能的原因就是用仿真器.

;==========================================================================

bnecopy_proc_beg;这种情况也不读取NANDFLASH.

;nop;如果是0才是真正从NAND启动,因为其4k被复制到0地址开始的stepingstone内部sram中

;注意adr得到的是相对地址,非绝对地址==ifuseMulti-ice,

;===========================================================

nand_boot_beg;这一段代码完成从NAND读代码到RAM

movr5,#NFCONF;首先设定NAND的一些控制寄存器

;settimingvalue

ldrr0,=(7<<12)|(7<<8)|(7<<4)

strr0,[r5]

;enablecontrol

ldrr0,=(0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0)

strr0,[r5,#4]

blReadNandID;按着读取NAND的ID号,结果保存在r5里

movr6,#0;r6设初值0.

ldrr0,=0xec73;期望的NANDID号

cmpr5,r0;这里进行比较

beq%F1;相等的话就跳到下一个1标号处

ldrr0,=0xec75;这是另一个期望值

cmpr5,r0

beq%F1;相等的话就跳到下一个1标号处

movr6,#1;不相等了,设置r6=1.

1

blReadNandStatus;读取NAND状态,结果放在r1里

movr8,#0;r8设初值0,意义为页号

ldrr9,=ResetEntry;r9设初值为初始化程序入口地址

;=========================================================================

;注意,在这里使用的是ldr伪指令,而不是上面用的adr伪指令,它加载的是ResetEntry

;的决对地址,也就是我们期望的RAM中的地址,在这里,它和|Image$$RO$$Base|一样

;也就是说,我如我们编译程序时ROBASE指定的地址在RAM里,而把生成的文件拷到

;NAND里运行,由ldr加载的r9的值还是定位在内存.

;=========================================================================

2

andsr0,r8,#0x1f;凡r8为0x1f(32)的整数倍-1,eq有效,ne无效

bne%F3;这句的意思是对每个块(32页)进行检错

movr0,r8;r8->r0

blCheckBadBlk;检查NAND的坏区

cmpr0,#0;比较r0和0

addner8,r8,#32;存在坏块的话就跳过这个坏块

bne%F4;没有的话就跳到标号4处

3

movr0,r8;当前页号->r0

movr1,r9;当前目标地址->r1

blReadNandPage;读取该页的NAND数据到RAM

addr9,r9,#512;每一页的大小是512Bytes

addr8,r8,#1;r8指向下一页

4

cmpr8,#256;比较是否读完256页即128KBytes

bcc%B2;如果r8小于256(没读完),就返回前面的标号2处

movr5,#NFCONF;DsNandFlash

ldrr0,[r5,#4]

bicr0,r0,#1

strr0,[r5,#4]

ldrpc,=copy_proc_beg;调用copy_proc_beg

;===========================================================

copy_proc_beg

adrr0,ResetEntry;ResetEntry值->r0

ldrr2,BaseOfROM;BaseOfROM值(后面有定义)->r2

cmpr0,r2;比较r0和r2

ldreqr0,TopOfROM;如果相等的话(在内存运行),TopOfROM->r0

beqInitRam;同时跳到InitRam

;=========================================================

;下面这个是针对代码在NORFLASH时的拷贝方法

;功能为把从ResetEntry起,TopOfROM-BaseOfROM大小的数据拷到BaseOfROM

;TopOfROM和BaseOfROM为|Image$$RO$$Limit|和|Image$$RO$$Base|

;|Image$$RO$$Limit|和|Image$$RO$$Base|由连接器生成

;为生成的代码的代码段运行时的起启和终止地址

;BaseOfBSS和BaseOfZero为|Image$$RW$$Base|和|Image$$ZI$$Base|

;|Image$$RW$$Base|和|Image$$ZI$$Base|也是由连接器生成

;两者之间就是初始化数据的存放地放

;=======================================================

ldrr3,TopOfROM

0

ldmiar0!,{r4-r7}

stmiar2!,{r4-r7}

cmpr2,r3

bcc%B0

subr2,r2,r3;r2=BaseOfROM-TopOfROM=(-)代码长度

subr0,r0,r2;r0=ResetEntry-(-)代码长度=ResetEntry+代码长度

InitRam

ldrr2,BaseOfBSS;BaseOfBSS->r2

ldrr3,BaseOfZero;BaseOfZero->r3

0

cmpr2,r3;比较BaseOfBSS和BaseOfZero

ldrccr1,[r0],#4;要是r21;meansFclk:Hclkisnot1:1.

;blMMU_SetAsyncBusMode

;|

;blMMU_SetFastBusMode;defaultvalue.

;]

;blLed_Test

;===========================================================

;进入C语言前的最后一步了,就是把我们用说查二级向量表

;的中断例程安装到一级向量表(异常向量表)里.

ldrr0,=HandleIRQ;Thisroutineisneeded

ldrr1,=IsrIRQ;ifthereisnot'subspc,lr,#4'at0x18,0x1c

strr1,[r0]

;;CopyandpasteRWdata/zeroinitializeddata

;ldrr0,=|Image$$RO$$Limit|;GetpointertoROMdata

;ldrr1,=|Image$$RW$$Base|;andRAMcopy

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

;

;;Zeroinitbase=>top
of
initialiseddata

;cmpr0,r1;Checkthattheyaredifferent

;beq%F2

;1

;cmpr1,r3;Copyinitdata

;ldrccr2,[r0],#4;-->LDRCCr2,[r0]+ADDr0,r0,#4

;strccr2,[r1],#4;-->STRCCr2,[r1]+ADDr1,r1,#4

;bcc%B1

;2

;ldrr1,=|Image$$ZI$$Limit|;Top
of
zeroinitsegment

;movr2,#0

;3

;cmpr3,r1;Zeroinit

;strccr2,[r3],#4

;bcc%B3

;*****************************************************************************

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

;妈呀,终说见到艳阳天了!!!!!!!!!!

;跳到C语言的main函数处了.

;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

;*****************************************************************************

[:LNOT:THUMBCODE

blMain;Donotusemain()because......

;ldrpc,=Main;hzh

b.

]

[THUMBCODE;forstart-upcodeforThumbmode

orrlr,pc,#1

bxlr

CODE16

blMain;Donotusemain()because......

b.

CODE32

]

;initializingstacks

InitStacks

;DonotuseDRAM,suchasstmfd,ldmfd......

;SVCstackisinitializedbefore

;Undertoolkitver2.5,'msrcpsr,r1'canbeusedinstead
of
'msrcpsr_cxsf,r1'

mrsr0,cpsr

bicr0,r0,#MODEMASK

orrr1,r0,#UNDEFMODE|NOINT

msrcpsr_cxsf,r1;UndefMode

ldrsp,=UndefStack;UndefStack=0x33FF_5C00

orrr1,r0,#ABORTMODE|NOINT

msrcpsr_cxsf,r1;AbortMode

ldrsp,=AbortStack;AbortStack=0x33FF_6000

orrr1,r0,#IRQMODE|NOINT

msrcpsr_cxsf,r1;IRQMode

ldrsp,=IRQStack;IRQStack=0x33FF_7000

orrr1,r0,#FIQMODE|NOINT

msrcpsr_cxsf,r1;FIQMode

ldrsp,=FIQStack;FIQStack=0x33FF_8000

bicr0,r0,#MODEMASK|NOINT

orrr1,r0,#SVCMODE

msrcpsr_cxsf,r1;SVCMode

ldrsp,=SVCStack;SVCStack=0x33FF_5800

;USERmodehasnotbeinitialized.

movpc,lr

;TheLRregisterwillnotbevalidifthecurrentmodeisnotSVCmode.

;===========================================================

ReadNandID

movr7,#NFCONF

ldrr0,[r7,#4];NFChipEn();

bicr0,r0,#2

strr0,[r7,#4]

movr0,#0x90;WrNFCmd(RdIDCMD);

strbr0,[r7,#8]

movr4,#0;WrNFAddr(0);

strbr4,[r7,#0xc]

1;while(NFIsBusy());

ldrr0,[r7,#0x20]

tstr0,#1

beq%B1

ldrbr0,[r7,#0x10];id=RdNFDat()<<8;

movr0,r0,lsl#8

ldrbr1,[r7,#0x10];id|=RdNFDat();

orrr5,r1,r0

ldrr0,[r7,#4];NFChipDs();

orrr0,r0,#2

strr0,[r7,#4]

movpc,lr

ReadNandStatus

movr7,#NFCONF

ldrr0,[r7,#4];NFChipEn();

bicr0,r0,#2

strr0,[r7,#4]

movr0,#0x70;WrNFCmd(QUERYCMD);

strbr0,[r7,#8]

ldrbr1,[r7,#0x10];r1=RdNFDat();

ldrr0,[r7,#4];NFChipDs();

orrr0,r0,#2

strr0,[r7,#4]

movpc,lr

WaitNandBusy

movr0,#0x70;WrNFCmd(QUERYCMD);

movr1,#NFCONF

strbr0,[r1,#8]

1;while(!(RdNFDat()&0x40));

ldrbr0,[r1,#0x10]

tstr0,#0x40

beq%B1

movr0,#0;WrNFCmd(READCMD0);

strbr0,[r1,#8]

movpc,lr

CheckBadBlk

movr7,lr

movr5,#NFCONF

bicr0,r0,#0x1f;addr&=~0x1f;

ldrr1,[r5,#4];NFChipEn()

bicr1,r1,#2

strr1,[r5,#4]

movr1,#0x50;WrNFCmd(READCMD2)

strbr1,[r5,#8]

movr1,#5;6;6->5

strbr1,[r5,#0xc];WrNFAddr(5);(6)6->5

strbr0,[r5,#0xc];WrNFAddr(addr)

movr1,r0,lsr#8;WrNFAddr(addr>>8)

strbr1,[r5,#0xc]

cmpr6,#0;if(NandAddr)

movner0,r0,lsr#16;WrNFAddr(addr>>16)

strnebr0,[r5,#0xc]

;blWaitNandBusy;WaitNFBusy()

;donotuseWaitNandBusy,afterWaitNandBusywillreadpartA!

movr0,#100

1

subsr0,r0,#1

bne%B1

2

ldrr0,[r5,#0x20]

tstr0,#1

beq%B2

ldrbr0,[r5,#0x10];RdNFDat()

subr0,r0,#0xff

movr1,#0;WrNFCmd(READCMD0)

strbr1,[r5,#8]

ldrr1,[r5,#4];NFChipDs()

orrr1,r1,#2

strr1,[r5,#4]

movpc,r7

ReadNandPage

movr7,lr

movr4,r1

movr5,#NFCONF

ldrr1,[r5,#4];NFChipEn()

bicr1,r1,#2

strr1,[r5,#4]

movr1,#0;WrNFCmd(READCMD0)

strbr1,[r5,#8]

strbr1,[r5,#0xc];WrNFAddr(0)

strbr0,[r5,#0xc];WrNFAddr(addr)

movr1,r0,lsr#8;WrNFAddr(addr>>8)

strbr1,[r5,#0xc]

cmpr6,#0;if(NandAddr)

movner0,r0,lsr#16;WrNFAddr(addr>>16)

strnebr0,[r5,#0xc]

ldrr0,[r5,#4];InitEcc()

orrr0,r0,#0x10

strr0,[r5,#4]

blWaitNandBusy;WaitNFBusy()

movr0,#0;for(i=0;i<512;i++)

1

ldrbr1,[r5,#0x10];buf[i]=RdNFDat()

strbr1,[r4,r0]

addr0,r0,#1

bicr0,r0,#0x10000

cmpr0,#0x200

bcc%B1

ldrr0,[r5,#4];NFChipDs()

orrr0,r0,#2

strr0,[r5,#4]

movpc,r7

;--------------------LEDtest

EXPORTLed_Test

Led_Test

movr0,#0x56000000

movr1,#0x5500

strr1,[r0,#0x50]

0

movr1,#0x50

strr1,[r0,#0x54]

movr2,#0x100000

1

subsr2,r2,#1

bne%B1

movr1,#0xa0

strr1,[r0,#0x54]

movr2,#0x100000

2

subsr2,r2,#1

bne%B2

b%B0

movpc,lr

;===========================================================

LTORG

;GCS0->SST39VF1601

;GCS1->16c550

;GCS2->IDE

;GCS3->CS8900

;GCS4->DM9000

;GCS5->CFCard

;GCS6->SDRAM

;GCS7->unused

SMRDATADATA

;Memoryconfigurationshouldbeoptimizedforbestperformance

;Thefollowingparameterisnotoptimized.

;Memoryaccesscycleparameterstrategy

;1)ThememorysettingsissafeparametersevenatHCLK=75Mhz.

;2)SDRAMrefreshperiodisforHCLK<=75Mhz.

DCD(0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))

DCD((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC));GCS0

DCD((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC));GCS1

DCD((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC));GCS2

DCD((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC));GCS3

DCD((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC));GCS4

DCD((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC));GCS5

DCD((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN));GCS6

DCD((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN));GCS7

DCD((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Tsrc<<18)+(Tchr<<16)+REFCNT)

DCD0x32;SCLKpowersavingmode,BANKSIZE128M/128M

DCD0x30;MRSR6CL=3clk

DCD0x30;MRSR7CL=3clk

BaseOfROMDCD|Image$$RO$$Base|

TopOfROMDCD|Image$$RO$$Limit|

BaseOfBSSDCD|Image$$RW$$Base|

BaseOfZeroDCD|Image$$ZI$$Base|

EndOfBSSDCD|Image$$ZI$$Limit|

ALIGN

;forenteringpowerdownmode

;1.SDRAMshouldbeinself-refreshmode.

;2.AllinterruptshouldbemakskedforSDRAM/DRAMself-refresh.

;3.LCDcontrollershouldbedisabledforSDRAM/DRAMself-refresh.

;4.TheI-cachemayhavetobeturnedon.

;5.Thelocation
of
thefollowingcodemayhavenottobechanged.

;voidEnterPWDN(intCLKCON);

EnterPWDN

movr2,r0;r2=rCLKCON

tstr0,#0x8;SLEEPmode?

bneENTER_SLEEP

ENTER_STOP

ldrr0,=REFRESH

ldrr3,[r0];r3=rREFRESH

movr1,r3

orrr1,r1,#BIT_SELFREFRESH

strr1,[r0];EnableSDRAMself-refresh

movr1,#16;waituntilself-refreshisissued.maynotbeneeded.

0subsr1,r1,#1

bne%B0

ldrr0,=CLKCON;enterSTOPmode.

strr2,[r0]

movr1,#32

0subsr1,r1,#1;1)waituntiltheSTOPmodeisineffect.

bne%B0;2)OrwaithereuntiltheCPU&Peripheralswillbeturned-off

;EnteringSLEEPmode,onlytheresetbywake-upisavailable.

ldrr0,=REFRESH;exitfromSDRAMselfrefreshmode.

strr3,[r0]

MOV_PC_LR

ENTER_SLEEP

;NOTE.

;1)rGSTATUS3shouldhavethereturn
address
afterwake-upfromSLEEPmode.

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

ldrr0,[r1]

orrr0,r0,#(7<<17);SetSCLK0=0,SCLK1=0,SCKE=0.

strr0,[r1]

ldrr0,=CLKCON;Entersleepmode

strr2,[r0]

b.;CPUwilldiehere.

WAKEUP_SLEEP

;ReleaseSCLKnafterwake-upfromtheSLEEPmode.

ldrr1,=MISCCR

ldrr0,[r1]

bicr0,r0,#(7<<17);SCLK0:0->SCLK,SCLK1:0->SCLK,SCKE:0->=SCKE.

strr0,[r1]

;Setmemorycontrolregisters

ldrr0,=SMRDATA;becareful!,hzh

ldrr1,=BWSCON;BWSCON
Address


addr2,r0,#52;EndaddressofSMRDATA

0

ldrr3,[r0],#4

strr3,[r1],#4

cmpr2,r0

bne%B0

movr1,#256

0subsr1,r1,#1;1)waituntiltheSelfRefreshisreleased.

bne%B0

ldrr1,=GSTATUS3;GSTATUS3hasthestart
address
justafterSLEEPwake-up

ldrr0,[r1]

movpc,r0

;=====================================================================

;Clockdivisiontest

;Assemblecode,becauseVSYNCtimeisveryshort

;=====================================================================

EXPORTCLKDIV124

EXPORTCLKDIV144

CLKDIV124

ldrr0,=CLKDIVN

ldrr1,=0x3;0x3=1:2:4

strr1,[r0]

;waituntilclockisstable

nop

nop

nop

nop

nop

ldrr0,=REFRESH

ldrr1,[r0]

bicr1,r1,#0xff

bicr1,r1,#(0x7<<8)

orrr1,r1,#0x470;REFCNT135

strr1,[r0]

nop

nop

nop

nop

nop

movpc,lr

CLKDIV144

ldrr0,=CLKDIVN

ldrr1,=0x4;0x4=1:4:4

strr1,[r0]

;waituntilclockisstable

nop

nop

nop

nop

nop

ldrr0,=REFRESH

ldrr1,[r0]

bicr1,r1,#0xff

bicr1,r1,#(0x7<<8)

orrr1,r1,#0x630;REFCNT675-1520

strr1,[r0]

nop

nop

nop

nop

nop

movpc,lr

ALIGN

AREARamData,DATA,READWRITE

^_ISR_STARTADDRESS;_ISR_STARTADDRESS=0x33FF_FF00

HandleReset#4

HandleUndef#4

HandleSWI#4

HandlePabort#4

HandleDabort#4

HandleReserved#4

HandleIRQ#4

HandleFIQ#4

;Donotusethelabel'IntVectorTable',

;ThevalueofIntVectorTableisdifferentwiththeaddressyouthinkitmaybe.

;IntVectorTable

;@0x33FF_FF20

HandleEINT0#4

HandleEINT1#4

HandleEINT2#4

HandleEINT3#4

HandleEINT4_7#4

HandleEINT8_23#4

HandleCAM#4;Addedfor2440.

HandleBATFLT#4

HandleTICK#4

HandleWDT#4

HandleTIMER0#4

HandleTIMER1#4

HandleTIMER2#4

HandleTIMER3#4

HandleTIMER4#4

HandleUART2#4

;@0x33FF_FF60

HandleLCD#4

HandleDMA0#4

HandleDMA1#4

HandleDMA2#4

HandleDMA3#4

HandleMMC#4

HandleSPI0#4

HandleUART1#4

HandleNFCON#4;Addedfor2440.

HandleUSBD#4

HandleUSBH#4

HandleIIC#4

HandleUART0#4

HandleSPI1#4

HandleRTC#4

HandleADC#4

;@0x33FF_FFA0
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: