久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 5576|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

ARM9學(xué)習(xí)4-S3C2410的啟動(dòng)代碼分析-For ADSv1.2

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:89763 發(fā)表于 2015-9-12 22:03 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
S3c2410啟動(dòng)代碼詳解
通常,啟動(dòng)代碼是指CPU復(fù)位后到進(jìn)入C語(yǔ)言的main函數(shù)之前需要執(zhí)行的那段匯編代碼.這是由于C語(yǔ)言程序的運(yùn)行需要具備一定的條件,比如:分配好外部數(shù)據(jù)空闿堆?臻g和中斷入口等筿另外匯編代碼可以更直接的對(duì)硬件進(jìn)行操使效率更高. 通常啟動(dòng)代碼是放在2410init.s匯編文件;特殊功能寄存器定義在2410addr.s;Memory Bank 配置在mencfg.s;還有系統(tǒng)的選項(xiàng)等在option.s文件;2410init.s不僅包括復(fù)位后執(zhí)行的代碼,還包括CPU進(jìn)入掉電模式,產(chǎn)生中斷等和處理器直接相關(guān)的,用匯編實(shí)現(xiàn)的代碼.
;=========================================
; NAME: 2410INIT.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,POWER_OFF mode
; 2003.05.19:jcs:Configure UPLL in init.s not usbmain.c
;=========================================

  //首先,啟動(dòng)代碼定義了一些常量 ,相當(dāng)于C中的INCLUDE
GET option.inc
GET memcfg.inc
GET 2410addr.inc


BIT_SELFREFRESH EQU (1<<22) //自刷新常量
//;;處理器模式常量
USERMODE    EQU  0x10
FIQMODE     EQU  0x11
IRQMODE     EQU  0x12
SVCMODE     EQU  0x13
ABORTMODE   EQU  0x17
UNDEFMODE   EQU  0x1b
MODEMASK    EQU  0x1f  //
系統(tǒng)模式
NOINT           EQU  0xc0  
//屏蔽所有的中斷,即置位I,F(xiàn)位
//;The location of stacks 定義處理器各模式下堆棧地址常量
UserStack        EQU (_STACK_BASEADDRESS-0x3800) ;0x33ff4800 ~
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 ~

;check if tasm.exe is used.
;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指令
;這段是為了統(tǒng)一目前的處理器工作狀態(tài)和軟件編譯方式(16位編譯環(huán)境使用tasm.exe編譯)
GBLL THUMBCODE ;設(shè)置一個(gè)全局邏輯變量
[ {CONFIG} = 16 ;if config==16 這里表示你的目前處于領(lǐng)先地16位編譯方式,{CONFIG}為匯編器內(nèi)置變量
THUMBCODE SETL {TRUE} ;設(shè)置THUMBCODE 為 true
CODE32 ;轉(zhuǎn)入32位編譯模式
|      ;else
THUMBCODE SETL {FALSE} ;設(shè)置THUMBCODE 為 false
]
[ THUMBCODE     ;if THUMBCODE==TRUE
CODE32          ;for start-up code for Thumb mode;轉(zhuǎn)入32位編譯方式
]
;注意下面這段程序是個(gè)宏定義 很多人對(duì)這段程序不理解 我再次強(qiáng)調(diào)這是一個(gè)宏定義 所以大家要注意了下面包含的HandlerXXX HANDLER HandleXXX將都被下面這段程序展開。
;這段程序用于把中斷服務(wù)程序的首地址裝載到pc中,有人稱之為“加載程序”。其大致作用是把宏的第一個(gè)參數(shù)$HandlerLabel轉(zhuǎn)變?yōu)橐粋(gè)標(biāo)號(hào),然后讓程序跳轉(zhuǎn)到第二個(gè)參數(shù) $HandleLabel(第二個(gè)參數(shù)應(yīng)該為一個(gè)地址)對(duì)應(yīng)的值的地址去?梢苑治龀,sp和r0在執(zhí)行前后都沒有變化,程序就實(shí)現(xiàn)了跳轉(zhuǎn)
;本初始化程序定義了一個(gè)數(shù)據(jù)區(qū)(在文件最后),34個(gè)字空間,存放相應(yīng)中斷服務(wù)程序的首地址。每個(gè)字空間都有一個(gè)標(biāo)號(hào),以Handle***命名。
;在向量中斷模式下使用“加載程序”來執(zhí)行中斷服務(wù)程序。
;這里就必須講一下向量中斷模式和非向量中斷模式的概念
;向量中斷模式是當(dāng)cpu讀取位于0x18處的IRQ中斷指令的時(shí)候,系統(tǒng)自動(dòng)讀取對(duì)應(yīng)于該中斷源確定地址上的指令取代0x18處的指令,通過跳轉(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ù)通過讀取interrupt pending寄存器中對(duì)應(yīng)標(biāo)志位 來判斷中斷源 并根據(jù)優(yōu)先級(jí)關(guān)系再跳到對(duì)應(yīng)中斷源的處理代碼中
MACRO
$HandlerLabel HANDLER $HandleLabel    //
$HandlerLabel
sub sp,sp,#4                     ;減少sp(預(yù)留一個(gè)字,用于存放轉(zhuǎn)跳地址)
stmfd sp!,{r0}                    ;把工作寄存器壓入棧(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]                  ;把中斷服務(wù)程序(ISR)壓入棧,保存在高一個(gè)地址預(yù)留的空間中,但SP沒變。
ldmfd   sp!,{r0,pc}              ;用出棧的方式恢復(fù)r0的原值和為pc設(shè)定新值(也就完成了到ISR的轉(zhuǎn)跳) ;
                   ADS僅支持FD(滿遞減)型堆棧,故只能用stmfd和ldmfd
