新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應用 > ARM啟動文件2440init.s分析

ARM啟動文件2440init.s分析

作者: 時間:2016-11-23 來源:網(wǎng)絡(luò) 收藏
;=========================================
; NAME: 2440INIT.S
; DESC: C start up codes
; Configure memory, ISR ,stacks
;Initialize C-variables
;=========================================
;注意:axd調(diào)試時,可以看到指令pc地址從0x30000000開始,這是因為ram的起始地址是0x30000000.
;并且如果從nand啟動,則處理器自動把nand首部的4k字節(jié),復制到ram中,然后pc跳到0x30000000,開始執(zhí)行。
;此源文件通常包含一些宏定義和常量定義
;通用的《啟動流程圖》:
;入口->屏蔽所有中斷,禁止看門狗->根據(jù)工作頻率設(shè)置PLL寄存器->初始化存儲控制相關(guān)寄存器
;->初始化各模式下的棧指針->設(shè)置缺省中斷處理函數(shù)->將數(shù)據(jù)拷貝到RAM中,數(shù)據(jù)段清零
;->跳轉(zhuǎn)到c語言main入口函數(shù)中
;GET偽指令用于將一個源文件包含到當前源文件中,并將被包含文件在當前位置進行匯編處理
;類似于c的include指令
;GET INLCUDE偽指令不能用來包含目標文件,INCBIN偽指令可以包含目標文件,
;被INCBIN偽指令包含的文件,不進行匯編處理,該執(zhí)行文件或數(shù)據(jù)直接放入當前文件,
;編譯器從INCBIN后邊開始繼續(xù)處理
GET option.inc ;定義芯片相關(guān)配置
GET memcfg.inc ;定義存儲器配置
GET 2440addr.inc ;定義寄存器符號
;REFRESH寄存器[22]bit :SDRAM刷新模式 0 - auto refresh
; 1 - self refresh
;用于節(jié)電模式中,SDRAM自動刷新
BIT_SELFREFRESH EQU (1<<22)
;Pre-defined constants
;模式預定義常量,給cpsr【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 ;1100 0000,中斷屏蔽掩碼
;The location of stacks
;0x30000000 = 768M
;定義各模式下的堆棧常量,是一個遞減棧,后邊標上了各個棧的大小
UserStack EQU (_STACK_BASEADDRESS-0x3800) ; ~ 0x33ff4800 大小不定,跟堆大小相對應
;畢竟是用戶態(tài)棧
SVCStack EQU (_STACK_BASEADDRESS-0x2800) ; ~ 0x33ff5800 4M
UndefStack EQU (_STACK_BASEADDRESS-0x2400) ; ~ 0x33ff5c00 1M
AbortStack EQU (_STACK_BASEADDRESS-0x2000) ; ~ 0x33ff6000 1M
IRQStack EQU (_STACK_BASEADDRESS-0x1000) ; ~ 0x33ff7000 4M
FIQStack EQU (_STACK_BASEADDRESS-0x0) ; ~ 0x33ff8000 4M
;處理器分為16位 32位兩種工作狀態(tài)程序的編譯器也是分16位和32兩種編譯方式
;下面程序根據(jù)處理器工作狀態(tài)確定編譯器編譯方式
;code16偽指令指示匯編編譯器后面的指令為16位的thumb指令
;code32偽指令指示匯編編譯器后面的指令為32位的arm指令
;Arm上電時處于ARM狀態(tài),故無論指令為ARM集或Thumb集,都先強制成ARM集,待init.s初始化完成后,再根據(jù)用
;戶的編譯配置轉(zhuǎn)換成相應的指令模式。為此,定義變量THUMBCODE作為指示,跳轉(zhuǎn)到main之前根據(jù)其值切換指令
;模式
;Check if tasm.exe(armasm -16 ...@ADS 1.0)is used.
;檢測工作模式,根據(jù)CONFIG的數(shù)值,確定工作模式
;{CONFIG}應該來自于ADS環(huán)境,在本環(huán)境中設(shè)置是進入時在ARM環(huán)境下,沒有設(shè)置ARM/THUMB混合環(huán)境
;關(guān)于是否設(shè)置混合編程,在環(huán)境設(shè)置選項里的ARM Assembler 選項下,由ATPCS -> ARM/Thumb interworking選
;項負責
;IF ELSE ENDIF指令
;[ 為 IF ; | 為 ELSE ; ] 為 ENDIF
GBLL THUMBCODE
[{CONFIG} = 16
THUMBCODE SETL {TRUE} ;如果設(shè)置了config,則允許thumb指令,
;但THUMBCODE為真并不表明以下就是thumb指令,只是允許
CODE32 ;code32表示以下是arm指令,在處理器剛開始時,必須以arm模式運行
| ;此處容易產(chǎn)生錯覺,丟掉CODE32這一行
THUMBCODE SETL {FALSE}
]
;-------------------------------------------------------------------------------------------------
;bx是帶狀態(tài)切換的跳轉(zhuǎn)指令,跳轉(zhuǎn)到Rm指定的地址執(zhí)行程序,若Rm的位[0]為1,則跳轉(zhuǎn)時自動將CPSR的標志T
;T置位,即把目標地址的代碼解釋為Thumb代碼;若Rm的位[0]為0,則跳轉(zhuǎn)時自動將CPSR中的標志T復位,即把
;目標地址的代碼解釋為ARM代碼
;定義兩個宏,宏的作用:子函數(shù)返回(無條件,有條件)。
MACRO
MOV_PC_LR
[ THUMBCODE ;如果允許thumb指令,則需要根據(jù)最低位設(shè)置狀態(tài)。
bx lr ;跳轉(zhuǎn),附帶狀態(tài)切換
|
mov pc,lr
]
MEND
MACRO
MOVEQ_PC_LR ;相等則跳轉(zhuǎn),相等與否由寄存器某些位確定,在此處,有其上一句的指令執(zhí)行結(jié)果決定
[ THUMBCODE
bxeq lr
|
moveq pc,lr
]
MEND
;MACRO和MEND偽指令用于宏定義,MACRO標識開始,MEND標識結(jié)束。用MACRO和MEND定義的一段代碼,稱為宏定義
;體,這樣在程序中就可以通過宏指令多次調(diào)用該代碼段。
;偽指令格式:
;MACRO
;{$label} macroname {$parameter} {$parameter} ...
;宏定義體
;MEND
;其中 $label 宏指令被展開時,label可被替換成相應的符號,通常為一個標號,
;在一個標號前使用$表示被匯編時將使用相應的值替代$后的符號。
;macroname 所定義的宏的名稱
;$parameter 宏指令的參數(shù),當宏指令被展開時將被替換成相應的值,類似于函數(shù)中的形式參數(shù)
;對于子程序代碼較短,而需要傳遞的參數(shù)比較多的情況下,可以使用匯編技術(shù)。
;首先要用MACRO和MEND偽指令定義宏,包括宏定義體代碼。在MACRO偽指令之后的第一行定義宏的原型,其中包
;含該宏定義的名稱,及需要的參數(shù)。在匯編程序中可以通過該宏定義的名稱來調(diào)用它,當源程序被匯編時,匯
;編編譯器將展開每個宏調(diào)用,用宏定義體代替源程序中的宏定義的名稱,并用實際的參數(shù)值代替宏定義時的形
;式參數(shù)
;-------------------------------------------------------------------------------------------------
;在arm中,用的是滿遞減堆棧:stmfd,ldmfd,如果用其他的方式,arm可能不能有效識別
;注意:滿遞減指的是在入棧時的操作方式,在出棧時則正好相反的次序
;例子:
;STMFD sp!,{R0-R7,LR}:(滿遞減:先減再放數(shù)值)sp根據(jù)數(shù)據(jù)個數(shù),減小相應個數(shù)值的數(shù)據(jù)單位(一步到
;位),然后利用for循環(huán)語句,從當前sp位置,依次存儲R0-R7,LR.即:sp處最后指向的是R0數(shù)據(jù)處
;LDMFD sp!,{R0-R7,LR}:復制一個變量為sp值,用該變量依次將數(shù)據(jù)存入R0-R7,LR,變量值增加,最后,變量指
;向下一個將要取的值,完成后sp獲得該變量值;
;重點分析下面這個宏,它對中斷處理函數(shù)的調(diào)用很重要
;確切說,這是宏函數(shù),編譯時對調(diào)用語句要做相應的展開
MACRO
$HandlerLabel HANDLER $HandleLabel
$HandlerLabel ;標號
sub sp,sp,#4 ;留出一個空間,為了存放跳轉(zhuǎn)地址給pc。
stmfd sp!,{r0} ;把r0中的內(nèi)容入棧,保存起來
ldr r0,=$HandleLabel ;這是一個偽指令,不是匯編指令,
;目的:把$HandleLabel本身所在的地址給r0
ldr r0,[r0] ;把$HandleLabel所指向的內(nèi)容(也就是中斷程序的入口地址)放入r0
str r0,[sp,#4] ;把入口地址放入剛才留出的一個空間里
ldmfd sp!,{r0,pc} ;出棧的方式恢復r0原值和為pc設(shè)定新值(也就完成了到ISR的轉(zhuǎn)跳)。
;注:棧中r0內(nèi)容在低地址
MEND
;-------------------------------------------------------------------------------------------------
;下面幾個變量是ads環(huán)境下自動設(shè)置的,可以見環(huán)境配置選項里:ARM Linker->Output下,RO Base,RW Base
;IMPORT 引用變量
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 to zero initialise
IMPORT |Image$$ZI$$Limit|
IMPORT MMU_SetAsyncBusMode
IMPORT MMU_SetFastBusMode ;想知道代碼具體內(nèi)容見cp15手冊,并以cp15指令內(nèi)容搜索2440a手冊
IMPORT Main ;The main entry of mon program
IMPORT RdNF2SDRAM ;Copy Image from Nand Flash to SDRAM
;-------------------------------------------------------------------------------------------------
;AREA偽指令用于定義一個代碼段或數(shù)據(jù)段,一個ARM源程序至少需要一個代碼段,大的程序可以包含多個代碼段
;及數(shù)據(jù)段
;格式:AREA sectionname {,attr} {,attr}...
AREA Init,CODE,READONLY
;-------------------------------------------------------------------------------------------------
;ENTRY偽指令用于指定程序的入口點
;一個程序(可以包含多個源文件)中至少要有一個ENTRY,可以有多個ENTRY,但一個源文件中最多只有一個
;ENTRY.
ENTRY
;-------------------------------------------------------------------------------------------------
;EXPORT聲明一個符號可以被其他文件引用,相當于聲明了一個全局變量。GLOBAL與EXPORT相同
;格式:EXPORT symbol{[WEAK]} [WEAK]聲明其他的同名符優(yōu)先于本符號被引用
;導出符號__ENTRY
EXPORT __ENTRY
;-------------------------------------------------------------------------------------------------
__ENTRY
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 thememory bus width.
;3)Thepseudo instruction,DCD can not be used here because the linker generates error.
;條件編譯,在編譯成機器碼前就設(shè)定好大小端轉(zhuǎn)換
;判斷ENDIAN_CHANGE是否已定義,ASSERT 是斷言偽指令,語法是:ASSERT + 邏輯表達式,def 是邏輯偽操作符,
;格式為::DEF:label,作用是:判斷l(xiāng)abel是否定義過
ASSERT :DEF:ENDIAN_CHANGE
[ ENDIAN_CHANGE ;在 option.inc 有定義。默認是FALSE,所以此句不會加入代碼中
ASSERT :DEF:ENTRY_BUS_WIDTH ;斷言指令,檢測是否定義該變量,若未定義,報錯
[ ENTRY_BUS_WIDTH=32 ;defined in option.inc
b ChangeBigEndian ;DCD 0xea000007
;如果是大端,則這是第一條指令,先設(shè)置成大端,
;再到復位指令
]
[ 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 ;本硬件用的是小端模式,這是第一個執(zhí)行語句,
;直接跳轉(zhuǎn)到復位指令處 0X00
]
;-------------------------------------------------------------------------------------------------
;這7個中斷,每個中斷都有固定的中斷入口地址,它們位于代碼的最前端,不允許另作他用
b HandlerUndef ;handler for Undefined mode 0X04
b HandlerSWI ;handlerfor SWI interrupt 0X08
b HandlerPabort ;handler for PAbort,指令預取中止 0X0C
b HandlerDabort ;handler for DAbort,數(shù)據(jù)中止 0X10
b . ;reserved 保留未用 注意小圓點 0X14
b HandlerIRQ ;handlerfor IRQ interrupt 0X18
b HandlerFIQ ;handlerfor FIQ interrupt 0X1C
;-------------------------------------------------------------------------------------------------
;@0x20
b EnterPWDN ;Must be @0x20
;------------------------------------------------------------------------------------------------
;下面是改變大小端的程序,采用直接定義 <機器碼> 的方式,為什么這么做就得問三星了
;反正我們程序里這段代碼也不會去執(zhí)行,不用去管它
;每一個匯編指令,都對應著一個二進制機器碼,這里沒有使用指令,直接用了機器碼,含義未知
ChangeBigEndian
;@0x24
;對存儲器控制寄存器操作,指定內(nèi)存模式為Big-endian
;因為剛開始CPU都是按照32位總線的指令格式運行的,如果采用其他的話,CPU運行不了,必須轉(zhuǎn)化
;但當系統(tǒng)初始化好以后,則CPU能自動識別
[ 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
]
;因為采用Big-endian模式,采用16位總線時,物理地址的高位和數(shù)據(jù)的地位對應
;所以指令的機器碼也相應的高低對調(diào)
[ 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 similarwith NOP and run well in both endian mode.
DCD 0xffffffff
DCD 0xffffffff
DCD 0xffffffff
DCD 0xffffffff
b ResetHandler ;設(shè)置成大端后,再次跳到復位指令處
;-------------------------------------------------------------------------------------------------
;本文件底部定義了一個數(shù)據(jù)區(qū)(在文件最后),34個字空間,存放相應中斷服務程序的首地址。每個字空間都
;有一個標號,以Handle***命名。
;這是宏實例,在這里Handler***就是通過HANDLER這個宏和Handle***建立聯(lián)系的.
;詳細分析:
;Handle*** 這是宏示例,也就是宏的調(diào)用指令,當編譯時編譯器會把宏調(diào)用指令展開
;Handler*** 這是向量中斷
;展開方式(舉例):
;HandlerFIQ HANDLER HandleFIQ
;展開后變成:
;標號HandlerFIQ,由 " b HandlerFIQ "指令使用(見上,復位處)
; sub sp,sp,#4
;留出一個空間,為了存放跳轉(zhuǎn)地址給pc。見:str r0,[sp,#4] ,注意sp值并未改變
; stmfd sp!,{r0}
;把r0中的內(nèi)容入棧,保存起來
; ldr r0,=HandleFIQ
;HandleFIQ標號,在本文件最下方定義
; ldr r0,[r0]
;把 HandleFIQ所指向的內(nèi)容(也就是中斷程序的入口地址)放入r0
; str r0,[sp,#4]
;把入口地址放入剛才留出的一個空間里
; ldmfd sp!,{r0,pc}
;出棧的方式恢復r0原值和為pc設(shè)定新值(也就完成了到ISR的轉(zhuǎn)跳)。注:棧中r0內(nèi)容在低地址
;后邊的語句展開方式,同上。編譯后,代碼都展開放置
HandlerFIQ HANDLER HandleFIQ
HandlerIRQ HANDLER HandleIRQ
HandlerUndef HANDLER HandleUndef
HandlerSWI HANDLER HandleSWI
HandlerDabort HANDLER HandleDabort
HandlerPabort HANDLER HandlePabort
;-------------------------------------------------------------------------------------------------
;非向量中斷總?cè)肟冢ㄐ枰约号袛嘀袛囝愋?,而不是直接跳轉(zhuǎn)到相應程序)
;產(chǎn)生中斷后,需要中斷服務程序自己來判斷,到底是哪個中斷請求,根據(jù)的就是INTOFFSET寄存器中的偏移,再
;計算中斷服務地址
IsrIRQ
sub sp,sp,#4 ;reserved for PC,預留返回指針的存儲位置
stmfd sp!,{r8-r9}
ldr r9,=INTOFFSET ;the interrupt request source offset
ldr r9,[r9]
ldr r8,=HandleEINT0 ;HandleEINT0 ,在本文件最下邊定義的
add r8,r8,r9,lsl #2 ;r9中只是偏移單位的個數(shù),需要*4變成具體字節(jié)偏移(相對于EINT0)
ldr r8,[r8]
str r8,[sp,#8] ;pc值放在了高位置
ldmfd sp!,{r8-r9,pc}
;-------------------------------------------------------------------------------------------------
;LTORG用于聲明一個文字池,在使用LDR偽指令時,要在適當?shù)牡胤郊尤隠TORG聲明文字池,這樣就會把要加載的
;數(shù)據(jù)保存在文字池內(nèi),再用ARM的《加載指令》讀出數(shù)據(jù)。(若沒有使用LTORG聲明文字池,則匯編器會在程序
;末尾自動聲明)
;LTORG 偽指令常放在無條件跳轉(zhuǎn)指令之后,或者子程序返回指令之后,這樣處理器就不會錯誤地將文字池中的
;數(shù)據(jù)當做指令來執(zhí)行
;注:在此,文字池內(nèi)存儲的是INTOFFSET宏所代表的值:0x4a000014 。畢竟,當把指令編譯成二進制代碼時,
;arm指令(32位)不能既表示出指令內(nèi)容,又表示出數(shù)據(jù)地址(32位)。估計在編譯時,會被匯編成其他的加載
;指令,再編譯成機器碼
;LTORG 只要單獨寫出來就可以了,其他的交給編譯器來做,而且它跟它下面的代碼沒有任何關(guān)系
LTORG
;-------------------------------------------------------------------------------------------------
;=======
; ENTRY
;=======
ResetHandler
;關(guān)看門狗
ldr r0,=WTCON ;watch dog disable 編譯時就是 ldr r0,=53000000;偽指令有=號
ldr r1,=0x0 ;這些宏定義都位于2440addr.inc中。 區(qū)分:變量定義 && 宏定義
str r1,[r0]
;-------------------------------------------------------------------------------------------------
;屏蔽所有中斷
ldr r0,=INTMSK ;在 INTMSK 寄存器設(shè)置屏蔽所有中斷
ldr r1,=0xffffffff ;all interrupt disable 要理解子中斷和中斷之間的關(guān)系
str r1,[r0]
ldr r0,=INTSUBMSK ;INTSUBMSK子中斷屏蔽寄存器,屏蔽所有子中斷
ldr r1,=0x7fff ;allsub interrupt disable
str r1,[r0]
;-------------------------------------------------------------------------------------------------
[ {FALSE}
;rGPFDAT = (rGPFDAT & ~(0xf<<4)) | ((~data & 0xf)<<4);
;Led_Display
ldr r0,=GPBCON
ldr r1,=0x00555555
str r1,[r0]
ldr r0,=GPBDAT
ldr r1,=0x07fe
str r1,[r0]
]
;-------------------------------------------------------------------------------------------------
;初始化PLL和時鐘
;鎖相環(huán) PLL ,作用是將外部晶振的輸入頻率倍頻到一個較高的頻率
;To reduce PLL lock time, adjust the LOCKTIME register.
ldr r0,=LOCKTIME ;LOCKTIME鎖定時間計數(shù)寄存器
ldr r1,=0xffffff
str r1,[r0]
[ PLL_ON_START ;defined inoption.inc {TRUE},選擇要不要設(shè)置頻率值
;Added for confirm clock divide. for 2440.
;Setting value Fclk:Hclk:Pclk
ldr r0,=CLKDIVN ;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]
;programhas not been copied, so use these directly
[ CLKDIV_VAL>1 ; means Fclk:Hclk is not 1:1.
;Fclk為cpu的運行時鐘,Hclk驅(qū)動 AHB總線設(shè)備(例如:SDRAM)
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
]
;在配置UPLLCON和MPLLCON寄存器時,必須先配置UPLLCON,然后再配置MPLLCON,而且兩者之間要有7 nop的間
;隔。(這是2440文檔明確要求的)
;Configure UPLL
ldr r0,=UPLLCON ;UPLLCON: UPLL configuration register
ldr r1,=((U_MDIV<<12)+(U_PDIV<<4)+U_SDIV) ;Fin = 12.0MHz, UCLK =48MHz,
;對于usb來說必須是48MHz
str r1,[r0]
nop ; Caution: After UPLL setting, at least7-clocks delay must be inserted
; for setting hardware be completed.
nop
nop
nop
nop
nop
nop
;Configure MPLL
ldr r0,=MPLLCON ;MPLLCON: MPLL configuration register
ldr r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV) ;Fin = 12.0MHz, FCLK= 400MHz
str r1,[r0]
]
;-------------------------------------------------------------------------------------------------
;Check if the boot is caused by the wake-up from SLEEP mode.
ldr r1,=GSTATUS2 ;這個寄存器數(shù)值表示哪個信號引起的復位動作產(chǎn)生
;檢測 GSTATUS2[2]來判斷是否是由 sleep 模式喚醒引起的電源開啟。
ldr r0,[r1]
tst r0,#0x2
;Incase of the wake-up from SLEEP mode, go to SLEEP_WAKEUP handler.
bne WAKEUP_SLEEP
;-------------------------------------------------------------------------------------------------
;設(shè)置總線寬度&等待狀態(tài)控制寄存器
EXPORT StartPointAfterSleepWakeUp
StartPointAfterSleepWakeUp
;Set memory control registers
;ldr r0,=SMRDATA ;(等效于下邊的指令)
adrl r0,SMRDATA ;be careful!中等范圍的地址讀取偽指令,
;用法類似于ldr(大范圍地址讀取)偽指令
ldr r1,=BWSCON ;BWSCON Address 總線寬度&等待狀態(tài)控制寄存器
add r2, r0, #52 ;End address of SMRDATA,共有13個寄存器地址(4字節(jié))需要賦值,13*4=52字節(jié)
0
ldr r3, [r0], #4 ;這些都是后變址指令
str r3, [r1], #4
cmp r2, r0
bne % B0 ;當<的時候,跳轉(zhuǎn)到0標號處繼續(xù)執(zhí)行
;------------------------------------------------------------------------------------------------
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;; When EINT0 is pressed, Clear SDRAM
;如果 EINT0 產(chǎn)生(這中斷就是我們按鍵產(chǎn)生的), 就清除SDRAM ,不過好像沒人會在這個時候按
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; check if EIN0 button is pressed
ldr r0,=GPFCON ;input,無上拉電阻
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??? ;當按鍵0沒有被按下的時候,也就是不相等,則向下跳到1標號
; 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 ,這幾條指令目的是:擦除sdram的所有數(shù)據(jù)
ldr r0,=0x30000000
0
stmia r0!,{r1-r8}
subs r9,r9,#32
bne ?% B0?
;Clear SDRAM End
1
;Initializestacks
bl InitStacks
;------------------------------------------------------------------------------------------------
;===========================================================
;OM0是flash選擇開關(guān),OM0接地時從nand 啟動,懸空時(核心板上有上拉電阻)從nor啟動
;OM1在核心板上,始終是接地,為0
;OM1:OM0取值:00 nandflash mode
; 01 16bit nor
; 10 32bit nor
; 11 test mode
;詳見:s3c2440 用戶手冊 5.memory controller 一節(jié)
;ands指令,加s表示結(jié)果影響cpsr寄存器的值
ldr r0, =BWSCON ;BWSCON總線寬度&等待控制寄存器
ldr r0, [r0]
ands r0, r0, #6 ;OM[1:0]!= 0, NOR FLash boot
bne copy_proc_beg ;do not read nand flash
adr r0, ResetEntry ;OM[1:0] == 0, NAND FLash boot
cmp r0, #0 ;ifuse Multi-ice,
bne copy_proc_beg ;donot read nand flash for boot
;nop
;===========================================================
;把nand中的數(shù)據(jù),拷貝到ram中
nand_boot_beg
[ {TRUE}
bl RdNF2SDRAM
]
ldr pc, =copy_proc_beg
;===========================================================
;這里的一段代碼時對內(nèi)存數(shù)據(jù)的初始化,涉及代碼段,數(shù)據(jù)段,bss段等
;因?qū)@里的變量設(shè)置等有異議,暫時未全面分析,但是基本原理想通,就是一個比較地址,復制數(shù)據(jù)的過程
copy_proc_beg
adr r0, ResetEntry
ldr r2, BaseOfROM
cmp r0, r2
ldreq r0, TopOfROM
beq InitRam
ldrr3, TopOfROM
0
ldmia r0!, {r4-r7}
stmia r2!, {r4-r7}
cmp r2, r3
bcc % B0???
sub r2, r2, r3
sub r0, r0, r2
InitRam
ldr r2, BaseOfBSS
ldr r3, BaseOfZero
0
cmp r2, r3
ldrcc r1, [r0], #4
strcc r1, [r2], #4
bcc % B0???
mov r0, #0
ldr r3, EndOfBSS
1
cmp r2, r3
strcc r0, [r2], #4
bcc % B1???
ldr pc, = % F2 ;gotocompiler address
2
; [CLKDIV_VAL>1 ; meansFclk:Hclk is not 1:1.
; bl MMU_SetAsyncBusMode
; |
; blMMU_SetFastBusMode ; default value.
; ]
;===========================================================
; Setup IRQ handler
; 把中斷服務函數(shù)的總?cè)肟诘刂?,賦給HandleIRQ地址(文件最低端定義)
ldr r0,=HandleIRQ ;Thisroutine is needed
ldr r1,=IsrIRQ ;ifthere is not subs pc,lr,#4 at 0x18, 0x1c
str r1,[r0]
[ :LNOT:THUMBCODE
bl Main ;Do not use main() because ......
b .
]
[ THUMBCODE ;for start-up code for Thumbmode
orr lr,pc,#1
bx lr
CODE16
bl Main ;Do not use main() because ......
b .
CODE32
]
;------------------------------------------------------------------------------------------------
;function initializing stacks
; 初始化??臻g(各個模式下的),為c函數(shù)運行做準備
InitStacks
;Donot use DRAM,such as stmfd,ldmfd......
;SVCstackis initialized before
;Undertoolkit 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
;USERmode has not be initialized.
mov pc,lr
;TheLR register will not be valid if the current mode is not SVC mode.
LTORG
;------------------------------------------------------------------------------------------------
SMRDATA DATA
;配置存儲器的管理方式
; Memory configuration should be optimizedfor 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 forHCLK<=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 0x30 ;MRSR6 CL=3clk
DCD 0x30 ;MRSR7 CL=3clk
;分配一個字的空間,并用后邊的數(shù)值來初始化該空間,這里命名有些混亂
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 ;按照4的倍數(shù)對齊
;------------------------------------------------------------------------------------------------
;Function for entering power down mode
; 1. SDRAM should be in self-refresh mode.
; 2. All interrupt should be maksked forSDRAM/DRAM self-refresh.
; 3. LCD controller should be disabled forSDRAM/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 ;REFRESH 是刷新控制寄存器
ldr r3,[r0] ;r3=rREFRESH
mov r1, r3
orr r1, r1, #BIT_SELFREFRESH
str r1, [r0] ;Enable SDRAMself-refresh
mov r1,#16 ;wait untilself-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 isin effect.
bne? % B0 ;2) Or wait here until theCPU&Peripherals will be turned-off
;Entering SLEEP mode, only the reset bywake-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 SDRAMself-refresh
mov r1,#16 ;Wait untilself-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
;ReleaseSCLKn 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]
;Setmemory control registers
ldr r0,=SMRDATA ;be careful!
ldr r1,=BWSCON ;BWSCONAddress
add r2, r0, #52 ;Endaddress 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 SelfRefreshis released.
bne? % B0?
ldr r1,=GSTATUS3 ;GSTATUS3 has the startaddress just after SLEEP wake-up
ldr r0,[r1]
mov pc,r0
;=====================================================================
; Clock division test
; Assemble code, because VSYNC time is veryshort
;=====================================================================
EXPORT CLKDIV124
EXPORT CLKDIV144
CLKDIV124
ldr r0, = CLKDIVN ;CLKDIVN 時鐘分頻器控制寄存器
ldr r1, = 0x3 ;0x3 = 1:2:4
str r1, [r0]
; waituntil 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]
; waituntil 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
;------------------------------------------------------------------------------------------------
;定義數(shù)據(jù)段
;^ 標志等價于MAP偽指令
;MAP用于定義一個結(jié)構(gòu)化的內(nèi)存表首地址,此時內(nèi)存表的位置計數(shù)器值,也變成該首地址值,就相當于在這個地
;址處操作
;#于FIELD同義,用于定義一個結(jié)構(gòu)化的內(nèi)存表的數(shù)據(jù)域,后邊數(shù)字表示該數(shù)據(jù)占用的字節(jié)數(shù)
;Handle*** 在此就是一個標號,為了標示數(shù)據(jù)量
;用法:把對應的終端處理函數(shù)的首地址,放到這里的對應的預留空間處,當發(fā)生中斷時,就能根據(jù)宏函數(shù),直
;接跳轉(zhuǎn)
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
;Do not use the label IntVectorTable,
;The value of IntVectorTable is differentwith 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


關(guān)鍵詞: ARM啟動文件2440ini

評論


技術(shù)專區(qū)

關(guān)閉