日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

S3C2440启动代码分析

發(fā)布時(shí)間:2024/4/18 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 S3C2440启动代码分析 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
;=========================================?
; 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.?
; 2009 06.24:Tinko Modified?
;=========================================?


??
;匯編不能使用include包含頭文件,所有用Get?
;匯編也不認(rèn)識(shí)*.h 文件,所有只能用*.inc?
?GET option.inc ? ?;定義芯片相關(guān)的配置?
?GET memcfg.inc ? ?;定義存儲(chǔ)器配置?
?GET 2440addr.inc ?;定義了寄存器符號(hào)?




;REFRESH寄存器[22]bit : 0- auto refresh; 1 - self refresh?
BIT_SELFREFRESH EQU (1<<22) ;用于節(jié)電模式中,SDRAM自動(dòng)刷新?




;處理器模式常量: 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 ?;M[4:0]?
NOINT ? ? ? EQU 0xc0?




;定義處理器各模式下堆棧地址常量?
UserStack EQU (_STACK_BASEADDRESS-0x3800) ;0x33ff4800 ~ ? _STACK_BASEADDRESS定義在option.inc中?
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í)行字對(duì)準(zhǔn)的arm指令 2.Thumb:16位 這種工作狀?
;態(tài)執(zhí)行半字對(duì)準(zhǔn)的Thumb指令?
;因?yàn)樘幚砥鞣譃?6位 32位兩種工作狀態(tài) 程序的編譯器也是分16位和32兩種編譯方式 所以下面的程序用?
;于根據(jù)處理器工作狀態(tài)確定編譯器編譯方式?
;code16偽指令指示匯編編譯器后面的指令為16位的thumb指令?
;code32偽指令指示匯編編譯器后面的指令為32位的arm指令?
;?
;Arm上電時(shí)處于ARM狀態(tài),故無(wú)論指令為ARM集或Thumb集,都先強(qiáng)制成ARM集,待init.s初始化完成后?
;再根據(jù)用戶(hù)的編譯配置轉(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 ? ;定義THUMBCODE全局變量注意EQU所定義的宏與變量的區(qū)別?


?[ {CONFIG} = 16 ? ;如果發(fā)現(xiàn)是在用16位代碼的話(huà)(編譯選項(xiàng)中指定使用thumb指令)?


THUMBCODE SETL {TRUE} ?;一方面把THUMBCODE設(shè)置為T(mén)URE?


? ? ?CODE32 ? ?;另一方面暫且把處理器設(shè)置成為ARM模式,以方便初始化?
? ? ?
? ?| ? ? ?;(|表示else)如果編譯選項(xiàng)本來(lái)就指定為ARM模式?
THUMBCODE SETL {FALSE} ?;把THUMBCODE設(shè)置為FALSE就行了?


?] ? ? ? ;結(jié)束?




? MACRO ? ?;一個(gè)根據(jù)THUMBCODE把PC寄存的值保存到LR的宏?
?MOV_PC_LR ? ?;宏名稱(chēng)?
? ?[ THUMBCODE ? ? ? ;如果定義了THUMBCODE,則?
? ? ?bx lr ? ? ;在ARM模式中要使用BX指令轉(zhuǎn)跳到THUMB指令,并轉(zhuǎn)換模式. bx指令會(huì)根據(jù)PC最后1位來(lái)確定是否進(jìn)入thumb狀態(tài)?
? ?| ? ? ;否則,?
? ? ?mov pc,lr ? ;如果目標(biāo)地址也是ARM指令的話(huà)就采用這種方式?
? ?]?
?MEND ? ? ;宏定義結(jié)束標(biāo)志?
??
? MACRO ? ? ;和上面的宏一樣,只是多了一個(gè)相等的條件?
?MOVEQ_PC_LR?
? ?[ THUMBCODE?
? ? ? ? bxeq lr?
? ?|?
? ? ?moveq pc,lr?
? ?]?
?MEND?




;=======================================================================================?
;下面這個(gè)宏是用于第一次查表過(guò)程的實(shí)現(xiàn)中斷向量的重定向,如果你比較細(xì)心的話(huà)就是發(fā)現(xiàn)?
;在_ISR_STARTADDRESS=0x33FF_FF00里定義的第一級(jí)中斷向量表是采用型如Handle***的方式的.?
;而在程序的ENTRY處(程序開(kāi)始處)采用的是b Handler***的方式.?
;在這里Handler***就是通過(guò)HANDLER這個(gè)宏和Handle***建立聯(lián)系的.?
;這種方式的優(yōu)點(diǎn)就是正真定義的向量數(shù)據(jù)在內(nèi)存空間里,而不是在ENTRY處的ROM(FLASH)空間里,?
;這樣,我們就可以在程序里靈活的改動(dòng)向量的數(shù)據(jù)了.?
;========================================================================================?
;;這段程序用于把中斷服務(wù)程序的首地址裝載到pc中,有人稱(chēng)之為“加載程序”。?
;本初始化程序定義了一個(gè)數(shù)據(jù)區(qū)(在文件最后),34個(gè)字空間,存放相應(yīng)中斷服務(wù)程序的首地址。每個(gè)字?
;空間都有一個(gè)標(biāo)號(hào),以Handle***命名。?
;在向量中斷模式下使用“加載程序”來(lái)執(zhí)行中斷服務(wù)程序。?
;這里就必須講一下向量中斷模式和非向量中斷模式的概念?
;向量中斷模式是當(dāng)cpu讀取位于0x18處的IRQ中斷指令的時(shí)候,系統(tǒng)自動(dòng)讀取對(duì)應(yīng)于該中斷源確定地址上的;?
;指令取代0x18處的指令,通過(guò)跳轉(zhuǎn)指令系統(tǒng)就直接跳轉(zhuǎn)到對(duì)應(yīng)地址?
;函數(shù)中 節(jié)省了中斷處理時(shí)間提高了中斷處理速度標(biāo) 例如 ADC中斷的向量地址為0xC0,則在0xC0處放如下?
;代碼:ldr PC,=HandlerADC 當(dāng)ADC中斷產(chǎn)生的時(shí)候系統(tǒng)會(huì)?
;自動(dòng)跳轉(zhuǎn)到HandlerADC函數(shù)中?
;非向量中斷模式處理方式是一種傳統(tǒng)的中斷處理方法,當(dāng)系統(tǒng)產(chǎn)生中斷的時(shí)候,系統(tǒng)將interrupt?
;pending寄存器中對(duì)應(yīng)標(biāo)志位置位 然后跳轉(zhuǎn)到位于0x18處的統(tǒng)一中斷?
;函數(shù)中 該函數(shù)通過(guò)讀取interrupt pending寄存器中對(duì)應(yīng)標(biāo)志位 來(lái)判斷中斷源 并根據(jù)優(yōu)先級(jí)關(guān)系再跳到?
;對(duì)應(yīng)中斷源的處理代碼中?
;?
;H|------| ? ? ? ? ? H|------| ? ? ? ?H|------| ? ? ? ? ? H|------| ? ? ? ? H|------| ? ? ? ?
; |/ / / | ? ? ? ? ? ?|/ / / | ? ? ? ? |/ / / | ? ? ? ? ? ?|/ / / | ? ? ? ? ?|/ / / | ? ? ? ?
; |------|<----sp ? ? |------| ? ? ? ? |------| ? ? ? ? ? ?|------| ? ? ? ? ?|------|<------sp ?
;L| ? ? ?| ? ? ? ? ? ?|------|<----sp L|------| ? ? ? ? ? ?|-isr--| ? ? ? ? ?|------| isr==>pc?
; | ? ? ?| ? ? ? ? ? ?| ? ? ?| ? ? ? ? |--r0--|<----sp ? ? |---r0-|<----sp ?L|------| r0==>r0?
; ? ?(0) ? ? ? ? ? ? ? ?(1) ? ? ? ? ? ? ?(2) ? ? ? ? ? ? ? ? ?(3) ? ? ? ? ? ? ? (4)?
??
?MACRO?
$HandlerLabel HANDLER $HandleLabel?


$HandlerLabel ? ? ;標(biāo)號(hào)?
?sub sp,sp,#4 ? ?;(1)減少sp(用于存放轉(zhuǎn)跳地址)?
?stmfd sp!,{r0} ? ;(2)把工作寄存器壓入棧(lr does not push because it return to original address)?
?ldr ? ? r0,=$HandleLabel;將HandleXXX的址址放入r0?
?ldr ? ? r0,[r0] ? ?;把HandleXXX所指向的內(nèi)容(也就是中斷程序的入口)放入r0?
?str ? ? r0,[sp,#4] ? ? ?;(3)把中斷服務(wù)程序(ISR)壓入棧?
?ldmfd ? sp!,{r0,pc} ? ? ;(4)用出棧的方式恢復(fù)r0的原值和為pc設(shè)定新值(也就完成了到ISR的轉(zhuǎn)跳)?
?MEND?




;=========================================================================================?
;在這里用IMPORT偽指令(和c語(yǔ)言的extren一樣)引入|Image$RO$Base|,|Image$RO$Limit|...?
;這些變量是通過(guò)ADS的工程設(shè)置里面設(shè)定的RO Base和RW Base設(shè)定的,?
;最終由編譯腳本和連接程序?qū)氤绦??
;那為什么要引入這玩意呢,最簡(jiǎn)單的用處是可以根據(jù)它們拷貝自已?
;==========================================================================================?
;Image$RO$Base等比較古怪的變量是編譯器生成的。RO, RW, ZI這三個(gè)段都保存在Flash中,但RW,ZI在Flash中?
;的地址肯定不是程序運(yùn)行時(shí)變量所存儲(chǔ)的位置,因此我們的程序在初始化時(shí)應(yīng)該把Flash中的RW,ZI拷貝到RAM的對(duì)應(yīng)位置。?
;一般情況下,我們可以利用編譯器替我們實(shí)現(xiàn)這個(gè)操作。比如我們跳轉(zhuǎn)到main()時(shí),使用 b ? __Main,編譯器就會(huì)在__Main?
;和Main之間插入一段匯編代碼,來(lái)替我們完成RW,ZI段的初始化。 如果我們使用 b ? Main, 那么初始化工作要我們自己做。?
;編譯器會(huì)生成如下變量告訴我們RO,RW,ZI三個(gè)段應(yīng)該位于什么位置,但是它并沒(méi)有告訴我們RW,ZI在Flash中存儲(chǔ)在什么位置,?
;實(shí)際上RW,ZI在Flash中的位置就緊接著RO存儲(chǔ)。我們知道了Image$RO$Base,Image$RO$Limit,那么Image$RO$Limit就?
;是RW(ROM data)的開(kāi)始。?


?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 ;hzh?
??
?IMPORT Main?




;從這里開(kāi)始就是正真的代碼入口了!?
?AREA ? ?Init,CODE,READONLY ;這表明下面的是一個(gè)名為Init的代碼段?


?ENTRY ? ?;定義程序的入口(調(diào)試用)?
?EXPORT __ENTRY ? ;導(dǎo)出符號(hào)_ENTRY,但在那用到就還沒(méi)查明?
__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 the memory bus width.?
;3)The pseudo instruction,DCD can not be used here because the linker generates error. ?
;條件編譯,在編譯成機(jī)器碼前就設(shè)定好?
?ASSERT :DEF:ENDIAN_CHANGE ? ;判斷ENDIAN_CHANGE是否已定義?
?[ ENDIAN_CHANGE ? ? ?;如果已經(jīng)定義了ENDIAN_CHANGE,則(在Option.inc里已經(jīng)設(shè)為FALSE )?
? ? ?ASSERT ?:DEF:ENTRY_BUS_WIDTH ;判斷ENTRY_BUS_WIDTH是否已定義?
? ? ?[ ENTRY_BUS_WIDTH=32 ? ;如果已經(jīng)定義了ENTRY_BUS_WIDTH,則判斷是不是為32?
? b ChangeBigEndian ? ? ? ;DCD 0xea000007?
? ? ?]?
?;在bigendian中,地址為A的字單元包括字節(jié)單元A,A+1,A+2,A+3,字節(jié)單元由高位到低位為A,A+1,A+2,A+3?
?; ? ?地址為A的字單元包括半字單元A,A+2,半字單元由高位到低位為A,A+2?
? ? ?[ ENTRY_BUS_WIDTH=16?
? andeq r14,r7,r0,lsl #20 ? ?;DCD 0x0007ea00 也是b ChangeBigEndian指令,只是由于總線不一樣而取機(jī)器碼的順序不一樣?
? ? ?] ? ? ? ?;先取低位->高位 上述指令是通過(guò)機(jī)器碼裝換而來(lái)的?


? ? ?[ ENTRY_BUS_WIDTH=8?
? streq r0,[r0,-r10,ror #1] ?;DCD 0x070000ea 也是b ChangeBigEndian指令,只是由于總線不一樣而取機(jī)器碼的順序不一樣?
? ? ?]?
?|?
? ? ?b ResetHandler ? ?;我們的程序由于ENDIAN_CHANGE設(shè)成FALSE就到這兒了,轉(zhuǎn)跳到復(fù)位程序入口?
? ? ]?


?b HandlerUndef ;handler for Undefined mode ?;0x04?
?b HandlerSWI ? ? ;handler for SWI interrupt ?;0x08?
?b HandlerPabort ;handler for PAbort ? ?;0x0c?
?b HandlerDabort ;handler for DAbort ? ?;0x10?
?b . ? ? ? ? ?;reserved 注意小圓點(diǎn) ? ;0x14?
?b HandlerIRQ ?;handler for IRQ interrupt ?;0x18?
?b HandlerFIQ ?;handler for FIQ interrupt ?;0x1c?
??
;@0x20?
?b EnterPWDN ; Must be @0x20.?
??
??
;==================================================================================?
;下面是改變大小端的程序,這里采用直接定義機(jī)器碼的方式,至說(shuō)為什么這么做就得問(wèn)三星了?
;反正我們程序里這段代碼也不會(huì)去執(zhí)行,不用去管它?
;==================================================================================?
;通過(guò)設(shè)置CP15的C1的位7,設(shè)置存儲(chǔ)格式為Bigendian,三種總線方式?


ChangeBigEndian ;//here ENTRY_BUS_WIDTH=16?
;@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?
? ? ?;對(duì)存儲(chǔ)器控制寄存器操作,指定內(nèi)存模式為Big-endian?
? ? ?;因?yàn)閯傞_(kāi)始CPU都是按照32位總線的指令格式運(yùn)行的,如果采用其他的話(huà),CPU別不了,必須轉(zhuǎn)化?
? ? ?;但當(dāng)系統(tǒng)初始化好以后,則CPU能自動(dòng)識(shí)別?
?]?
?[ ENTRY_BUS_WIDTH=16?
? ? ?DCD 0x0f10ee11?
? ? ?DCD 0x0080e380?
? ? ?DCD 0x0f10ee01?
? ? ?;因?yàn)椴捎肂ig-endian模式,采用16位總線時(shí),物理地址的高位和數(shù)據(jù)的地位對(duì)應(yīng)?
? ? ?;所以指令的機(jī)器碼也相應(yīng)的高低對(duì)調(diào)?
?]?
?[ 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 ?;r2=rCLKCON 保存原始數(shù)據(jù) 0x4c00000c 使能各模塊的時(shí)鐘輸入?
?tst r0,#0x8 ?;測(cè)試bit[3] SLEEP mode? 1=>sleep?
?bne ENTER_SLEEP ;C=0,即TST結(jié)果非0,bit[3]=1?


;//進(jìn)入PWDN后如果不是sleep則進(jìn)入stop?


;//進(jìn)入Stop mode?
ENTER_STOP?
?ldr r0,=REFRESH ?;0x48000024 ? DRAM/SDRAM refresh config?
?ldr r3,[r0] ? ;r3=rREFRESH?
?mov r1, r3?
?orr r1, r1, #BIT_SELFREFRESH ;Enable SDRAM self-refresh?
?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?
;//wait 16 fclks for self-refresh?
?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 ?;back to main process?
? ?


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?
;//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?
;//Wait until self-refresh is issued,which may not be needed?


?ldr r1,=MISCCR ?;IO register?
?ldr r0,[r1]?
?orr r0,r0,#(7<<17) ?;Set SCLK0=1, SCLK1=1, SCKE=1.?
?str r0,[r1]?


?ldr r0,=CLKCON ?; Enter sleep mode?
?str r2,[r0]?


?b . ? ;CPU will die here.?
;//進(jìn)入Sleep Mode,1)設(shè)置SDRAM為self-refresh?
;// ? ? ? 2)設(shè)置MISCCR bit[17] 1:sclk0=sclk 0:sclk0=0?
;// ? ? ? ? bit[18] 1:sclk1=sclk 0:sclk1=0?
;// ? ? ? ? bit[19] 1:Self refresh retain enable?
;// ? ? ? ? ? 0:Self refresh retain disable ?
;// ? ? ? ? ? When 1, After wake-up from sleep, The self-refresh will be retained.?


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]?
;//設(shè)置MISCCR?


