;=======
; ENTRY(CPU復位的入口)
;=======
ResetHandler
ldr r0,=WTCON ;關看門狗
ldr r1,=0x0
str r1,[r0]
ldr r0,=INTMSK
ldr r1,=0xffffffff ;關中斷
str r1,[r0]
ldr r0,=INTSUBMSK
ldr r1,=0x7fff ;關子中斷
str r1,[r0]
[ {TRUE}
;rGPFDAT = (rGPFDAT & ~(0xf<<4)) | ((~data & 0xf)<<4);
;點led燈
ldr r0,=GPBCON
ldr r1,=0x00555555
str r1,[r0]
ldr r0,=GPBDAT
ldr r1,=0x07fe
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]
; MMU_SetAsyncBusMode and MMU_SetFastBusMode over 4K, so do not call here
; call it after copy
; [ CLKDIV_VAL>1 ; means Fclk:Hclk is not 1:1.
; bl MMU_SetAsyncBusMode
; |
; bl MMU_SetFastBusMode ; default value.
; ]
;===============================================================
;MMU_SetAsyncBusMode 和 MMU_SetFastBusMode 都在4K代碼以上(三星就提供4K的內部SRAM),
;如果你想你編譯出來的程序能在NAND上運行的話,就不能在這調用這兩函數了.
;如果你不要求的話,你就可以直接調用
;下面的代碼就是實現和上面兩函數一樣的功能.
;利用的協處理器的命令實現了對總線模式的設置
;===============================================================
;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.配置 MPLL 一定要使最後的頻率爲16.9344MHz,不然你甭想用USB接口了,
ldr r0,=UPLLCON
ldr r1,=((U_MDIV<<12)+(U_PDIV<<4)+U_SDIV)
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=16.9344MHz
str r1,[r0]
]
;Check if the boot is caused by the wake-up from SLEEP mode.
ldr r1,=GSTATUS2
ldr r0,[r1]
tst r0,#0x2 ; Check GSTATUS2[2] in order to know whether or not
;the power-up is caused by the wake-up from SLEEP mode.
bne WAKEUP_SLEEP ;如果是,則跳轉到WAKEUP_SLEEP
EXPORT StartPointAfterSleepWakeUp ;定義外部的StartPointAfterSleepWakeUp
StartPointAfterSleepWakeUp
;===============================================================
;設置存儲器控制寄存器,此段代碼把13個存儲控制器的內容批量的讀取到了對應的特殊功能寄存器中
;首先是有一個數據區SMRDATA,在程序的後面有定義,這個數據區給13個寄存器分配52字節的地址空間。在下面
;的代碼中,r0是這個數據區的起始地址,r2是數據區的結束地址,r1是寄存器的起始地址。這樣,用一個判斷語句
; cmp r2, r0
; bne %B0,就可以把內存中的數據賦給這13個存儲控制寄存器了。
;===============================================================
;ldr r0,=SMRDATA
adrl r0, SMRDATA ;be careful!
ldr r1,=BWSCON ;BWSCON Address
add r2, r0, #52 ;End address of SMRDATA
0
ldr r3, [r0], #4
str r3, [r1], #4
cmp r2, r0
bne %B0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;; When EINT0 is pressed, Clear SDRAM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; check if EIN0 button is pressed
ldr r0,=GPFCON
ldr r1,=0x0
str r1,[r0] ;置F(0:15)input
ldr r0,=GPFUP
ldr r1,=0xff
str r1,[r0] ;不使用上拉電阻
ldr r1,=GPFDAT ; GPFDAT=0xff
ldr r0,[r1]
bic r0,r0,#(0x1e<<1) ; bit clear
tst r0,#0x1
bne %F1
; Clear SDRAM Start
;清楚內存
ldr r0,=GPFCON
ldr r1,=0x55aa
str r1,[r0]
; ldr r0,=GPFUP
; ldr r1,=0xff
; str r1,[r0]
ldr r0,=GPFDAT
ldr r1,=0x0
str r1,[r0] ;LED=****
mov r1,#0
mov r2,#0
mov r3,#0
mov r4,#0
mov r5,#0
mov r6,#0
mov r7,#0
mov r8,#0
;64MB的SDRAM,0x30000000—0x34000000
ldr r9,=0x4000000
ldr r0,=0x30000000
0
stmia r0!,{r1-r8}
subs r9,r9,#32
bne %B0
;Clear SDRAM End
1
;Initialize stacks
bl InitStacks 初始化堆棧
;===========================================================
這段程序能在nor nand flash 運行,也可以在內存中運行。在nor nand flash運行,需要拷貝數據;
;===========================================================
ldr r0, =BWSCON
ldr r0, [r0]
ands r0, r0, #6 ;OM[1:0] != 0, NOR FLash 或者內存啓動
bne copy_proc_beg ;不要讀取 nand flash
adr r0, ResetEntry ;OM[1:0] == 0, NAND FLash 啓動
cmp r0, #0 ;再比較入口是否爲0地址處,如果不是則用了仿真器
bne copy_proc_beg ;用仿真器的情況也不要用 nand flash啓動
;nop
;===========================================================
nand_boot_beg ;這一段代碼完成從NAND讀代碼到RAM
mov r5, #NFCONF ;設置NAND FLASH的控制寄存器
;set timing value
ldr r0, =(7<<12)|(7<<8)|(7<<4)
str r0, [r5]
;enable control
ldr r0, =(0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0)
str r0, [r5, #4] ;設置NFCONT,使能NAND FLASH
;控制;禁止片選;初始化ECC等,具體查看手冊
bl ReadNandID ;按着讀取NAND的ID號,結果保存在r5裏
mov r6, #0 ;r6設初值0.
ldr r0, =0xec73 ;期望的NAND ID號
cmp r5, r0 ;這裏進行比較
beq %F1 ;相等的話就跳到下一個1標號處
ldr r0, =0xec75 ;這是另一個期望值
cmp r5, r0 ;再進行比較
beq %F1 ;相等的話就跳到下一個1標號處
mov r6, #1 ;不相等了,設置r6=1.
1
bl ReadNandStatus ;讀取NAND狀態,結果放在r1裏
mov r8, #0 ;r8設初值0,意義爲頁號
ldr r9, =ResetEntry
;===============================================================
; 注意,在這裏使用的是ldr僞指令,而不是上面用的adr僞指令,它加載的是ResetEntry
; 的絕對地址,也就是我們期望的RAM中的地址,在這裏,它和|Image$$RO$$Base|
;一樣 也就是說,我如我們編譯程序時RO BASE指定的地址在RAM裏,而把生成的
;文件拷到 NAND裏運行,由ldr加載的r9的值還是定位在內存.
;Ldr與ADR的區別http://blog.163.com/ncx995/blog/static/28003127200851085043536/
;===============================================================
2
ands r0, r8, #0x1f ;凡r8爲0x1f(32)的整數倍,eq有效,ne無效
bne %F3 ;這句的意思是對每個塊(32頁)進行檢錯
mov r0, r8 ;r8->r0
bl CheckBadBlk ;檢查NAND的壞區
cmp r0, #0 ;比較r0和0
addne r8, r8, #32 ;存在壞塊的話就跳過這個壞塊
bne %F4 ;沒有的話就跳到標號4處
3
mov r0, r8 ;當前頁號->r0
mov r1, r9 ;當前目標地址->r1
bl ReadNandPage ;讀取該頁的NAND數據到RAM
add r9, r9, #512 ;每一頁的大小是512Bytes
add r8, r8, #1 ; r8指向下一頁
4
cmp r8, #8192 ;比較是否讀完8192頁
bcc %B2 ;如果r8小於8192(沒讀完),就返回前面的標號2處
mov r5, #NFCONF ;設置NAND FLASH 控制寄存器
ldr r0, [r5, #4]
bic r0, r0, #1
str r0, [r5, #4] ; NAND flash controller enable
ldr pc, =copy_proc_beg ;copy nand flash 到ram
;===========================================================
copy_proc_beg
adr r0, ResetEntry ;ResetEntry值->r0
ldr r2, ;BaseOfROM BaseOfROM值(後面有定義)->r2
cmp r0, r2 ;比較r0和r2
ldreq r0, TopOfROM ;如果相等的話(在內存運行),TopOfROM->r0
beq InitRam ;同時跳到InitRam