📄 2410init.s
字号:
;**********************************
;2410init.s
;s3c2410 startup code
;Original Author:SAMSUNG Crop.
;This Version is Modify By Decell.Zhou,NetKit Crop.
;Only Use for study and personal development,
;for commercial use ,please contract the SAMSUNG Crop. for more detail
;Version History:
; v0.1 |070718 |Nand flash boot support
; v0.2 |071028 |Improve the performerce when booting from Nor by copy the code to ram
;**********************************
GET Option.inc
GET Memcfg.inc
GET 2410addr.inc
BIT_SELFREFRESH EQU (1<<22)
;Pre-defined constants,used for process operation mode switch and interrupt mask
USERMODE EQU 0x10
FIQMODE EQU 0x11
IRQMODE EQU 0x12
SVCMODE EQU 0x13
ABORTMODE EQU 0x17
UNDEFMODE EQU 0x1b
MODEMASK EQU 0x1f
NOINT EQU 0xc0
;The location of stacks,used for stack pointer seting
UserStack EQU (_STACK_BASEADDRESS-0x3800) ;0x33ff4800 ~
SVCStack EQU (_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 ;defind a global boolean variable, name THUMBCODE,note that the position of the "GBLI" can not be change
[ {CONFIG} = 16 ;IF(CONFIG == 16){ //CONFIG is a arm assamble language constant indicate which mode is use,THUMB or ARM
THUMBCODE SETL {TRUE} ;set THUMBCODE to true, indicate this is a thumb code
CODE32 ;set it to the ARM mode
| ;}ELSE{
THUMBCODE SETL {FALSE} ;set THUMBCODE to false,indicate this is a ARM code
] ;}
MACRO ;macro define start
MOV_PC_LR ;macro name is MOV_PC_LR
[ THUMBCODE ;IF(THUMBCODE == TRUE){
bx lr ;MOV_PC_LR is converted to bx lr
| ;}ELSE{
mov pc,lr ;MOV_PC_LR is converted to mov pc,lr
] ;}
MEND ;marco define end
MACRO ;marco define start
MOVEQ_PC_LR ;define macro MOVEQ_PC_LR
[ THUMBCODE ;IF(THUMBCODE == TRUE){
bxeq lr ;MOVQR_PC_LR is converted to bxeq lr
| ;}ELSE{
moveq pc,lr ;MOVEQ_PC_LR is converted to moveq pc,lr
] ;}
MEND ;macro define end
MACRO ;macro define start
$HandlerLabel HANDLER $HandleLabel ;marco name is HandlerXXX HANDLER HandleXXX
$HandlerLabel ;macro variable HandlerLabel
sub sp,sp,#4 ;decrement sp,reserve 4 Byet to store the pc later
stmfd sp!,{r0} ;PUSH the work register to stack,lr does't push because we don not 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 at address sp + 4,the stack pointer do not increase
ldmfd sp!,{r0,pc} ;POP the work register and pc(jump to ISR),because sp did not change, so r0 will pop up first
MEND
;import some external label
;import the bin file section address which is generate by complier
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 the external C language function
IMPORT __main ; The main entry of this program
IMPORT nandRead ;the nand flash read method entry point
AREA Init,CODE,READONLY
ENTRY
;cpu reset entry point.s3c2410 will fetch instruction at 0X0,we must place reset handler at address 0x0
b ResetHandler ;reset handler @0x00
b HandlerUndef ;undefine exception handler @0x04
b HandlerSWI ;software interrput exception handler @0x08
b HandlerPabort ;instruction prefetching abort exception hander @0x0c
b HandlerDabort ;data abort exception handler @0x10
b . ;reserved @0x14
b HandlerIRQ ;IRQ interrupt exception handler @0x18
b HandlerFIQ ;FIQ interrupt exception handler @0x1c
HandlerUndef HANDLER HandleUndef ;undefine exception handler macro
HandlerSWI HANDLER HandleSWI ;software interrput exception handler macro
HandlerPabort HANDLER HandlePabort ;instruction prefetching abort exception handler macro
HandlerDabort HANDLER HandleDabort ;data abort exception handler macro
HandlerIRQ HANDLER HandleIRQ ;IRQ interrupt exception handler macro
HandlerFIQ HANDLER HandleFIQ ;FIQ interrupt exception handler macro
;IRQ exception handle routine, this rountine will be installed at the end of the reset handler
IsrIRQ
sub sp,sp,#4 ;decrement sp,reserve 4 Byte to store the pc later
stmfd sp!,{r8-r9} ;store the register that we will be use later
ldr r9,=INTOFFSET ;load the address of the interrput offset register into r9
ldr r9,[r9] ;load the content of the interrput offset register into r9
ldr r8,=HandleEINT0 ;load the address of EINT0 handler into r8
add r8,r8,r9,lsl #2 ;we first shift the interrput offset register 2 bit to left because we need 4 byte align, then add it to the start point of the ISR routines
ldr r8,[r8] ;get the entry point of the generated interrput
str r8,[sp,#8] ;store the entry point to the stack,we do not change the value of the sp here
ldmfd sp!,{r8-r9,pc} ;restore r8-r9, and then jump to the routine
;Reset handler
;when system boot up
;the cpu will jump to this handler first
ResetHandler
ldr r0,=WTCON ;disable watchdog timer
ldr r1,=0x0 ;
str r1,[r0] ;
ldr r0,=INTMSK
ldr r1,=0xffffffff ;all interrupt disable
str r1,[r0] ;
ldr r0,=INTSUBMSK
ldr r1,=0x7ff ;all sub interrupt disable
str r1,[r0] ;
;Led_Display
;if the user set the global boolean variable DEBUG_LED in the option.inc file
;the led debug function will be turn on
;must be note that, some genernal port are low active
[ DEBUG_LED
ldr r0, =GPGCON ;we use GPG8, and GPG9 port as the debug led port
ldr r1, =0x00050000 ;config them as the output port
str r1, [r0] ;
ldr r0, =GPGDAT ;wirte the data to the output port, active the corresponding led,must note the ioport is low active
ldr r1, =0x0100 ;here we active GPG8
str r1, [r0] ;
ldr r3,=0x00010000 ;delay for some time
1 subs r3,r3,#1 ;
bne %b1 ;
ldr r1,=0x0200 ;here we deactive GPG8, active GPG9
str r1,[r0] ;
ldr r3,=0x00010000 ;delay for some time
1 subs r3,r3,#1 ;
bne %b1 ;
ldr r1,=0x0000 ;finally active both of them
str r1,[r0] ;
]
;To reduce PLL lock time, adjust the LOCKTIME register.
;here we set the lock time to the most safely value,that is the maximum value
ldr r0,=LOCKTIME ;load the locktime resgister address
ldr r1,=0xffffff ;
str r1,[r0]
;set the PLL value. the MPLL value,which is the same with the FCLK in the normal mode, is determiate by the M,P,SDIV value
;by default,when system come up ,the system clock is set to 12Mhz, because the PLL might not be unstable.this clock value
;is the extern crystal value.if the global boolean variable PLL_ON_START is set to true in the option.inc file,
;then we will wirte the pll value to the pll configure register.
[ PLL_ON_START
ldr r0,=MPLLCON ;load the mpllcon register address
ldr r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV) ;Fin=12MHz,Fout=50MHz
str r1,[r0]
]
;Set memory control registers
;configure each bank with the parameter define in Memcfg.inc
ldr r0,=SMRDATA ;load the address of the DATA area which hold the parameter
ldr r1,=BWSCON ;BWSCON Address
add r2, r0, #52 ;End address of SMRDATA
0
ldr r3, [r0], #4 ;loop for 52 times to copy the value into those registers
str r3, [r1], #4 ;
cmp r2, r0 ;
bne %B0 ;
;Initialize stacks
;include all process mode stack ,prepare for C language function execution
bl InitStacks
;Install IRQ handler
;we do not install it previously because we do not init stack and ram
;the environment for the ISR execution is not well prepared.
ldr r0,=HandleIRQ
ldr r1,=IsrIRQ
str r1,[r0]
;this code is for nand boot
;because the limited of the 4K step stone
;if your system is booting from nand flash,
;set the boolean varible NAND_BOOT in the option.inc file
;we will copy the data from the nand flash to the ram
;and start continue our execution
[ NAND_BOOT
mov fp,#0 ;set the frame pointer(r11) to zero because there is not previous frame
ldr r0,=_BOOT_RAM_BASE ;set the first parameter,the target address
ldr r1,=0x0 ;set the second parameter, the source address,we start copy from the start of the nand flash
ldr r2,=0x20000 ;set the third parameter,the size we want to copy.here we copy 128KB
bl nandRead ;jump to the C function
tst r0,#0x0 ;check C function return value
beq pre_nand_boot ;if the C function return 0,jump to pre_nand_boot
b . ;else let cpu die here
b .
pre_nand_boot
ldr r0,=on_the_ram ;get the address of label on_the_ram
ldr r1,=_BOOT_RAM_BASE ;load the startup code ram base adderss after the copy
add r0,r0,r1 ;add it together to get the jump address
mov pc,r0 ;load it to pc,jump to ram
b . ;cpu will nerver get here
]
[ NOR_COPY
ldr r2,=0x20000
ldr r1,=0x0
ldr r3,=_BOOT_RAM_BASE
0
ldr r0,[r1],#4
str r0,[r3],#4
cmp r2,r1
bne %B0
ldr r0,=on_the_ram ;get the address of label on_the_ram
ldr r1,=_BOOT_RAM_BASE ;load the startup code ram base adderss after the copy
add r0,r0,r1 ;add it together to get the jump address
mov pc,r0 ;load it to pc,jump to ram
b .
]
on_the_ram
;Copy and paste RW data/zero initialized data
ldr r0, =|Image$$RO$$Limit| ;load the end address of the RO area
ldr r1, =|Image$$RW$$Base| ;load the start address of the RW area
ldr r3, =|Image$$ZI$$Base| ;load the start address of the ZI area
cmp r0, r1 ;check to see if the end address of the RO area and the start address of the RW area are different
beq %F2 ;if they are the same, there is no need to copy the RW data, because the the RW section is just in RW area
[ NAND_BOOT ;when booting from nand flash,we copy the RW data after the nand flash copy
ldr r4,=_BOOT_RAM_BASE ;this is because the RO section might be larger than 4K
add r0,r0,r4 ;so cause the RW data start address is large then 4K
]
1
cmp r1, r3 ;copy the RW section data to the RW area
ldrcc r2, [r0], #4 ;--> LDRCC r2, [r0] + ADD r0, r0, #4
strcc r2, [r1], #4 ;--> STRCC r2, [r1] + ADD r1, r1, #4
bcc %B1
2
ldr r1, =|Image$$ZI$$Limit| ;initialize the ZI area, load the ZI area end address
mov r2, #0 ;intial value is zero
3
cmp r3, r1 ;fill it will zero
strcc r2, [r3], #4
bcc %B3
[ :LNOT:THUMBCODE
bl __main ;Don't use main() because ......
b . ;cpu should not get here
]
[ THUMBCODE ;for start-up code for Thumb mode
orr lr,pc,#1
bx lr
CODE16
bl __main ;Don't use main() because ......
b .
CODE32
]
;function initializing stacks
InitStacks
;Don't use DRAM,such as stmfd,ldmfd......
;SVCstack is initialized before
;Under toolkit ver 2.5, 'msr cpsr,r1' can be used instead of 'msr cpsr_cxsf,r1'
mrs r0,cpsr
bic r0,r0,#MODEMASK
orr r1,r0,#UNDEFMODE|NOINT
msr cpsr_cxsf,r1 ;UndefMode
ldr sp,=UndefStack
orr r1,r0,#ABORTMODE|NOINT
msr cpsr_cxsf,r1 ;AbortMode
ldr sp,=AbortStack
orr r1,r0,#IRQMODE|NOINT
msr cpsr_cxsf,r1 ;IRQMode
ldr sp,=IRQStack
orr r1,r0,#FIQMODE|NOINT
msr cpsr_cxsf,r1 ;FIQMode
ldr sp,=FIQStack
bic r0,r0,#MODEMASK|NOINT
orr r1,r0,#SVCMODE
msr cpsr_cxsf,r1 ;SVCMode
ldr sp,=SVCStack
;USER mode has not be initialized.
mov pc,lr
;The LR register won't be valid if the current mode is not SVC mode.
LTORG
SMRDATA DATA
; Memory configuration should be optimized for best performance
; The following parameter is not optimized.
; Memory access cycle parameter strategy
; 1) The memory settings is safe parameters even at HCLK=75Mhz.
; 2) SDRAM refresh period is for HCLK=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)+(Trc<<18)+(Tchr<<16)+REFCNT)
DCD 0x32 ;SCLK power saving mode, BANKSIZE 128M/128M
DCD 0x30 ;MRSR6 CL=3clk
DCD 0x30 ;MRSR7
ALIGN
AREA RamData,DATA,READWRITE
^ _ISR_STARTADDRESS
HandleReset # 4
HandleUndef # 4
HandleSWI # 4
HandlePabort # 4
HandleDabort # 4
HandleReserved # 4
HandleIRQ # 4
HandleFIQ # 4
;Don't use the label 'IntVectorTable',
;The value of IntVectorTable is different with the address you think it may be.
;IntVectorTable
HandleEINT0 # 4
HandleEINT1 # 4
HandleEINT2 # 4
HandleEINT3 # 4
HandleEINT4_7 # 4
HandleEINT8_23 # 4
HandleRSV6 # 4
HandleBATFLT # 4
HandleTICK # 4
HandleWDT # 4
HandleTIMER0 # 4
HandleTIMER1 # 4
HandleTIMER2 # 4
HandleTIMER3 # 4
HandleTIMER4 # 4
HandleUART2 # 4
HandleLCD # 4
HandleDMA0 # 4
HandleDMA1 # 4
HandleDMA2 # 4
HandleDMA3 # 4
HandleMMC # 4
HandleSPI0 # 4
HandleUART1 # 4
HandleRSV24 # 4
HandleUSBD # 4
HandleUSBH # 4
HandleIIC # 4
HandleUART0 # 4
HandleSPI1 # 4
HandleRTC # 4
HandleADC # 4
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -