基于OK6410的嵌入式開發(fā)教程(上)_第1頁
基于OK6410的嵌入式開發(fā)教程(上)_第2頁
基于OK6410的嵌入式開發(fā)教程(上)_第3頁
基于OK6410的嵌入式開發(fā)教程(上)_第4頁
基于OK6410的嵌入式開發(fā)教程(上)_第5頁
已閱讀5頁,還剩55頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、U-BOOT編寫(基于OK6410) Written by water1.U-BOOT工作原理及設計藍圖 在所有章節(jié)開始必須首先介紹一下U-BOOT,所謂U-BOOT就是bootloader的一種,可用于多種cpu(x86,ARM等),在不同系統(tǒng)像Linux,Vxworks,QNX等上運行調試。它能起到在上電后能對硬件,存儲器,內核等完成初始化,并且引導內核和文件系統(tǒng)正常工作的作用。U-BOOT并不是單純的裸機程序,在學完此課程后,可以完成大部分裸機程序的調試,移植與開發(fā)。最后得說明,我所用的開發(fā)板是OK6410,而我所做的學習筆記完全是建立在國嵌視頻上的,我會在這個筆記中對視頻的內容進行總結

2、,順序會有所調整。1.1 U-BOOT工作原理要講解這個首先需要讓大家看一張圖(注:這張圖是2440的機理圖,放在這里是為了能方便講解和理解):這張圖共分為兩部分,左邊部分是用于nor flash啟動,而右邊這部分就是用于nand flash啟動了,這個也是我們講的重點。首先需要明確一點,上電后第一條程序,肯定是從0地址(0x00000000)開始執(zhí)行的。左圖顯示0地址是在SROM中,這個我們不去管它,而右圖顯示第一條指令是從SRAM中執(zhí)行的,而這個存儲器只有4K,在這里我們就需要先明確一下“墊腳石(Stepping Stone)”這個概念了。在2440選擇從nand flash啟動剛上電時,

3、系統(tǒng)會自動將nand flash中bootloader的前4K,放入到我們前面所述的0地址,也就是Boot internal SRAM中,此時系統(tǒng)會執(zhí)行bootloader的前4K,同時系統(tǒng)還會將整個bootloader復制到我們的內存,前4k執(zhí)行完后,就跳轉至內存繼續(xù)執(zhí)行剩余的bootloader,而我們這里4K大小的SRAM就是墊腳石(stepping stone)。為什么需要它,這點很簡單,兩圖對比,我們就能發(fā)現(xiàn)我們的nand flash沒參與我們的統(tǒng)一編址,所以只能借stepping stone作為我們的橋梁。介紹完2440,我們來看看6410。先給大家?guī)讖垐D: 圖1 圖2 圖3我們先

4、看圖2,從圖2我們可以看出6410可以從哪些部分啟動,而那些部分又被存放在哪兒,我們可以注意到nand flash是被存放在IROM中的。接下來我們看圖2,我們可以看到0地址處放的是一個最大可達到128M的存儲器,描述和備注我就不贅述了,可以看出他是個鏡像存儲器,接下來就是IROM和stepping stone,下面的存儲器我們暫時不研究,不說了。看完兩張圖,可能最有疑問的是最后一張圖,我們說過上電執(zhí)行的第一條程序應該在0地址處,為什么那里不像2440一樣放的是stepping stone,而是一個鏡像存儲器呢。其實聰明一些的話,應該已經注意到了,既然是鏡像存儲器,那當上電后,我們的IROM和

5、stepping stone(兩個最大都能達到64M),會被鏡像入0地址處的存儲器(最大可達128M)中,然后剩下的就和2440一樣了。在這里可能大家還會有疑問,2440是直接從stepping stone中直接啟動,6410前面突然多了個IROM,好象有些不適應。我們來看圖1。圖1是6410bootloader的工作原理圖,我們可以看到IROM里存放的是BL0,這個BL0他會首先完成對硬件的初始化,同時會將BL1也就是BL的前8k(6410的steeping stone為8K)放入墊腳石中,然后就和2440一樣,將BL放入內存繼續(xù)執(zhí)行。至此,bootloader的工作原理講解完畢?,F(xiàn)在必須要