MEND
;========================================================================================
//在這里用IMPORT偽指令(c語(yǔ)言的extren一樣)引入|Image$$RO$$Base|,|Image$$RO$$Limit|...
//這些變量是通過ADS的工程設(shè)置里面設(shè)定的RO BaseRW Base設(shè)定的,最終由編譯腳本和連接程序?qū)氤绦?/font>.
//那為什么要引入這玩意呢,最簡(jiǎn)單的用處是可以根據(jù)它們拷貝自已 ,從把RW和ZI變量從加載域中復(fù)制到運(yùn)行域中
//一個(gè)armRO,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 entry of mon program
;從這里開始就是正真的代碼入口了!
AREA    Init,CODE,READONLY       ;這表明下面的是一個(gè)名為Init的代碼段
ENTRY                                            
;定義程序的入口(調(diào)試用) 其中關(guān)鍵字ENTRY是指定編譯器保留這段代碼,因?yàn)?/font>
                                                       編譯器可能會(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ù)位后就來到這了,轉(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ī)器碼的方式,至說為什么這么做就得問三星了
;反正我們程序里這段代碼也不會(huì)去執(zhí)行,不用去管它

;==================================================================================
ChangeBigEndian    //通過設(shè)置CP15中的C1的位7來設(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.等待自刷新生效
0 subs r1,r1,#1
bne %B0                                    
//表示不相等則往回跳轉(zhuǎn)到標(biāo)號(hào)為0的位置,在此為上一句。
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 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.
0 subs r1,r1,#1
bne %B0

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

ldr r0,=CLKCON
str r2,[r0]   

b .   ;CPU will die here.

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

從掉電模式喚醒的過程
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、               通過將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寄存器用來設(shè)置一些USB等相關(guān)的時(shí)鐘周期等
ldr r0,[r1]
bic r0,r0,#(7<<17)        
//SCLK0:0->SCLK, SCLK1:0->SCLK, SCKE:L->H
str r0,[r1]                     //通過將MISCCR[19:17]設(shè)置為000b,釋放SDRAM信號(hào)保護(hù)。
;Set memory control registers配置內(nèi)存控制寄存器。
ldr r0,=SMRDATA      
//在程序的后面 LTORG SMRDATA DATA中定義了
                                    //一個(gè)數(shù)據(jù)緩沖池就是用來配置相關(guān)的內(nèi)存控制寄存器的
