2440init.s
BIT_SELFREFRESH EQU (1<<22)
;Pre-defined constants USERMODE EQU
0x10
FIQMODE EQU 0x11 IRQMODE EQU 0x12 SVCMODE EQU 0x13
ABORTMODE EQU 0x17 UNDEFMODE EQU MODEMASK EQU
0x1b 0x1f
GET option.inc GET memcfg.inc GET 2440addr.inc
NOINT EQU 0xc0
;The location of stacks UserStack SVCStack
EQU EQU
(_STACK_BASEADDRESS-0x3800) ;0x33ff4800 ~ (_STACK_BASEADDRESS-0x2800) ;0x33ff5800 ~
UndefStack EQU (_STACK_BASEADDRESS-0x2400) ;0x33ff5c00 ~ AbortStack EQU (_STACK_BASEADDRESS-0x2000) ;0x33ff6000 ~ IRQStack EQU (_STACK_BASEADDRESS-0x1000) ;0x33ff7000 ~ FIQStack EQU (_STACK_BASEADDRESS-0x0) ;0x33ff8000 ~
;Check if tasm.exe(armasm -16 ...@ADS 1.0) is used. GBLL THUMBCODE [ {CONFIG} = 16
THUMBCODE SETL {TRUE}
CODE32 |
THUMBCODE SETL {FALSE} ]
MACRO
MOV_PC_LR [ THUMBCODE bx lr
| mov pc,lr ] MEND
MACRO
MOVEQ_PC_LR [ THUMBCODE bxeq lr |
moveq pc,lr
] MEND
MACRO
$HandlerLabel HANDLER $HandleLabel
$HandlerLabel sub sp,sp,#4 ;decrement sp(to store jump address)
stmfd sp!,{r0} ;PUSH the work register to stack(lr does't push because it return to original address)
ldr r0,=$HandleLabel;load the address of HandleXXX to r0 ldr r0,[r0] ;load the contents(service routine start address) of HandleXXX str r0,[sp,#4] ;store the contents(ISR) of HandleXXX to stack ldmfd sp!,{r0,pc} ;POP the work register and pc(jump to ISR) MEND
IMPORT |Image$$RO$$Limit| ; End of ROM code (=start of ROM data) IMPORT |Image$$RW$$Base| ; Base of RAM to initialise IMPORT |Image$$ZI$$Base| ; Base and limit of area IMPORT |Image$$ZI$$Limit| ; to zero initialise IMPORT Main
AREA Init,CODE,READONLY ENTRY
;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't be used here because the linker generates error. ASSERT :DEF: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
] b
b b b b b b
HandlerUndef ;handler for Undefined mode HandlerSWI ;handler for SWI interrupt HandlerPabort ;handler for PAbort HandlerDabort;handler for DAbort . ;reserved HandlerIRQ ;handler for IRQ interrupt HandlerFIQ ;handler for FIQ interrupt
;@0x20
b
EnterPWDN ; Must be @0x20.
ChangeBigEndian ;@0x24 [ ENTRY_BUS_WIDTH=32 DCD 0xee110f10 ;0xee110f10 => mrc p15,0,r0,c1,c0,0
DCD DCD
0xe3800080 ;0xe3800080 => orr r0,r0,#0x80; //Big-endian 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.
; 2. All interrupt should be maksked for SDRAM/DRAM self-refresh. ; 3. LCD controller should be disabled for SDRAM/DRAM self-refresh. ; 4. The I-cache may have to be turned on.
; 5. The location of the following code may have not to be changed.
;void EnterPWDN(int CLKCON); EnterPWDN
mov r2,r0 tst r0,#0x8
;r2=rCLKCON ;SLEEP mode?
bne ENTER_SLEEP
ENTER_STOP
ldr r0,=REFRESH 0 0
mov r1,#16 subs r1,r1,#1 bne °
;wait until self-refresh is issued. may not be needed.
ldr r3,[r0] ;r3=rREFRESH mov r1, r3
orr r1, r1, #BIT_SELFREFRESH str r1, [r0]
;Enable SDRAM self-refresh
ldr r0,=CLKCON str r2,[r0]
;enter STOP mode.
mov r1,#32
subs r1,r1,#1 ;1) wait until the STOP mode is in effect.
bne ° ;2) Or wait here until the CPU&Peripherals will be turned-off ; Entering SLEEP mode, only the reset by wake-up is available. ldr r0,=REFRESH ;exit from SDRAM self refresh mode. str r3,[r0] MOV_PC_LR
ENTER_SLEEP
;NOTE.
;1) rGSTATUS3 should have the return address after wake-up from SLEEP mode. ldr r0,=REFRESH ldr r1,[r0] ;r1=rREFRESH
相关推荐: