在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

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

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

            作者: 時(shí)間:2016-11-23 來(lái)源:網(wǎng)絡(luò) 收藏
            ;=========================================
            ; NAME: 2440INIT.S
            ; DESC: C start up codes
            ; Configure memory, ISR ,stacks
            ;Initialize C-variables
            ;=========================================
            ;注意:axd調(diào)試時(shí),可以看到指令pc地址從0x30000000開(kāi)始,這是因?yàn)閞am的起始地址是0x30000000.
            ;并且如果從nand啟動(dòng),則處理器自動(dòng)把nand首部的4k字節(jié),復(fù)制到ram中,然后pc跳到0x30000000,開(kāi)始執(zhí)行。
            ;此源文件通常包含一些宏定義和常量定義
            ;通用的《啟動(dòng)流程圖》:
            ;入口->屏蔽所有中斷,禁止看門狗->根據(jù)工作頻率設(shè)置PLL寄存器->初始化存儲(chǔ)控制相關(guān)寄存器
            ;->初始化各模式下的棧指針->設(shè)置缺省中斷處理函數(shù)->將數(shù)據(jù)拷貝到RAM中,數(shù)據(jù)段清零
            ;->跳轉(zhuǎn)到c語(yǔ)言main入口函數(shù)中
            ;GET偽指令用于將一個(gè)源文件包含到當(dāng)前源文件中,并將被包含文件在當(dāng)前位置進(jìn)行匯編處理
            ;類似于c的include指令
            ;GET INLCUDE偽指令不能用來(lái)包含目標(biāo)文件,INCBIN偽指令可以包含目標(biāo)文件,
            ;被INCBIN偽指令包含的文件,不進(jìn)行匯編處理,該執(zhí)行文件或數(shù)據(jù)直接放入當(dāng)前文件,
            ;編譯器從INCBIN后邊開(kāi)始繼續(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),故無(wú)論指令為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)該來(lái)自于ADS環(huán)境,在本環(huán)境中設(shè)置是進(jìn)入時(shí)在ARM環(huán)境下,沒(méi)有設(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指令,在處理器剛開(kāi)始時(shí),必須以arm模式運(yùn)行
            | ;此處容易產(chǎn)生錯(cuò)覺(jué),丟掉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ù)返回(無(wú)條件,有條件)。
            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í)開(kāi)始,MEND標(biāo)識(shí)結(jié)束。用MACRO和MEND定義的一段代碼,稱為宏定義
            ;體,這樣在程序中就可以通過(guò)宏指令多次調(diào)用該代碼段。
            ;偽指令格式:
            ;MACRO
            ;{$label} macroname {$parameter} {$parameter} ...
            ;宏定義體
            ;MEND
            ;其中 $label 宏指令被展開(kāi)時(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)宏指令被展開(kāi)時(shí)將被替換成相應(yīng)的值,類似于函數(shù)中的形式參數(shù)
            ;對(duì)于子程序代碼較短,而需要傳遞的參數(shù)比較多的情況下,可以使用匯編技術(shù)。
            ;首先要用MACRO和MEND偽指令定義宏,包括宏定義體代碼。在MACRO偽指令之后的第一行定義宏的原型,其中包
            ;含該宏定義的名稱,及需要的參數(shù)。在匯編程序中可以通過(guò)該宏定義的名稱來(lái)調(diào)用它,當(dāng)源程序被匯編時(shí),匯
            ;編編譯器將展開(kāi)每個(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)語(yǔ)句,從當(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)用很重要
            ;確切說(shuō),這是宏函數(shù),編譯時(shí)對(duì)調(diào)用語(yǔ)句要做相應(yīng)的展開(kāi)
            MACRO
            $HandlerLabel HANDLER $HandleLabel
            $HandlerLabel ;標(biāo)號(hào)
            sub sp,sp,#4 ;留出一個(gè)空間,為了存放跳轉(zhuǎn)地址給pc。
            stmfd sp!,{r0} ;把r0中的內(nèi)容入棧,保存起來(lá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è)置的,可以見(jiàn)環(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)容見(jiàn)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 是斷言偽指令,語(yǔ)法是:ASSERT + 邏輯表達(dá)式,def 是邏輯偽操作符,
            ;格式為::DEF:label,作用是:判斷l(xiāng)abel是否定義過(guò)
            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í)行語(yǔ)句,
            ;直接跳轉(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ī)器碼> 的方式,為什么這么做就得問(wèn)三星了
            ;反正我們程序里這段代碼也不會(huì)去執(zhí)行,不用去管它
            ;每一個(gè)匯編指令,都對(duì)應(yīng)著一個(gè)二進(jìn)制機(jī)器碼,這里沒(méi)有使用指令,直接用了機(jī)器碼,含義未知
            ChangeBigEndian
            ;@0x24
            ;對(duì)存儲(chǔ)器控制寄存器操作,指定內(nèi)存模式為Big-endian
            ;因?yàn)閯傞_(kāi)始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***就是通過(guò)HANDLER這個(gè)宏和Handle***建立聯(lián)系的.
            ;詳細(xì)分析:
            ;Handle*** 這是宏示例,也就是宏的調(diào)用指令,當(dāng)編譯時(shí)編譯器會(huì)把宏調(diào)用指令展開(kāi)
            ;Handler*** 這是向量中斷
            ;展開(kāi)方式(舉例):
            ;HandlerFIQ HANDLER HandleFIQ
            ;展開(kāi)后變成:
            ;標(biāo)號(hào)HandlerFIQ,由 " b HandlerFIQ "指令使用(見(jiàn)上,復(fù)位處)
            ; sub sp,sp,#4
            ;留出一個(gè)空間,為了存放跳轉(zhuǎn)地址給pc。見(jiàn):str r0,[sp,#4] ,注意sp值并未改變
            ; stmfd sp!,{r0}
            ;把r0中的內(nèi)容入棧,保存起來(lá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)容在低地址
            ;后邊的語(yǔ)句展開(kāi)方式,同上。編譯后,代碼都展開(kā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ù)程序自己來(lái)判斷,到底是哪個(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ù)。(若沒(méi)有使用LTORG聲明文字池,則匯編器會(huì)在程序
            ;末尾自動(dòng)聲明)
            ;LTORG 偽指令常放在無(wú)條件跳轉(zhuǎn)指令之后,或者子程序返回指令之后,這樣處理器就不會(huì)錯(cuò)誤地將文字池中的
            ;數(shù)據(jù)當(dāng)做指令來(lái)執(zhí)行
            ;注:在此,文字池內(nèi)存儲(chǔ)的是INTOFFSET宏所代表的值:0x4a000014 。畢竟,當(dāng)把指令編譯成二進(jìn)制代碼時(shí),
            ;arm指令(32位)不能既表示出指令內(nèi)容,又表示出數(shù)據(jù)地址(32位)。估計(jì)在編譯時(shí),會(huì)被匯編成其他的加載
            ;指令,再編譯成機(jī)器碼
            ;LTORG 只要單獨(dú)寫出來(lái)就可以了,其他的交給編譯器來(lái)做,而且它跟它下面的代碼沒(méi)有任何關(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來(lái)說(shuō)必須是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]來(lái)判斷是否是由 sleep 模式喚醒引起的電源開(kāi)啟。
            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 ,不過(guò)好像沒(méi)人會(huì)在這個(gè)時(shí)候按
            ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
            ; check if EIN0 button is pressed
            ldr r0,=GPFCON ;input,無(wú)上拉電阻
            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沒(méi)有被按下的時(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選擇開(kāi)關(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
            ;詳見(jiàn):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ù)的過(guò)程
            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(各個(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ù)值來(lái)初始化該空間,這里命名有些混亂
            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)閉