6、分析bootloader啟動流程以完成我們自己的bootloader的架構設計。我們采用分析U-BOOT的方法,來建立屬于我們自己的bootloader。由于分析的過程冗長耗時,在這里我就不分析了,但我會給出一張分析出的結果圖:2.U-BOOT編寫2.1 一些需要知道的知識概述首先大家必須先要了解的是ARM處理器的七種工作模式:圖1圖2兩張圖表明ARM處理器一共有7種工作模式,在這里我列一張表格來敘述其名稱及作用:用戶模式usr用于普通狀態(tài)下正常執(zhí)行程序系統(tǒng)模式sys運行具有特權的操作系統(tǒng)任務管理模式svc對操作系統(tǒng)的保護模式數據訪問中斷模式abt當數據或指令預取終止時進入該模式,可用于虛擬存

7、儲或存儲保護未定義指令終止模式und當未定義的指令執(zhí)行時進入該模式,可用于支持硬件外部中斷模式irq用于通用的中斷處理快速中斷模式fiq用于高速數據傳輸或信道處理有幾點需要說明普通的應用程序是在usr下運行,而我們的內核和bootloader是在svc下運行。至此,7種工作模式交代完畢,而圖1中0bxxxxx,這種東西是用于CPSR,即程序狀態(tài)寄存器使用的。這也是我們接下來要說的,我們的處理器一共有37個寄存器,如圖2,其中有31個通用寄存器和6個程序狀態(tài)寄存器,r0-r7為不分組寄存器,r8-r14為分組寄存器,最后還有個r15,也就是我們所熟知的程序計數器(pc)。其實這當中還有些特殊的寄

8、存器,比如r13(堆棧指針sp),r14(鏈接寄存器)。這個我們以后會說的。這部分內容相對簡單,我也不想細說,如有疑問,請自己查資料。接下來我們來談談CPSR(程序狀態(tài)寄存器)和SPSR(程序狀態(tài)保存寄存器),我這里先給出一張表:圖3然后我們再來談談CPSR和SPSR的作用和工作原理,看完圖2,再查完一些資料,應該會對這個有一定的了解,先研究圖2,圖2顯示我們所說的7種工作模式下都有CPSR,而SPSR只有5種工作模式下存在,這5種工作模式被我們稱為異常模式,除usr以外的其他工作模式被稱為特權模式,那我們就要問,為什么要這樣設計?或者說,這樣的設計能反映CPSR和SPSR怎樣的工作原理?這個

9、問題很好回答,首先當我們在usr下運行時,我們的程序會在CPSR下存有備份,現(xiàn)在可以把它理解成備份,這個時候出現(xiàn)中斷,我們這個時候就切入了異常模式,我們會先將狀態(tài)從CPSR轉移至SPSR,等處理器處理完了此次中斷,然后在將SPSR的數據返還至CPSR,使狀態(tài)回復至之前的狀態(tài)。解釋完了這些,我們現(xiàn)在來看看圖3,它反映的是SPSR和CPSR的寄存器數據格式。這里我們我們不需要全部記下來,但有5位需要注意,分別是N,Z,I,F(xiàn),M。我這里只做簡單敘述,詳情請查閱ARM Architecture Reference Mannual。N位占31位,當兩數相減結果為負時置位。Z位占30位,當兩數相減結果為

10、0時置位。I位占7位,當被置位時,irq不可用。F位占6位,當被置位時,fiq不可用。M位占0-4位,這里是設置各種模式用的,圖1的0bxxxxx就是用在這里的。到這里我們就把所有的模式及寄存器講完了,接下來我們就需要編程了,編程我是不會在學習筆記中贅述的,但我會截圖說明,涉及到原理的,我可能會大篇敘述,如有疑問大家請自己查閱資料。2.1 匯編框架的編寫及異常向量表既然是匯編文件,我們肯定需要一個.S的匯編文件,除此之外,我們編寫的bootloader可能文件有些繁雜,所以我們需要一個makefile文件,最后還需要一個.lds的匯編器腳本文件。我們先編寫匯編器腳本:然后我們再來編寫makef

