新聞中心

EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > S3C2410啟動(dòng)代碼詳解(2)

S3C2410啟動(dòng)代碼詳解(2)

作者: 時(shí)間:2016-11-11 來(lái)源:網(wǎng)絡(luò) 收藏
;========================================================================================

//在這里用IMPORT偽指令(和c語(yǔ)言的extren一樣)引入|Image$$RO$$Base|,|Image$$RO$$Limit|...

本文引用地址:http://2s4d.com/article/201611/316603.htm

//這些變量是通過(guò)ADS的工程設(shè)置里面設(shè)定的RO Base和RW Base設(shè)定的,最終由編譯腳本和連接程序?qū)氤绦?

//那為什么要引入這玩意呢,最簡(jiǎn)單的用處是可以根據(jù)它們拷貝自已,從把RW和ZI變量從加載域中復(fù)制到運(yùn)行域中

//一個(gè)arm由RO,RW,ZI三個(gè)斷組成其中RO為代碼段,RW是已經(jīng)初始化的全局變量,ZI是未初始化的全局變量(對(duì)于GNU工具對(duì)應(yīng)的概念是TEXT ,DATA,BSS)。

;========================================================================================
IMPORT |Image$$RO$$Base| ; ROM code(也就是代碼)的開始地址
IMPORT |Image$$RO$$Limit| ;ROM code的結(jié)束地址 (也就是RW在加載域中的起始地址)
IMPORT |Image$$RW$$Base| ;在運(yùn)行域中要初始化的RAM的開始地址
IMPORT |Image$$ZI$$Base| ; area(需要清零的RAM區(qū)域)的開始地址
IMPORT |Image$$ZI$$Limit| ; area的結(jié)束地址

;這里引入一些在其它文件中實(shí)現(xiàn)在函數(shù),包括為我們所熟知的main函數(shù)
IMPORT Main ; The main entryof mon program

;從這里開始就是正真的代碼入口了!
AREA Init,CODE,READONLY;這表明下面的是一個(gè)名為Init的代碼段
ENTRY ;定義程序的入口(調(diào)試用)其中關(guān)鍵字ENTRY是指定編譯器保留這段代碼,因?yàn)?/p>

編譯器可能會(huì)認(rèn)為這是一段亢余代碼而加以優(yōu)化。鏈接的時(shí)候要確保這段代碼

被鏈接在0地址處,并且作為整個(gè)程序的入口
;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.
ASSERT :DEF:ENDIAN_CHANGE
[ ENDIAN_CHANGE ;下面是大小端的一個(gè)判斷,在Option.inc里已經(jīng)設(shè)為FALSE
ASSERT :DEF:ENTRY_BUS_WIDTH
[ ENTRY_BUS_WIDTH=32 //‘[’=IF
b ChangeBigEndian ;DCD 0xea000007
]

[ 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 ;因?yàn)樵O(shè)成FALSE,所以系統(tǒng)復(fù)位后就來(lái)到這了,轉(zhuǎn)跳到復(fù)位程序入口

]

//=====================================================================================

;ARM要求中斷向量表必須放置在仿地址開始,連續(xù)8X4字節(jié)的空間內(nèi).每當(dāng)一個(gè)中斷發(fā)生以后,ARM處理器便強(qiáng)制把PC指針置為向量表中對(duì)應(yīng)中斷類型的地址值。因?yàn)槊總€(gè)中斷只占據(jù)向量表中1個(gè)字的存儲(chǔ)空間,只能放置一條ARM指令,使程序跳轉(zhuǎn)到存儲(chǔ)器的其他地方,再執(zhí)行中斷處理

//=====================================================================================
b HandlerUndef ;轉(zhuǎn)跳到Undefined mode程序入口
b HandlerSWI ;轉(zhuǎn)跳到SWI 中斷程序入口
b HandlerPabort ;轉(zhuǎn)跳到PAbort(指令異常)程序入口
b HandlerDabort ;轉(zhuǎn)跳到DAbort(數(shù)據(jù)異常)程序入口
b . ;保留
b HandlerIRQ ;轉(zhuǎn)跳到IRQ 中斷程序入口
b HandlerFIQ ;轉(zhuǎn)跳到FIQ 中斷程序入口

