AREA Init,CODE,READONLY //AREA用于定义一个代码段或数据段,此处为代码段。Init为名称,CODE表明是代码段,READONLY表示只读属性
ENTRY //入口点指令
EXPORT __ENTRY
__ENTRY ResetEntry
;1)The code, which converts to Big-endian, should be in little endian code.
;2)The following little endian code will be compiled in Big-Endian mode.
; The code byte order should be changed as the memory bus width.
;3)The pseudo instruction,DCD can not be used here because the linker generates error.
ASSERT :DEF:ENDIAN_CHANGE //判断是否定义了ENDIAN_CHANGE ,如果有定义,则报告该处错误信息
[ ENDIAN_CHANGE
ASSERT :DEF:ENTRY_BUS_WIDTH
[ ENTRY_BUS_WIDTH=32 //相应总线宽度的执行
b ChangeBigEndian ;DCD 0xea000007
]
[ ENTRY_BUS_WIDTH=16
andeq r14,r7,r0,lsl #20 ;DCD 0x0007ea00
]
[ ENTRY_BUS_WIDTH=8
streq r0,[r0,-r10,ror #1] ;DCD 0x070000ea
]
|
b ResetHandler //如果没有定义总线宽度,跳到ResetHandler处复位
]
b HandlerUndef ;handler for Undefined mode 未定义
b HandlerSWI ;handler for SWI interrupt 软件中断
b HandlerPabort ;handler for PAbort 指令预取中止
b HandlerDabort ;handler for DAbort 数据访问中止
b . ;reserved 保留,跳转到地址自身处,即进入死循环
b HandlerIRQ ;handler for IRQ interrupt 外部中断请求
b HandlerFIQ ;handler for FIQ interrupt 快速中断请求
;@0x20
b EnterPWDN ; Must be @0x20. //进入POWER Down模式
ChangeBigEndian //一下是改变大小端的程式,直接定义了机器码的方式
;@0x24
[ ENTRY_BUS_WIDTH=32
DCD 0xee110f10 ;0xee110f10 => mrc p15,0,r0,c1,c0,0
DCD 0xe3800080 ;0xe3800080 => orr r0,r0,#0x80; //Big-endian
DCD 0xee010f10 ;0xee010f10 => mcr p15,0,r0,c1,c0,0
]
[ ENTRY_BUS_WIDTH=16
DCD 0x0f10ee11
DCD 0x0080e380
DCD 0x0f10ee01
]
[ ENTRY_BUS_WIDTH=8
DCD 0x100f11ee
DCD 0x800080e3
DCD 0x100f01ee
]
DCD 0xffffffff ;swinv 0xffffff is similar with NOP and run well in both endian mode.
DCD 0xffffffff
DCD 0xffffffff
DCD 0xffffffff
DCD 0xffffffff
b ResetHandler
//采用HANDLER宏,建立Handler***和Handle***之间的关系
HandlerFIQ HANDLER HandleFIQ
HandlerIRQ HANDLER HandleIRQ
HandlerUndef HANDLER HandleUndef
HandlerSWI HANDLER HandleSWI
HandlerDabort HANDLER HandleDabort
HandlerPabort HANDLER HandlePabort
/*ARM将所有的中断归纳成了IRQ和FIQ,以下的程式用于查找具体的中断类型,即二级中断向量表。利用INTOFFSET寄存器判定IRQ中断源*/
IsrIRQ
sub sp,sp,#4 ;reserved for PC
stmfd sp!,{r8-r9}
ldr r9,=INTOFFSET
ldr r9,[r9]
ldr r8,=HandleEINT0
add r8,r8,r9,lsl #2
ldr r8,[r8]
str r8,[sp,#8]
ldmfd sp!,{r8-r9,pc}
LTORG
;=======
; ENTRY
;=======
ResetHandler //系统上电或复位后,由0x0处的跳转指令,跳转到该处开始真正执行系统的初始化工作
ldr r0,=WTCON ;watch dog disable //在系统初始化的过程中,不需要看门狗,所以将此功能关闭
ldr r1,=0x0
str r1,[r0]
ldr r0,=INTMSK //此时也不应该相应任何的中断,因此屏蔽所有的中断以及子中断
ldr r1,=0xffffffff ;all interrupt disable
str r1,[r0]
ldr r0,=INTSUBMSK
ldr r1,=0x7fff ;all sub interrupt disable
str r1,[r0]
/*由于启动文件是无法仿真的,因此为了判断该文件中的语句是否正确执行了,往往在需要的地方加上点亮led的程式,这样就可以知道程式是否按照所设计的执行了。*/
[ {FALSE}
;rGPFDAT = (rGPFDAT & ~(0xf<<4)) | ((~data & 0xf)<<4);
; Led_Display
ldr r0,=GPBCON
ldr r1,=0x155500
str r1,[r0]
ldr r0,=GPBDAT
ldr r1,=0x0
str r1,[r0]
]
;To reduce PLL lock time, adjust the LOCKTIME register.
ldr r0,=LOCKTIME
ldr r1,=0xffffff
str r1,[r0]
[ PLL_ON_START
; Added for confirm clock divide. for 2440.
; Setting value Fclk:Hclk:Pclk
ldr r0,=CLKDIVN
ldr r1,=CLKDIV_VAL ; 0=1:1:1, 1=1:1:2, 2=1:2:2, 3=1:2:4, 4=1:4:4, 5=1:4:8, 6=1:3:3, 7=1:3:6.
str r1,[r0]
;program has not been copied, so use these directly
[ CLKDIV_VAL>1 ; means Fclk:Hclk is not 1:1.
mrc p15,0,r0,c1,c0,0
orr r0,r0,#0xc0000000;R1_nF:OR:R1_iA
mcr p15,0,r0,c1,c0,0
|
mrc p15,0,r0,c1,c0,0
bic r0,r0,#0xc0000000;R1_iA:OR:R1_nF
mcr p15,0,r0,c1,c0,0
]
;Configure UPLL
ldr r0,=UPLLCON
ldr r1,=((U_MDIV<<12)+(U_PDIV<<4)+U_SDIV) ;Fin = 12.0MHz, UCLK = 48MHz
str r1,[r0]
nop ; Caution: After UPLL setting, at least 7-clocks delay must be inserted for setting hardware be completed.
nop
nop
nop
nop
nop
nop
;Configure MPLL
ldr r0,=MPLLCON
ldr r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV) ;Fin = 12.0MHz, FCLK = 400MHz
str r1,[r0]
]
//检测启动是否由睡眠模式唤醒,如果是的话,就跳到WAKEUP_SLEEP执行相应的操作
;Check if the boot is caused by the wake-up from SLEEP mode.
ldr r1,=GSTATUS2
ldr r0,[r1]
tst r0,#0x2
;In case of the wake-up from SLEEP mode, go to SLEEP_WAKEUP handler.
bne WAKEUP_SLEEP
nxzcc 于 2011-03-15 08:42:03发表:
支持楼主
txgc_wm 于 2011-03-14 22:09:03发表:
对于中断模块、电源及时钟频率的一些具体说明,本人还不是很明了。待后续的补充!