ldr r1,=BWSCON         ;BWSCON Address
add r2, r0, #52            ;End address 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 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

如上所說,這里采用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

;===================================================================================
;呵呵,來了來了.好戲來了,這一段程序就是用來進(jìn)行第二次查表的過程了.
;如果說第一次查表是由硬件來完成的,那這一次查表就是由軟件來實(shí)現(xiàn)的了.
;為什么要查兩次表??
;沒有辦法,ARM把所有的中斷都?xì)w納成一個(gè)IRQ中斷異常和一個(gè)FIRQ中斷異常
;第一次查表主要是查出是什么異常,可我們總要知道是這個(gè)中斷異常中的什么中斷呀!
;沒辦法了,再查一次表唄!
;===================================================================================
IsrIRQ                     
//第二次中斷查表,因?yàn)锳RM把所有的中斷都?xì)w為一個(gè)IRQ異常,通過此處查表可知道具體中斷
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)成功!

;================================================================================
; ENTRY  系統(tǒng)上電后經(jīng)過一個(gè)b ResetHandler就跳轉(zhuǎn)到此處來。在此完成一些相關(guān)的軟硬件配置工作
1.        屏蔽所有中斷,關(guān)看門狗。
2.        根據(jù)工作頻率設(shè)置PLL寄存器
3.        初始化存儲(chǔ)控制相關(guān)寄存器
4.        初始化各模式下的棧指針
5.        設(shè)置缺省中斷處理函數(shù)
6.        將數(shù)據(jù)段拷貝到RAM中,將零初始化數(shù)據(jù)段清零
7.        跳轉(zhuǎn)到C 語(yǔ)言Main入口函數(shù)中

;================================================================================
ResetHandler
ldr r0,=WTCON       ;watch dog disable
關(guān)看門狗
ldr r1,=0x0         
str r1,[r0]

ldr r0,=INTMSK
ldr r1,=0xffffffff         ;all interrupt disable
屏蔽所有中斷
str r1,[r0]

ldr r0,=INTSUBMSK
ldr r1,=0x3ff            ;all sub interrupt disable
屏蔽所有子中斷
str r1,[r0]

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

;
To reduce PLL lock time, adjust the LOCKTIME register. 為了減少PLL的lock time, 調(diào)整LOCKTIME寄存器.
ldr r0,=LOCKTIME     
//LOCKTIME為鎖定計(jì)數(shù)定時(shí)器,即設(shè)置PLL穩(wěn)定過渡時(shí)間,一般大于150uS
ldr r1,=0xffffff
str r1,[r0]
      

;=================================================================================
上電復(fù)位時(shí)的時(shí)鐘行為。晶振在幾毫秒內(nèi)開始振蕩。當(dāng)OSC時(shí)鐘穩(wěn)定后,PLL根據(jù)默認(rèn)PLL設(shè)置開始生效,但是通常這個(gè)時(shí)候是不穩(wěn)定的,因此在軟件重新配置PLLCON寄存器之前FCLK直接使用Fin而不是MPLL,即使用戶不希望改變PLLCON的默認(rèn)值,用戶也應(yīng)該執(zhí)行一邊寫PLLCON操作。
;這里介紹一下計(jì)算公式
;Fpllo=(m*Fin)/(p*2^s)
;m=MDIV+8,p=PDIV+2,s=SDIV
;Fpllo必須大于20Mhz小于66Mhz
;Fpllo*2^s必須小于170Mhz
;如下面的PLLCON設(shè)定中的M_DIV P_DIV S_DIV是取自option.h中M_DIV=0x5c=92 P_DIV=0x4  S_DIV=0x2

所以Fpllo=(m*Fin)/(p*2^s)=(92+8)*12M/(4+2)*2^2=50M
;==================================================================================  
     [ PLL_ON_START
;Configure MPLL
ldr r0,=MPLLCON         
//M_DIV=0x5c=92 P_DIV=0x4  S_DIV=0x2
ldr r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV)  ;Fin=12MHz,Fout=50MHz
str r1,[r0]
       ;Configure UPLL
