2410Init.s
;2410Init.s包括了板子上電后的初始話,具體有幾個步驟:
;講述S3C2410啟動程序設(shè)計(jì)
;1.?????? 屏蔽所有中斷,關(guān)看門狗。
;2.?????? 根據(jù)工作頻率設(shè)置PLL寄存器
;3.?????? 初始化存儲控制相關(guān)寄存器
;4.?????? 初始化各模式下的棧指針
;5.?????? 設(shè)置缺省中斷處理函數(shù)
;6.?????? 將數(shù)據(jù)段拷貝到RAM中,將零初始化數(shù)據(jù)段清零
;7.?????? 跳轉(zhuǎn)到C語言Main入口函數(shù)中
;=========================================
; NAME: 2440INIT.S
; DESC: C start up codes
;?????? Configure memory, ISR ,stacks
; Initialize C-variables
; HISTORY:
; 2002.02.25:kwtark: ver 0.0
; 2002.03.20:purnnamu: Add some functions for testing STOP,Sleep mode
; 2003.03.14:DonGo: Modified for 2440.
;=========================================
?GET option.inc?????????????????????? ;匯編不能使用include包含頭文件,所以用Get
?GET memcfg.inc?????????????????????? ;匯編也不認(rèn)識*.h 文件,所有只能用*.inc
?GET 2440addr.inc
BIT_SELFREFRESH EQU (1<<22)???????????? ;用于節(jié)電模式中,SDRAM自動刷新
;Pre-defined constants????????????????????? ;處理器模式常量: CPSR寄存器的后5位決定目前處理器模式 M[4:0]
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????????????????????? ;定義處理器各模式下堆棧地址常量,都用于后面的各個模式堆棧初始化
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 ~
;arm處理器有兩種工作狀態(tài) 1.arm:32位 這種工作狀態(tài)下執(zhí)行字對準(zhǔn)的arm指令
;2.Thumb:16位 這種工作狀態(tài)執(zhí)行半字對準(zhǔn)的Thumb指令
;因?yàn)樘幚砥鞣譃?6位 32位兩種工作狀態(tài) 程序的編譯器也是分16位和32兩種編譯方式 所以下面的程序用
;于根據(jù)處理器工作狀態(tài)確定編譯器編譯方式
;code16偽指令指示匯編編譯器后面的指令為16位的thumb指令
;code32偽指令指示匯編編譯器后面的指令為32位的arm指令
;
;Arm上電時處于ARM狀態(tài),故無論指令為ARM集或Thumb集,都先強(qiáng)制成ARM集,待init.s初始化完成后再根據(jù)用
;戶的編譯配置轉(zhuǎn)換成相應(yīng)的指令模式。為此,定義變量THUMBCODE作為指示,跳轉(zhuǎn)到main之前根據(jù)其值切換指令模式
;
;以下這段是為了統(tǒng)一目前的處理器工作狀態(tài)和軟件編譯方式(16位編譯環(huán)境使用tasm.exe編譯)
;Check if tasm.exe(armasm -16 ...@ADS 1.0) is used.
?GBLL??? THUMBCODE
?[ {CONFIG} = 16?????????????????? ;如果發(fā)現(xiàn)是在用16位代碼的話(編譯選項(xiàng)中指定使用thumb指令)
THUMBCODE SETL? {TRUE}??????????????????? ;設(shè)置THUMBCODE 為 true
???? CODE32
?? |
THUMBCODE SETL? {FALSE}
??? ]
?? MACRO
?MOV_PC_LR
?? [ THUMBCODE
???? bx lr????????????????????? ;在ARM模式中要使用BX指令轉(zhuǎn)跳到THUMB指令,并轉(zhuǎn)換模式. bx指令會根據(jù)PC最后1位來確定是否進(jìn)入thumb狀態(tài)
?? |
???? mov pc,lr
?? ]
?MEND?????????????????????????? ;宏結(jié)束標(biāo)準(zhǔn)
?? MACRO
?MOVEQ_PC_LR
?? [ THUMBCODE
??????? bxeq lr
?? |
???? moveq pc,lr
?? ]
?MEND
;=======================================================================================
;下面這個宏是用于第一次查表過程的實(shí)現(xiàn)中斷向量的重定向,如果你比較細(xì)心的話就是發(fā)現(xiàn)
;在_ISR_STARTADDRESS=0x33FF_FF00里定義的第一級中斷向量表是采用型如Handle***的方式的.
;而在程序的ENTRY處(程序開始處)采用的是b Handler***的方式.
;在這里Handler***就是通過HANDLER這個宏和Handle***建立聯(lián)系的.
;這種方式的優(yōu)點(diǎn)就是正真定義的向量數(shù)據(jù)在內(nèi)存空間里,而不是在ENTRY處的ROM(FLASH)空間里,
;這樣,我們就可以在程序里靈活的改動向量的數(shù)據(jù)了.
;========================================================================================
;;這段程序用于把中斷服務(wù)程序的首地址裝載到pc中,有人稱之為"加載程序"。
;本初始化程序定義了一個數(shù)據(jù)區(qū)(在文件最后),34個字空間,存放相應(yīng)中斷服務(wù)程序的首地址。每個字
;空間都有一個標(biāo)號,以Handle***命名。
;在向量中斷模式下使用"加載程序"來執(zhí)行中斷服務(wù)程序。
;這里就必須講一下向量中斷模式和非向量中斷模式的概念
;向量中斷模式是當(dāng)cpu讀取位于0x18處的IRQ中斷指令的時候,系統(tǒng)自動讀取對應(yīng)于該中斷源確定地址上的;
;指令取代0x18處的指令,通過跳轉(zhuǎn)指令系統(tǒng)就直接跳轉(zhuǎn)到對應(yīng)地址
;函數(shù)中 節(jié)省了中斷處理時間提高了中斷處理速度標(biāo) 例如 ADC中斷的向量地址為0xC0,則在0xC0處放如下
;代碼:ldr PC,=HandlerADC 當(dāng)ADC中斷產(chǎn)生的時候系統(tǒng)會
;自動跳轉(zhuǎn)到HandlerADC函數(shù)中
;非向量中斷模式處理方式是一種傳統(tǒng)的中斷處理方法,當(dāng)系統(tǒng)產(chǎn)生中斷的時候,系統(tǒng)將interrupt pending寄存器中對應(yīng)標(biāo)志位置位 然后跳轉(zhuǎn)到位于0x18處的統(tǒng)一中斷
;函數(shù)中 該函數(shù)通過讀取interrupt pending寄存器中對應(yīng)標(biāo)志位 來判斷中斷源 并根據(jù)優(yōu)先級關(guān)系再跳到
;對應(yīng)中斷源的處理代碼中
?? 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偽指令(和c語言的extren一樣)引入|Image$$RO$$Base|,|Image$$RO$$Limit|...
;這些變量是通過ADS的工程設(shè)置里面設(shè)定的RO Base和RW Base設(shè)定的,
;最終由編譯腳本和連接程序?qū)氤绦?
;那為什么要引入這玩意呢,最簡單的用處是可以根據(jù)它們拷貝自已
;==========================================================================================
;Image$$RO$$Base等比較古怪的變量是編譯器生成的。RO, RW, ZI這三個段都保存在Flash中,但RW,ZI在Flash中的
;地址肯定不是程序運(yùn)行時變量所存儲的位置,因此我們的程序在初始化時應(yīng)該把Flash中的RW,ZI拷貝到RAM的對應(yīng)位置。
;一般情況下,我們可以利用編譯器替我們實(shí)現(xiàn)這個操作。比如我們跳轉(zhuǎn)到main()時,使用 b __Main,編譯器就會在__Main
;和Main之間插入一段匯編代碼,來替我們完成RW,ZI段的初始化。 如果我們使用 b Main, 那么初始化工作要我們自己做。
;編譯器會生成如下變量告訴我們RO,RW,ZI三個段應(yīng)該位于什么位置,但是它并沒有告訴我們RW,ZI在Flash中存儲在什么位置,
;實(shí)際上RW,ZI在Flash中的位置就緊接著RO存儲。我們知道了Image$$RO$$Base,Image$$RO$$Limit,那么Image$$RO$$Limit就
;是RW(ROM data)的開始。
;一個arm("程序" 筆者少敲倆字 呵呵)由RO,RW,ZI三個斷組成 其中RO為代碼段,RW是已經(jīng)初始化的全局變量,ZI是未初始化的全局變量
;(對于GNU工具 對應(yīng)的概念是TEXT ,DATA,BSS)bootloader
;bootloader要將RW段復(fù)制到ram中并將ZI段清零(這句很重要) 編譯器使用下列段來記錄各段的起始和結(jié)束地址
; |Image$$RO$$Base| ; RO段起始地址
; |Image$$RO$$Limit| ; RO段結(jié)束地址加1
; |Image$$RW$$Base| ; RW段起始地址
; |Image$$RW$$Limit| ; RW段結(jié)束地址加1
; |Image$$ZI$$Base| ; ZI段起始地址
; |Image$$ZI$$Limit| ; ZI段結(jié)束地址加1
?IMPORT? |Image$$RO$$Base|?? ; Base of ROM code
?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
?
;這里引入一些在其它文件中實(shí)現(xiàn)在函數(shù),包括為我們所熟知的main函數(shù)
?IMPORT MMU_SetAsyncBusMode
?IMPORT MMU_SetFastBusMode
?IMPORT? Main??? ; The main entry of mon program
;=================================================================
;從這里開始就是正真的代碼入口了!
;=================================================================
?AREA??? Init,CODE,READONLY?????????????? ;這表明下面的是一個名為Init的代碼段
;板子上電和復(fù)位后 程序開始從位于0x0處開始執(zhí)行硬件剛剛上電復(fù)位后 程序從這里開始執(zhí)行跳轉(zhuǎn)到標(biāo)?
;為ResetHandler處執(zhí)行
?ENTRY??????????????????????????????????? ;定義程序的入口(調(diào)試用)
?
?EXPORT __ENTRY
__ENTRY
;========
;復(fù)位
;========
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 t be used here because the linker generates error.
;異常中斷矢量表(每個表項(xiàng)占4個字節(jié)) 下面是中斷向量表 一旦系統(tǒng)運(yùn)行時有中斷發(fā)生 即使移植了操作;系統(tǒng) 如linux 處理器已經(jīng)把控制權(quán)交給了操作系統(tǒng) 一旦發(fā)生中斷 處理器還是會跳轉(zhuǎn)到從0x0開始
;中斷向量表中某個中斷表項(xiàng)(依據(jù)中斷類型)開始執(zhí)行
?ASSERT :DEF:ENDIAN_CHANGE????????????? ;判斷ENDIAN_CHANGE是否已定義,ASSERT 是斷言偽指令,語法是:ASSERT +邏輯表達(dá)式 ,def 是邏輯偽操作符,格式為: :DEF:label,作用是:判斷l(xiāng)abel是否定義過
?[ ENDIAN_CHANGE????????????????????????? ;如果已經(jīng)定義了ENDIAN_CHANGE,則(在Option.inc里已經(jīng)設(shè)為FALSE )
???? ASSERT? :DEF:ENTRY_BUS_WIDTH????????? ;判斷ENTRY_BUS_WIDTH是否已定義
???? [ ENTRY_BUS_WIDTH=32????????????????? ;在bigendian中,地址為A的字單元包括字節(jié)單元A,A+1,A+2,A+3,字節(jié)單元由高位到低位為A,A+1,A+2,A+3
? b ChangeBigEndian???? ;DCD 0xea000007?? ;是b ChangeBigEndian指令,只是由于總線不一樣而取機(jī)器碼的順序不一樣
???? ]
???? [ ENTRY_BUS_WIDTH=16
? andeq r14,r7,r0,lsl #20?? ;DCD 0x0007ea00
???? ]
???? [ ENTRY_BUS_WIDTH=8
? streq r0,[r0,-r10,ror #1] ;DCD 0x070000ea
???? ]
?|
???? ;我們的程序由于ENDIAN_CHANGE設(shè)成FALSE就到這兒了,轉(zhuǎn)跳到復(fù)位程序入口
???? b 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.
;==================================================================================
;下面是改變大小端的程序,這里采用直接定義機(jī)器碼的方式,至說為什么這么做就得問三星了
;反正我們程序里這段代碼也不會去執(zhí)行,不用去管它
;==================================================================================
?
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
?
;下面是具體的中斷處理函數(shù)跳轉(zhuǎn)的宏,通過上面的$HandlerLabel的宏定義展開后跳轉(zhuǎn)到對應(yīng)的中斷處理;函數(shù)(對于向量中斷)
?
HandlerFIQ????? HANDLER HandleFIQ
HandlerIRQ????? HANDLER HandleIRQ
HandlerUndef??? HANDLER HandleUndef
HandlerSWI????? HANDLER HandleSWI
HandlerDabort?? HANDLER HandleDabort
HandlerPabort?? HANDLER HandlePabort
;下面這段程序是用來處理非向量中斷,具體判斷I_ISPR中各位是否置1 置1表示目前此中斷等待響應(yīng)(每次只能有一位置1),從最高優(yōu)先級中斷位開始判斷,檢測到等待服務(wù)
;中斷就將pc置為中斷服務(wù)函數(shù)首地址
IsrIRQ
?sub sp,sp,#4?????? ;reserved for PC? ;預(yù)留返回指針的存儲位置
?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
;=======
;扳子上電和復(fù)位后 程序開始從位于0x0執(zhí)行b ResetHandler 程序從跳轉(zhuǎn)到這里執(zhí)行
;板子上電復(fù)位后 執(zhí)行幾個步驟這里通過標(biāo)號在注釋中加1,2,3....標(biāo)示 標(biāo)號表示執(zhí)行順序
;1.禁止看門狗 屏蔽所有中斷
ResetHandler
?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,=GPFCON
?ldr r1,=0x5500
?str r1,[r0]
?ldr r0,=GPFDAT
?ldr r1,=0x10
?str r1,[r0]
?]
;2.根據(jù)工作頻率設(shè)置pll
;這里介紹一下計(jì)算公式
;Fpllo=(m*Fin)/(p*2^s)
;m=MDIV+8,p=PDIV+2,s=SDIV
;Fpllo必須大于20Mhz小于66Mhz
;Fpllo*2^s必須小于170Mhz
;如下面的PLLCON設(shè)定中的M_DIV P_DIV S_DIV是取自option.h中
;#elif (MCLK==40000000)
;#define PLL_M (0x48)
;#define PLL_P (0x3)
;#define PLL_S (0x2)
;所以m=MDIV+8=80,p=PDIV+2=5,s=SDIV=2
;硬件使用晶振為10Mhz,即Fin=10Mhz
;Fpllo=80*10/5*2^2=40Mhz
?;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]
?
?[ 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)?
?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
?;In case of the wake-up from SLEEP mode, go to SLEEP_WAKEUP handler.
?bne WAKEUP_SLEEP
; EXPORT StartPointAfterSleepWakeUp
;StartPointAfterSleepWakeUp
;2.根據(jù)工作頻率設(shè)置pll
;這里介紹一下計(jì)算公式
;Fpllo=(m*Fin)/(p*2^s)
;m=MDIV+8,p=PDIV+2,s=SDIV
;Fpllo必須大于20Mhz小于66Mhz
;Fpllo*2^s必須小于170Mhz
;如下面的PLLCON設(shè)定中的M_DIV P_DIV S_DIV是取自option.h中
;#elif (MCLK==40000000)
;#define PLL_M (0x48)
;#define PLL_P (0x3)
;#define PLL_S (0x2)
;所以m=MDIV+8=80,p=PDIV+2=5,s=SDIV=2
;硬件使用晶振為10Mhz,即Fin=10Mhz
;Fpllo=80*10/5*2^2=40Mhz
?;Set memory control registers
? ;ldr r0,=SMRDATA
? adrl r0, SMRDATA
?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
?
?;delay
?mov r0, #&1000
1
?subs r0, r0, #1
?bne %B1
?;===
;================================================================================
;如果 EINT0 產(chǎn)生(這中斷就是我們按鍵產(chǎn)生的), 就清除SDRAM ,不過好像沒人會在這個時候按
;================================================================================
; check if EIN0 button is pressed
?ldr r0,=GPFCON
?ldr r1,=0x0
?str r1,[r0]
?ldr r0,=GPFUP
?ldr r1,=0xff
?str r1,[r0]
?ldr r1,=GPFDAT
?ldr r0,[r1]
?bic r0,r0,#(0x1e<<1)? ; bit clear
?tst r0,#0x1
?bne %F1????? ;%表示搜索,B表示反向-back(F表示向前-forward),1為局部標(biāo)號(0~99)
; 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
?
?ldr r9,=0x4000000?? ;64MB
?ldr r0,=0x30000000
0
?stmia r0!,{r1-r8}
?subs r9,r9,#32
?bne %B0???? ;%表示搜索,B表示反向-back(F表示向前-forward),0為局部標(biāo)號(0~99)
;Clear SDRAM End
1
?;Initialize stacks
?bl InitStacks
; 進(jìn)入C語言前的最后一步了,就是把我們常說查二級向量表的中斷例程安裝到一級向量表(異常向量表)里.
;5.設(shè)置缺省中斷處理函數(shù)
?? ; Setup IRQ handler//建立中斷表
?ldr r0,=HandleIRQ?????? ;This routine is needed
?ldr r1,=IsrIRQ?? ;if there isn t 'subs pc,lr,#4' at 0x18, 0x1c
?str r1,[r0]????????? ;//initialize the IRQ 將普通中斷判斷程序的入口地址給HandleIRQ
;=======================================================================
; 哈哈,下面又有看頭了,這個初始化程序好像被名曰hzh的高手改過
; 能在NOR NAND 還有內(nèi)存中運(yùn)行,當(dāng)然了,在內(nèi)存中運(yùn)行最簡單了.
; 在NOR NAND中運(yùn)行的話都要先把自己拷到內(nèi)存中.
; 此外,還記得上面提到的|Image$$RO$$Base|,|Image$$RO$$Limit|...嗎?
; 這就是拷貝的依據(jù)了!!!
;=========================================================================
;BWSCON的[2:1]反映了外部引腳OM[1:0]:若OM[1:0] != 00, 從NOR FLash啟動或直接在內(nèi)存運(yùn)行;若OM[1:0]==00,則為Nand Flash Mode
?;bl Led_Test
?
?ldr r0, =BWSCON
?ldr r0, [r0]
?ands r0, r0, #6? ;OM[1:0] != 0, NOR FLash boot
?bne NORRoCopy? ;don t read nand flash
?adr r0, ResetEntry? ;OM[1:0] == 0, NAND FLash boot // ADR 裝載參照的地址=sub r0,pc,#0x268;
?cmp r0, #0??? ;if use Multi-ice,//JTAG調(diào)試時是直接下載到內(nèi)存中運(yùn)行,不需要再從nand拷貝
?bne InitRamZero? ;don t read nand flash for boot
?;nop
;===========================================================
;//將程序從nandflash拷貝到sdram
;===========================================================
nand_boot_beg
?mov r5, #NFCONF
?;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]
?
?bl ReadNandID
?mov r6, #0
?ldr r0, =0xecF1
?cmp r5, r0
?beq %F1
?ldr r0, =0xec76
?cmp r5, r0
?beq %F1
?mov r6, #1
1
?bl ReadNandStatus
?
?mov r8, #0
?ldr r9, =ResetEntry
?mov r10,#32?? ;+081010 feiling
2
?ands r0, r8, #0x3f ;如果是第一頁,則檢測壞塊
?bne? %F3
?mov? r0, r8
?bl? CheckBadBlk
?cmp? r0, #0
?addne r8, r8, #64 ;每塊的頁數(shù)? 此處有BUG r8同時也做計(jì)數(shù)用。。
?addne r10,r10,#64 ;+081010 feiling
?bne? %F4
3
?mov r0, r8
?mov r1, r9
?bl ReadNandPage
?add r9, r9, #2048 ;每頁的字節(jié)數(shù)
?add r8, r8, #1? ;頁數(shù)+1
4
?cmp r8, r10?? ;要拷貝的頁數(shù) 081010 pht:#32->r10
?bcc %B2
?
?mov r5, #NFCONF?? ;DsNandFlash
?ldr r0, [r5, #4]
?bic r0, r0, #1
?str r0, [r5, #4]
?ldr pc, =InitRamZero
;此處跳轉(zhuǎn)到內(nèi)存空間 LDR 裝載數(shù)據(jù),尋址靈活。 但不改變PSR要裝載一個被存儲的‘狀態(tài)’并正確的恢復(fù)它 可以這樣寫:ldr r0, [base] 換行? moves pc, r0
;=============================================================================================
;若是從NAND啟動,則拷貝工作已經(jīng)在nand_boot_beg中完成,所以直接跳轉(zhuǎn)到main
;若是從NOR啟動,則將RO和RW部分都拷貝到內(nèi)存,然后跳轉(zhuǎn)到內(nèi)存運(yùn)行(也可在NOR中運(yùn)行,只是速度稍慢)
;
;注:若在NOR中直接運(yùn)行,需把RO/BASE改為0并定義RW/BASE 會跳過RO拷貝
;=============================================================================================
NORRoCopy?? ;copy_proc_beg? by pht
?adr r0, ResetEntry? ;判斷是否在ROM中運(yùn)行,ROM即RO指定的地址 從NOR啟動時ResetEntry為0
?ldr r2, BaseOfROM? ;如果是則跳轉(zhuǎn)到RwCopy 否則的話,將程序拷貝到ROM地址
?cmp r0, r2
?beq NORRwCopy???
?ldr r3, TopOfROM? ;
0??????
?ldmia r0!, {r4-r7}
?stmia r2!, {r4-r7}
?cmp r2, r3
?bcc %B0
?
?
NORRwCopy
?ldr r0, TopOfROM
?ldr r1, BaseOfROM
?sub r0, r0, r1?? ;TopOfROM-BaseOfROM得到從0開始RW的偏移地址
?ldr r2, BaseOfBSS? ;將RW部分的數(shù)據(jù)從ROM拷貝到RAM
?ldr r3, BaseOfZero
0
?cmp r2, r3
?ldrcc r1, [r0], #4
?strcc r1, [r2], #4
?bcc %B0
?
InitRamZero
?mov r0, #0
?ldr r2, BaseOfZero
?ldr r3, EndOfBSS
1
?cmp r2, r3??? ;初始化Zero部分 不管從哪里啟動,這部分都需要執(zhí)行
?strcc r0, [r2], #4
?bcc %B1
?
?ldr pc, =CEntry? ;goto compiler address
?
; [ CLKDIV_VAL>1?? ; means Fclk:Hclk is not 1:1.
; bl MMU_SetAsyncBusMode
; |
; bl MMU_SetFastBusMode ; default value.
; ]
?
;====================================================================
;終于要干完在2440sram中要干的活了,接下來的工作將要去sdram中執(zhí)行Main了.
;=====================================================================
CEntry
? bl Main ;Don t use main() because ......
? b .
;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? ; UndefStack=0x33FF_5C00
?orr r1,r0,#ABORTMODE|NOINT
?msr cpsr_cxsf,r1? ;AbortMode
?ldr sp,=AbortStack? ; AbortStack=0x33FF_6000
?orr r1,r0,#IRQMODE|NOINT
?msr cpsr_cxsf,r1? ;IRQMode
?ldr sp,=IRQStack? ; IRQStack=0x33FF_7000
?orr r1,r0,#FIQMODE|NOINT
?msr cpsr_cxsf,r1? ;FIQMode
?ldr sp,=FIQStack? ; FIQStack=0x33FF_8000
?bic r0,r0,#MODEMASK|NOINT
?orr r1,r0,#SVCMODE
?msr cpsr_cxsf,r1? ;SVCMode
?ldr sp,=SVCStack? ; SVCStack=0x33FF_5800
?;USER mode has not be initialized.
?mov pc,lr
?;The LR register won t be valid if the current mode is not SVC mode.
?
;===========================================================
ReadNandID
?mov????? r7,#NFCONF
?ldr????? r0,[r7,#4]? ;NFChipEn();
?bic????? r0,r0,#2
?str????? r0,[r7,#4]
?mov????? r0,#0x90? ;WrNFCmd(RdIDCMD);
?strb???? r0,[r7,#8]
?mov????? r4,#0?? ;WrNFAddr(0);
?strb???? r4,[r7,#0xc]
1?????? ;while(NFIsBusy());
?ldr????? r0,[r7,#0x20]
?tst????? r0,#1
?beq????? %B1
?ldrb???? r0,[r7,#0x10] ;id? = RdNFDat()<<8;
?mov????? r0,r0,lsl #8
?ldrb???? r1,[r7,#0x10] ;id |= RdNFDat();
?orr????? r5,r1,r0
?ldr????? r0,[r7,#4]? ;NFChipDs();
?orr????? r0,r0,#2
?str????? r0,[r7,#4]
?mov?? pc,lr
?
ReadNandStatus
?mov?? r7,#NFCONF
?ldr????? r0,[r7,#4]? ;NFChipEn();
?bic????? r0,r0,#2
?str????? r0,[r7,#4]
?mov????? r0,#0x70? ;WrNFCmd(QUERYCMD);
?strb???? r0,[r7,#8]
?ldrb???? r1,[r7,#0x10] ;r1 = RdNFDat();
?ldr????? r0,[r7,#4]? ;NFChipDs();
?orr????? r0,r0,#2
?str????? r0,[r7,#4]
?mov?? pc,lr
WaitNandBusy
?mov????? r0,#0x70? ;WrNFCmd(QUERYCMD);
?mov????? r1,#NFCONF
?strb???? r0,[r1,#8]
1?????? ;while(!(RdNFDat()&0x40));
?ldrb???? r0,[r1,#0x10]
?tst????? r0,#0x40
?beq?? %B1
?mov????? r0,#0?? ;WrNFCmd(READCMD0);
?strb???? r0,[r1,#8]
?mov????? pc,lr
CheckBadBlk
?mov? r7, lr
?mov? r5, #NFCONF
?
?bic????? r0,r0,#0x3f ;addr &= ~0x3f;
?ldr????? r1,[r5,#4]? ;NFChipEn()
?bic????? r1,r1,#2
?str????? r1,[r5,#4]
?mov????? r1,#0x00? ;WrNFCmd(READCMD)
?strb???? r1,[r5,#8]
?mov????? r1, #0?? ;2048&0xff
?strb???? r1,[r5,#0xc] ;WrNFAddr(2048&0xff);
?mov????? r1, #8?? ;(2048>>8)&0xf
?strb???? r1,[r5,#0xc]
?
?strb???? r0,[r5,#0xc] ;WrNFAddr(addr)
?mov????? r1,r0,lsr #8 ;WrNFAddr(addr>>8)
?strb???? r1,[r5,#0xc]
?
?mov????? r1,#0x30?? ;WrNFCmd(0x30)
?strb???? r1,[r5,#8]
?
; cmp????? r6,#0?? ;if(NandAddr)?
; movne??? r0,r0,lsr #16 ;WrNFAddr(addr>>16)
; strneb?? r0,[r5,#0xc]
?
; bl? WaitNandBusy ;WaitNFBusy()
?;don t use WaitNandBusy, after WaitNandBusy will read part A!
?mov r0, #100
1
?subs r0, r0, #1
?bne %B1
2
?ldr r0, [r5, #0x20]
?tst r0, #1
?beq %B2
?ldrb r0, [r5,#0x10] ;RdNFDat()
?sub? r0, r0, #0xff
?
; mov????? r1,#0?? ;WrNFCmd(READCMD0)
; strb???? r1,[r5,#8]
?
?ldr????? r1,[r5,#4]? ;NFChipDs()
?orr????? r1,r1,#2
?str????? r1,[r5,#4]
?
?mov? pc, r7
?
ReadNandPage
?mov?? r7,lr
?mov????? r4,r1
?mov????? r5,#NFCONF
?ldr????? r1,[r5,#4]? ;NFChipEn()
?bic????? r1,r1,#2
?str????? r1,[r5,#4]
?mov????? r1,#0?? ;WrNFCmd(READCMD0)
?strb???? r1,[r5,#8]
?strb???? r1,[r5,#0xc] ;WrNFAddr(0)
?strb???? r1,[r5,#0xc] ;WrNFAddr(0)
?strb???? r0,[r5,#0xc] ;WrNFAddr(addr)
?mov????? r1,r0,lsr #8 ;WrNFAddr(addr>>8)
?strb???? r1,[r5,#0xc]
?mov????? r1,#0x30?? ;WrNFCmd(0x30)
?strb???? r1,[r5,#8]
?
; cmp????? r6,#0?? ;if(NandAddr)?
; movne??? r0,r0,lsr #16 ;WrNFAddr(addr>>16)
; strneb?? r0,[r5,#0xc]
?
?ldr????? r0,[r5,#4]? ;InitEcc()
?orr????? r0,r0,#0x10
?str????? r0,[r5,#4]
?
?bl?????? WaitNandBusy ;WaitNFBusy()
?
?mov????? r0,#0?? ;for(i=0; i<2048; i++)
1
?ldrb???? r1,[r5,#0x10] ;buf[i] = RdNFDat()
?strb???? r1,[r4,r0]
?add????? r0,r0,#1
?bic????? r0,r0,#0x10000 ;?
?cmp????? r0,#0x800
?bcc????? %B1
?
?ldr????? r0,[r5,#4]? ;NFChipDs()
?orr????? r0,r0,#2
?str????? r0,[r5,#4]
?
?mov?? pc,r7
;--------------------LED test
?EXPORT Led_Test
Led_Test
?mov r0, #0x56000000
?mov r1, #0x5500
?str r1, [r0, #0x50]
?
0
?mov r1, #0x50
?str r1, [r0, #0x54]
?mov r2, #0x100000
1
?subs r2, r2, #1
?bne %B1
?
?mov r1, #0xa0
?str r1, [r0, #0x54]
?mov r2, #0x100000
2
?subs r2, r2, #1
?bne %B2
?b %B0
?mov pc, lr
;===========================================================
?LTORG
;GCS0->SST39VF1601
;GCS1->16c550
;GCS2->IDE
;GCS3->CS8900
;GCS4->DM9000
;GCS5->CF Card
;GCS6->SDRAM
;GCS7->unused
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)+(Tsrc<<18)+(Tchr<<16)+REFCNT)
?DCD 0x32???? ;SCLK power saving mode, BANKSIZE 128M/128M
?;DCD 0x02???? ;SCLK power saving disable, BANKSIZE 128M/128M
?DCD 0x20???? ;MRSR6 CL=2clk
?DCD 0x20???? ;MRSR7 CL=2clk
?
BaseOfROM DCD |Image$$RO$$Base|
TopOfROM DCD |Image$$RO$$Limit|
BaseOfBSS DCD |Image$$RW$$Base|
BaseOfZero DCD |Image$$ZI$$Base|
EndOfBSS DCD |Image$$ZI$$Limit|
?ALIGN
?
;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? ;r2=rCLKCON
?tst r0,#0x8? ;SLEEP mode?
?bne ENTER_SLEEP
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.
0 subs r1,r1,#1
?bne %B0
?ldr r0,=CLKCON? ;enter STOP mode.
?str r2,[r0]
?mov r1,#32
0 subs 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 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
?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.
0 subs r1,r1,#1
?bne %B0
?ldr r1,=MISCCR
?ldr r0,[r1]
?orr r0,r0,#(7<<17)? ;Set SCLK0=0, SCLK1=0, SCKE=0.
?str r0,[r1]
?ldr r0,=CLKCON? ; Enter sleep mode
?str r2,[r0]
?b .?? ;CPU will die here.
WAKEUP_SLEEP
?;Release SCLKn after wake-up from the SLEEP mode.
?ldr r1,=MISCCR
?ldr r0,[r1]
?bic r0,r0,#(7<<17)? ;SCLK0:0->SCLK, SCLK1:0->SCLK, SCKE:0->=SCKE.
?str r0,[r1]
?;Set memory control registers
? ldr r0,=SMRDATA
?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
?mov r1,#256
0 subs r1,r1,#1 ;1) wait until the SelfRefresh is released.
?bne %B0
?ldr r1,=GSTATUS3? ;GSTATUS3 has the start address just after SLEEP wake-up
?ldr r0,[r1]
?mov pc,r0
?
;=====================================================================
; Clock division test
; Assemble code, because VSYNC time is very short
;=====================================================================
?EXPORT CLKDIV124
?EXPORT CLKDIV144
?
CLKDIV124
?
?ldr???? r0, = CLKDIVN
?ldr???? r1, = 0x3? ; 0x3 = 1:2:4
?str???? r1, [r0]
; wait until clock is stable
?nop
?nop
?nop
?nop
?nop
?ldr???? r0, = REFRESH
?ldr???? r1, [r0]
?bic? r1, r1, #0xff
?bic? r1, r1, #(0x7<<8)
?orr? r1, r1, #0x470 ; REFCNT135
?str???? r1, [r0]
?nop
?nop
?nop
?nop
?nop
?mov???? pc, lr
CLKDIV144
?ldr???? r0, = CLKDIVN
?ldr???? r1, = 0x4? ; 0x4 = 1:4:4
?str???? r1, [r0]
; wait until clock is stable
?nop
?nop
?nop
?nop
?nop
?ldr???? r0, = REFRESH
?ldr???? r1, [r0]
?bic? r1, r1, #0xff
?bic? r1, r1, #(0x7<<8)
?orr? r1, r1, #0x630 ; REFCNT675 - 1520
?str???? r1, [r0]
?nop
?nop
?nop
?nop
?nop
?mov???? pc, lr
?ALIGN
?AREA RamData, DATA, READWRITE
?^?? _ISR_STARTADDRESS? ; _ISR_STARTADDRESS=0x33FF_FF00
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
;@0x33FF_FF20
HandleEINT0? #?? 4
HandleEINT1? #?? 4
HandleEINT2? #?? 4
HandleEINT3? #?? 4
HandleEINT4_7 #?? 4
HandleEINT8_23 #?? 4
HandleCAM? #?? 4? ; Added for 2440.
HandleBATFLT #?? 4
HandleTICK? #?? 4
HandleWDT? #?? 4
HandleTIMER0? #?? 4
HandleTIMER1? #?? 4
HandleTIMER2? #?? 4
HandleTIMER3? #?? 4
HandleTIMER4? #?? 4
HandleUART2?? #?? 4
;@0x33FF_FF60
HandleLCD?? #?? 4
HandleDMA0? #?? 4
HandleDMA1? #?? 4
HandleDMA2? #?? 4
HandleDMA3? #?? 4
HandleMMC? #?? 4
HandleSPI0? #?? 4
HandleUART1? #?? 4
HandleNFCON? #?? 4? ; Added for 2440.
HandleUSBD? #?? 4
HandleUSBH? #?? 4
HandleIIC? #?? 4
HandleUART0? #?? 4
HandleSPI1?? #?? 4
HandleRTC?? #?? 4
HandleADC?? #?? 4
;@0x33FF_FFA0
?END
本文來自CSDN博客,轉(zhuǎn)載請標(biāo)明出處:http://blog.csdn.net/redxu/archive/2010/12/09/6066159.aspx
轉(zhuǎn)載于:https://www.cnblogs.com/processakai/archive/2011/05/01/2033961.html
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的2410Init.s的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【思维】中位数与顺序统计
- 下一篇: ie6下padding bug