11、ile文件:最后,我們來編寫start.S這個文件,要編寫這個,我們必須要先查閱一下ARM Architecture Reference Mannual。圖1在這里,我們先來解釋一下異常(Exception)的概念,異常指因為內部或者外部的一些事件,使處理器不得不停下正在處理的事件,轉而去處理這些發(fā)生的事件。我們說ARM處理器共有7種工作模式,其中有5種異常模式,而在這些異常模式下又有7種異常,它們分別是Reset(復位),Undefined instructions(未定義指令),SWI(軟中斷),Prefetch Abort(指令預取失?。珼ata Abort(數據預取失?。?,IRQ(外

12、部中斷),F(xiàn)IQ(快速中斷)。我們再來解釋一下什么叫異常向量,當有異常發(fā)生時,ARM處理器會自動跳轉到對應該異常的一個固定的地址來執(zhí)行異常處理程序,而這個固定地址就是異常向量。這個就對應圖1后面的address兩列,第一列是我們通常情況下使用的地址,后面是高位地址,我們可以通過cp15配置,使cpu選擇高位地址還是低位地址,通常我們選用低位的。有了前面這些概念,我們現(xiàn)在再來看異常向量表就非常簡單了:圖2值得注意的是,我們在編寫編譯器腳本時里面有一句.=ALIGN(4),這就說明我們接下來的代碼是4字節(jié)對齊的,所以我們可以看到每一行代碼跳4個字節(jié),另外由于中間確實了一部分,所以我們用一個無用的函

13、數名not_used補全,這樣就方便了許多。這樣就結束了,不懂的可以自己在看一遍或查資料。2.2 設置svc模式我們前面說過普通的應用程序是在usr下運行的,而內核和bootloader是在svc模式下運行,所以要運行bootloader,我們必須先將處理器設置為svc模式。我們之前也提過模式的設置是在CPSR的0-4位,這樣我們就能找到設置的方向。參照2.1里的圖1和圖3,我們可以清楚的看到svc模式是將CPSR0-4位設置為10011。另外還有一點也要說明,我們制作的是相對簡單的bootloader,所以irq和fiq最好也設置為不可用,之前在講CPSR時,也同樣提到I位和F位的作用,在這

14、里我們就可以設置了,我們的目的是將第6,7位設為1,第0-4位設為10011,而其他位不變。編程如下:mrs r0, cpsrbic r0, r0, 0x1forr r0, r0, 0b11010011msr r0, cpsrmov pc, lr2.3 關閉看門狗首先我們先來介紹一下關門狗是什么,起到什么作用。Watchdog也就是我們所稱的看門狗,一般是一個硬件模塊,在長期無人值守的地方,電子器件可能會出現(xiàn)死機的情況,這是無人干預,就需要系統(tǒng)自己帶有一個自動重啟的機制,它在硬件上實現(xiàn)了計時功能,啟動計時后,需要用戶(軟件)來在其計時結束前重新開始計時,俗稱“喂狗”,否則watchdog就會認

15、為死機了,就會重啟系統(tǒng)。說白了,它的作用就是在死機時使系統(tǒng)自動重啟。很多人看到這里,可能會想這看門狗好像很有用,那我們?yōu)槭裁匆P閉它?這個結論是我們之前分析U-BOOT時得到的,我們認為bootloader很簡單,一般不會死機,而不關閉它反而在程序運行時要不斷喂狗,這樣很消耗資源,所以我們就把它直接關閉了。這里我先給一張看門狗的原理圖:圖1這里的話,我就不對這個原理圖多加贅述了。我們直接看如何關閉看門狗吧。我們在這里就得看看門狗的控制寄存器(WTCON)了,我們要關注一下第0,2位,分別是控制了看門狗超時后重啟和中斷的功能,我們都將其設置為0就行。編程如下:#define WTCON 0x7e

16、004000ldr r0, =WTCONmov r1, 0x0str r1, r0mov pc. Lr2.4 關閉中斷關閉中斷說白了就是關閉外部中斷(irq)和快速中斷(fiq),我們先給一張圖:圖1我們從左到右可以在圖中清楚的看到一個中斷源會經過SRCPND,接下來要達到真正的中斷還需要MODE和MASK的支持,我們需要做兩件事才能真正地關閉中斷,分別是設置CPSR和設置中斷屏蔽寄存器。第一件事我們在前面進入svc模式時已經做過,忘了的可以回頭看看,第二件就是我們現(xiàn)在將要做的。再給幾張圖(基于6410):圖2圖3圖4圖2我并沒有截全,只截了重要的部分,我們可以看到一個description是

17、Interrupt Enable Clear Register(中斷使能寄存器)的寄存器,我們把那個寄存器找到,描述看圖3,后面的備注告訴我們,這個寄存器只能用以設置中斷使能,如果要關閉中斷,需要一個叫INTENCLEAR的寄存器,我們繼續(xù)找這個寄存器,如圖4,這個就是我們要找的寄存器。我們需要把VIC0,VIC1都設置為1。這樣編程就簡單了。編程如下:#define INTCLR_VIC0 0x71200014#define INTCLR_VIC1 0x71300014ldr r0, =INTCLR_VIC0mvn r1, 0x0str r1, r0ldr r0, =INTCLR_VIC1s

18、tr r1, r0mov pc, lr2.5 關閉mmu和cache 我們在編程前,必須要知道m(xù)mu是什么,起什么作用且為什么要關閉他。但是由于各種考慮,這些東西我覺得應該大家自己查閱資料,我這里只做簡單介紹。 我們先給出百度對mmu給出的定義。圖1說白了,mmu就是將虛擬地址處理成內存中的物理地址,它與虛擬內存是緊密相關的。另外cache,也就是高速緩沖存儲器,或許根本不需要解釋。我們這里只給ARM11核的幾張圖,大家意會一下,不懂可以去查資料。圖2圖2是計算機存儲體系的一張非常有名的金字塔模型,同樣適用于嵌入式系統(tǒng),它反映了不同存儲器與系統(tǒng)的關系緊密程度,存儲器容量與速度大小與級別高低。圖

19、3圖3在給出各種需要了解的重要概念的定義的同時也反映虛擬地址的作用,用它可以再繼續(xù)深入到mmu的作用,方便易記。圖4圖4反映了MMU和cache在虛擬地址轉物理地址時與cpu和主存之間的關系,上圖是ARM11之前的系統(tǒng),而下圖則是ARM11之后(包括ARM11)的系統(tǒng)。 看完這些,自己再查閱一些資料以后,相信會對一些基礎知識有所了解,我們在來說為什么要關閉mmu和cache,其實這兩件東西都是好東西,我們智慧需要的時候會在打開,但現(xiàn)在由于系統(tǒng)還未配置好,所以現(xiàn)在打開它,可能會造成內核取址(mmu)和內核數據往內存的下載(cache)上的錯誤,所以現(xiàn)在先關閉它。我們現(xiàn)在來編程吧。我們需要ARM1

20、1的核手冊,因為要配置mmu和cache需要設置cp15。我們先給幾張圖:圖5圖6我們需要做兩件事,第一件時使D-cache里的數據失效,見圖5,已經給出了明確的說明,我們選擇第3行。第二件就是徹底使mmu和cache關閉,見圖6,我們需要配置0位和2位,1位我們也順便配置了,其實1位配不配置都無傷大雅。編程如下:mcr p15, 0, r0, c7, c7, 0mrc p15, 0, r0, c1, c0, 0bic r0, r0, #0x00000007mcr p15, 0, r0, c1, c0, 0mov pc, lr2.6 點亮LED 先不說技術上的問題,我們先來談談技術上的問題。在

21、我們編程時,我們可能會因為各種原因而犯錯,但此時由于是bootloader初期,我們并未對我們串口等硬件初始化,我們的調試手段相當有限,而我們又不知道哪里犯了錯,所以我們必須使用一個可視化的檢查機制來告訴我們我們之前的程序是否出錯,這樣每添加一段程序,我們就可以使用此機制來驗證,這樣效率會提高很多。然后我們來談一下技術上的事,畢竟LED大家都懂,不需要我來特地浪費篇幅解釋。我們要做點亮LED需要做兩件事,不過在此之前,我們需要了解一些概念。我先給幾張圖: 圖1圖2圖3圖1是6410底板LED的原理圖,圖2是核心板cpu上有關LED的GPIO引腳圖,圖3是圖2所指區(qū)域的放大圖。我們先看圖1,可以

22、看出我們板上有4個用戶使用的LED,他們所對應的GPIO引腳分別是NLED1,2,3,4。另外我們知道要使LED亮,我們需要在引腳上設置為輸出低電平。圖2位核心板cpu GPIO的示意圖。在講解這些之前,我們先了解一下什么叫GPIO。 GPIO(General-Perpose Input/Output Ports)也被稱為通用輸入輸出端口,在嵌入式系統(tǒng)中,cpu通常需要控制一些簡單的外部設備和電路,這些設備或電路通常只有開關兩種狀態(tài),控制這些用USB或串口就顯得復雜,所以嵌入式微處理器上通常提供了“通用可編程I/O端口”,也就是GPIO。 看完這些我們再來梳理一下思路,要使LED亮需要使線路輸

23、出低電平,也就是要控制LED的GPIO輸出低電平,而圖3告訴我們,控制LED的GPIO分別是GPM0,1,2,3。 現(xiàn)在我們我們的思路就清楚了,然而我們還需要了解一個關于GPIO寄存器的知識,GPIO一般是由至少2個寄存器控制,6410應該是3個,我不確定,第3個我們暫時不需要了解。第一個是控制寄存器,控制引腳的輸入輸出,第二個是數據寄存器,控制高低電平。了解了這些我們就可以編程了。圖4我們需要就GPM0,1,2,3都設置為輸出,再把它們設為低電平。編程如下:#define GPMCON 0x7f008820#define GPMDAT 0x7f008824ldr r0, =GPMCONldr

24、 r1, =0x1111str r1, r0ldr r0, =GPMDATmov r1, #0xfstr r1, r02.7 時鐘初始化這個章節(jié)基礎的知識很多,我們先解析一些概念。我們先來了解一下時鐘脈沖信號,時鐘頻率和時鐘源這三個概念。時鐘脈沖信號按一定的電壓幅度,一定的時間間隔連續(xù)發(fā)出的脈沖信號。時鐘脈沖信號是時序邏輯的基礎,它用于決定邏輯單元中的狀態(tài)何時更新。數字芯片中眾多的晶體管都工作在開關狀態(tài),它們的導通和關斷動作無不是按照時鐘信號的節(jié)奏進行的。說白了他們就是一個時鐘,告訴系統(tǒng)何時該做什么事而何時又結束。時鐘脈沖頻率就是單位時間產生的時鐘脈沖個數。時鐘源這個可以分成兩類,一種是晶振,

25、另一種是PLL(鎖相環(huán))。第一種晶振,全稱晶體振蕩器,是將石英進行精密切磨然后通電產生,其振動頻率與它們的材料,形狀與切割方向密切相關。是一種簡單的典型的系統(tǒng)時鐘振蕩器源。PLL(鎖相環(huán))合成器是一種更加復雜的系統(tǒng)時鐘源,它需要一個外部晶體并包含一個能對特定頻率加倍或分頻的PLL(鎖相環(huán))集成電路。PLL比較晶振所需的晶體振動頻率更低,但是他能合成符合各種需求的振動頻率。它的成本更低,精密程度不落于晶振,是一種優(yōu)秀的系統(tǒng)時鐘源。現(xiàn)在,我們需要了解一些關于6410開發(fā)板的時鐘體系,首先6410的晶振頻率是12MHZ,然后我們需要知道它有哪些PLL,PLL又產生出了哪些時鐘,這些時鐘又有些什么用。

26、圖1從這張圖上我們了解到6410有APLL,MPLL和EPLL三種PLL,而這三種PLL又分別產生ARMCLK,HCLK,PCLK和SCLK。這四種時鐘有什么用呢?我們來看看。圖2圖3圖2大家了解一下就行,圖3使我們各種時鐘的作用。圖4我們可以從圖中看出,我們在初始化時鐘時配置完后會出現(xiàn)Lock time,而在這之中SYSCLK的時鐘頻率會歸零,之后會按照分頻的頻率運行,SYSCLK也就是我們這里的ACLK,畢竟系統(tǒng)時鐘,會和內核聯(lián)系在一起?,F(xiàn)在我們來看看初始化時鐘需要哪些步驟。第一步是設置Lock Time第二步是設置分頻系數。第三步是設置cpu到異步工作模式。最后是設置PCLK和MCLK(

27、見圖5) 有人可能會對上面的步驟抱有異議,那我們現(xiàn)在來看看為什么要這樣設置。第一步設置Lock Time,大家應該是不會說什么的,但是我們這里不設置,我們保持它的默認值不動。第二步,我們之前說過PLL可以通過分頻來滿足一個系統(tǒng)中不同時鐘體系的需求,很顯然我們要用它,所以我們需要設置分頻系數。第三步,當ARMCLK(核的時鐘)和HCLK(系統(tǒng)總線時鐘)分頻系數不同時,需要設置為異步模式。第四步,分完頻,至少我們需要設置其中某個量為基準值。而圖5也告訴我們APLL和MPLL似乎是基準值。這樣似乎就合理了,下面我們來編程吧。圖5圖6圖7圖8圖9圖10這里我已經給出了所有信息,但是這里我不講(其實是偷

28、懶),我希望大家能根據我的編程來理清自己的思路,另外大家要注意的是圖5中很多選擇器,它所需的寄存器(CLK_SRC,OTHERS等)甚至已在圖中列出,大家也需要去設置。就這樣,我們直接來編程。編程如下:#define CLK_DIV0 0x7e00f020#define OTHERS 0x7e00f900#define MPLL_CON 0x7e00f010#define APLL_CON 0x7e00f00c#define CLK_SRC 0x7e00f01c#define DIV_VAL (0x0<<0)|(0x1<<9)|(0x1<<8)|(0x3&l

29、t;<12)#define PLL_VAL (1<<31)|(266<<16)|(3<<8)|(1<<0)ldr r0, =CLK_DIV0ldr r1, =DIV_VALstr r1, r0ldr r0, =OTHERSldr r1, r0bic r1,r1,#0xc0str r1, r0ldr r0, =APLL_CONldr r1, =PLL_VALstr r1, r0ldr r0, =MPLL_CONldr r1, =PLL_VALstr r1, r0ldr r0, =CLK_SRCmov r1, #0x3str r1, r0mov