ldr r0,=UPLLCON         
ldr r1,=((U_MDIV<<12)+(U_PDIV<<4)+U_SDIV)  ;Fin=12MHz,UPLLout=48MHz
str r1,[r0]
]

;Check if the boot is caused by the wake-up from POWER_OFF mode.
ldr r1,=GSTATUS2
ldr r0,[r1]
tst r0,#0x2
        
;In case of the wake-up from POWER_OFF mode, go to POWER_OFF_WAKEUP handler.
bne WAKEUP_POWER_OFF

EXPORT StartPointAfterPowerOffWakeUp
StartPointAfterPowerOffWakeUp

;====================================================================================
//設(shè)置內(nèi)存控制器等寄存器的值,因?yàn)檫@些寄存器是連續(xù)排列的,所以采用如下辦法對(duì)這些 ;寄存器進(jìn)行連續(xù)設(shè)置.其中用到了SMRDATA的數(shù)據(jù),這在代碼后面有定義 ;Set memory control registers
;=====================================================================================
ldr r0,=SMRDATA
ldr r1,=BWSCON                     ;BWSCON Address
add r2, r0, #52                        ;End address of SMRDATA,共13個(gè)DCD,52個(gè)字節(jié)
0      
ldr r3, [r0], #4   
str r3, [r1], #4   
cmp r2, r0  
bne %B0                       
  //上面這段小程序?qū)⒑竺娑x的數(shù)據(jù)復(fù)制到相關(guān)內(nèi)存控制寄存器
     ;Initialize stacks
bl InitStacks                     
//調(diào)用堆棧初始化子程序
;==================================================================================
關(guān)于異常中斷系統(tǒng):異常中斷矢量表(每個(gè)表項(xiàng)占4個(gè)字節(jié)) 下面是中斷向量表 一旦系統(tǒng)運(yùn)行時(shí)有中斷發(fā)生 即使移植了操作系統(tǒng) 如linux 處理器已經(jīng)把控制權(quán)交給了操作系統(tǒng) 一旦發(fā)生中斷 處理器還是會(huì)跳轉(zhuǎn)到從0x0開始
;中斷向量表中某個(gè)中斷表項(xiàng)(依據(jù)中斷類型)開始執(zhí)行;具體中斷向量布局請(qǐng)參考s3c44b0 spec 例如 adc中斷向量為 0x000000c0下面對(duì)應(yīng)表中第49項(xiàng)位置 向量地址0x0+4*(49-1)=0x000000c0

2410異常中斷系統(tǒng)中有兩張中斷轉(zhuǎn)移表,經(jīng)過二重轉(zhuǎn)移才跳到中斷處理程序。第一張中斷向量表由硬件決定,所在區(qū)域?yàn)镽OM(flash),地址空間從0X00開始,其中0X00-0X1C為異常向量入口地址。另一張中斷向量表在RAM 中,可以隨便改,其位置在程序連接后才定。ARM7的內(nèi)核實(shí)際上只有8個(gè)(1個(gè)保留)異常向量,對(duì)于其他所有眾多的中斷源,ARM7 的內(nèi)核是通過IRQ或FRQ 的軟件查詢中斷狀態(tài)寄存器的位來獲得ISR的起始地址。
;===================================================================================
  
; Setup IRQ handler  //;設(shè)置缺省中斷處理函數(shù)
ldr r0,=HandleIRQ       //;This routine is needed;//使用ldr偽指令裝載HandleIRQ的地址到r0中
ldr r1,=IsrIRQ          //If there isn't 'subs pc,lr,#4' at 0x18, 0x1c;//使用ldr偽指令裝載IsrIRQ的地址到r1中
str r1,[r0]            //把r1的值寫到r0指向的存儲(chǔ)地址中,把IsrIRQ這個(gè)函數(shù)的地址寫入到HandleIRQ存儲(chǔ)單元里面


