LPC1788外扩两片SDRAM,测试通不过,会是什么原因导致的?
本帖最后由 shandian 于 2014-2-9 23:42 编辑硬件为LPC1788外扩两片K4S561632E-TC75,组成32bit位宽512Mbit的内存。可是数据读写测试总是通不过,每次校验的时候总会有一小段数据为0,而不等于写入的数据。而且每次运行错误的位置都是不同的。
如果只使用其中1片SDRAM,程序改为16bit位宽的话,可以顺利通过内存测试。
使用两片SDRAM芯片的时候每次出错地址都不同,而且我有两块板子,存在的问题都一样,所以我觉得应该不是硬件的问题(布线的时候SDRAM倒是没有做等长处理,但是我觉得才60MHz,不等长应该也没问题)。
不知道有没有人遇到过相同的问题?
以下是我的原理图和SDRAM控制器的初始化代码?大家帮我看看有没问题。
接线:
初始化代码:
SDRAM.h
#define SDRAM_BASE_ADDR 0xA0000000
#define SDRAM_SIZE 0x04000000 /* 64M */
#define SDRAM_REFRESH 7813 // 'tREFRESH = 64ms/8192'
#define SDRAM_TRP 20 // 'tRP = 20ns'
#define SDRAM_TRAS 45 // 'tRAS = 45ns'
#define SDRAM_TAPR 1 // 'tAPR = 1CLK
#define SDRAM_TDAL 3 // 'tDAL = 2CLK + tRP'
#define SDRAM_TWR 3 // 'tWR = 2CLK'
#define SDRAM_TRC 65 // 'tRC = 65'
#define SDRAM_TRFC 66 // 'tRFC = 65'
#define SDRAM_TXSR 67 // 'tXSR = 1CLK'
#define SDRAM_TRRD 15 // 'tRRD = 15'
#define SDRAM_TMRD 3 // 'tMRD = 2CLK'
SDRAM.c
void SDRAM_Init( void )
{
volatile uint32_t i;
volatile unsigned long Dummy;
// PINSEL_ConfigPin(2,14,1); /* P2.14 - /EMC_CS2 */
// PINSEL_ConfigPin(2,15,1); /* P2.15 - /EMC_CS3 */
PINSEL_ConfigPin(2,16,1); /* P2.16 - /EMC_CAS */
PINSEL_ConfigPin(2,17,1); /* P2.17 - /EMC_RAS */
PINSEL_ConfigPin(2,18,1); /* P2.18 - EMC_CLK */
// PINSEL_ConfigPin(2,19,1); /* P2.19 - EMC_CLK */
PINSEL_ConfigPin(2,20,1); /* P2.20 - EMC_DYCS0 */
// PINSEL_ConfigPin(2,21,1); /* P2.21 - EMC_DYCS1 */
//PINSEL_ConfigPin(2,22,1); /* P2.22 - EMC_DYCS2 */
// PINSEL_ConfigPin(2,23,1); /* P2.23 - EMC_DYCS3 */
PINSEL_ConfigPin(2,24,1); /* P2.24 - EMC_CKE0 */
// PINSEL_ConfigPin(2,25,1); /* P2.25 - EMC_CKE1 */
// PINSEL_ConfigPin(2,26,1); /* P2.26 - EMC_CKE2 */
// PINSEL_ConfigPin(2,27,1); /* P2.27 - EMC_CKE3 */
PINSEL_ConfigPin(2,28,1); /* P2.28 - EMC_DQM0 */
PINSEL_ConfigPin(2,29,1); /* P2.29 - EMC_DQM1 */
PINSEL_ConfigPin(2,30,1); /* P2.30 - EMC_DQM2 */
PINSEL_ConfigPin(2,31,1); /* P2.31 - EMC_DQM3 */
// PINSEL_ConfigPin(4,24,1); /* P4.24 - /EMC_OE */
PINSEL_ConfigPin(4,25,1); /* P4.25 - /EMC_WE */
// PINSEL_ConfigPin(4,30,1); /* P4.30 - /EMC_CS0 */
// PINSEL_ConfigPin(4,31,1); /* P4.31 - /EMC_CS1 */
for(i = 0; i < 32; i++)
{
PINSEL_ConfigPin(3,i,1); /* P3.0-P3.31 - EMC_D */
}
for(i = 0; i < 15; i++)
{
PINSEL_ConfigPin(4,i,1); /* P4.0-P4.14 - EMC_A */
}
// EMC_Init();
// Init SDRAM controller
LPC_SC->PCONP |= 0x00000800;
/*Init SDRAM controller*/
LPC_SC->EMCDLYCTL |= (8<<0);
/*Set data read delay*/
LPC_SC->EMCDLYCTL |=(8<<8);
LPC_SC->EMCDLYCTL |= (0x08 <<16);
LPC_EMC->Control =1;
LPC_EMC->DynamicReadConfig = 1;
LPC_EMC->DynamicRasCas0 = 0;
LPC_EMC->DynamicRasCas0 |=(3<<8);
LPC_EMC->DynamicRasCas0 |= (3<<0);
LPC_EMC->DynamicRP = P2C(SDRAM_TRP);
LPC_EMC->DynamicRAS = P2C(SDRAM_TRAS);
LPC_EMC->DynamicSREX = P2C(SDRAM_TXSR);
LPC_EMC->DynamicAPR = SDRAM_TAPR;
LPC_EMC->DynamicDAL = SDRAM_TDAL+P2C(SDRAM_TRP);
LPC_EMC->DynamicWR = SDRAM_TWR;
LPC_EMC->DynamicRC = P2C(SDRAM_TRC);
LPC_EMC->DynamicRFC = P2C(SDRAM_TRFC);
LPC_EMC->DynamicXSR = P2C(SDRAM_TXSR);
LPC_EMC->DynamicRRD = P2C(SDRAM_TRRD);
LPC_EMC->DynamicMRD = SDRAM_TMRD;
// 13 row, 9 - col, SDRAM
LPC_EMC->DynamicConfig0 = 0x0004680;
// JEDEC General SDRAM Initialization Sequence
// DELAY to allow power and clocks to stabilize ~100 us
// NOP
LPC_EMC->DynamicControl = 0x0183;
for(i= 200*30; i;i--);
// PALL
LPC_EMC->DynamicControl = 0x0103;
LPC_EMC->DynamicRefresh = 2;
for(i= 256; i; --i); // > 128 clk
LPC_EMC->DynamicRefresh = P2C(SDRAM_REFRESH) >> 4;
// COMM
LPC_EMC->DynamicControl = 0x00000083; /* Issue MODE command */
Dummy = *((volatile uint32_t *)(SDRAM_BASE_ADDR | (0x32<<13)));
// NORM
LPC_EMC->DynamicControl = 0x0000;
LPC_EMC->DynamicConfig0 |=(1<<19);
for(i = 100000; i;i--);
}
120MHz可以用的,是不是电源有问题?退偶不好 两个参数不对
第一个 SDRAM的配置地方,16位 32位宽度不一样
第二个地方 16位 32位虚拟写也不一样
具体时间太长 我忘了 但是配置地方你要注意 如果是低功耗位置位的话,这个 Base address + (mode register value << (bank bits + column bits + bus width/16) 是错误的,好像不应该加bank bits。也就是SDRAM的RBC和BRC的配置区别。
另外 我使用的是lpcopen 那里面代码需要添加上面说的部分处理
我使用它的配置部分是这样的
#ifdefSDRAMBIT16
dwtemp = *((volatile uint32_t *)(SDRAM_BASE_ADDR | (0x23<<(2+9+1))));
#else
dwtemp = *((volatile uint32_t *)(SDRAM_BASE_ADDR | (0x22<<(2+9+2))));/* Mode Register Setting: 4 burst, 3 CAS latency */
#endif
如楼上所说,32bit和16bit配置是有区别的,不是简单的配置引脚配置容量大小。 size327948964 发表于 2014-2-10 09:07
两个参数不对
第一个 SDRAM的配置地方,16位 32位宽度不一样
第二个地方 16位 32位虚拟写也不一样
关于第一点,我在配置LPC_EMC->DynamicConfig0的时候不一样的,在使用16位的时候和32位的时候这个配置不一样的。
第二点我再好好研究下吧,说实话SDRAM的时序太麻烦了,很多时间参数什么的代表什么意思,以及LPC1788 SDRAM控制器很多寄存器的作用等等我都没怎么仔细去看。我再好好研究下手册看。 nongxiaoming 发表于 2014-2-10 09:23
如楼上所说,32bit和16bit配置是有区别的,不是简单的配置引脚配置容量大小。 ...
恩,好。不知道晓明兄这有没有现成的32bit的初始化代码。有的话可以让我参考一下吗? 有是有 但是我用的是库 直接寄存器操作的找不到了
下面使用了库 采用RBC配置方式 片子是hy57v2562
config.ChipSize = 256;
#ifdefSDRAMBIT16
config.AddrBusWidth = 16;
#else
config.AddrBusWidth = 32;
#endif
config.AddrMap = EMC_ADD_MAP_ROW_BANK_COL;
config.CSn = 0;
config.DataWidth = 16;
config.TotalSize = SDRAM_SIZE;
config.CASLatency= 3;
config.RASLatency= 3;
config.Active2ActivePeriod = EMC_NS2CLK(63); //Trc=63ns
config.ActiveBankLatency = EMC_NS2CLK(15); //Trrd=15ns
config.AutoRefrehPeriod = EMC_NS2CLK(65); //Trc=65ns
config.DataIn2ActiveTime = EMC_NS2CLK(20)+2;//Tdal=20ns+2CLK
config.DataOut2ActiveTime= 0xf; // 不懂 找不到
config.WriteRecoveryTime = 2; //Tdpl=2CLK
config.ExitSelfRefreshTime = 0x1f;//没有
config.LoadModeReg2Active= 2; //Tmrd=2CLK
config.PrechargeCmdPeriod= EMC_NS2CLK(20); //Trp=20ns
config.ReadConfig = 1;/* Command delayed strategy, using EMCCLKDELAY *///不懂
config.RefreshTime = EMC_SDRAM_REFRESH(64); //64ms
config.Active2PreChargeTime= EMC_NS2CLK(42); //Tras=42ns
config.SeftRefreshExitTime = 1;//EMC_NS2CLK(70);; //Tsre=1ClK+Trc
DynMem_Init(&config);
EMC_DynCtrlSDRAMInit(EMC_DYNAMIC_CTRL_SDRAM_NOP); /* Issue NOP command */
TIM_Waitms(100); /* wait 200ms */
EMC_DynCtrlSDRAMInit(EMC_DYNAMIC_CTRL_SDRAM_PALL); /* Issue Pre-charge command */
for(i = 0; i < 0x80; i++); /* wait 128 AHB clock cycles */
TIM_Waitms(100);
EMC_DynCtrlSDRAMInit(EMC_DYNAMIC_CTRL_SDRAM_MODE); /* Issue MODE command */
#ifdefSDRAMBIT16
dwtemp = *((volatile uint32_t *)(SDRAM_BASE_ADDR | (0x33<<(2+9+1))));
#else
dwtemp = *((volatile uint32_t *)(SDRAM_BASE_ADDR | (0x32<<(2+9+2))));/* Mode Register Setting: 4 burst, 3 CAS latency */
#endif size327948964 发表于 2014-2-10 11:33
有是有 但是我用的是库 直接寄存器操作的找不到了
下面使用了库 采用RBC配置方式 片子是hy57v2562
config. ...
恩,非常感谢。我试一下看。 shandian 发表于 2014-2-10 10:46
恩,好。不知道晓明兄这有没有现成的32bit的初始化代码。有的话可以让我参考一下吗? ...
看我以前分享的代码,在sdram.h中有个宏,改一下就可以16bit 32bit切换了 nongxiaoming 发表于 2014-2-10 14:24
看我以前分享的代码,在sdram.h中有个宏,改一下就可以16bit 32bit切换了
恩,好。谢谢! 本帖最后由 long_stay 于 2014-2-12 11:58 编辑
nongxiaoming 发表于 2014-2-10 14:24
看我以前分享的代码,在sdram.h中有个宏,改一下就可以16bit 32bit切换了
请问使用两个16BIT合并成32BIT通道的DRAM的时
将DYCS接在同样的位置上
在改写SDRAM的初始程序就可以了吗
因为手册上DYCS0只支援到的256Mbit的样子
==================================
我看错了他是写 dynamic memory
chip selects cover a range of 256 megabytes each
是mbQQ
所以修改SDRAM的初始程序为32BIT就可行了吗 nongxiaoming 发表于 2014-2-10 14:24
看我以前分享的代码,在sdram.h中有个宏,改一下就可以16bit 32bit切换了
我对比了一下你的初始化代码和我的代码,初始化方法都一样的。
于是我用官方库里面两片K4S561632E的例程,测试OK。就把例程的初始化函数拷进我的程序里,测试还是和原来一样,校验的时候在不固定的地址会出错。
最后实在没办法了,把我程序其他代码复制进官方的SDRAM工程里面了。现在每次测试都正常了。只是还清楚到底是什么原因引起的校验出错。我自己建立的那个工程,编译器的设置什么的我都检查过了,没发现问题。先不管了,继续弄下去算了。 shandian 发表于 2014-2-12 12:13
我对比了一下你的初始化代码和我的代码,初始化方法都一样的。
于是我用官方库里面两片K4S561632E的例程 ...
可能是你的时钟配置不一样,官方库好像是配的96Mhz主频,EMC跑主频的一半 可能你的硬件短接了
页:
[1]