聲明:本文轉自http://blog.csdn.net/mcudoc/article/details/8758222
DDR初始化
一、DDR的容量
我們在DDR芯片資料上的開頭都會標明DDR的容量:如我們的手上的OK6410A的DDR(K4X1G163PC),它的芯片資料上寫的是32M x16 Mobile-DDR SDRAM。但是廠家跟說ok6410a有128M的容量。看到這裏不禁就個疑問了。芯片上明明寫是32M爲什麼,FL說是128M呢。在這裏就能給你答案,板子上有兩片DDR。那它的容量是32Mx16位x2=32Mx32位。它這裏32M指的32位數據,而我們通常所講的容量是以字節爲單位,而不是字爲單位。32M的32位就等於32Mx4的8位。這樣就根FL給出的數據一樣了。所以我們以後在看內存容量時一定要注意到這一點。
二、DDR信號
--------------------------------------------------------------------------------
信號名 作用
-----------------------------------------------------------------------------------
CK,nCK 差分時鐘
nCS 片選信號 低電平有效
CKE 時鐘使能 高電平有效
A0~A12 地址線 行列地址線複用,行地址:A0~A12 列地址:A0~A9
BA0~BA1 BANK選擇 00 01 10 11。第個BAND爲4M
nRAS 行地址鎖存 低電平有效
nCAS 列地址鎖存 低電平有效
nWE 讀寫使能 低電平有效
L(U)DM 數據屏蔽
L(U)DQS 數據選通
DQ0~DQ15 數據線
VDD/VSS 電源與地
VDDQ/VSSQ 數據輸出電源與地
-----------------------------------------------------------------------------------------------------------------------------------------------
三、S3C6410的DRAM控制器初始化
DRAM控制器初始化流程:
(1)以‘3’b100’執行memc_cmd,使得DRAM 控制器輸入‘配置’狀態。
(2)寫存儲器時間參數,芯片配置和ID 配置寄存器。
(3)等待200μs 來使SDRAM 電源和時鐘穩定。當CPU 開始工作時,電源和時鐘已經被穩定下來。
(4)執行存儲器初始化順序。
(5)以‘3’b000’執行memc_cmd,使得DRAM 控制器輸入‘準備’狀態。
(6)在memc_stat 中檢查存儲器狀態域,直到存儲器狀態變爲‘2’b01’,即‘準備’。
DDR 初始化流程:
(1)在direct_cmd,以‘2’b10’執行mem_cmd,使得DRAM 控制器產生‘NOP’存儲器命令。
(2)在direct_cmd,以‘2’b00’執行mem_cmd,使得DRAM 控制器產生‘Prechargeall’存儲器命令。
(3)在direct_cmd,以‘2’b11’執行mem_cmd,使得DRAM 控制器產生‘Autorefresh’存儲器命令。
(4)在direct_cmd,以‘2’b10’執行mem_cmd,使得DRAM 控制器產生‘MRS’存儲器命令。
EMRS 塊地址必須被設置。
(5)在direct_cmd,以‘2’b10’執行mem_cmd,使得DRAM 控制器產生‘MRS’存儲器命令。
MRS 塊地址必須被設置。
(6)在direct_cmd,以‘2’b11’執行mem_cmd,使得DRAM 控制器產生‘Autorefresh’存儲器命令。
(7)在direct_cmd,以‘2’b11’執行mem_cmd,使得DRAM 控制器產生‘Autorefresh’存儲器命令。
(8)在direct_cmd,以‘2’b11’執行mem_cmd,使得DRAM 控制器產生‘Prechargeall’存儲器命令。
如下圖所示:
五、DDR初始化程序
在初始化DDR控制器,要結合DDR的芯片手冊。通常需要從DDR芯片手冊中獲取如下參數:
1、地址線的分佈(列地址行地址分別各爲多少條)。
2、DDR的刷新週期(通常爲7.8US)
3、位寬二片DDR,即爲32位
4、DDR的訪問時序參數
程序如下
頭文件:
- #ifndef __COMMON_H
- #define __COMMON_H
- #define vi *( volatile unsigned int * )
- #define set_zero( addr, bit ) ( (vi addr) &= ( ~ ( 1 << (bit) ) ) )
- #define set_one( addr, bit ) ( (vi addr) |= ( 1 << ( bit ) ) )
- #define set_bit( addr, bit, val ) ( (vi addr) = (( vi addr)&=(~(1<<(bit))) ) | ( (val)<<(bit) ) )
- #define set_2bit( addr, bit, val ) ( (vi addr) = (( vi addr)&(~(3<<(bit))) ) | ( (val)<<(bit) ) )
- #define set_nbit( addr, bit, len, val ) \
- ( (vi addr) = ((( vi addr)&(~(( ((1<<(len))-1) )<<(bit)))) | ( (val)<<(bit) ) ))
- #define get_bit( addr, bit ) ( (( vi addr ) & ( 1 << (bit) )) > 0 )
- #define get_val( addr, val ) ( (val) = vi addr )
- #define read_val( addr ) ( vi ( addr ) )
- #define set_val( addr, val ) ( (vi addr) = (val) )
- #define or_val( addr, val ) ( (vi addr) |= (val) )
- ///////////////////////////////
- typedef unsigned char u8;
- typedef unsigned short u16;
- typedef unsigned int u32;
- // function declare
- int delay( int );
- #endif
DDR 初始化程序
- #include "common.h"
- #define MEMCCMD 0x7e001004
- #define P1REFRESH 0x7e001010
- #define P1CASLAT 0x7e001014
- #define MEM_SYS_CFG 0x7e00f120
- #define P1MEMCFG 0x7e00100c
- #define P1T_DQSS 0x7e001018
- #define P1T_MRD 0x7e00101c
- #define P1T_RAS 0x7e001020
- #define P1T_RC 0x7e001024
- #define P1T_RCD 0x7e001028
- #define P1T_RFC 0x7e00102c
- #define P1T_RP 0x7e001030
- #define P1T_RRD 0x7e001034
- #define P1T_WR 0x7e001038
- #define P1T_WTR 0x7e00103c
- #define P1T_XP 0x7e001040
- #define P1T_XSR 0x7e001044
- #define P1T_ESR 0x7e001048
- #define P1MEMCFG2 0X7e00104c
- #define P1_chip_0_cfg 0x7e001200
- #define P1MEMSTAT 0x7e001000
- #define P1MEMCCMD 0x7e001004
- #define P1DIRECTCMD 0x7e001008
- #define HCLK 133000000
- #define nstoclk(ns) (ns/( 1000000000/HCLK)+1)
- int sdram_init( void )
- {
- // 設置DRAM控制器狀態爲配置模式
- set_val( MEMCCMD, 0x4 );
- // 設置DDR刷新週期爲7.8US
- set_val( P1REFRESH, nstoclk(7800) );
- // 設置DDR時序參數
- set_val( P1CASLAT, ( 3 << 1 ) );
- set_val( P1T_DQSS, 0x1 ); // 0.75 - 1.25時鐘週期
- set_val( P1T_MRD, 0x2 ); //min=2個時鐘週期
- set_val( P1T_RAS, nstoclk(45) );//45us
- set_val( P1T_RC, nstoclk(68) );//68us
- u32 trcd = nstoclk( 23 );
- set_val( P1T_RCD, trcd | (( trcd - 3 ) << 3 ) );//22.5us
- u32 trfc = nstoclk( 80 );
- set_val( P1T_RFC, trfc | ( ( trfc-3 ) << 5 ) );
- u32 trp = nstoclk( 23 );
- set_val( P1T_RP, trp | ( ( trp - 3 ) << 3 ) );
- set_val( P1T_RRD, nstoclk(15) );
- set_val( P1T_WR, nstoclk(15) );
- set_val( P1T_WTR, 0x7 );
- set_val( P1T_XP, 0x2 );
- set_val( P1T_XSR, nstoclk(120) );
- set_val( P1T_ESR, nstoclk(120) );
- // set mem cfg
- set_nbit( P1MEMCFG, 0, 3, 0x2 );
- //把第0位開始的後三位清零,然後把這三位設置爲ox2
- set_nbit( P1MEMCFG, 3, 3, 0x2 );
- set_zero( P1MEMCFG, 6 );
- set_nbit( P1MEMCFG, 15, 3, 0x2 );
- set_nbit( P1MEMCFG2, 0, 4, 0x5 );
- set_2bit( P1MEMCFG2, 6, 0x1 );
- set_nbit( P1MEMCFG2, 8, 3, 0x3 );
- set_2bit( P1MEMCFG2, 11, 0x1 ); //讀延遲1 週期
- set_one( P1_chip_0_cfg, 16 );
- // DDR 初始化
- set_val( P1DIRECTCMD, 0xc0000 ); // NOP
- set_val( P1DIRECTCMD, 0x000 ); // precharge
- set_val( P1DIRECTCMD, 0x40000 );// auto refresh
- set_val( P1DIRECTCMD, 0x40000 );// auto refresh
- set_val( P1DIRECTCMD, 0xa0000 ); // EMRS
- set_val( P1DIRECTCMD, 0x80032 ); // MRS
- set_val( MEM_SYS_CFG, 0x0 );
- // 使得DRAM 控制器輸入‘準備’狀態
- set_val( P1MEMCCMD, 0x000 );
- // 直到存儲器狀態變爲‘2’b01’,即‘準備
- while( !(( read_val( P1MEMSTAT ) & 0x3 ) == 0x1));
- }
以下爲本人找的:
在s3c6410x文檔中的第五章DRAMC中的5.4.1爲初始化流程,5.4.3爲ddr初始化流程