;@0x20不知道是什么意思,地址?
b EnterPWDN ; Must be @0x20.

;==================================================================================
;下面是改變大小端的程序,這里采用直接定義機(jī)器碼的方式,至說(shuō)為什么這么做就得問(wèn)三星了
;反正我們程序里這段代碼也不會(huì)去執(zhí)行,不用去管它
;==================================================================================
ChangeBigEndian //通過(guò)設(shè)置CP15中的C1的位7來(lái)設(shè)置存儲(chǔ)格式為大端模式。
;@0x24
[ ENTRY_BUS_WIDTH=32
DCD 0xee110f10 ;0xee110f10 => mrc p15,0,r0,c1,c0,0
DCD 0xe3800080 ;0xe3800080 => orr r0,r0,#0x80; //Big-endian
DCD 0xee010f10 ;0xee010f10 => mcr p15,0,r0,c1,c0,0
]
[ ENTRY_BUS_WIDTH=16
DCD 0x0f10ee11
DCD 0x0080e380
DCD 0x0f10ee01
]
[ ENTRY_BUS_WIDTH=8
DCD 0x100f11ee
DCD 0x800080e3
DCD 0x100f01ee
]
DCD 0xffffffff ;swinv 0xffffff is similar with NOP and run well in both endian mode.
DCD 0xffffffff
DCD 0xffffffff
DCD 0xffffffff
DCD 0xffffffff
b ResetHandler

;Function for entering power down mode,下面這段程序?yàn)檫M(jìn)入掉電模式及從掉電模式中喚醒的相關(guān)設(shè)置和處理
; 1. SDRAM should be in self-refresh mode. SDRAm應(yīng)該設(shè)置為自刷新的模式
; 2. All interrupt should be maksked for SDRAM/DRAM self-refresh. 所有中斷必須屏蔽 for SDRAM/DRAM self-ref
; 3. LCD controller should be disabled for SDRAM/DRAM self-refresh. LCD 控制器關(guān)閉
; 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); //PWDN:powerdown
EnterPWDN
mov r2,r0;r2=rCLKCON //rCLKCONr [3;2]位為電源模式標(biāo)置位。若[3]為1,表示轉(zhuǎn)為了掉電模式
tst r0,#0x8;POWER_OFF mode?//按位與判斷,若[3]為1則跳轉(zhuǎn)到ENTER_POWER_OFF
bne ENTER_POWER_OFF

ENTER_STOP//進(jìn)入停止模式相關(guān)處理
ldr r0,=REFRESH
ldr r3,[r0];r3=rREFRESH
mov r1, r3
orr r1, r1, #BIT_SELFREFRESH
str r1, [r0] ;Enable SDRAM self-refresh

mov r1,#16 ;wait until self-refresh is issued. may not be needed.等待自刷新生效
0subs r1,r1,#1
bne %B0//表示不相等則往回跳轉(zhuǎn)到標(biāo)號(hào)為0的位置,在此為上一句。

ldr r0,=CLKCON;enter STOP mode.
str r2,[r0]

mov r1,#32
0subs 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 POWER_OFF mode, only the reset by wake-up is available.

//進(jìn)入掉電 模式后,僅喚醒中斷有效

ldr r0,=REFRESH;exit from SDRAM self refresh mode.
str r3,[r0]

MOV_PC_LR//開始處定義的返回跳轉(zhuǎn)宏

ENTER_POWER_OFF
;NOTE.注意在rGSTATUS3寄存器中應(yīng)該保存掉電模式喚醒的返回地址,rGSTATUS3,4可在掉電下保存信息
;1) rGSTATUS3 should have the return address after wake-up from POWER_OFF mode.

ldr r0,=REFRESH
ldr r1,[r0];r1=rREFRESH
orr r1, r1, #BIT_SELFREFRESH
str r1, [r0];Enable SDRAM self-refresh

mov r1,#16 ;Wait until self-refresh is issued,which may not be needed.
0subs r1,r1,#1
bne %B0

ldr r1,=MISCCR
ldrr0,[r1]
orrr0,r0,#(7<<17) ;Make sure that SCLK0:SCLK->0, SCLK1:SCLK->0, SCKE=L during boot-up
strr0,[r1]

