s3c6410初始化256Mddr补充

6410初始化ddr的过程基本都写在了说明手册中,但是各种教程里都或多或少缺失了对一部分细节的解释。韦东山

的教程真的是很不错,可惜有些地方没解释到,在这里做个补充吧。其中ddr的型号为K4X1G163PC。

首先是对ddr初始化代码的注释部分的补充,如下。

#include "common.h"

#define P1MEMSTAT	0x7e001000
#define P1MEMCCMD	0x7e001004
#define P1DIRECTCMD	0x7e001008
#define P1MEMCFG	0x7e00100c

#define P1REFRESH	0x7e001010
#define P1CASLAT	0x7e001014
#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 MEM_SYS_CFG	0x7e00f120

#define P1_chip_0_cfg	0x7e001200

#define P1_user_cfg	0x7e001304


	
#define HCLK	133000000

#define nstoclk(ns)	(ns/( 1000000000/HCLK)+1)

int sdram_init( void )
{	
	set_val( MEM_SYS_CFG, 0x0 );//设置复用的数据线为ddr所用(第七位的设置默认为1,为rom所用)
	
	//告诉DRAMC开始配置				
	set_val( P1MEMCCMD, 0x4 );

	// set refresh period 设置刷新时间
	set_val( P1REFRESH, nstoclk(7800) );

	//设置时间参数	没有注释的参数均可在ddr手册中查到取值范围	
	set_val( P1CASLAT, ( 3 << 1 ) );  
	set_val( P1T_DQSS, 0x1 );
	set_val( P1T_MRD, 0x2 );
	set_val( P1T_RAS, nstoclk(45) );
	set_val( P1T_RC, nstoclk(68) );		

	u32 trcd = nstoclk( 23 );
	set_val( P1T_RCD, trcd | (( trcd - 3 ) << 3 ) );
	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, 0x1 );		/*对应tCDLR*/
	set_val( P1T_XP, 0x1 );			/*对应tPDEX*/
	set_val( P1T_XSR, nstoclk(120) );	
	//set_val( P1T_ESR, nstoclk(120) );	/*ddr手册里没有,无需配置?*/
	
	// set mem cfg 
	set_nbit( P1MEMCFG, 0, 3, 0x2 );	/* 10列 */
	set_nbit( P1MEMCFG, 3, 3, 0x3 );	/* 32Mx16为13行,对64Mx16是14行,这里应设置为0x3*/
	set_zero( P1MEMCFG, 6 );		/* A10/AP */
	set_nbit( P1MEMCFG, 15, 3, 0x2 );	/* Burst 4 */

	set_nbit( P1MEMCFG2, 0, 4, 0x4 );	/*个人认为在异步模式下应设置为0x4*/ 
	set_2bit( P1MEMCFG2, 6, 0x1 );		/* 32 bit */
	set_nbit( P1MEMCFG2, 8, 3, 0x3 );	/* Mobile DDR SDRAM */
	set_2bit( P1MEMCFG2, 11, 0x1 );		/*read delay 1 cycle for MDDR*/

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

	// memory init
	set_val( P1DIRECTCMD, 0xc0000 );	// NOP
	set_val( P1DIRECTCMD, 0x00000 );	// precharge
	set_val( P1DIRECTCMD, 0x40000 );	// auto refresh
	set_val( P1DIRECTCMD, 0x40000 );	// auto refresh
	set_val( P1DIRECTCMD, 0xa0000 );	// EMRS	
	set_val( P1DIRECTCMD, 0x80032 );	// MRS	
		
	// set dramc to "go" status	
	set_val( P1MEMCCMD, 0x000 );

	// wait ready
	while( !(( read_val( P1MEMSTAT ) & 0x3 ) == 0x1));
}

其中仍然没有搞清楚的是tESR的设置以及P1MEMCFG2低四位的设置。实际测试的时候不设置tESR且将P1MEMCFG2

低四位设置为0x4、0x5时,ddr均能正常工作,不明白原因所在。


其次是对时钟部分设置的补充,这也是让我的程序一直调不通的原因。ddr运行时是在时钟上升沿和下降沿都进行

数据的传输,所以提供给ddr的时钟频率是ddr controller时钟频率的一半。在K4X1G163PC的芯片手册第一页可看

到在CL为3时,工作频率可设置为166MHz或133MHz。

1


6410的3.3.4.2节,ARM and AXI/AHB/APB bus clock generation这一块又提到

即ddr controller最高工作频率为266MHz,假设将ddr controller的时钟频率设置为266MHz,则ddr的时钟频率为

133MHz。在上面又说到HCLKX2是是ddr controller的时钟。在3.3.1节硬件架构中有这么一副图



从中可以看到ddr是通过AXI总线连接到6410的,再看3.3.4.1


从中可知AXI总线的时钟是HCLK。所以ddr的时钟就是HCLK。因此在初始化时钟的过程中,必须要将DIV_HCLK设置

1,即HCLKx2的频率始终为HCLK的2倍,否则时钟频率对不上,ddr的初始化就无法正常执行,更不用说使用ddr了。

最后附上调整时钟主要涉及到的几个寄存器的参考图吧。



 



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值