30、 pc,lr2.8 內存初始化 既然講到內存初始化,那就必須先講與內存相關的一些知識。 我們先來談談內存的分類,內存一般分為SRAM和DRAM,SRAM即靜態(tài)隨機存儲器,它是具有靜止存取功能的內存,它不需要定期刷新就可保存內部數據,因此存取速度較快,但是成本較高,一般用在存儲容量要求不高,但速度要求很快的場合,比如stepping stone。 而DRAM(動態(tài)隨機存儲器)是由許許多多個小電容組成,電容可以在兩個極板上保存電荷,它不具備靜止存取數據的功能,它需要不停地刷新(充能),才能保存數據,因此它的速度較慢。DRAM有幾種需要分成幾類講:1.SDRAM 2.DDR 3.DDR2圖1圖2圖1

31、和圖2講的很好,這里需要補充一下,SDRAM和DDR的傳輸速度理論是1:2的關系,是因為在一個時鐘周期內SDRAM只能傳輸或接收一次數據,而DDR則2次。這里就引出了時鐘周期,可以聯(lián)想到我們之前所說的時鐘脈沖信號,這個和那個有些關系,大家可以去引申一下,時鐘周期是一個時鐘的量,它反映了SDRAM所能運行的最高速率,更小的周期代表更高的運行速率。大家有興趣可以去查閱一下資料。 現(xiàn)在我們再說一下內存的內部結構。 實際上我們可以把內存的內部當成一個表結構,如圖3,當我們存取數據時我們先指定行地址,再指定列地址,這樣我們就能準確地找到我們所需的數據。而這張表我們稱為Logical Bank(L-Ban

32、k)。圖3然而由于技術等各種原因,我們的一塊內存不可能只用一個L-Bank,我們一般把它分成4個L-Bank,這樣我們的尋址信息就變成先指定L-Bank,再指定行地址,最后確定列地址,而我們內存大小就等于4*行*列*一個單元格所能容納的數據大小?,F(xiàn)在就該講到編程了,我們決定先從2440講起,這樣在原理上深入會比較簡單。圖4 從圖4我們可以看出2440的芯片一共27根地址線,27根地址線對應了128M的內存,然而我們說內存不可能只有128M,那生產廠商用了什么方法使它的外設空間變?yōu)?G呢?在這里我們需要引出片選信號這種說法。 片選信號,也就是說不止這一塊內存芯片,片選信號可以指定從不同的芯片中存