ldr r0,=CLKCON
str r2,[r0]

b .;CPU will die here.


;=================================================================================

從掉電模式喚醒的過(guò)程

1、某個(gè)喚醒源生效將產(chǎn)生一個(gè)內(nèi)部復(fù)位信號(hào)。復(fù)位時(shí)間由一個(gè)內(nèi)部16位計(jì)數(shù)器決定,此計(jì)數(shù)器的時(shí)鐘是tRST=(65535/XTAL_frequency)。

2、查詢GSTATUS[2]位看從掉電模式喚醒是否產(chǎn)生了一個(gè)POWER-UP。

3、通過(guò)將MISCCR[19:17]設(shè)置為000b,釋放SDRAM信號(hào)保護(hù)。

4、配置SDRAM控制器。

5、等待SDRAM自我刷新完畢。大部分SDRAM需要refresh cycle of all SDRAM row。

6、GSTATUS3,4的信息可以被用戶使用,因?yàn)镚STATUS3,4的值已經(jīng)在掉電模式下被保存了。

7、對(duì)于EINT[3:0],檢查SRCPND寄存器;對(duì)于EINT[15:4],檢查EINTPND寄存器;對(duì)于RTC報(bào)警喚醒,檢查RTC時(shí)間,因?yàn)樵趩拘褧r(shí)SRCPND寄存器的RTC位不被置位;如果在掉電模式期間有nBATT-FLT assertion,SRCPND寄存器的相關(guān)位被置位。

;==================================================================================

WAKEUP_POWER_OFF
;Release SCLKn after wake-up from the POWER_OFF mode.

ldr r1,=MISCCR//MISCCR寄存器用來(lái)設(shè)置一些USB等相關(guān)的時(shí)鐘周期等
ldrr0,[r1]
bicr0,r0,#(7<<17)//SCLK0:0->SCLK, SCLK1:0->SCLK, SCKE:L->H

strr0,[r1]//通過(guò)將MISCCR[19:17]設(shè)置為000b,釋放SDRAM信號(hào)保護(hù)。

;Set memory control registers配置內(nèi)存控制寄存器。
ldrr0,=SMRDATA//在程序的后面LTORGSMRDATA DATA中定義了

//一個(gè)數(shù)據(jù)緩沖池就是用來(lái)配置相關(guān)的內(nèi)存控制寄存器的
ldrr1,=BWSCON ;BWSCON Address
addr2, r0, #52 ;End address of SMRDATA
0
ldrr3, [r0], #4
strr3, [r1], #4
cmpr2, r0
bne%B0

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

ldr r1,=GSTATUS3 ; GSTATUS3 has the start address just after POWER_OFF wake-up
ldr r0,[r1]
mov pc,r0 //從掉電模式下喚醒后,將保存在GSTATUS3 返回地址傳給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)辦法了,再查一次表唄!
;===================================================================================
IsrIRQ//第二次中斷查表,因?yàn)锳RM把所有的中斷都?xì)w為一個(gè)IRQ異常,通過(guò)此處查表可知道具體中斷
sub sp,sp,#4 ;給PC寄存器保留
stmfd sp!,{r8-r9} ;把r8-r9壓入棧

ldr r9,=INTOFFSET ;把INTOFFSET的地址裝入r9
ldr r9,[r9] ;把INTOFFSET的值裝入r9
ldr r8,=HandleEINT0 ;這就是我們第二個(gè)中斷向量表的入口的,先裝入r8
;===================================================================================
;哈哈,這查表方法夠好了吧,r8(入口)+index*4(別望了一條指令是4 bytes的喔),
;這不就是我們要找的那一項(xiàng)了嗎.找到了表項(xiàng),下一步做什么?肯定先裝入了!
;==================================================================================
add r8,r8,r9,lsl #2
ldr r8,[r8] ;裝入中斷服務(wù)程序的入口
str r8,[sp,#8] ;把入口也入棧,準(zhǔn)備用舊招
ldmfd sp!,{r8-r9,pc};施招,彈出棧,哈哈,順便把r8彈出到PC,O了,跳轉(zhuǎn)成功!



關(guān)鍵詞: S3C2410啟動(dòng)代

評(píng)論


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

關(guān)閉