?;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 ;數(shù)據(jù)處理后R0自加4,[R0]->R3,R0+4->R0?
?str r3, [r1], #4?
?cmp r2, r0?
?bne %B0?
;//設(shè)置所有的memory control register,他的初始地址為BWSCON,初始化?
;//數(shù)據(jù)在以SMRDATA為起始的存儲(chǔ)區(qū)?


?mov r1,#256?
0?
?subs r1,r1,#1 ;1) wait until the SelfRefresh is released.?
?bne %B0?
;//1) wait until the SelfRefresh is released.?


?ldr r1,=GSTATUS3 ?;GSTATUS3 has the start address just after SLEEP wake-up?
?ldr r0,[r1]?


?mov pc,r0?
;//跳出Sleep Mode,進(jìn)入Sleep狀態(tài)前的PC?




;============================================================================================?
??


;如上所說(shuō),這里采用HANDLER宏去建立Hander***和Handle***之間的聯(lián)系?
?LTORG ? ? ? ;聲明文字池,因?yàn)槲覀冇昧薼dr偽指令?


HandlerFIQ ? ? ?HANDLER HandleFIQ?
HandlerIRQ ? ? ?HANDLER HandleIRQ?
HandlerUndef ? ?HANDLER HandleUndef?
HandlerSWI ? ? ?HANDLER HandleSWI?
HandlerDabort ? HANDLER HandleDabort?
HandlerPabort ? HANDLER HandlePabort?