;======================================================================================
;Copy and paste RW data/zero initialized data
//以下程序段將加載哉中的數(shù)據(jù)段RW拷貝到運(yùn)行域的ram中 將ZI段中的零初始化數(shù)據(jù)段清零
//跳入C語(yǔ)言的main函數(shù)執(zhí)行到這步結(jié)束bootloader初步引導(dǎo)結(jié)束   
程序先把 ROM 里|Image$$RO$$Limt|開始的 RW 初始數(shù)據(jù)拷貝到 RAM 里面|Image$$RW$$Base|開始的地址,當(dāng)RAM這邊的目標(biāo)地址到達(dá)|Image$$ZI$$Base|后就表示RW區(qū)的結(jié)束和ZI區(qū)的開始,接下去就對(duì)這片ZI區(qū)進(jìn)行清零操作,直到遇到結(jié)束地址|Image$$ZI$$Limit|。
;======================================================================================
ldr r0, =|Image$$RO$$Limit|     //Get pointer to ROM data,rom中的RW數(shù)據(jù)源的起始地址
ldr r1, =|Image$$RW$$Base|   //and RAM copyRW區(qū)在RAM里的執(zhí)行區(qū)起始地址
ldr r3, =|Image$$ZI$$Base|      //ZI區(qū)在RAM里面的起始地址

;Zero init base => top of initialised data檢查裝載地址和執(zhí)行地址是否相同
cmp r0, r1      ; Check that they are different
beq %F2            ;//若相等則跳轉(zhuǎn)到2,相同,則不拷貝該區(qū)間,初始化零數(shù)據(jù)區(qū)
1      
cmp r1, r3            ; Copy init data;//如果r0不等于r1,r1和r3比較,Copy init data,不相同,將裝載區(qū)拷貝到執(zhí)行區(qū)
ldrcc r2, [r0], #4    ;--> LDRCC r2, [r0] + ADD r0, r0, #4   當(dāng)無符號(hào)數(shù)r1<r3時(shí),讀取r0地址處的內(nèi)容      
strcc r2, [r1], #4    ;--> STRCC r2, [r1] + ADD r1, r1, #4
bcc %B1               ;//若相等則跳轉(zhuǎn)到1,相同,則不拷貝該區(qū)間,初始化零數(shù)據(jù)區(qū)

2      
ldr r1, =|Image$$ZI$$Limit|      ; Top of zero init segment,ZI區(qū)在RAM里面的結(jié)束地址后面的一個(gè)地址
mov r2, #0
3      
cmp r3, r1      ; Zero init
strcc r2, [r3], #4     //當(dāng)ZI區(qū)的起始地址未達(dá)等于結(jié)束地址時(shí),繼續(xù)清0
bcc %B3                ;//當(dāng)無符號(hào)數(shù)r3<r1時(shí),跳轉(zhuǎn)到3處,這樣做就完成了zi區(qū)的初始化清0


    [ :LNOT:THUMBCODE
     bl Main        ;Don't use
main() because ......跳到Main()主函數(shù),注意大小寫
     b .                       
    ]

    [ THUMBCODE         ;for start-up code for Thumb mode
     orr lr,pc,#1
     bx lr
     CODE16
     bl Main        ;Don't use main() because ......
     b .
     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                        
;//讀取CPSR的值,R0=CPSR,CPSR為當(dāng)前程序狀態(tài)寄存器
bic r0,r0,#MODEMASK       ;//R0=R0&(~MODEMASK),MODEMASK=0X1F,也就是低五位清0
orr r1,r0,#UNDEFMODE|NOINT  ;//R1=R0|(MODEMASK|NONINT),R1為未定義模式,也就是低八位為11X11011
msr cpsr_cxsf,r1  ;UndefMode   
;//寫把R1的值寫到狀態(tài)寄存器cpsr_cxsf(也就是CPSR),UndefMode
ldr sp,=UndefStack                   ;//設(shè)置未定義模式下的堆棧指針

orr r1,r0,#ABORTMODE|NOINT
msr cpsr_cxsf,r1  ;AbortMode
ldr sp,=AbortStack

orr r1,r0,#IRQMODE|NOINT
msr cpsr_cxsf,r1  ;IRQMode
ldr sp,=IRQStack
   
orr r1,r0,#FIQMODE|NOINT
msr cpsr_cxsf,r1  ;FIQMode
ldr sp,=FIQStack

bic r0,r0,#MODEMASK|NOINT
orr r1,r0,#SVCMODE
msr cpsr_cxsf,r1  ;SVCMode
ldr sp,=SVCStack

//USER mode has not be initialized.注意:不要切換到User模式進(jìn)行User模式的堆棧設(shè)置,因?yàn)檫M(jìn)入U(xiǎn)ser模式后就
//不能再操作CPSR回到別的模式了,可能會(huì)對(duì)接下去的程序執(zhí)行造成影響

mov pc,lr                        
    //堆棧初始化完成返回
;The LR register won't be valid if the current mode is not SVC mode.

;以下是上面提到的對(duì)存儲(chǔ)寄存器初始化的數(shù)據(jù)map,共13個(gè)DCD
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))  //BAN1,6,7為32位數(shù)據(jù)完,其他除0外為16
     DCD ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))   ;GCS0;BANK0的相關(guān)訪問模式及各訪問周期設(shè)置, 各位定義可參考memcfg.inc文件
     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)+(Trc<<18)+(Tchr<<16)+REFCNT)   
