新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > S3C2440 SDRAM內存驅動

        S3C2440 SDRAM內存驅動

        作者: 時間:2016-11-20 來源:網絡 收藏
        SDRAM(Synchronous Dynamic Random Access Memory,同步動態隨機存儲器)也就是通常所說的內存。內存的工作原理、控制時序、及相關控制器的配置方法一直是嵌入式系統學習、開發過程中的一個難點。我們從其硬件的角度來分析其原理,然后再引出SDRAM的驅動編寫過程。
        內存是代碼的執行空間,以PC機為例,程序是以文件的形式保存在硬盤里面的,程序在運行之前先由操作系統裝載入內存中,由于內存是RAM(隨機訪問存儲器),可以通過地址去定位一個字節的數據,CPU在執行程序時將PC的值設置為程序在內存中的開始地址,CPU會依次的從內存里取址,譯碼,執行,在內存沒有被初始化之前,內存好比是未建好的房子,是不能讀取和存儲數據的,因此我們要想讓MTOS運行在內存里必須進行內存的初始化。
        通用存儲設備:
        在介紹內存工作原理之前有必要了解下存儲設備的存儲方式:ROM,RAM
        lROM(Read-Only Memory):只讀存儲器,是一種只能讀出事先所存數據的固態半導體存儲器。其特性是一旦儲存資料就無法再將之改變或刪除。通常用在不需經常變更資料的電子或電腦系統中,資料并且不會因為電源關閉而消失。如:PC里面的BIOS。
        lRAM(Random Access Memory):隨機訪問存儲器,存儲單元的內容可按需隨意取出或存入,且存取的速度與存儲單元的位置無關的存儲器。可以理解為,當你給定一個隨機有效的訪問地址,RAM會返回其存儲內容(隨機尋址),它訪問速度與地址的無關。這種存儲器在斷電時將丟失其存儲內容,故主要用于存儲短時間內隨機訪問使用的程序。計算機系統里內存地址是一個四字節對齊的地址(32位機),CPU的取指,執行,存儲都是通過地址進行的,因此它可以用來做內存。
        RAM按照硬件設計的不同,隨機存儲器又分為DRAM(Dynamic RAM)動態隨機存儲器和SRAM(Static RAM)靜態隨機存儲器。
        lDRAM:它的基本原件是小電容,電容可以在兩個極板上短時間內保留電荷,可以通過兩極之間有無電壓差代表計算機里的0和1,由于電容的物理特性,要定期的為其充電,否則數據會丟失。對電容的充電過程叫做刷新,但是制作工藝較簡單,體積小,便于集成化,經常做為計算機里內存制作原件。比如:PC的內存,SDRAM, DDR, DDR2, DDR3等,缺點:由于要定期刷新存儲介質,存取速度較慢。
        lSRAM:它是一種具有靜止存取功能的內存,不需要刷新電路即能保存它內部存儲的數據。因此其存取速度快,但是體積較大,功耗大,成本高,常用作存儲容量不高,但存取速度快的場合,比如CPU的L1 cache,L2cache(一級,二級緩存),寄存器。

        為了滿足開發的需要MINI2440在出廠時搭載了三種存儲介質:
        (1)NOR FLASH(2M):ROM存儲器,通常用來保存BootLoader,引導系統啟動
        (2)NAND FLASH(256M,型號不一樣,Nandflash大小不一樣):保存操作系統映像文件和文件系統
        (3)SDRAM(64M):內存,執行程序
        lNORFLASH:它的特點是支持XIP芯片內執行(eXecute In Place),這樣應用程序可以直接在Flash閃存內運行,不必再把代碼讀到系統RAM中,也就是說可以隨機尋址。NOR FLASH的成本較高。
        lNAND FLASH:它能提供極高的單元密度,可以達到高存儲密度,并且寫入和擦除的速度也很快。其成本較低,不支持XIP。可做嵌入式里的數據存儲介質。如:手機存儲卡,SD卡等。

        1.1.1S3C2440存儲器地址段(Bank)

        S3C2440對外引出了27根地址線ADDR0~ADDR26,它最多能夠尋址128MB,而S3C2440的尋址空間可以達到1GB,這是由于S3C2440將1GB的地址空間分成了8個BANKS(Bank0~Bank7),其中每一個BANK對應一根片選信號線nGCS0~nGCS7,當訪問BANKx的時候,nGCSx管腳電平拉低,用來選中外接設備,S3C2440通過8根選信號線和27根地址線,就可以訪問1GB。如圖2-48所示。


        圖2-48 S3C2440存儲器BANK
        如圖所示,左側圖對應不使用Nandflash啟動時(通過跳線設置),存儲器Bank分布圖,通常在這種啟動方式里選擇Norflash啟動,將Norflash焊接在Bank0,系統上電后,CPU從Bank0的開始地址0x00000000開始取指運行。
        上圖右側是選擇從Nandflash引導啟動(通過跳線設置),系統上電后,CPU會自動將Nandflash里前4K的數據復制到S3C2440內部一個4K大小SRAM類型存儲器里(叫做Steppingstone),然后從Steppingstone取指啟動。
        其中Bank0~Bank5可以焊接ROM或SRAM類型存儲器,Bank6~Bank7可以焊接ROM,SRAM,SDRAM類型存儲器,也就是說,S3C2440的SDRAM內存應該焊接在Bank6~Bank7上,最大支持內存256M,Bank0~Bank5通常焊接一些用于引導系統啟動小容量ROM,具體焊接什么樣存儲器,多大容量,根據每個開發板生產商不同而不同,比如MINI2440開發板將2M的Norflash焊接在了Bank0上,用于存放系統引導程序Bootloader,將兩片32M,16Bit位寬SDRAM內存焊接在Bank6和Bank7上,并聯形成64M,32位內存。
        由于S3C2440是32位芯片,理論上講可以達到4GB的尋址范圍,除去上述8個BANK用于連接外部設備,還有一部分的地址空間是用于設備特殊功能寄存器,其余地址沒有被使用。
        表2-14 S3C2440設備寄存器地址空間
        外接設備起始地址結束地址
        存儲控制器0x480000000x48000030
        USB Host控制器0x490000000x49000058
        中斷控制器0x4A0000000x4A00001C
        DMA0x4B0000000x4B0000E0
        時鐘和電源管理0x4C0000000x4C000014
        LCD控制器0x4D0000000x4D000060
        NAND FLASH控制器0x4E0000000x4E000014
        攝像頭接口0x4F0000000x4F0000A0
        UART0x500000000x50008028
        脈寬調制計時器0x510000000x51000040
        USB設備0x520001400x5200026F
        WATCHDOG計時器0x530000000x53000008
        IIC控制器0x540000000x5400000C
        IIS控制器0x550000000x55000012
        I/O端口0x560000000x560000B0
        實時時鐘RTC0x570000400x5700008B
        A/D轉換器0x580000000x58000010
        SPI0x590000000x59000034
        SD接口0x5A0000000x5A000040
        AC97音頻編碼接口0x5B0000000x5B00001C

        1.1.2SDRAM內存工作原理

        SDRAM的內部是一個存儲陣列。陣列就如同表格一樣,將數據“填”進去。在數據讀寫時和表格的檢索原理一樣,先指定一個行(Row),再指定一個列(Column),我們就可以準確地找到所需要的單元格,這就是內存芯片尋址的基本原理,如圖2-49所示。


        圖2-49內存行,列地址尋址示意圖
        這個單元格(存儲陣列)就叫邏輯Bank(Logical Bank,下文簡稱L-Bank)。由于技術、成本等原因,不可能只做一個全容量的L-Bank,而且最重要的是,由于SDRAM的工作原理限制,單一的L-Ban k將會造成非常嚴重的尋址沖突,大幅降低內存效率。所以人們在SDRAM內部分割成多個L-Bank,目前基本都是4個(這也是SDRAM規范中的最高L-Bank數量),由此可見,在進行尋址時就要先確定是哪個L-Bank,然后在這個選定的L-Bank中選擇相應的行與列進行尋址。因此對內存的訪問,一次只能是一個L-Bank工作。如圖2-50:


        圖2-50內存存儲單元
        當對內存進行操作時(見下圖),先要確定操作L-Bank,因此要對L-Bank進行選擇。在內存芯片的外部管腳上多出了兩個管腳BA0, BA1,用來片選4個L-Bank。如前所述,32位的地址長度由于其存儲結構特點,分成了行地址和列地址。通過下面的內存結構圖可知,內存外接管腳地址線只有13根地址線A0~A12,它最多只能尋址8M內存空間,到底使用什么機制來實現對64M內存空間進行尋址的呢?SDRAM的行地址線和列地址線是分時復用的,即地址要分兩次送出,先送出行地址(nSRAS行有效操作),再送出列地址(nSCAS列有效操作)。這樣,可以大幅度減少地址線的數目,提高器件的性能和制作工藝復雜度。但尋址過程也會因此而變得復雜。實際上,現在的SDRAM一般都以L-Bank為基本尋址對象的。由L-Bank地址線BAn控制L-Bank間的選擇,行地址線和列地址線貫穿連接所有的L-Bank,每個L-Bank的數據的寬度和整個存儲器的寬度相同,這樣,可以加快數據的存儲速度。同時,BAn還可以使未被選中的L-Bank工作于低功耗的模式下,從而降低器件的功耗。


        圖2-51 HY57561620內部結構圖

        開發板內存控制器管腳接線(以MINI2440開發板為例):
        (1)確定BA0、BA1的接線
        表2-15 BA0、BA1接線



        Bank Size:外接內存容量大小(HY57561620是4Mbit*16bit*4Bank*2Chips/8=64MB)
        Bus Width:總線寬度 (兩片16位HY57561620,并聯成32位)
        Base Component:單個芯片容量(bit)(256Mb)
        Memory Configration:內存配置((4M*16*4banks)*2Chips )
        由硬件手冊Bank Address管腳連接配置表可知,使用A[25:24]兩根地址線作為Bank片選信號,正好兩根接線可以片選每個存儲單元的4個BANKS。
        (2)確定其它接線
        SDRAM內存是焊接在BANK6~BANK7上的,其焊接管腳,如圖2-52:


        圖2-52 S3C2440 16位寬內存芯片
        上圖是S3C2440提供的兩片16位芯片并聯連接示意圖,An是CPU地址總線,其中A2~A14為內存芯片尋址總線,之所以地址尋址總線從A2開始是因為內存地址都是按字節對齊的,,A24,A25為L-Bank片選信號,Dn為CPU數據總線,其它為對應控制信號線。
        表2-16內存芯片各管腳說明
        外接管腳名內接管腳名全稱描述
        A2~A14A0~A12Address地址線
        D0 ~D31DQ0~DQ31Data Input/Output數據線
        A24,A25BA0,BA1Bank AddressL-BANK片選信號
        DQM0~DQM3LDQM, UDQMData Input/Output Mask高,低字節數據掩碼信號
        SCKESCKEClock Enable輸入時鐘有效信號
        SCLKSCLKClock輸入時鐘
        nSCS0nSCSGeneral Chip Select片選信號(它與nGCS6是同一管腳的兩個功能)
        nSRASnSRASRow Address Strobe行地址選通信號
        nSCASnSCASColumn Address Strobe列地址選通信號
        nWEnewnWEWrite Enable寫入有效信號
        我們通過S3C2440 16位寬內存芯片接線圖可以看出,兩片內存芯片只有兩個地方不一樣,LDQM, UDQM和數據總線DQn接線方式不一樣。
        由于存儲芯片位寬為16位,一次可以進行兩個字節的讀取。但是,通常操作系統里最小尋址單位是1字節,因此內存控制器必須要保證可以訪問內存里每一個字節。UDQM,LDQM分別代表16位數據的高,低字節讀取信號,當讀取數據時,LDQM /UDQM分別用來控制16位數據中高低字節能否被讀取,當LDQM /UDQM為低電平時,對應的高/低字節就可以被讀取,如果LDQM /UDQM為高電平時,對應的高/低字節就不能被讀取。當向內存里寫入數據時,LDQM /UDQM控制數據能否被寫入,當LDQM /UDQM為低電平時,對應的高/低字節就可以被寫入,如果LDQM /UDQM為高電平時,對應的高/低字節就不能被寫入。通過對LDQM /UDQM信號的控制可以控制對兩個存儲芯片存儲數據,由于兩個存儲單元的地址線是通用的,他們都能接收到CPU發出的地址信號,但是,發給兩個存儲單元的LDQM /UDQM信號是不同的,以此來區分一個字的高低字節。
        S3C2440A為32位CPU,也就是說其數據總線和地址總線寬度都是32位(可以理解為32根線一端連接CPU內部,另外一端連接向內存控制器),那么內存數據的輸入/輸出端也要保證是32位總線,MINI2440上采用兩片16位寬總線內存芯片并聯構成32位總線。其中一個芯片連接到CPU數據總線的低16位,另外一個芯片連接到數據總線上的高16位,并聯成32位總線,因此兩個芯片的輸入/輸出總線連接到CPU總線上的不同管腳上。

        1.1.3SDRAM的讀操作

        SDRAM進行讀操作時,先向地址線上送上要讀取數據的地址,通過前面的知識了解到,地址被分成3部分,行地址,列地址,L-Bank片選信號。片選(L-Bank的定址)操作和行有效操作可以同時進行。
        在CS、L-Bank定址的同時,RAS(nSRAS行地址選通信號)也處于有效狀態。此時An地址線則發送具體的行地址。A0~A12,共有13根地址線(可表示8192行),A0~A12的不同數值就確定了具體的行地址。由于行有效的同時也是相應L-Bank有效,所以行有效也可稱為L-Bank有效。
        行地址確定之后,就要對列地址進行尋址了。但是,地址線仍然是行地址所用的A0~A12。沒錯,在SDRAM中,行地址與列地址線是復用的。列地址復用了A0~A8,共9根(可表示512列)。那么,讀/寫的命令是怎么發出的呢?其實沒有一個信號是發送讀或寫的明確命令的,而是通過芯片的可寫狀態的控制來達到讀/寫的目的。顯然WE信號(nWE)就是一個關鍵。WE無效時,當然就是讀取命令。有效時,就是寫命令。
        SDRAM基本操作命令,通過各種控制/地址信號的組合來完成(H代表高電平,L代表低電平,X表示高,低電平均沒有影響)。此表中,除了自刷新命令外,所有命令都是默認CKE(SCKEl輸入時鐘頻率有效)有效。列尋址信號與讀寫命令是同時發出的。雖然地址線與行尋址共用,但CAS(nSCAS列地址選通信號)信號則可以區分開行與列尋址的不同,配合A0~A8,A9~A11來確定具體的列地址。
        讀取命令與列地址一塊發出(當WE為低電平是即為寫命令)然而,在發送列讀寫命令時必須要與行有效命令有一個間隔,這個間隔被定義為tRCD,即RAS to CAS Delay(RAS至CAS延遲),這個很好理解,在地址線上送完行地址之后,要等到行地址穩定定位后再送出列地址,tRCD是SDRAM的一個重要時序參數,相關數值參看對應芯片硬件手冊。通常tRCD以時鐘周期(tCK,Clock Time)數為單位,比如筆者MINI2440所用內存芯片里面寫到tRCD為20nst,如果將來內存工作在100MHz,那么RCD至少要為2個時鐘周期,RCD=2。


        圖2-53SDRAM讀操作時序圖
        在選定列地址后,就已經確定了具體的存儲單元,剩下就是等待數據通過數據I/O通道(DQ)輸出到內存數據總線上了。但是在列地址選通信號CAS發出之后,仍要經過一定的時間才能有數據輸出,從CAS與讀取命令發出到第一筆數據輸出的這段時間,被定義為CL(CAS Latency,CAS潛伏期)。由于CL只在讀取時出現,所以CL又被稱為讀取潛伏期(RL,Read Latency)。CL的單位與tRCD一樣,也是時鐘周期數,具體耗時由時鐘頻率決定(筆者官方手冊CL=3)。不過,CAS并不是在經過CL周期之后才送達存儲單元。實際上CAS與RAS一樣是瞬間到達的。由于芯片體積的原因,存儲單元中的電容容量很小,所以信號要經過放大來保證其有效的識別性,這個放大/驅動工作由S-AMP負責。但它要有一個準備時間才能保證信號的發送強度,這段時間我們稱之為tAC(Access Time from CLK,時鐘觸發后的訪問時間)。

        1.1.4SDRAM預充電操作

        從存儲體的結構圖上可以看出,原本邏輯狀態為1的電容在讀取操作后,會因放電而變為邏輯0。由于SDRAM的尋址具有獨占性,所以在進行完讀寫操作后,如果要對同一L-Bank的另一行進行尋址,就要將原先操作行關閉,重新發送行/列地址。在對原先操作行進行關閉時,DRAM為了在關閉當前行時保持數據,要對存儲體中原有的信息進行重寫,這個充電重寫和關閉操作行過程叫做預充電,發送預充電信號時,意味著先執行存儲體充電,然后關閉當前L-Bank操作行。預充電中重寫的操作與刷新操作(后面詳細介紹)一樣,只不過預充電不是定期的,而只是在讀操作以后執行的。

        1.1.5SDRAM突發操作

        突發(Burst)是指在同一行中相鄰的存儲單元連續進行數據傳輸的方式,連續傳輸所涉及到存儲單元(列)數量就是突發長度(Burst Length,簡稱BL)。
        在目前,由于內存控制器一次讀/寫P-Bank位寬的數據,也就是8個字節,但是在現實中小于8個字節的數據很少見,所以一般都要經過多個周期進行數據的傳輸,上文寫到的讀/寫操作,都是一次對一個存儲單元進行尋址,如果要連續讀/寫,還要對當前存儲單元的下一單元進行尋址,也就是要不斷的發送列地址與讀/寫命令(行地址不變,所以不用再對地尋址)。雖然由于讀/寫延遲相同可以讓數據傳輸在I/O端是連續的,但是它占用了大量的內存控制資源,在數據進行連續傳輸時無法輸入新的命令效率很低。為此,引入了突發傳輸機制,只要指定起始列地址與突發長度,內存就會依次自動對后面相應長度數據的數據存儲單元進行讀/寫操作而不再需要控制器連續地提供列地址,這樣,除了第一筆數據的傳輸需要若干個周期(主要是之間的延遲,一般的是tRCD + CL)外,其后每個數據只需一個周期即可。
        總結下:
        SDRAM的基本讀操作需要控制線和地址線相配合地發出一系列命令來完成。先發出芯片有效命令(ACTIVE),并鎖定相應的L-BANK地址(BA0、BA1給出)和行地址(A0~A12給出)。芯片激活命令后必須等待大于tRCD(SDRAM的RAS到CAS的延遲指標)時間后,發出讀命令。CL(CAS延遲值)個時鐘周期后,讀出數據依次出現在數據總線上。在讀操作的最后,要向SDRAM發出預充電(PRECHARGE)命令,以關閉已經激活的L-BANK。等待tRP時間(PRECHAREG命令后,相隔tRP時間,才可再次訪問該行)后,可以開始下一次的讀、寫操作。SDRAM的讀操作支持突發模式(Burst Mode),突發長度為1、2、4、8可選。

        1.1.6SDRAM寫操作

        SDRAM的基本寫操作也需要控制線和地址線相配合地發出一系列命令來完成。先發出芯片有效命令,并鎖定相應的L-BANK地址(BA0、BA1給出)和行地址(A0~A12給出)。芯片有效命令發出后必須等待大于tRCD的時間后,發出寫命令數據,待寫入數據依次送到DQ(數據線)上。在最后一個數據寫入后,延遲tWR時間。發出預充電命令,關閉已經激活的頁。等待tRP時間后,可以展開下一次操作。寫操作可以有突發寫和非突發寫兩種。突發長度同讀操作。


        圖2-54 SDRAM寫操作時序圖

        1.1.7SDRAM的刷新

        SDRAM之所以成為DRAM就是因為它要不斷進行刷新(Refresh)才能保留住數據,因此它是SDRAM最重要的操作。
        刷新操作與預充電中重寫的操作一樣,都是用S-AMP先讀再寫。但為什么有預充電操作還要進行刷新呢?因為預充電是對一個或所有L-Bank中的工作行操作,并且是不定期的,而刷新則是有固定的周期,依次對所有行進行操作,以保留那些很長時間沒經歷重寫的存儲體中的數據。但與所有L-Bank預充電不同的是,這里的行是指所有L-Bank中地址相同的行,而預充電中各L-Bank中的工作行地址并不是一定是相同的。那么要隔多長時間重復一次刷新呢?目前公認的標準是,存儲體中電容的數據有效保存期上限是64ms(毫秒,1/1000秒),也就是說每一行刷新的循環周期是64ms。這樣刷新時間間隔就是:64m/行數s。我們在看內存規格時,經常會看到4096 Refresh Cycles/64ms或8192 Refresh Cycles/64ms的標識,這里的4096與8192就代表這個芯片中每個L-Bank的行數。刷新命令一次對一行有效,刷新間隔也是隨總行數而變化,4096行時為15.625μs(微秒,1/1000毫秒),8192行時就為7.8125μs。刷新操作分為兩種:Auto Refresh,簡稱AR與Self Refresh,簡稱SR。不論是何種刷新方式,都不需要外部提供行地址信息,因為這是一個內部的自動操作。對于AR,SDRAM內部有一個行地址生成器(也稱刷新計數器)用來自動的依次生成行地址。由于刷新是針對一行中的所有存儲體進行,所以無需列尋址,或者說CAS在RAS之前有效。所以,AR又稱CBR(CAS Before RAS,列提前于行定位)式刷新。由于刷新涉及到所有L-Bank,因此在刷新過程中,所有L-Bank都停止工作,而每次刷新所占用的時間為9個時鐘周期(PC133標準),之后就可進入正常的工作狀態,也就是說在這9個時鐘期間內,所有工作指令只能等待而無法執行。64ms之后則再次對同一行進行刷新,如此周而復始進行循環刷新。顯然,刷新操作肯定會對SDRAM的性能造成影響,但這是沒辦法的事情,也是DRAM相對于SRAM(靜態內存,無需刷新仍能保留數據)取得成本優勢的同時所付出的代價。SR則主要用于休眠模式低功耗狀態下的數據保存,這方面最著名的應用就是STR(Suspend to RAM,休眠掛起于內存)。在發出AR命令時,將CKE置于無效狀態,就進入了SR模式,此時不再依靠系統時鐘工作,而是根據內部的時鐘進行刷新操作。在SR期間除了CKE之外的所有外部信號都是無效的(無需外部提供刷新指令),只有重新使CKE有效才能退出自刷新模式并進入正常操作狀態。
        SDRAM相關寄存器:
        (1)BWSCON寄存器(BUS WIDTH & WAIT CONTROL REGISTER)
        表2-17 SDRAM控制寄存器(BWSCON)




        根據開發板的存儲器配置和芯片型號,設置每個BANK焊接芯片的位寬和等待狀態
        BWSCON,每4位對應一個BANK,這4位分別表示:
        lSTx:啟動/禁止SDRAM的數據掩碼引腳(UB/LB),SDRAM沒有高低位掩碼引腳,此位為0,SRAM連接有UB/LB管腳,設置為1
        l注:UB/LB數據掩碼引腳用來控制芯片讀取/寫入的高字節和低字節(對比硬件手冊SDRAM和SRAM的接線圖)
        lWSx:是否使用存儲器的WAIT信號,通常設為0
        lDWx:設置焊接存儲器芯片的位寬,筆者開發板使用兩片容量為32M,位寬為16的SDRAM組成64M,32位存儲器,因此DW7,DW6位設置為0b10,其它BANK不用設置采用默認值即可。
        lBANK0對應的是系統引導BANK,這4位比較特殊,它的設置是由硬件跳線決定的,因此不用設置
        lBWSCON設置結果:0x22000000
        (2)BANKCON0~BANKCON5 (BANK CONTROL REGISTER)
        表2-18 BANKCON0~BANKCON5控制寄存器(BANKCON0~BANKCON5)


        這6個寄存器用來設置對應BANK0~BANK5的訪問時序,采用默認值0x700即可
        (3)BANKCON6~BANKCON7 (BANK CONTROL REGISTER)
        表2-19 BANKCON6~BANKCON7控制寄存器(BANKCON6~BANKCON7)




        由于內存都焊接在這兩個BANK上,因此內存驅動主要是對這兩個寄存器進行設置
        lMT:設置BANK6~BANK7的存儲器類型,
        00=ROM or SRAM 01=保留
        10=保留11=SDRAM
        內存為SDRAM,設置為0b11,對應的應該設置Trcd和SCAN位,其它位和SDRAM無關
        lTrcd:RAS to CAS Delay行地址選通到列地址選通延遲,這個參數請看后面的內存工作原理擴展部分解釋,筆者內存芯片為HY57V561620,由其芯片手冊可知其Trcd為最少20ns,如果內存工作在100MHz,則該值至少要為2個時鐘周期,通常設置為3個時鐘周期,因此設置為0b01
        lSCAN:SDRAM Column Address Number SDRAM的列地址數,筆者內存芯片為HY57V561620,列地址數為9,設置為0b01
        lBANK6,BANK7設置結果為:0x18005
        (4)REFRESH (REFRESH CONTROL REGISTER)
        表2-20刷新頻率設置寄存器(REFRESH)




        SDRAM的刷新有效,刷新頻率設置寄存器(刷新)
        lREFEN:開啟/關閉刷新功能,設置為1,開啟刷新
        lTREFMD:SDRAM刷新模式,0=CBR/AutoRefresh,1=Self Refresh,設置為0,自動刷新
        lTrp:行地址選通預充電時間,一般設置為0b00即可
        lTsrc:單行刷新時間,設置為0b11即可。
        lRefresh Counter:內存存儲單元刷新數,它通過下面公式計算出:
        Refresh Counter = 2^11 + 1 – SDRAM時鐘頻率(MHz)* SDRAM刷新周期(uS)
        SDRAM的刷新周期,也就是內存存儲單元間隔需要多久進行一次刷新,前面內存工作原理分析可知電容數據保存上限為64ms,筆者使用內存芯片每個L-Bank共有8192行,因此每次刷新最大間隔為:64ms/8192 = 7.8125uS,如果內存工作在外部晶振頻率12MHz下,Refresh Counter = 1955,如果內存工作在100MHz下,那么Refresh Counter = 1269(取大整數)
        lREFRESH寄存器設置為:
        0x8e0000 + 1269 = 0x008e04f5(HCLK = 100MHz)
        0x8e0000 + 1955 = 0x008e07a3(HCLK = 12MHz)
        (5)BANKSIZE寄存器(BANKSIZE REGISTER)
        表2-21 BANKSIZE寄存器(BANKSIZE)



        設置內存的突發傳輸模式,省電模式和內存容量。
        lBURST_EN:是否開啟突發模式,0 = ARM內核禁止突發傳輸1 =開啟突發傳輸,設置為1,開啟突發傳輸
        lSCKE_EN:是否使用SCKE信號作為省電模式控制信號,0 =不使用SCKE信號作為省電模式控制信號1 =使用SCKE信號作為省電模式控制信號,通常設置為1
        lSCLK_EN: 設置向存儲器輸入工作頻率,0 =一直輸入SCLK頻率,即使沒有內存操作也會輸入,1 =僅當進行內存數據操作時才輸入SCLK頻率,通常設置為1
        lBK76MAP:設置Bank6/7的內存容量,筆者使用開發板內存為兩片32M內存芯片并聯成64M,它們全部都外接到Bank6上,因此選擇0b001
        lBANKSIZE寄存器設置為:0xb1
        (6)SDRAM模式設置寄存器MRSRx (SDRAM MODE REGISTER SET REGISTER)
        表2-22 SDRAM模式設置寄存器(MRSRx)



        該寄存器用于設置CAS潛伏周期,可以手動設置的位只有CL[6:4]位,通過前面內存工作原理可知,筆者使用開發板CL=3,即0b011
        lMRSR6,MRSR7設置為:0x00000030

        1.1.8內存驅動實驗

        設置該工程加載時運行時地址為0x30000000,如圖2-55所示:

        圖2-55設置加載時運行時地址
        init.s:本程序文件主要實現了,關閉看門狗,初始化內存,拷貝ROM數據到內存中,然后跳往內存中執行xmain函數,從xmain函數返回之后,將全部led點亮,進入死循環。
        ;
        ;內存初始化實驗
        ;
        AREA Init, CODE, READONLY
        ENTRY
        start
        ; close watchdog
        ldr r0, = 0x53000000;將看門狗控制寄存器地址放入r0
        mov r1, #0
        str r1, [r0];設置看門狗控制寄存器的值為0

        bl initmem;跳轉到initmem代碼段,初始化內存

        bl copyall;跳轉到數據拷貝代碼段,將ROM中數據拷貝到內存中

        IMPORT xmain;引入main.c中的xmain函數
        ldr sp, =0x34000000;調用C程序之前先初始化棧指針
        ldr lr, =endxmain;設置xmain函數的返回地址
        ldr pc, =xmain;跳轉到C程序中的xmain函數的入口處執行

        endxmain
        ldr r0, =0x56000010; LED的GPIO接口配置寄存器
        ldr r1, =0x00015400; GPIO配置數據
        str r1, [r0];設置GPIO
        ldr r0, =0x56000014; LED控制寄存器地址
        ldr r1, =0x0;全部LED亮
        str r1,[r0]
        loop
        b loop;死循環

        copyall
        IMPORT |Image
        RO
        Base|;引入編譯器Image
        RO
        Base符號變量
        IMPORT |Image
        RW
        Limit|;引入編譯器Image
        RW
        Limit符號變量
        ldr r0, = |Image$$RO$Base|;取得Image$$RO$Base域基址的值
        ldr r1, = |Image
        RW
        Limit|;取得Image$$RW$Base域結束地址的值
        ldr r2, =0x0;數據拷貝源地址
        copyallloop
        teq r0,r1;測試是否拷貝完成
        beq quitcopyallloop;拷貝完成,跳往quitcopyallloop退出
        ldr r3, [r2], #4;四字節加載
        str r3, [r0], #4;四字節存儲
        b copyallloop;返回繼續執行
        quitcopyallloop
        mov pc, lr;調用返回

        initmem;內存初始化
        ldr r0, =0x48000000;加載內存相關寄存器首地址r0
        ldr r1, =0x48000034;加載內存相關寄存器尾地址到r1
        adr r2, memdata;將寄存器配置數據地址段首地址加載到r2
        initmemloop
        ldr r3, [r2], #4;循環設置存寄存器
        str r3, [r0], #4
        teq r0, r1
        bne initmemloop;循環到最后一個寄存器時退出函數
        mov pc,lr

        memdata
        DCD0x22000000;BWSCON
        DCD0x00000700;BANKCON0
        DCD0x00000700;BANKCON1
        DCD0x00000700;BANKCON2
        DCD0x00000700;BANKCON3
        DCD0x00000700;BANKCON4
        DCD0x00000700;BANKCON5
        DCD0x00018005;BANKCON6
        DCD0x00018005;BANKCON7
        DCD0x008e07a3;REFRESH
        DCD0x000000b1;BANKSIZE
        DCD0x00000030;MRSRB6
        DCD0x00000030;MRSRB7

        END
        main.c:本程序文件主要實現led燈的初始化,然后四個led燈循環滾動亮5遍,xmain函數返回。
        /* C語言函數*/
        /*端口F寄存器預定義*/
        #defineGPBCON(*(volatile unsigned long *)0x56000010)
        #defineGPBDAT(*(volatile unsigned long *)0x56000014)
        #defineLEDS(1<<5|1<<6|1<<7|1<<8)
        #defineDELAYVAL(0x1ffff)
        extern int delay(int time);/*聲明外部聲明匯編函數*/

        int i = 5;
        int xmain()
        {
        GPBCON= 0x00015400;//GPF4--GPF7設置為output
        while(i > 0) {
        //第一個LED燈亮
        GPBDAT=(GPBDAT&(~LEDS)) | (1<<6|1<<7|1<<8);
        delay(DELAYVAL);//調用匯編語言編寫的延時程序

        //第二個LED燈亮
        GPBDAT=(GPBDAT&(~LEDS)) | (1<<5|1<<7|1<<8);
        delay(DELAYVAL);//調用匯編語言編寫的延時程序

        //第三個LED燈亮
        GPBDAT=(GPBDAT&(~LEDS)) | (1<<5|1<<6|1<<8);
        delay(DELAYVAL);//調用匯編語言編寫的延時程序

        //第四個LED燈亮
        GPBDAT=(GPBDAT&(~LEDS)) | (1<<5|1<<6|1<<7);
        delay(DELAYVAL);//調用匯編語言編寫的延時程序
        i--;
        }
        return 0;
        }

        delay.s:本程序文件主要通常匯編來實現延時功能。
        ;匯編指令延時程序
        EXPORT delay
        AREADELAY,CODE,READONLY;該偽指令定義了一個代碼段,段名為Init,屬性只讀
        ;下面是延遲子程序
        delay
        sub r0,r0,#1;r0=r0-1
        cmp r0,#0x0;將r0的值與0相比較
        bne delay;比較的結果不為0(r0不為0),繼續調用delay,否則執行下一條語句
        mov pc,lr;返回

        END;程序結束符

        內存的初始化也可以用下面的C程序實現:
        C語言版本:
        #defineMEM_CTL_BASE0x48000000
        #defineMEM_CTL_END0x48000034
        /* SDRAM 13個寄存器的值*/
        unsigned longconstmem_cfg_val[]={//聲明數組存放內存控制器設置數據
        0x22000000,//BWSCON
        0x00000700,//BANKCON0
        0x00000700,//BANKCON1
        0x00000700,//BANKCON2
        0x00000700,//BANKCON3
        0x00000700,//BANKCON4
        0x00000700,//BANKCON5
        0x00018005,//BANKCON6
        0x00018005,//BANKCON7
        0x008e07a3,//REFRESH(HCLK = 12MHz,該值為0x008e07a3
        //HCLK = 100MHz 0x008e04f5)
        0x000000b1,//BANKSIZE
        0x00000030,//MRSRB6
        0x00000030,//MRSRB7
        };
        void mem_init(void)
        {
        inti = 0;
        unsigned long *p = (unsigned long *)MEM_CTL_BASE;
        for(; i < (MEM_CTL_END - MEM_CTL_BASE)/4; i++)
        p[i] = mem_cfg_val[i];
        }


        關鍵詞: S3C2440SDRAM內存驅

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 大关县| 丰台区| 乌审旗| 永登县| 和静县| 安化县| 北辰区| 浦城县| 青河县| 饶阳县| 建瓯市| 汉中市| 巴彦县| 余干县| 德州市| 卓尼县| 康马县| 甘孜县| 从江县| 石棉县| 孝昌县| 太康县| 镇平县| 迁安市| 大荔县| 桑植县| 门头沟区| 清水县| 普安县| 扎赉特旗| 大宁县| 来凤县| 门头沟区| 茶陵县| 沙田区| 襄汾县| 南康市| 丹棱县| 海晏县| 吴堡县| 贵德县|