33、取數據。看圖5圖5其實細心一點可以在圖4中觀察到8個片選信號nGCS0-7,現(xiàn)在我們來看一張更加早期的圖:大家都應該知道2440的內存是從0x30000000開始的,為什么他要從這地方開始,現(xiàn)在我們應該有答案,內存是處于bank6和bank7的,bank6的起始地址就是0x30000000。 我們轉而看6410的內存地址0x50000000,這個比2440要大,為什么呢?我們來看看6410的地址分布。圖6保留區(qū)我們就不說了,外設區(qū)說白了就是我們之前那些寄存器的放置空間,而主存儲區(qū)似乎我們應該更深入的去看一下。圖7這樣,我們就能明白為什么6410內存是從0x50000000開始了,因為內存是在D

34、ynamic memory里的。另外還有一點要提:圖8我們在之前可以看到2440cpu有32根地址線,而內存的兩塊芯片每塊只有16根地址線,這要怎么連呢,很簡單,就是16+16=32的問題,存取數據時,兩塊芯片個存取一半數據。6410在這方面也是同樣的原理。 最后我們還需要了解一個非常重要的東西-存儲控制器,當我們訪問某一塊內存空間時,我們往往就是輸入地址,我們并沒有用到之前學的尋址方式,先L-Bank啊,行列地址之類的,這完全歸因于存儲控制器,當cpu拿到我們的地址時,他并不知道該去哪找數據,這是存儲控制器就會進行轉化,使cpu能找到數據。如圖9:圖9所以,我們要控制內存,要初始化內存,實際

