shandian 发表于 2014-2-9 23:38:14

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

enovo2468 发表于 2014-2-10 08:15:42

120MHz可以用的,是不是电源有问题?退偶不好

size327948964 发表于 2014-2-10 09:07:11

两个参数不对
第一个 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

nongxiaoming 发表于 2014-2-10 09:23:16

如楼上所说,32bit和16bit配置是有区别的,不是简单的配置引脚配置容量大小。

shandian 发表于 2014-2-10 10:44:14

size327948964 发表于 2014-2-10 09:07
两个参数不对
第一个 SDRAM的配置地方,16位 32位宽度不一样
第二个地方 16位 32位虚拟写也不一样


关于第一点,我在配置LPC_EMC->DynamicConfig0的时候不一样的,在使用16位的时候和32位的时候这个配置不一样的。

第二点我再好好研究下吧,说实话SDRAM的时序太麻烦了,很多时间参数什么的代表什么意思,以及LPC1788 SDRAM控制器很多寄存器的作用等等我都没怎么仔细去看。我再好好研究下手册看。

shandian 发表于 2014-2-10 10:46:36

nongxiaoming 发表于 2014-2-10 09:23
如楼上所说,32bit和16bit配置是有区别的,不是简单的配置引脚配置容量大小。 ...

恩,好。不知道晓明兄这有没有现成的32bit的初始化代码。有的话可以让我参考一下吗?

size327948964 发表于 2014-2-10 11:33:28

有是有 但是我用的是库 直接寄存器操作的找不到了
下面使用了库 采用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

shandian 发表于 2014-2-10 12:17:22

size327948964 发表于 2014-2-10 11:33
有是有 但是我用的是库 直接寄存器操作的找不到了
下面使用了库 采用RBC配置方式 片子是hy57v2562
config. ...

恩,非常感谢。我试一下看。

nongxiaoming 发表于 2014-2-10 14:24:32

shandian 发表于 2014-2-10 10:46
恩,好。不知道晓明兄这有没有现成的32bit的初始化代码。有的话可以让我参考一下吗? ...

看我以前分享的代码,在sdram.h中有个宏,改一下就可以16bit 32bit切换了

shandian 发表于 2014-2-10 15:44:47

nongxiaoming 发表于 2014-2-10 14:24
看我以前分享的代码,在sdram.h中有个宏,改一下就可以16bit 32bit切换了

恩,好。谢谢!

long_stay 发表于 2014-2-12 11:49:48

本帖最后由 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就可行了吗

shandian 发表于 2014-2-12 12:13:50

nongxiaoming 发表于 2014-2-10 14:24
看我以前分享的代码,在sdram.h中有个宏,改一下就可以16bit 32bit切换了

我对比了一下你的初始化代码和我的代码,初始化方法都一样的。
于是我用官方库里面两片K4S561632E的例程,测试OK。就把例程的初始化函数拷进我的程序里,测试还是和原来一样,校验的时候在不固定的地址会出错。
最后实在没办法了,把我程序其他代码复制进官方的SDRAM工程里面了。现在每次测试都正常了。只是还清楚到底是什么原因引起的校验出错。我自己建立的那个工程,编译器的设置什么的我都检查过了,没发现问题。先不管了,继续弄下去算了。

nongxiaoming 发表于 2014-2-12 13:55:25

shandian 发表于 2014-2-12 12:13
我对比了一下你的初始化代码和我的代码,初始化方法都一样的。
于是我用官方库里面两片K4S561632E的例程 ...

可能是你的时钟配置不一样,官方库好像是配的96Mhz主频,EMC跑主频的一半

爺@龙行天下 发表于 2014-4-15 09:12:21

可能你的硬件短接了
页: [1]
查看完整版本: LPC1788外扩两片SDRAM,测试通不过,会是什么原因导致的?