;===================================================================================?
;呵呵,來(lái)了來(lái)了.好戲來(lái)了,這一段程序就是用來(lái)進(jìn)行第二次查表的過(guò)程了.?
;如果說(shuō)第一次查表是由硬件來(lái)完成的,那這一次查表就是由軟件來(lái)實(shí)現(xiàn)的了.?
;為什么要查兩次表???
;沒(méi)有辦法,ARM把所有的中斷都?xì)w納成一個(gè)IRQ中斷異常和一個(gè)FIRQ中斷異常?
;第一次查表主要是查出是什么異常,可我們總要知道是這個(gè)中斷異常中的什么中斷呀!?
;沒(méi)辦法了,再查一次表唄!?
;===================================================================================?
;//外部中斷號(hào)判斷,通過(guò)中斷服務(wù)程序入口地址存儲(chǔ)器的地址偏移確定?
;//PC=[HandleEINT0+[INTOFFSET]]?
;H|------| ? ? ? ? ? ? ?
; |/ / / | ? ? ? ? ? ? ? ?
; |--isr-| ? ====>pc?
;L|--r8--| ? ? ? ? ? ?
; |--r9--|<----sp ? ? ? ? ? ? ? ?
IsrIRQ?
?sub sp,sp,#4 ? ? ? ?;給PC寄存器保留 reserved for PC?
?stmfd sp!,{r8-r9} ;把r8-r9壓入棧?


