OK6410裸机程序(四)——DDR初始化

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 /* __COMMON_H */

 

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 );  /* 配置成10位 列地址 */

	/* set_nbit: 把从第bit位开始的一共len位消零,然后把这几位设为val */
	//把第0位开始的后三位清零,然后把这三位设置为ox2
	
	set_nbit( P1MEMCFG, 3, 3, 0x2 );  /* 配置成13 行地址 */
	
	set_zero( P1MEMCFG, 6 );		  /* 地址位10设为预充电位的编码位置*/
	set_nbit( P1MEMCFG, 15, 3, 0x2 ); /* 脉冲 4 */
	
	set_nbit( P1MEMCFG2, 0, 4, 0x5 ); /* 将AXI与内存时钟相同 */
	set_2bit( P1MEMCFG2, 6, 0x1 );		/* 32 bit */
	set_nbit( P1MEMCFG2, 8, 3, 0x3 );	/* 设置DDR样式Mobile DDR SDRAM */
	set_2bit( P1MEMCFG2, 11, 0x1 );    //读延迟1 周期

	set_one( P1_chip_0_cfg, 16 );		/* Bank-Row-Column organization */

	// 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));
}




 

 

   

 

 

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值