35、上就是要對我們的存儲控制器進行初始化,2440只要初始化存儲控制器就可以了,但6410還須對我們的DDR進行初始化。不過也很簡單,它已經把所有的步驟列出來了,我們只要照做就行。圖10照著步驟一步步做就行,有些東西參照一下U-BOOT,具體的寄存器大家請參照6410的芯片手冊,這里由于篇幅原因我就不列了。另外由于此程序篇幅很長,所以我們另起一個匯編文件,用.global定義一下全局符號。編程如下:.text.global mem_initmem_init: ldr r0, =0x7e00f120 mov r1, #0x8 str r1, r0 ldr r0, =0x7e001004 mov r1

36、, #0x4 str r1, r0 ldr r0, =0x7e001010 ldr r1, =( ( 7800 / ( 1000000000/133000000 ) + 1 ) ) str r1, r0 ldr r0, =0x7e001014 mov r1, #(3 << 1) str r1, r0 ldr r0, =0x7e001018 mov r1, #0x1 str r1, r0 ldr r0, =0x7e00101c mov r1, #0x2 str r1, r0 ldr r0, =0x7e001020 ldr r1, =( ( 45 / ( 1000000000 / 13

37、3000000 ) + 1 ) ) str r1, r0 ldr r0, =0x7e001024 ldr r1, =( ( 68 / ( 1000000000 / 133000000 ) + 1 ) ) str r1, r0 ldr r0, =0x7e001028 ldr r1, =( ( 23 / ( 1000000000 / 133000000 ) + 1 ) ) str r1, r0 ldr r0, =0x7e00102c ldr r1, =( ( 80 / ( 1000000000 / 133000000 ) + 1 ) ) str r1, r0 ldr r0, =0x7e001030