?ldr r9,=INTOFFSET ;把INTOFFSET的地址裝入r9 ?INTOFFSET是一個(gè)內(nèi)部的寄存器,存著中斷的偏移?
?ldr r9,[r9] ? ;I_ISR?
?ldr r8,=HandleEINT0 ;這就是我們第二個(gè)中斷向量表的入口的,先裝入r8?
;===================================================================================?
;哈哈,這查表方法夠好了吧,r8(入口)+index*4(別望了一條指令是4 bytes的喔),?
;這不就是我們要找的那一項(xiàng)了嗎.找到了表項(xiàng),下一步做什么?肯定先裝入了!?
;==================================================================================?
?add r8,r8,r9,lsl #2 ?;地址對(duì)齊,因?yàn)槊總€(gè)中斷向量占4個(gè)字節(jié),即isr = IvectTable + Offeset * 4?
?ldr r8,[r8] ? ?;裝入中斷服務(wù)程序的入口?
?str r8,[sp,#8] ? ;把入口也入棧,準(zhǔn)備用舊招?
?ldmfd sp!,{r8-r9,pc} ;施招,彈出棧,哈哈,順便把r8彈出到PC了,跳轉(zhuǎn)成功!?
??
?LTORG?
??
;==============================================================================?
; ENTRY(好了,我們的CPU要在這復(fù)位了.)?
;==============================================================================?
ResetHandler?
?ldr r0,=WTCON ? ? ? ;1.關(guān)看門(mén)狗?
?ldr r1,=0x0 ? ? ? ? ;bit[5]: 0 - disable; 1 - enable (reset 默認(rèn))?
?str r1,[r0]?


?ldr r0,=INTMSK?
?ldr r1,=0xffffffff ?;2.關(guān)中斷?
?str r1,[r0]?


?ldr r0,=INTSUBMSK?
?ldr r1,=0x7fff ? ;3.關(guān)子中斷?
?str r1,[r0]?


?[ {FALSE} ?;4.得有些表示了,該點(diǎn)點(diǎn)LED燈了,不過(guò)被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]?
?]?


;5.為了減少PLL的lock time, 調(diào)整LOCKTIME寄存器.?
;To reduce PLL lock time, adjust the LOCKTIME register.?
?ldr r0,=LOCKTIME?
?ldr r1,=0xffffff ? ?;reset的默認(rèn)值?
?str r1,[r0]?
??
?;6.下面就來(lái)設(shè)置PLL了,你的板快不快就看這了!!?
?;這里介紹一下計(jì)算公式?
;//Fpllo=(m*Fin)/(p*2^s)?
;//m=MDIV+8,p=PDIV+2,s=SDIV?
;The proper range of P and M: 1<=P<=62, 1<=M<=248?


