s3c6410初始化256Mddr补充

时间:2021-08-12 21:07:52

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。

s3c6410初始化256Mddr补充


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

s3c6410初始化256Mddr补充

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

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

s3c6410初始化256Mddr补充


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

s3c6410初始化256Mddr补充

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

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

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


s3c6410初始化256Mddr补充