38、 ldr r1, =( ( 23 / ( 1000000000 / 133000000 ) + 1 ) ) str r1, r0 ldr r0, =0x7e001034 ldr r1, =( ( 15 / ( 1000000000 / 133000000 ) + 1 ) ) str r1, r0 ldr r0, =0x7e001038 ldr r1, =( ( 15 / ( 1000000000 / 133000000 ) + 1 ) ) ldr r2, r0 str r1, r0 ldr r0, =0x7e00103c mov r1, #0x07 str r1, r0 ldr r0, =0x

39、7e001040 mov r1, #0x02 str r1, r0 ldr r0, =0x7e001044 ldr r1, =( ( 120 / ( 1000000000 / 133000000 ) + 1 ) ) str r1, r0 ldr r0, =0x7e001048 ldr r1, =( ( 120 / ( 1000000000 / 133000000 ) + 1 ) ) str r1, r0 ldr r0, =0x7e00100c ldr r1, =0x00010012 str r1, r0 ldr r0, =0x7e00104c ldr r1, =0x0b45 str r1, r

40、0 ldr r0, =0x7e001200 ldr r1, =0x150f8 str r1, r0 ldr r0, =0x7e001304 mov r1, #0x0 str r1, r0 ldr r0, =0x7e001008 ldr r1, =0x000c0000 str r1, r0 ldr r1, =0x00000000 str r1, r0 ldr r1, =0x00040000 str r1, r0 ldr r1, =0x000a0000 str r1, r0 ldr r1, =0x00080032 str r1, r0 ldr r0, =0x7e001004 mov r1, #0x