;Fpllo必須大于200Mhz小于600Mhz?
;Fpllo*2^s必須小于1.2GHz?
;如下面的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 ?
?[ 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. option.inc中定義CLKDIV_VAL=7?
?str r1,[r0] ? ?;//數(shù)據(jù)表示分頻數(shù)?
??


;===============================================================================?
;MMU_SetAsyncBusMode 和 MMU_SetFastBusMode 都在4K代碼以上,?
;如果你想你編譯出來(lái)的程序能在NAND上運(yùn)行的話(huà),就不要在這調(diào)用這兩函數(shù)了.?
;如果你不要求的話(huà),你就用把.啥事沒(méi)有.?
;為什么是4K,問(wèn)三星吧,就提供4K的內(nèi)部SRAM,要是提供400K多好呀.?
;好了,好了,4K就4K吧,不能用這兩函數(shù),自己寫(xiě)還不行嗎,下面的代碼這這么來(lái)了,?
;實(shí)現(xiàn)和上面兩函數(shù)一樣的功能.?
;===============================================================================?
; [ CLKDIV_VAL>1 ? ; 意思是 Fclk:Hclk 不是 1:1.?
; bl MMU_SetAsyncBusMode?
; |?
; bl MMU_SetFastBusMode ; default value.?
; ]?


; ==手冊(cè)第243頁(yè)==?
; If HDIVN is not 0, the CPU bus mode has to be changed from the fast bus mode to the asynchronous?
; bus mode using following instructions?
;MMU_SetAsyncBusMode?
;mrc p15,0,r0,c1,c0,0?
;orr r0,r0,#R1_nF:OR:R1_iA?
;mcr p15,0,r0,c1,c0,0?
?[ CLKDIV_VAL>1 ? ; 意思是 Fclk:Hclk 不是 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?
?]?




?;配置 UPLL?
?;//Configure UPLL Fin=12.0MHz UFout=48MHz?
?ldr r0,=UPLLCON?
?ldr r1,=((U_MDIV<<12)+(U_PDIV<<4)+U_SDIV) ;//USB PLL CONFIG 56,2,2===>48MHz?
?str r1,[r0]?
??
?;7個(gè)nop必不可少!!?
?nop ;// Caution: After UPLL setting, at least 7-clocks delay must be inserted for setting hardware be completed.?
?nop?
?nop?
?nop?
?nop?
?nop?
?nop?
??
?;配置 MPLL?
?;//Configure MPLL Fin=12.0MHz MFout=304.8MHz?
?ldr r0,=MPLLCON?
?ldr r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV) ;68,1,1 ==>304MHz?
?str r1,[r0]?
? ? ]?
? ??


??


? ?;檢查是否從SLEEP模式中恢復(fù)?
? ? ;//Check if the boot is caused by the wake-up from SLEEP mode.?
?ldr r1,=GSTATUS2?
?ldr r0,[r1]?
?tst r0,#0x2 ?;test if bit[1] is 1 or 0 0->C=1?
? ? ?; ? ? ? ?1->C=0?
?;In case of the wake-up from SLEEP mode, go to SLEEP_WAKEUP handler.?
?bne WAKEUP_SLEEP ;C=0,jump?


??


?EXPORT StartPointAfterSleepWakeUp?
StartPointAfterSleepWakeUp?


??


;===============================================================================?
;設(shè)置內(nèi)存控制器等寄存器的值,因?yàn)檫@些寄存器是連續(xù)排列的,所以采用如下辦法對(duì)這些?
;寄存器進(jìn)行連續(xù)設(shè)置.其中用到了SMRDATA的數(shù)據(jù),這在代碼后面有定義?
;===============================================================================?
;這是設(shè)置SDRAM,flash ROM 存儲(chǔ)器連接和工作時(shí)序的程序,片選定義的程序?
;SMRDATA map在下面的程序中定義?
;SMRDATA中涉及的值請(qǐng)參考memcfg.inc程序?
;Set memory control registers?


? ;ldr r0,=SMRDATA ;dangerous!!!?
? adrl r0, SMRDATA ?;be careful!, tinko?
?ldr r1,=BWSCON ?;BWSCON Address?
?add r2, r0, #52 ?;End address of SMRDATA ;SMRDATA數(shù)據(jù)的結(jié)束地址,共有52字節(jié)的數(shù)據(jù)?


??
0?
?ldr r3, [r0], #4?
?str r3, [r1], #4?
?cmp r2, r0?
?bne %B0 ? ;%表示搜索,B表示反向-back(F表示向前-forward),0為局部標(biāo)號(hào)(0~99)?
??




;================================================================================?
;如果 EINT0 產(chǎn)生(這中斷就是我們按鍵產(chǎn)生的), 就清除SDRAM ,不過(guò)好像沒(méi)人會(huì)在這個(gè)時(shí)候按?
;================================================================================?
; check if EIN0 button is pressed?


?ldr r0,=GPFCON?
?ldr r1,=0x0 ? ? ;00 = Input?
?str r1,[r0]?
?ldr r0,=GPFUP ?
?ldr r1,=0xff ? ;1- The pull up function is disabled.?
?str r1,[r0]?


?ldr r1,=GPFDAT?
?ldr r0,[r1]?
? ? bic r0,r0,#(0x1e<<1) ; bit clear?
?tst r0,#0x1?
?bne %F1 ? ;如果沒(méi)有按,就跳到后面的1標(biāo)號(hào)處 => Initialize stacks?


??


; 這就是清零內(nèi)存的代碼?
? ?
?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?


;到這就結(jié)束了.?
??




;//4.初始化各模式下的棧指針?
;Initialize stacks?


1?
?bl InitStacks?