//;設(shè)置刷新周期
DCD 0x32            ; ;SCLK power  saving mode, ARM  core burst disable, BANKSIZE 128M/128M
     DCD 0x30            ;MRSR6 CL=3clk CL:CAS latency
     DCD 0x30            ;MRSR7
;     DCD 0x20            ;MRSR6 CL=2clk
;     DCD 0x20            ;MRSR7

//下面是對(duì)ram區(qū)域map的定義;這里定義了處理器工作于各模式的堆棧區(qū)在ram中map.
ALIGN                  //字對(duì)齊
     AREA RamData, DATA, READWRITE

        ^   _ISR_STARTADDRESS         //^=map
HandleReset  #   4                               //#=field
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
HandleEINT0    #   4
HandleEINT1    #   4
HandleEINT2    #   4
HandleEINT3    #   4
HandleEINT4_7 #   4
HandleEINT8_23 #   4
HandleRSV6 #   4
HandleBATFLT    #   4
HandleTICK    #   4
HandleWDT #   4
HandleTIMER0  #   4
HandleTIMER1  #   4
HandleTIMER2  #   4
HandleTIMER3  #   4
HandleTIMER4  #   4
HandleUART2   #   4
HandleLCD  #   4
HandleDMA0 #   4
HandleDMA1 #   4
HandleDMA2 #   4
HandleDMA3 #   4
HandleMMC #   4
HandleSPI0 #   4
HandleUART1 #   4
HandleRSV24 #   4
HandleUSBD #   4
HandleUSBH #   4
HandleIIC    #   4
HandleUART0  #   4
HandleSPI1  #   4
HandleRTC  #   4
HandleADC  #   4

        END


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏2 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 久色| 夜夜草| 337p日本欧洲亚洲大胆鲁鲁 | 91社区在线高清 | 国产精品乱码一区二三区小蝌蚪 | 亚洲一区在线播放 | 五十女人一级毛片 | 欧美13videosex性极品 | av超碰 | 精久久久| 亚洲女人的天堂 | 久久久精品天堂 | 亚洲精品中文字幕在线观看 | 玖草资源 | 亚洲高清免费视频 | 欧美精品99 | 国产日韩欧美一区 | 免费a大片 | 懂色av蜜桃av | 国产一级视频在线 | 日韩欧美一二三区 | 亚洲综合在线播放 | 一本色道精品久久一区二区三区 | 真人毛片 | 国产精品美女久久久久久免费 | 成年人视频免费在线观看 | 中文字幕在线三区 | 精品国产乱码久久久久久牛牛 | 18成人在线观看 | 成人精品国产一区二区4080 | 99久久婷婷国产亚洲终合精品 | 一级h片 | 日韩成人久久 | 中国一级毛片免费 | 午夜欧美 | 欧美国产激情二区三区 | 伊人久久大香线 | 在线欧美一区二区 | 羞羞网站免费观看 | 99视频免费在线观看 | 精品欧美乱码久久久久久 |