41、0 str r1, r0check_dmc1_ready: ldr r0, =0x7e001000 ldr r1, r0 mov r2, #0x3 and r1, r1, r2 cmp r1, #0x1 bne check_dmc1_ready nop mov pc, lr最后我們還得了解一點,第一段匯編中的寄存器0x7e00f120,那個是什么寄存器呢?我們在芯片手冊搜一下看看。圖11圖12圖11和圖12我們可以看到這個寄存器各位的描述都不短,但我們現(xiàn)在只研究其中的第七位,我們應該設成0還是1。描述中Xm1是什么?其實他對應的是6410的Dynamic memory的數據線,也就是我們的DR

42、AM的數據線,我們選0,是將他設為數據傳輸,選1是將他用于SROMC,明顯應該選0。最后再附上6410的兩塊內存的圖,以免有人看不清楚。圖132.9 代碼搬移(基于6410)事先說明一下,因為我們還沒接觸到nand flash,所以我們現(xiàn)在編寫的代碼只是先熱個身,日后等我們了解到了nand flash,會在回頭看這段代碼。在前面講到bootloader的工作原理時,我們提到了代碼的搬移,即當上電后,bootloader的前幾K(6410為8K,2440為4K)會被放入墊腳石中運行,這個我們不去管它,他是自動的,但是接下來整段代碼從nand flash搬移到內存中,這個我們就需要進行干預了,我們

43、需要通過代碼來完成它。但有一點我們要注意,我們現(xiàn)在還沒學到nand flash,而且我們現(xiàn)在的bootloader還遠未達到4k或8k,所以我們現(xiàn)在不從nand flash搬移,而從我們的墊腳石中搬移代碼。等日后學習了nand flash,我們再回頭改這段代碼。要搬移代碼,我們需要注意3點:1. 搬移起點2. 搬移終點3. 搬移方式先說搬移起點,既然我們是從墊腳石搬移的,那我們就看墊腳石的起始地址。圖1從圖1中,我們可以看出墊腳石的起始地址是0x0c000000,這樣我們第一個問題就解決了。第二個問題是搬移終點的問題,這個其實不是問題,我們之前編寫過了編譯器腳本文件里就有答案,我們在其中設置過程需的起始地址,也就是鏈接地址-. = 0x500

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論