;=======================================================================?
; 哈哈,下面又有看頭了,這個(gè)初始化程序好像被名曰hzh的高手改過(guò)?
; 能在NOR NAND 還有內(nèi)存中運(yùn)行,當(dāng)然了,在內(nèi)存中運(yùn)行最簡(jiǎn)單了.?
; 在NOR NAND中運(yùn)行的話(huà)都要先把自己拷到內(nèi)存中.?
; 此外,還記得上面提到的|Image$RO$Base|,|Image$RO$Limit|...嗎??
; 這就是拷貝的依據(jù)了!!!?
;=========================================================================?


;BWSCON的[2:1]反映了外部引腳OM[1:0]:若OM[1:0] != 00, 從NOR FLash啟動(dòng)或直接在內(nèi)存運(yùn)行;若OM[1:0]==00,則為Nand Flash Mode?
?ldr r0, =BWSCON?
?ldr r0, [r0]?
?ands r0, r0, #6 ? ; #6 == 0110 --> BWSCON[2:1]?
?bne copy_proc_beg ? ;OM[1:0] != 00,NOR FLash boot,不讀取NAND FLASH?
??
?adr r0, ResetEntry ? ;否則,OM[1:0] == 0, 為從NAND FLash啟動(dòng)?
?cmp r0, #0 ? ? ;再比較入口是否為0地址處?
? ? ? ?;如果是0才是真正從NAND 啟動(dòng),因?yàn)槠?k被復(fù)制到0地址開(kāi)始的stepingstone 內(nèi)部sram中?
; 注意adr得到的是 相對(duì) 地址,非絕對(duì)地址 == if use Multi-ice,?
?bne copy_proc_beg ? ;如果!=0,說(shuō)明在using ice, 這種情況也不讀取NAND FLASH. don't read nand flash for boot?
;nop?


