;========================================================================================
//在这儿用IMP
//这些变量是经过ADS的工程设置里边设定的RO Base和RW Base设定的,终究由编译脚本和衔接程序导入程序.
//那为什么要引进这玩意呢,最简略的用途是能够依据它们复制自已,从把RW和ZI变量从加载域中复制到运转域中
//一个arm由RO,RW,ZI三个断组成其间RO为代码段,RW是现已初始化的全局变量,ZI是未初始化的全局变量(关于GNU东西对应的概念是TEXT ,DA
;========================================================================================
IMP
IMP
IMP
IMP
IMP
;这儿引进一些在其它文件中完成在函数,包含为咱们所熟知的main函数
IMP
;从这儿开端便是正真的代码进口了!
AREA Init,CO
ENTRY ;界说程序的进口(调试用)其间关键字ENTRY是指定编译器保存这段代码,由于
编译器可能会以为这是一段亢余代码而加以优化。链接的时分要保证这段代码
被链接在0地址处,而且作为整个程序的进口
;1)The co
;2)The following little endian co
; The co
;3)The pseudo instruction,DCD can not be used here because the linker generates error.
ASSERT :DEF:ENDIAN_CHANGE
[ ENDIAN_CHANGE ;下面是巨细端的一个判别,在Option.inc里现已设为FALSE
ASSERT :DEF:ENTRY_BUS_WIDTH
[ ENTRY_BUS_WIDTH=32 //‘[’=IF
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 ;由于设成FALSE,所以体系复位后就来到这了,转跳到复位程序进口
]
//=====================================================================================
;ARM要求中止向量表有必要放置在仿地址开端,接连8X4字节的空间内.每逢一个中止发生今后,ARM处理器便强制把PC指针置为向量表中对应中止类型的地址值。由于每个中止只占有向量表中1个字的存储空间,只能放置一条ARM指令,使程序跳转到存储器的其他地方,再履行中止处理
//=====================================================================================
b HandlerUndef ;转跳到Undefined mode程序进口
b HandlerSWI ;转跳到SWI 中止程序进口
b HandlerPabort ;转跳到PAbort(指令反常)程序进口
b HandlerDabort ;转跳到DAbort(数据反常)程序进口
b . ;保存
b HandlerIRQ ;转跳到IRQ 中止程序进口
b HandlerFIQ ;转跳到FIQ 中止程序进口
;@0x20不知道是什么意思,地址?
b EnterPWDN ; Must be @0x20.
;==================================================================================
;下面是改动巨细端的程序,这儿选用直接界说机器码的办法,至说为什么这么做就得问三星了
;横竖咱们程序里这段代码也不会去履行,不必去管它
;==================================================================================
ChangeBigEndian //经过设置CP15中的C1的位7来设置存储格局为大端形式。
;@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
;Function for entering power down mode,下面这段程序为进入掉电形式及从掉电形式中唤醒的相关设置和处理
; 1. SDRAM should be in self-refresh mode. SDRAm应该设置为自改写的形式
; 2. All interrupt should be maksked for SDRAM/DRAM self-refresh. 一切中止有必要屏蔽 for SDRAM/DRAM self-ref
; 3. LCD controller should be disabled for SDRAM/DRAM self-refresh. LCD 操控器封闭
; 4. The I-cache may have to be turned on.
; 5. The location of the following co
//;void EnterPWDN(int CLKCON); //PWDN:powerdown
EnterPWDN
mov r2,r0;r2=rCLKCON //rCLKCONr [3;2]位为电源形式标置位。若[3]为1,表明转为了掉电形式
tst r0,#0x8;POWER_OFF mode?//按位与判别,若[3]为1则跳转到ENTER_POWER_OFF
bne ENTER_POWER_OFF
ENTER_STOP//进入中止形式相关处理
ldr r0,=REFRESH
ldr r3,[r0];r3=rREFRESH
mov r1, r3
orr r1, r1, #BIT_SELFREFRESH
str r1, [r0] ;Enable SDRAM self-refresh
mov r1,#16 ;wait until self-refresh is issued. may not be needed.等候自改写收效
0subs r1,r1,#1
bne %B0//表明不相等则往回跳转到标号为0的方位,在此为上一句。
ldr r0,=CLKCON;enter STOP mode.
str r2,[r0]
mov r1,#32
0subs r1,r1,#1 ;1) wait until the STOP mode is in effect.
bne %B0 ;2) Or wait here until the CPU&Peripherals will be turned-off
; Entering POWER_OFF mode, on
//进入掉电 形式后,仅唤醒中止有用
ldr r0,=REFRESH;exit from SDRAM self refresh mode.
str r3,[r0]
MOV_PC_LR//开端处界说的回来跳转宏
ENTER_POWER_OFF
;NOTE.注意在rGSTATUS3寄存器中应该保存掉电形式唤醒的回来地址,rGSTATUS3,4可在掉电下保存信息
;1) rGSTATUS3 should have the return address after wake-up from POWER_OFF mode.
ldr r0,=REFRESH
ldr r1,[r0];r1=rREFRESH
orr r1, r1, #BIT_SELFREFRESH
str r1, [r0];Enable SDRAM self-refresh
mov r1,#16 ;Wait until self-refresh is issued,which may not be needed.
0subs r1,r1,#1
bne %B0
ldr r1,=MISCCR
ldrr0,[r1]
orrr0,r0,#(7<<17) ;Make sure that SCLK0:SCLK->0, SCLK1:SCLK->0, SCKE=L during boot-up
strr0,[r1]
ldr r0,=CLKCON
str r2,[r0]
b .;CPU will die here.
;=================================================================================
从掉电形式唤醒的进程
1、某个唤醒源收效将发生一个内部复位信号。复位时刻由一个内部16位计数器决议,此计数器的时钟是tRST=(65535/XTAL_frequency)。
2、查询GSTATUS[2]位看从掉电形式唤醒是否发生了一个POWER-UP。
3、经过将MISCCR[19:17]设置为000b,开释SDRAM信号维护。
4、装备SDRAM操控器。
5、等候SDRAM自我改写结束。大部分SDRAM需求refresh cycle of all SDRAM row。
6、GSTATUS3,4的信息能够被用户运用,由于GSTATUS3,4的值现已在掉电形式下被保存了。
7、关于EINT[3:0],查看SRCPND寄存器;关于EINT[15:4],查看EINTPND寄存器;关于RTC报警唤醒,查看RTC时刻,由于在唤醒时SRCPND寄存器的RTC位不被置位;如果在掉电形式期间有nBATT-FLT assertion,SRCPND寄存器的相关位被置位。
;==================================================================================
WAKEUP_POWER_OFF
;Release SCLKn after wake-up from the POWER_OFF mode.
ldr r1,=MISCCR//MISCCR寄存器用来设置一些USB等相关的时钟周期等
ldrr0,[r1]
bicr0,r0,#(7<<17)//SCLK0:0->SCLK, SCLK1:0->SCLK, SCKE:L->H
strr0,[r1]//经过将MISCCR[19:17]设置为000b,开释SDRAM信号维护。
;Set memory control registers装备内存操控寄存器。
ldrr0,=SMRDATA//在程序的后边LTORGSMRDATA DA
//一个数据缓冲池便是用来装备相关的内存操控寄存器的
ldrr1,=BWSCON ;BWSCON Address
addr2, r0, #52 ;End address of SMRDATA
0
ldrr3, [r0], #4
strr3, [r1], #4
cmpr2, r0
bne%B0
mov r1,#256
0subs r1,r1,#1 ;1) wait until the SelfRefresh is released.
bne %B0
ldr r1,=GSTATUS3 ; GSTATUS3 has the start address just after POWER_OFF wake-up
ldr r0,[r1]
mov pc,r0 //从掉电形式下唤醒后,将保存在GSTATUS3 回来地址传给PC
如上所说,这儿选用HANDLER宏去树立Hander***和Handle***之间的联络
LTORG ;声明文字池,由于咱们用了ldr伪指令
HandlerFIQ HANDLER HandleFIQ
HandlerIRQ HANDLER HandleIRQ
HandlerUndef HANDLER HandleUndef
HandlerSWI HANDLER HandleSWI
HandlerDabort HANDLER HandleDabort
HandlerPabort HANDLER HandlePabort
;===================================================================================
;呵呵,来了来了.好戏来了,这一段程序便是用来进行第2次查表的进程了.
;如果说第一次查表是由硬件来完结的,那这一次查表便是由软件来完成的了.
;为什么要查两次表??
;没有办法,ARM把一切的中止都概括成一个IRQ中止反常和一个FIRQ中止反常
;第一次查表主要是查出是什么反常,可咱们总要知道是这个中止反常中的什么中止呀!
;没办法了,再查一次表呗!
;===================================================================================
IsrIRQ//第2次中止查表,由于ARM把一切的中止都归为一个IRQ反常,经过此处查表可知道详细中止
sub sp,sp,#4 ;给PC寄存器保存
stmfd sp!,{r8-r9} ;把r8-r9压入栈
ldr r9,=INTOFFSET ;把INTOFFSET的地址装入r9
ldr r9,[r9] ;把INTOFFSET的值装入r9
ldr r8,=HandleEINT0 ;这便是咱们第二个中止向量表的进口的,先装入r8
;===================================================================================
;哈哈,这查表办法够好了吧,r8(进口)+index*4(别望了一条指令是4 bytes的喔),
;这不便是咱们要找的那一项了吗.找到了表项,下一步做什么?必定先装入了!
;==================================================================================
add r8,r8,r9,lsl #2
ldr r8,[r8] ;装入中止服务程序的进口
str r8,[sp,#8] ;把进口也入栈,预备用旧招
ldmfd sp!,{r8-r9,pc};施招,弹出栈,哈哈,顺便把r8弹出到PC,O了,跳转成功!