uboot-step 8 內(nèi)存初始化
內(nèi)存的初始化相比前面的那些步驟略微的麻煩了些,為了能夠比較清楚地說(shuō)明下內(nèi)存的初始化,(ps:雖然我也不是特別的清楚),首先簡(jiǎn)單的說(shuō)下這篇文章的大概流程:
- 1.對(duì)內(nèi)存相關(guān)的一些簡(jiǎn)單介紹
- 2.s3c6410的內(nèi)存控制器的初始化流程
- 3.對(duì)照datasheet說(shuō)明實(shí)現(xiàn)代碼的工作流程
關(guān)于內(nèi)存
內(nèi)存的分類
這里所說(shuō)的內(nèi)存僅指RAM(RandomAccessMemory,隨機(jī)存取存儲(chǔ)器),它具有可以隨機(jī)讀寫訪問(wèn)的特點(diǎn),并且存儲(chǔ)的數(shù)據(jù)在斷電后會(huì)自動(dòng)消失,現(xiàn)在所用的主要有以下兩種類型:
- SRAM :靜態(tài)RAM,不需要一直刷新,雙穩(wěn)態(tài)電路形式存儲(chǔ)數(shù)據(jù),集成度較低,體積大,造價(jià)高,容量小,通常用作Cache
- DRAM : 動(dòng)態(tài)RAM, 需要不斷刷新,通過(guò)MOS電容存儲(chǔ)電荷來(lái)存儲(chǔ)數(shù)據(jù),結(jié)構(gòu)簡(jiǎn)單,集成度高,成本低,便于大容量制造,常見的幾種DRAM:
- SDRAM :Synchronous Dynamic RAM ,同步動(dòng)態(tài)隨機(jī)存儲(chǔ)器,工作頻率與系統(tǒng)的頻率相同,逐漸被DDR SDRAM所取代
- DDR SDRAM : Double Data Rate SDRAM 雙倍同步動(dòng)態(tài)隨機(jī)存儲(chǔ)器,習(xí)慣上稱之為DDR,相比SDRAM,速度和容量上有所提升,本質(zhì)上雖然沒有提高時(shí)鐘頻率,但是可以在時(shí)鐘的上升沿和下降沿同時(shí)傳輸數(shù)據(jù),因此其速度是標(biāo)準(zhǔn)SDRAM 的兩倍
- mobile DDR : 相比pC端的DDR,電壓更低,封裝更小
內(nèi)存的結(jié)構(gòu)
內(nèi)存的內(nèi)部結(jié)構(gòu)就像表格一樣,每一張表格稱為一個(gè)邏輯BANK,L_BANK,每張表格有若干行地址線和若干列地址線,尋址的時(shí)候,首先去找到數(shù)據(jù)在哪一個(gè)bank里面,然后在分別確定行地址和列地址,這樣就可以找到需要的數(shù)據(jù)所在的單元了,由于成本,制造工藝的原因,無(wú)法將整個(gè)地址空間做到一個(gè)bank里面,現(xiàn)在一般都將整個(gè)地址空間分為4個(gè)L-bank,四個(gè)L-bank具有公用的行地址和列地址
內(nèi)存的容量
一般內(nèi)存容量的表示方法如上圖所示,64M表示有多少個(gè)存儲(chǔ)單元,32表示每個(gè)存儲(chǔ)單位的容量為多少bit,可以將其換算為Byte,如上圖所示的內(nèi)存容量為64M32bit=644Byte=256MByte。
內(nèi)存引腳說(shuō)明
如上圖所示,RAM的引腳主要有以下幾種:
- 電源引腳: 數(shù)據(jù)電源VDDQ,VSSQ,電源VDD,VSS
- 時(shí)鐘相關(guān)引腳: CK 上升沿和下降沿兩個(gè),CKE時(shí)鐘使能引腳
- 片選引腳: CS 低有效
- 列,行地址,寫使能引腳: 列,行地址選中使能,寫使能引腳,低有效
- DMx引腳:輸入數(shù)據(jù)屏蔽引腳
- BA0,1:bank選擇引腳
- A[n:0]:地址線
- DQ:數(shù)據(jù)總線
- DQSx:輸出數(shù)據(jù)閘門
下圖是S3c6410 內(nèi)存端口引腳說(shuō)明,可以看出與上面的內(nèi)存芯片的datasheet中的引腳說(shuō)明正好一一對(duì)應(yīng)
硬件原理圖如下圖所示:
更多內(nèi)存相關(guān)的知識(shí)請(qǐng)找度娘或參考下面的鏈接
終極圖解內(nèi)存上
終極圖解內(nèi)存下
s3c6410 DRAMC初始化流程
S3c6410的DRAM 控制器支持SDR SDRAM,mobile SDR SDRAM ,DDR SDRAM,和mobile DDR SDRAM多種類型,根據(jù)芯片手冊(cè)上的描述:
DRAM 控制器支持多達(dá)兩片同樣類型的最大256M的內(nèi)存,所有的內(nèi)存片都共享同樣的引腳,除了時(shí)鐘使能和片選信號(hào),當(dāng)上電復(fù)位以后,軟件必須初始化DRAM控制器和連接到DRAM控制器上的內(nèi)存,初始化流程需要參考SDRAM datasheet,可供參考的初始化流程如下圖,第一張圖是DRAM 控制器的初始化流程,第二張圖是內(nèi)存的初始化流程:
由于所采用的開發(fā)板上的內(nèi)存芯片為Mobile DDR SDRAM,因此這里只貼出了這種類型的內(nèi)存初始化流程,先來(lái)看下DRAM控制器的初始化流程:
- 1.編程memc_cmd 寫入'3b100',使DRAM控制器進(jìn)入Config (配置)狀態(tài)
- 2.向相關(guān)的寄存器中寫入內(nèi)存時(shí)序參數(shù),內(nèi)存片的配置,id配置相關(guān)
- 3.等待200us,使內(nèi)存上電和時(shí)鐘穩(wěn)定,但是其實(shí)當(dāng)cpu開始工作的時(shí)候,內(nèi)存電源和時(shí)鐘都已經(jīng)穩(wěn)定了
- 4.執(zhí)行內(nèi)存初始化流程,即下面的流程
- 5.編程memc_cmd寫入'3b000',使DRAM控制器進(jìn)入’Ready‘(準(zhǔn)備)狀態(tài)
- 6.檢查寄存器memc_stat 內(nèi)存狀態(tài)域直到內(nèi)存狀態(tài)為’2b01‘,這意味著DRAM控制器已經(jīng)準(zhǔn)備好了
看完了DRAM控制器的初始化流程,再來(lái)看下內(nèi)存初始化的流程:
- 1.編程mem_cmd 在direct_cmd 寫入’2b11‘,使DRAM控制器發(fā)送'NOP'命令到內(nèi)存
- 2.編程mem_cmd 在direct_cmd 寫入’2b00‘,使內(nèi)存控制器發(fā)送’Prechargeall'命令到內(nèi)存
- 3.編程mem_cmd 在direct_cmd 寫入‘2b11’,使DRAM控制器發(fā)送'Autorefresh'命令到內(nèi)存
- 4.編程mem_cmd 在direct_cmd 寫入‘2b11’,使DRAM控制器發(fā)送'Autorefresh'命令到內(nèi)存
- 5.編程mem_cmd '2b10'在direct_cmd,使DRAM 控制器發(fā)送MRS內(nèi)存命令-EMRS的bank地址一定要設(shè)定
- 6.編程mem_cmd '2b10'在direct_cmd,使DRAM 控制器發(fā)送MRS內(nèi)存命令-MRS的bank地址一定要設(shè)定
接下來(lái)按照上面的流程來(lái)進(jìn)行內(nèi)存的初始化
1,Dram控制器進(jìn)入配置狀態(tài)
按照上圖的說(shuō)明,向memc_cmd寄存器中寫入100即可
2,內(nèi)存時(shí)序參數(shù),id等相關(guān)配置
-
Refresh period 配置
refresh period.png
內(nèi)存刷新周期設(shè)置,根據(jù)下圖內(nèi)存芯片手冊(cè)的值,由s3c6410的時(shí)鐘體系配置,內(nèi)存使用的為AHB總線時(shí)鐘,為133Mhz,7.8us對(duì)應(yīng)寄存器的值應(yīng)為7800*(1000 000 000/133 000 000),此值不是一個(gè)整數(shù),最后在加上1,即為寄存器中的值
data refresh.png -
CAS latency
cas.png
如下圖,內(nèi)存芯片手冊(cè)上的數(shù)字為2或3,這里設(shè)為3
data cas.png -
t_DQSS
t_dqss.png
如下圖,內(nèi)存芯片手冊(cè)上的為0.75到1.25之間,這里設(shè)為1
data tdqss.png -
t_MRD
t mrd.png
如下圖,內(nèi)存芯片手冊(cè)上的為2
-
t_RAS
t_ras.png
如下圖,內(nèi)存芯片手冊(cè)上的為40 到70000ns之間,我們大概選個(gè)時(shí)間就好
data tras.png -
t_RC
t_rc.png -
t_RCD
t_rcd.png -
t_RFC
t_rfc.png -
t_RP
t_rp.png -
t_RRD
t_rrd.png -
t_WR
t_wr.png -
t_WTR
t_wtr.png -
t_XP
t_xp.png -
t_XSR
t_xsr.png -
t_ESR
t_esr.png
上面這些時(shí)序參數(shù)配置大部分在內(nèi)存芯片手冊(cè)上都可以找到,只要相應(yīng)的填進(jìn)去就好,實(shí)在沒有的可以參考其它人的代碼來(lái)寫:
-
MEMCFG 寄存器 行列地址,burst length,內(nèi)存片數(shù)量
memcfg.png
memcfg1.png
這里內(nèi)存芯片只有一片,芯片手冊(cè)上相關(guān)數(shù)據(jù)如下:
data addr.png
data burst.png -
MEMCFG2 寄存器 配置,內(nèi)存類型,數(shù)據(jù)寬度等信息,這里32bit,mobileDDR內(nèi)存
memcfg2.png -
chipcfg 配置AXI 內(nèi)存地址
chipcfg.png -
usrcfg 用戶寄存器
usrcfg.png
3.這樣就完成了內(nèi)存參數(shù)的設(shè)置,下面進(jìn)行內(nèi)存初始化流程
- 1、發(fā)送NOP命令
- 2、發(fā)送Prechargeall命令
- 3、發(fā)送Autofresh
- 4、發(fā)送Autofresh
- 5、發(fā)送mrs命令,設(shè)置mrs寄存器
-
6、發(fā)送mrs命令,設(shè)置emrs寄存器
對(duì)于5,6點(diǎn)的內(nèi)存寄存器的設(shè)置需要根據(jù)內(nèi)存芯片手冊(cè)進(jìn)行相關(guān)配置,如下圖:
data mrs.png
data emrs.png
4.完成了內(nèi)存的初始化流程之后,就剩下最后的ready了
- 發(fā)送ready到memc_cmd 命令000 使DRAM控制器進(jìn)入ready狀態(tài)
-
檢查mem_stat寄存器,檢查DRAM控制器是否已經(jīng)進(jìn)入ready狀態(tài)
memstat.png
代碼實(shí)現(xiàn)如下:
.text
.global mem_init
mem_init:
ldr r0, =0x7e00f120 @設(shè)置xm1data引腳為dramc 數(shù)據(jù)引腳
mov r1, #0x8
str r1, [r0]
ldr r0, =0x7e001004 @內(nèi)存控制命令寄存器
mov r1, #0x4 @根據(jù)手冊(cè)得知需要先進(jìn)入配置模式
str r1, [r0]
ldr r0, =0x7e001010 @刷新寄存器地址
ldr r1, =( ( 7800 / ( 1000000000/133000000 ) + 1 ) ) @設(shè)置刷新時(shí)間
str r1, [r0]
ldr r0, =0x7e001014 @CAS latency寄存器
mov r1, #(3 << 1)
str r1, [r0]
ldr r0, =0x7e001018 @t_DQSS寄存器
mov r1, #0x1
str r1, [r0]
ldr r0, =0x7e00101c @T_MRD寄存器
mov r1, #0x2
str r1, [r0]
ldr r0, =0x7e001020 @t_RAS寄存器
ldr r1, =( ( 45 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0]
ldr r0, =0x7e001024 @t_RC寄存器
ldr r1, =( ( 68 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0]
ldr r0, =0x7e001028 @t_RCD寄存器
ldr r1, =( ( 23 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0]
ldr r0, =0x7e00102c @t_RFC寄存器
ldr r1, =( ( 80 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0]
ldr r0, =0x7e001030 @t_RP寄存器
ldr r1, =( ( 23 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0]
ldr r0, =0x7e001034 @t_rrd寄存器
ldr r1, =( ( 15 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0]
ldr r0, =0x7e001038 @t_wr寄存器
ldr r1, =( ( 15 / ( 1000000000 / 133000000 ) + 1 ) )
@ ldr r2, [r0]
str r1, [r0]
ldr r0, =0x7e00103c @t_wtr寄存器
mov r1, #0x07
str r1, [r0]
ldr r0, =0x7e001040 @t_xp寄存器
mov r1, #0x02
str r1, [r0]
ldr r0, =0x7e001044 @t_xsr寄存器
ldr r1, =( ( 120 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0]
ldr r0, =0x7e001048 @t_esr寄存器
ldr r1, =( ( 120 / ( 1000000000 / 133000000 ) + 1 ) )
str r1, [r0]
ldr r0, =0x7e00100c @內(nèi)存控制配置寄存器
ldr r1, =0x00010012 @配置控制器
str r1, [r0]
ldr r0, =0x7e00104c @32位DRAM配置控制寄存器
ldr r1, =0x0b45
str r1, [r0]
ldr r0, =0x7e001200 @片選寄存器
ldr r1, =0x150f8
str r1, [r0]
ldr r0, =0x7e001304 @用戶配置寄存器
mov r1, #0x0
str r1, [r0]
ldr r0, =0x7e001008
ldr r1, =0x000c0000 @nop
str r1, [r0]
ldr r1, =0x00000000 @Prechargeall
str r1, [r0]
ldr r1, =0x00040000 @Autofresh
str r1, [r0]
ldr r1, =0x000a0000 @emrs 寄存器設(shè)置
str r1, [r0]
ldr r1, =0x00080032 @mrs 設(shè)置
str r1, [r0]
ldr r0, =0x7e001004 @發(fā)送ready命令
mov r1, #0x0
str r1, [r0]
check_dmc1_ready: @檢測(cè)ready命令是否已經(jīng)完成
ldr r0, =0x7e001000
ldr r1, [r0]
mov r2, #0x3
and r1, r1, r2
cmp r1, #0x1
bne check_dmc1_ready
nop
mov pc, lr
此去經(jīng)年
zhaiyk@sina.cn
August 3, 2016