??
;==============這一段代碼完成從NAND Flash讀代碼到RAM=====================?
nand_boot_beg ? ;?
?mov r5, #NFCONF ;首先設(shè)定NAND的一些控制寄存器?
;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 ?;按著讀取NAND的ID號(hào),結(jié)果保存在r5里?
?mov r6, #0 ? ;r6設(shè)初值0.?
?ldr r0, =0xec73 ;期望的NAND ID號(hào)?
?cmp r5, r0 ? ;這里進(jìn)行比較?
?beq %F1 ? ;相等的話(huà)就跳到下一個(gè)1標(biāo)號(hào)處?
?ldr r0, =0xec75 ;這是另一個(gè)期望值?
?cmp r5, r0?
?beq %F1 ? ;相等的話(huà)就跳到下一個(gè)1標(biāo)號(hào)處?
?mov r6, #1 ? ;不相等,設(shè)置r6=1.?
1?
?bl ReadNandStatus ;讀取NAND狀態(tài),結(jié)果放在r1里?
?mov r8, #0 ? ?; r8設(shè)初值0,意義為頁(yè)號(hào)?
?ldr r9, =ResetEntry ; r9設(shè)初值為初始化程序入口地址?
? ? ? ; 注意,在這里使用的是ldr偽指令,而不是上面用的adr偽指令,它加載的是ResetEntry?
? ? ? ; ?的絕對(duì)地址,也就是我們期望的RAM中的地址,在這里,它和|Image$RO$Base|一樣?
? ? ? ; ?也就是說(shuō),我如我們編譯程序時(shí)RO base指定的地址在RAM里,而把生成的文件拷到?
? ? ? ; ?NAND里運(yùn)行,由ldr加載的r9的值還是定位在內(nèi)存. ????
??
2?
?ands r0, r8, #0x1f ?;凡r8為0x1f(32)的整數(shù)倍-1,eq有效,ne無(wú)效?
?bne %F3 ? ?;這句的意思是對(duì)每個(gè)塊(32頁(yè))進(jìn)行檢錯(cuò) -- 在每個(gè)塊的開(kāi)始頁(yè)進(jìn)行?
?mov r0, r8 ? ?;r8->r0?
?bl CheckBadBlk ? ;檢查NAND的壞區(qū)?
?cmp r0, #0 ? ;比較r0和0?
?addne r8, r8, #32 ?;存在壞塊的話(huà)就跳過(guò)這個(gè)壞塊: + 32得到下一塊. 故: r8 = blockpage addr,因?yàn)樽x寫(xiě)是按頁(yè)進(jìn)行的(每頁(yè)512Byte)?
?bne %F4 ? ?;然后跳到4進(jìn)行循環(huán)條件判斷。沒(méi)有的話(huà)就跳到標(biāo)號(hào)3處copy當(dāng)前頁(yè)?
3?
?mov r0, r8 ? ?;當(dāng)前頁(yè)號(hào)->r0?
?mov r1, r9 ? ?;當(dāng)前目標(biāo)地址->r1?
?bl ReadNandPage ?;讀取該頁(yè)的NAND數(shù)據(jù)到RAM?
?add r9, r9, #512 ?;每一頁(yè)的大小是512Bytes?
?add r8, r8, #1 ? ;r8指向下一頁(yè)?
4?
?cmp r8, #256 ? ;比較是否讀完256頁(yè)即128KBytes?
? ? ? ;注意:這說(shuō)明此程序默認(rèn)拷貝128KByte的代碼(by Tinko) ?
? ? ??
?bcc %B2 ? ?;如果r8小于256(沒(méi)讀完),就返回前面的標(biāo)號(hào)2處?
; now ?copy completed?
?mov r5, #NFCONF ?;Disable NandFlash?
?ldr r0, [r5, #4]?
?bic r0, r0, #1?
?str r0, [r5, #4]?
??
?ldr pc, =copy_proc_beg ?;調(diào)用copy_proc_beg ?
? ? ? ?;個(gè)人認(rèn)為應(yīng)該為InitRam ??????????????????????????????
??
??
??
;===========================================================?
copy_proc_beg?
?adrl r0, ResetEntry ;ResetEntry值->r0?
? ? ? ? ;這里應(yīng)該注意,使用的是adr,而不是ldr。使用ldr說(shuō)明ResetEntry是個(gè)絕對(duì)地址,這個(gè)地址是在程序鏈接的時(shí)候?
? ? ? ? ? ? ? ? ? ? ? ?;確定的。而使用adr則說(shuō)明ResetEntry的地址和當(dāng)前代碼的執(zhí)行位置有關(guān),它是一個(gè)相對(duì)的地址。比如這段代碼?
? ? ? ? ? ? ? ? ? ? ? ?;在stepingstone里面執(zhí)行,那么ResetEntry的地址就是零。如果在RAM里執(zhí)行,那么ResetEntry就應(yīng)是RAM的一個(gè)?
? ? ? ? ? ? ? ? ? ? ? ?;地址,應(yīng)該等于RO base。?
?ldr r2, BaseOfROM ? ;BaseOfROM值(后面有定義)->r2?
?cmp r0, r2 ? ?;比較 ResetEntry 和 BaseOfROM?
?ldreq r0, TopOfROM ?;如果相等的話(huà)(在內(nèi)存運(yùn)行 --- ice -- 無(wú)需復(fù)制code區(qū)中的ro段,但需要復(fù)制code區(qū)中的rw段),TopOfROM->r0?
?beq InitRam ? ;同時(shí)跳到InitRam?
? ? ? ;否則,下面開(kāi)始復(fù)制code的RO段?
;=========================================================?
;下面這個(gè)是針對(duì)代碼在NOR FLASH時(shí)的拷貝方法?
;功能為把從ResetEntry起,TopOfROM-BaseOfROM大小的數(shù)據(jù)拷到BaseOfROM?
;TopOfROM和BaseOfROM為|Image$RO$Limit|和|Image$RO$Base|?
;|Image$RO$Limit|和|Image$RO$Base|由連接器生成?
;為生成的代碼的代碼段運(yùn)行時(shí)的起啟和終止地址?
;BaseOfBSS和BaseOfZero為|Image$RW$Base|和|Image$ZI$Base|?
;|Image$RW$Base|和|Image$ZI$Base|也是由連接器生成?
;兩者之間就是初始化數(shù)據(jù)的存放地?
; --在加載階段,不存在ZI區(qū)域--?
;=======================================================?
?ldr r3, TopOfROM?
0?
?ldmia r0!, {r4-r7} ? ? ;開(kāi)始時(shí),r0 = ResetEntry --- source?
?stmia r2!, {r4-r7} ? ? ;開(kāi)始時(shí),r2 = BaseOfROM ?--- destination?
?cmp r2, r3 ? ? ? ;終止條件:復(fù)制了TopOfROM-BaseOfROM大小?
?bcc %B0?


?;---------------------------------------------------------------?
?; 下面2行,根據(jù)理解,由tinko添加?
?; 猜測(cè)上面的代碼不應(yīng)該用" ! ",以至于地址被修改。這里重新賦值?
?;---------------------------------------------------------------?
?adrl r0, ResetEntry ? ;don't use adr, 'cause out of range error occures?
?ldr r2, BaseOfROM?
? ? ? ?;旨在計(jì)算出正確的RW區(qū)起始位置?
?; 下面2行目的是為了計(jì)算正確的r0(必須使之指向code區(qū)中的rw域開(kāi)始處)?
?sub r2, r2, r3 ? ?;r2=BaseOfROM-TopOfROM=(-)代碼長(zhǎng)度?
?sub r0, r0, r2 ? ?;r0=ResetEntry-(-)代碼長(zhǎng)度=ResetEntry+代碼長(zhǎng)度?
??
InitRam?
?;復(fù)制代碼加載位置中的RM區(qū)到|Image$RW$Base|?
?ldr r2, BaseOfBSS ? ;BaseOfBSS->r2 , ?BaseOfBSS = |Image$RW$Base|?
?ldr r3, BaseOfZero ? ;BaseOfZero->r3 , BaseOfZero = |Image$ZI$Base|?
0?
?cmp r2, r3 ? ;比較BaseOfBSS和BaseOfZero?
?ldrcc r1, [r0], #4 ? ? ?;當(dāng)代碼在內(nèi)存中運(yùn)行時(shí),r0(初始值) = TopOfROM.這之后的BaseOfZero-BaseOfBSS仍屬于code,需拷貝到BaseOfBSS?
?strcc r1, [r2], #4?
?bcc %B0?
??
?;用0初始化ZI區(qū)?
?mov r0, #0?
?ldr r3, EndOfBSS ? ;EndOfBSS = |Image$ZI$Limit|?
1?
?cmp r2, r3?
?strcc r0, [r2], #4?
?bcc %B1?


?;要是r21 ? ; means Fclk:Hclk is not 1:1.?
; bl MMU_SetAsyncBusMode?
; |?
; bl MMU_SetFastBusMode ; default value.?
; ]?
;bl Led_Test?
;===========================================================?


; 進(jìn)入C語(yǔ)言前的最后一步了,就是把我們用說(shuō)查二級(jí)向量表?
; 的中斷例程安裝到一級(jí)向量表(異常向量表)里.?
;//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?
??
;//?
;注意,以下這段可能不需要!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!?
;//6.將數(shù)據(jù)段拷貝到ram中 將零初始化數(shù)據(jù)段清零跳入C語(yǔ)言的main函數(shù)執(zhí)行到這步結(jié)束bootloader初步引導(dǎo)結(jié)束?
?;If main() is used, the variable initialization will be done in __main().?
?[ {FALSE} ? ? ? ? ? ;by tinko -- 最外面的條件由tinko添加,實(shí)際上不再執(zhí)行這段?
? ? [ :LNOT:USE_MAIN ;initialized {FALSE}?
? ? ? ? ;Copy and paste RW data/zero initialized data?
? ? ? ??
?LDR ? ? r0, =|Image$RO$Limit| ; Get pointer to ROM data?
?LDR ? ? r1, =|Image$RW$Base| ?; and RAM copy?
?LDR ? ? r3, =|Image$ZI$Base|?
??
?;Zero init base => top of initialised data?
?CMP ? ? r0, r1 ? ? ?; Check that they are different just for debug???????????????????????????
?BEQ ? ? %F2?
1 ? ? ?
?CMP ? ? r1, r3 ? ? ?; Copy init data?
?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| ; Top of zero init segment?
?MOV ? ? r2, #0?
3 ? ? ?
?CMP ? ? r3, r1 ? ? ?; Zero init?
?STRCC ? r2, [r3], #4?
?BCC ? ? %B3?
? ? ]?
? ? ]?
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!?


;***************************************?
?;by tinko?
?[ {TRUE} ?;得有些表示了,該點(diǎn)點(diǎn)LED燈了?
? ? ?;rGPFDAT = (rGPFDAT & ~(0xf<<4)) | ((~data & 0xf)<<4);?
? ? ?; Led_Display?
?ldr r0,=GPFCON?
?ldr r1,=0x5500?
?str r1,[r0]?
?ldr r0,=GPFDAT?
?ldr r1,=0xe0?
?str r1,[r0]?
??
?ldr r2, =0xffffffff;?
1?
?sub r2,r2,#1?
?bne %b1?
?ldr r0,=GPFDAT?
?ldr r1,=0xe0?
?;b ?. ? ;die here?
?]?
;*****************************************?
;*****************************************************************************?
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!?
; 媽呀,終說(shuō)見(jiàn)到艷陽(yáng)天了!!!!!!!!!!?
; ? ? ? 跳到C語(yǔ)言的main函數(shù)處了.?
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!?
;*****************************************************************************?
? ??
? ? [ :LNOT:THUMBCODE ;if thumbcode={false} bl main ? L代表logic變量?
? ? ?bl Main ? ? ? ?;Don't use main() because ......?
? ? ?b . ? ? ? ? ? ;注意小圓點(diǎn) ? ? ? ? ?
? ? ]?


;//if thumbcod={ture}?
? ? [ THUMBCODE ? ? ? ? ;for start-up code for Thumb mode?
? ? ?orr lr,pc,#1?
? ? ?bx lr?
? ? ?CODE16?
? ? ?bl Main ? ? ? ?;Don't use main() because ......?
? ? ?b . ? ? ? ? ? ;注意小圓點(diǎn)?
? ? ?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 ?; 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.?
?;//為什么不用初始化user的stacks,系統(tǒng)剛啟動(dòng)的時(shí)候運(yùn)行在哪個(gè)模式下??
?mov pc,lr?
?;The LR register won't be valid if the current mode is not SVC mode.??
;//系統(tǒng)一開(kāi)始運(yùn)行就是SVCmode??
;===========================================================?
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,#0x1f ;addr &= ~0x1f;?
?ldr ? ? ?r1,[r5,#4] ;NFChipEn()?
?bic ? ? ?r1,r1,#2?
?str ? ? ?r1,[r5,#4]?
?mov ? ? ?r1,#0x50 ;WrNFCmd(READCMD2)?
?strb ? ? r1,[r5,#8]?
?mov ? ? ?r1, #5;6 ;6->5?
?strb ? ? r1,[r5,#0xc] ;WrNFAddr(5);(6) 6->5?
?strb ? ? r0,[r5,#0xc] ;WrNFAddr(addr)?
?mov ? ? ?r1,r0,lsr #8 ;WrNFAddr(addr>>8)?
?strb ? ? r1,[r5,#0xc]?
?cmp ? ? ?r6,#0 ? ;if(NandAddr) ?
?movne ? ?r0,r0,lsr #16 ;WrNFAddr(addr>>16)?
?strneb ? r0,[r5,#0xc]?
; bl WaitNandBusy ;WaitNFBusy()?
;do not 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 ? ? r0,[r5,#0xc] ;WrNFAddr(addr)?
?mov ? ? ?r1,r0,lsr #8 ;WrNFAddr(addr>>8)?
?strb ? ? r1,[r5,#0xc]?
?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<512; i++)?
1?
?ldrb ? ? r1,[r5,#0x10] ;buf[i] = RdNFDat()?
?strb ? ? r1,[r4,r0]?
?add ? ? ?r0,r0,#1?
?bic ? ? ?r0,r0,#0x10000?
?cmp ? ? ?r0,#0x200?
?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?
;===========================================================?
;=====================================================================?
; 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?
??


;存儲(chǔ)器控制寄存器的定義區(qū)?
?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)) ;各bank的bus width; 沒(méi)有B0,因?yàn)橛蒓M[1:0]pins 確定?
?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 ? B6_MT定義在memcfg.inc中,11-->SDRAM ; B6_SCAN - 非reset 默認(rèn)值?
?DCD ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN)) ? ?;GCS7?
?DCD ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT) ?;Tchr- not used?
?;DCD 0x32 ? ? ;SCLK power saving mode, BANKSIZE 128M/128M?
?DCD 0x31 ? ? ;SCLK power saving mode, BANKSIZE 64M/64M?
?DCD 0x30 ? ? ;MRSR6 CL=3clk?
?DCD 0x30 ? ? ;MRSR7 CL=3clk?
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?
?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

總結(jié)

以上是生活随笔為你收集整理的S3C2440启动代码分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。