<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

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

          ARM啟動(dòng)文件2440init.s分析

          作者: 時(shí)間:2016-11-23 來源:網(wǎng)絡(luò) 收藏
          ;=========================================
          ; NAME: 2440INIT.S
          ; DESC: C start up codes
          ; Configure memory, ISR ,stacks
          ;Initialize C-variables
          ;=========================================
          ;注意:axd調(diào)試時(shí),可以看到指令pc地址從0x30000000開始,這是因?yàn)閞am的起始地址是0x30000000.
          ;并且如果從nand啟動(dòng),則處理器自動(dòng)把nand首部的4k字節(jié),復(fù)制到ram中,然后pc跳到0x30000000,開始執(zhí)行。
          ;此源文件通常包含一些宏定義和常量定義
          ;通用的《啟動(dòng)流程圖》:
          ;入口->屏蔽所有中斷,禁止看門狗->根據(jù)工作頻率設(shè)置PLL寄存器->初始化存儲(chǔ)控制相關(guān)寄存器
          ;->初始化各模式下的棧指針->設(shè)置缺省中斷處理函數(shù)->將數(shù)據(jù)拷貝到RAM中,數(shù)據(jù)段清零
          ;->跳轉(zhuǎn)到c語言main入口函數(shù)中
          ;GET偽指令用于將一個(gè)源文件包含到當(dāng)前源文件中,并將被包含文件在當(dāng)前位置進(jìn)行匯編處理
          ;類似于c的include指令
          ;GET INLCUDE偽指令不能用來包含目標(biāo)文件,INCBIN偽指令可以包含目標(biāo)文件,
          ;被INCBIN偽指令包含的文件,不進(jìn)行匯編處理,該執(zhí)行文件或數(shù)據(jù)直接放入當(dāng)前文件,
          ;編譯器從INCBIN后邊開始繼續(xù)處理
          GET option.inc ;定義芯片相關(guān)配置
          GET memcfg.inc ;定義存儲(chǔ)器配置
          GET 2440addr.inc ;定義寄存器符號(hào)
          ;REFRESH寄存器[22]bit :SDRAM刷新模式 0 - auto refresh
          ; 1 - self refresh
          ;用于節(jié)電模式中,SDRAM自動(dòng)刷新
          BIT_SELFREFRESH EQU (1<<22)
          ;Pre-defined constants
          ;模式預(yù)定義常量,給cpsr【4-0】賦值,改變運(yùn)行模式
          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
          ;定義各模式下的堆棧常量,是一個(gè)遞減棧,后邊標(biāo)上了各個(gè)棧的大小
          UserStack EQU (_STACK_BASEADDRESS-0x3800) ; ~ 0x33ff4800 大小不定,跟堆大小相對(duì)應(yīng)
          ;畢竟是用戶態(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上電時(shí)處于ARM狀態(tài),故無論指令為ARM集或Thumb集,都先強(qiáng)制成ARM集,待init.s初始化完成后,再根據(jù)用
          ;戶的編譯配置轉(zhuǎn)換成相應(yīng)的指令模式。為此,定義變量THUMBCODE作為指示,跳轉(zhuǎn)到main之前根據(jù)其值切換指令
          ;模式
          ;Check if tasm.exe(armasm -16 ...@ADS 1.0)is used.
          ;檢測(cè)工作模式,根據(jù)CONFIG的數(shù)值,確定工作模式
          ;{CONFIG}應(yīng)該來自于ADS環(huán)境,在本環(huán)境中設(shè)置是進(jìn)入時(shí)在ARM環(huán)境下,沒有設(shè)置ARM/THUMB混合環(huán)境
          ;關(guān)于是否設(shè)置混合編程,在環(huán)境設(shè)置選項(xiàng)里的ARM Assembler 選項(xiàng)下,由ATPCS -> ARM/Thumb interworking選
          ;項(xiàng)負(fù)責(zé)
          ;IF ELSE ENDIF指令
          ;[ 為 IF ; | 為 ELSE ; ] 為 ENDIF
          GBLL THUMBCODE
          [{CONFIG} = 16
          THUMBCODE SETL {TRUE} ;如果設(shè)置了config,則允許thumb指令,
          ;但THUMBCODE為真并不表明以下就是thumb指令,只是允許
          CODE32 ;code32表示以下是arm指令,在處理器剛開始時(shí),必須以arm模式運(yùn)行
          | ;此處容易產(chǎn)生錯(cuò)覺,丟掉CODE32這一行
          THUMBCODE SETL {FALSE}
          ]
          ;-------------------------------------------------------------------------------------------------
          ;bx是帶狀態(tài)切換的跳轉(zhuǎn)指令,跳轉(zhuǎn)到Rm指定的地址執(zhí)行程序,若Rm的位[0]為1,則跳轉(zhuǎn)時(shí)自動(dòng)將CPSR的標(biāo)志T
          ;T置位,即把目標(biāo)地址的代碼解釋為Thumb代碼;若Rm的位[0]為0,則跳轉(zhuǎn)時(shí)自動(dòng)將CPSR中的標(biāo)志T復(fù)位,即把
          ;目標(biāo)地址的代碼解釋為ARM代碼
          ;定義兩個(gè)宏,宏的作用:子函數(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標(biāo)識(shí)開始,MEND標(biāo)識(shí)結(jié)束。用MACRO和MEND定義的一段代碼,稱為宏定義
          ;體,這樣在程序中就可以通過宏指令多次調(diào)用該代碼段。
          ;偽指令格式:
          ;MACRO
          ;{$label} macroname {$parameter} {$parameter} ...
          ;宏定義體
          ;MEND
          ;其中 $label 宏指令被展開時(shí),label可被替換成相應(yīng)的符號(hào),通常為一個(gè)標(biāo)號(hào),
          ;在一個(gè)標(biāo)號(hào)前使用$表示被匯編時(shí)將使用相應(yīng)的值替代$后的符號(hào)。
          ;macroname 所定義的宏的名稱
          ;$parameter 宏指令的參數(shù),當(dāng)宏指令被展開時(shí)將被替換成相應(yīng)的值,類似于函數(shù)中的形式參數(shù)
          ;對(duì)于子程序代碼較短,而需要傳遞的參數(shù)比較多的情況下,可以使用匯編技術(shù)。
          ;首先要用MACRO和MEND偽指令定義宏,包括宏定義體代碼。在MACRO偽指令之后的第一行定義宏的原型,其中包
          ;含該宏定義的名稱,及需要的參數(shù)。在匯編程序中可以通過該宏定義的名稱來調(diào)用它,當(dāng)源程序被匯編時(shí),匯
          ;編編譯器將展開每個(gè)宏調(diào)用,用宏定義體代替源程序中的宏定義的名稱,并用實(shí)際的參數(shù)值代替宏定義時(shí)的形
          ;式參數(shù)
          ;-------------------------------------------------------------------------------------------------
          ;在arm中,用的是滿遞減堆棧:stmfd,ldmfd,如果用其他的方式,arm可能不能有效識(shí)別
          ;注意:滿遞減指的是在入棧時(shí)的操作方式,在出棧時(shí)則正好相反的次序
          ;例子:
          ;STMFD sp!,{R0-R7,LR}:(滿遞減:先減再放數(shù)值)sp根據(jù)數(shù)據(jù)個(gè)數(shù),減小相應(yīng)個(gè)數(shù)值的數(shù)據(jù)單位(一步到
          ;位),然后利用for循環(huán)語句,從當(dāng)前sp位置,依次存儲(chǔ)R0-R7,LR.即:sp處最后指向的是R0數(shù)據(jù)處
          ;LDMFD sp!,{R0-R7,LR}:復(fù)制一個(gè)變量為sp值,用該變量依次將數(shù)據(jù)存入R0-R7,LR,變量值增加,最后,變量指
          ;向下一個(gè)將要取的值,完成后sp獲得該變量值;
          ;重點(diǎn)分析下面這個(gè)宏,它對(duì)中斷處理函數(shù)的調(diào)用很重要
          ;確切說,這是宏函數(shù),編譯時(shí)對(duì)調(diào)用語句要做相應(yīng)的展開
          MACRO
          $HandlerLabel HANDLER $HandleLabel
          $HandlerLabel ;標(biāo)號(hào)
          sub sp,sp,#4 ;留出一個(gè)空間,為了存放跳轉(zhuǎn)地址給pc。
          stmfd sp!,{r0} ;把r0中的內(nèi)容入棧,保存起來
          ldr r0,=$HandleLabel ;這是一個(gè)偽指令,不是匯編指令,
          ;目的:把$HandleLabel本身所在的地址給r0
          ldr r0,[r0] ;把$HandleLabel所指向的內(nèi)容(也就是中斷程序的入口地址)放入r0
          str r0,[sp,#4] ;把入口地址放入剛才留出的一個(gè)空間里
          ldmfd sp!,{r0,pc} ;出棧的方式恢復(fù)r0原值和為pc設(shè)定新值(也就完成了到ISR的轉(zhuǎn)跳)。
          ;注:棧中r0內(nèi)容在低地址
          MEND
          ;-------------------------------------------------------------------------------------------------
          ;下面幾個(gè)變量是ads環(huán)境下自動(dòng)設(shè)置的,可以見環(huán)境配置選項(xiàng)里: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手冊(cè),并以cp15指令內(nèi)容搜索2440a手冊(cè)
          IMPORT Main ;The main entry of mon program
          IMPORT RdNF2SDRAM ;Copy Image from Nand Flash to SDRAM
          ;-------------------------------------------------------------------------------------------------
          ;AREA偽指令用于定義一個(gè)代碼段或數(shù)據(jù)段,一個(gè)ARM源程序至少需要一個(gè)代碼段,大的程序可以包含多個(gè)代碼段
          ;及數(shù)據(jù)段
          ;格式:AREA sectionname {,attr} {,attr}...
          AREA Init,CODE,READONLY
          ;-------------------------------------------------------------------------------------------------
          ;ENTRY偽指令用于指定程序的入口點(diǎn)
          ;一個(gè)程序(可以包含多個(gè)源文件)中至少要有一個(gè)ENTRY,可以有多個(gè)ENTRY,但一個(gè)源文件中最多只有一個(gè)
          ;ENTRY.
          ENTRY
          ;-------------------------------------------------------------------------------------------------
          ;EXPORT聲明一個(gè)符號(hào)可以被其他文件引用,相當(dāng)于聲明了一個(gè)全局變量。GLOBAL與EXPORT相同
          ;格式:EXPORT symbol{[WEAK]} [WEAK]聲明其他的同名符優(yōu)先于本符號(hào)被引用
          ;導(dǎo)出符號(hào)__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.
          ;條件編譯,在編譯成機(jī)器碼前就設(shè)定好大小端轉(zhuǎn)換
          ;判斷ENDIAN_CHANGE是否已定義,ASSERT 是斷言偽指令,語法是:ASSERT + 邏輯表達(dá)式,def 是邏輯偽操作符,
          ;格式為::DEF:label,作用是:判斷l(xiāng)abel是否定義過
          ASSERT :DEF:ENDIAN_CHANGE
          [ ENDIAN_CHANGE ;在 option.inc 有定義。默認(rèn)是FALSE,所以此句不會(huì)加入代碼中
          ASSERT :DEF:ENTRY_BUS_WIDTH ;斷言指令,檢測(cè)是否定義該變量,若未定義,報(bào)錯(cuò)
          [ ENTRY_BUS_WIDTH=32 ;defined in option.inc
          b ChangeBigEndian ;DCD 0xea000007
          ;如果是大端,則這是第一條指令,先設(shè)置成大端,
          ;再到復(fù)位指令
          ]
          [ 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 ;本硬件用的是小端模式,這是第一個(gè)執(zhí)行語句,
          ;直接跳轉(zhuǎn)到復(fù)位指令處 0X00
          ]
          ;-------------------------------------------------------------------------------------------------
          ;這7個(gè)中斷,每個(gè)中斷都有固定的中斷入口地址,它們位于代碼的最前端,不允許另作他用
          b HandlerUndef ;handler for Undefined mode 0X04
          b HandlerSWI ;handlerfor SWI interrupt 0X08
          b HandlerPabort ;handler for PAbort,指令預(yù)取中止 0X0C
          b HandlerDabort ;handler for DAbort,數(shù)據(jù)中止 0X10
          b . ;reserved 保留未用 注意小圓點(diǎn) 0X14
          b HandlerIRQ ;handlerfor IRQ interrupt 0X18
          b HandlerFIQ ;handlerfor FIQ interrupt 0X1C
          ;-------------------------------------------------------------------------------------------------
          ;@0x20
          b EnterPWDN ;Must be @0x20
          ;------------------------------------------------------------------------------------------------
          ;下面是改變大小端的程序,采用直接定義 <機(jī)器碼> 的方式,為什么這么做就得問三星了
          ;反正我們程序里這段代碼也不會(huì)去執(zhí)行,不用去管它
          ;每一個(gè)匯編指令,都對(duì)應(yīng)著一個(gè)二進(jìn)制機(jī)器碼,這里沒有使用指令,直接用了機(jī)器碼,含義未知
          ChangeBigEndian
          ;@0x24
          ;對(duì)存儲(chǔ)器控制寄存器操作,指定內(nèi)存模式為Big-endian
          ;因?yàn)閯傞_始CPU都是按照32位總線的指令格式運(yùn)行的,如果采用其他的話,CPU運(yùn)行不了,必須轉(zhuǎn)化
          ;但當(dāng)系統(tǒng)初始化好以后,則CPU能自動(dòng)識(shí)別
          [ 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
          ]
          ;因?yàn)椴捎肂ig-endian模式,采用16位總線時(shí),物理地址的高位和數(shù)據(jù)的地位對(duì)應(yīng)
          ;所以指令的機(jī)器碼也相應(yīng)的高低對(duì)調(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è)置成大端后,再次跳到復(fù)位指令處
          ;-------------------------------------------------------------------------------------------------
          ;本文件底部定義了一個(gè)數(shù)據(jù)區(qū)(在文件最后),34個(gè)字空間,存放相應(yīng)中斷服務(wù)程序的首地址。每個(gè)字空間都
          ;有一個(gè)標(biāo)號(hào),以Handle***命名。
          ;這是宏實(shí)例,在這里Handler***就是通過HANDLER這個(gè)宏和Handle***建立聯(lián)系的.
          ;詳細(xì)分析:
          ;Handle*** 這是宏示例,也就是宏的調(diào)用指令,當(dāng)編譯時(shí)編譯器會(huì)把宏調(diào)用指令展開
          ;Handler*** 這是向量中斷
          ;展開方式(舉例):
          ;HandlerFIQ HANDLER HandleFIQ
          ;展開后變成:
          ;標(biāo)號(hào)HandlerFIQ,由 " b HandlerFIQ "指令使用(見上,復(fù)位處)
          ; sub sp,sp,#4
          ;留出一個(gè)空間,為了存放跳轉(zhuǎn)地址給pc。見:str r0,[sp,#4] ,注意sp值并未改變
          ; stmfd sp!,{r0}
          ;把r0中的內(nèi)容入棧,保存起來
          ; ldr r0,=HandleFIQ
          ;HandleFIQ標(biāo)號(hào),在本文件最下方定義
          ; ldr r0,[r0]
          ;把 HandleFIQ所指向的內(nèi)容(也就是中斷程序的入口地址)放入r0
          ; str r0,[sp,#4]
          ;把入口地址放入剛才留出的一個(gè)空間里
          ; ldmfd sp!,{r0,pc}
          ;出棧的方式恢復(fù)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)到相應(yīng)程序)
          ;產(chǎn)生中斷后,需要中斷服務(wù)程序自己來判斷,到底是哪個(gè)中斷請(qǐng)求,根據(jù)的就是INTOFFSET寄存器中的偏移,再
          ;計(jì)算中斷服務(wù)地址
          IsrIRQ
          sub sp,sp,#4 ;reserved for PC,預(yù)留返回指針的存儲(chǔ)位置
          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中只是偏移單位的個(gè)數(shù),需要*4變成具體字節(jié)偏移(相對(duì)于EINT0)
          ldr r8,[r8]
          str r8,[sp,#8] ;pc值放在了高位置
          ldmfd sp!,{r8-r9,pc}
          ;-------------------------------------------------------------------------------------------------
          ;LTORG用于聲明一個(gè)文字池,在使用LDR偽指令時(shí),要在適當(dāng)?shù)牡胤郊尤隠TORG聲明文字池,這樣就會(huì)把要加載的
          ;數(shù)據(jù)保存在文字池內(nèi),再用ARM的《加載指令》讀出數(shù)據(jù)。(若沒有使用LTORG聲明文字池,則匯編器會(huì)在程序
          ;末尾自動(dòng)聲明)
          ;LTORG 偽指令常放在無條件跳轉(zhuǎn)指令之后,或者子程序返回指令之后,這樣處理器就不會(huì)錯(cuò)誤地將文字池中的
          ;數(shù)據(jù)當(dāng)做指令來執(zhí)行
          ;注:在此,文字池內(nèi)存儲(chǔ)的是INTOFFSET宏所代表的值:0x4a000014 。畢竟,當(dāng)把指令編譯成二進(jìn)制代碼時(shí),
          ;arm指令(32位)不能既表示出指令內(nèi)容,又表示出數(shù)據(jù)地址(32位)。估計(jì)在編譯時(shí),會(huì)被匯編成其他的加載
          ;指令,再編譯成機(jī)器碼
          ;LTORG 只要單獨(dú)寫出來就可以了,其他的交給編譯器來做,而且它跟它下面的代碼沒有任何關(guān)系
          LTORG
          ;-------------------------------------------------------------------------------------------------
          ;=======
          ; ENTRY
          ;=======
          ResetHandler
          ;關(guān)看門狗
          ldr r0,=WTCON ;watch dog disable 編譯時(shí)就是 ldr r0,=53000000;偽指令有=號(hào)
          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和時(shí)鐘
          ;鎖相環(huán) PLL ,作用是將外部晶振的輸入頻率倍頻到一個(gè)較高的頻率
          ;To reduce PLL lock time, adjust the LOCKTIME register.
          ldr r0,=LOCKTIME ;LOCKTIME鎖定時(shí)間計(jì)數(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 時(shí)鐘分頻控制寄存器
          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的運(yùn)行時(shí)鐘,Hclk驅(qū)動(dòng) 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寄存器時(shí),必須先配置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,
          ;對(duì)于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 ;這個(gè)寄存器數(shù)值表示哪個(gè)信號(hào)引起的復(fù)位動(dòng)作產(chǎn)生
          ;檢測(cè) 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(大范圍地址讀?。﹤沃噶?/div>
          ldr r1,=BWSCON ;BWSCON Address 總線寬度&等待狀態(tài)控制寄存器
          add r2, r0, #52 ;End address of SMRDATA,共有13個(gè)寄存器地址(4字節(jié))需要賦值,13*4=52字節(jié)
          0
          ldr r3, [r0], #4 ;這些都是后變址指令
          str r3, [r1], #4
          cmp r2, r0
          bne % B0 ;當(dāng)<的時(shí)候,跳轉(zhuǎn)到0標(biāo)號(hào)處繼續(xù)執(zhí)行
          ;------------------------------------------------------------------------------------------------
          ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
          ;;;;;;;;;;;;; When EINT0 is pressed, Clear SDRAM
          ;如果 EINT0 產(chǎn)生(這中斷就是我們按鍵產(chǎn)生的), 就清除SDRAM ,不過好像沒人會(huì)在這個(gè)時(shí)候按
          ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
          ; 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??? ;當(dāng)按鍵0沒有被按下的時(shí)候,也就是不相等,則向下跳到1標(biāo)號(hào)
          ; 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接地時(shí)從nand 啟動(dòng),懸空時(shí)(核心板上有上拉電阻)從nor啟動(dòng)
          ;OM1在核心板上,始終是接地,為0
          ;OM1:OM0取值:00 nandflash mode
          ; 01 16bit nor
          ; 10 32bit nor
          ; 11 test mode
          ;詳見:s3c2440 用戶手冊(cè) 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
          ;===========================================================
          ;這里的一段代碼時(shí)對(duì)內(nèi)存數(shù)據(jù)的初始化,涉及代碼段,數(shù)據(jù)段,bss段等
          ;因?qū)@里的變量設(shè)置等有異議,暫時(shí)未全面分析,但是基本原理想通,就是一個(gè)比較地址,復(fù)制數(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
          ; 把中斷服務(wù)函數(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ù)運(yùn)行做準(zhǔn)備
          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
          ;配置存儲(chǔ)器的管理方式
          ; 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
          ;分配一個(gè)字的空間,并用后邊的數(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ù)對(duì)齊
          ;------------------------------------------------------------------------------------------------
          ;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 時(shí)鐘分頻器控制寄存器
          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ù)段
          ;^ 標(biāo)志等價(jià)于MAP偽指令
          ;MAP用于定義一個(gè)結(jié)構(gòu)化的內(nèi)存表首地址,此時(shí)內(nèi)存表的位置計(jì)數(shù)器值,也變成該首地址值,就相當(dāng)于在這個(gè)地
          ;址處操作
          ;#于FIELD同義,用于定義一個(gè)結(jié)構(gòu)化的內(nèi)存表的數(shù)據(jù)域,后邊數(shù)字表示該數(shù)據(jù)占用的字節(jié)數(shù)
          ;Handle*** 在此就是一個(gè)標(biāo)號(hào),為了標(biāo)示數(shù)據(jù)量
          ;用法:把對(duì)應(yīng)的終端處理函數(shù)的首地址,放到這里的對(duì)應(yīng)的預(yù)留空間處,當(dāng)發(fā)生中斷時(shí),就能根據(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啟動(dòng)文件2440ini

          評(píng)論


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

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();