打印

STM32F7 同时挂载两片SDRAM时无法使用BANK6

[复制链接]
264|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
丑帅丑帅的|  楼主 | 2018-8-16 14:32 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
eric大大好,小弟目前有一个疑问,想请教您:

虽然我没有买过您的开发板(因为之前入门的时候用的是正点原子的。。),但是我觉得您很专注于技术的研讨,十分想和您请教,
我自己做了一个PCB,用的F767IGT6,176管脚,因为项目中需要大容量的SDRAM,因此,我设计挂载了两片SDRAM,管脚连接如下:

第一个 W9825G6DH 与 第二个 W9825G6DH 的  地址线A0-A12 ,BA0-BA1,数据线D0-D15 , 时钟 SDCLK, NBL0 NBL1 , SDNWE, SDNCAS, SDNRAS,  全部共用。
第一个 W9825G6DH 与 第二个 W9825G6DH 的 SDNE 与 SDCKE 分别独立连接 (第一个SDRAM 用 SDNE0 SDCKE0,第二个SDRAM 用 SDNE1 SDCKE1), NE0 和NE1 分别独立连接上拉电阻10K。

对应的,SDNE0 这个 SDRAM 地址是 #define Bank5_SDRAM_ADDR    ((u32)(0XC0000000))

              SDNE1 这个 SDRAM 地址是 #define Bank6_SDRAM_ADDR    ((u32)(0XD0000000))


一下是我的初始化过程:

void SDRAM_Init(void)
{
    u32 sdctrlreg=0,sdtimereg=0;
    u16 mregval=0;
   
    RCC->AHB3ENR|=1<<0;         //使能FMC时钟  
    RCC->AHB1ENR|=0X1F<<2;        //使能PC/PD/PE/PF/PG时钟  
   
    RCC->AHB1ENR|=1<<7;     //使能PORTH时钟
    GPIO_Set(GPIOH,PIN6|PIN7,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);  // 添加 SDNE1 和 SDCKE1管脚         
   
    GPIO_Set(GPIOC,PIN0|PIN2|PIN3,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);            //PC0/2/3            
    GPIO_Set(GPIOD,3<<0|7<<8|3<<14,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);        //PD0/1/8/9/10/14/15        
    GPIO_Set(GPIOE,3<<0|0X1FF<<7,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);            //PE0/1/7~15               
    GPIO_Set(GPIOF,0X3F<<0|0X1F<<11,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);        //PG0~5/11~15                    
    GPIO_Set(GPIOG,7<<0|3<<4|PIN8|PIN15,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);    //PF0~2/4/5/8/15               

   
    GPIO_AF_Set(GPIOH,6,12);   
     GPIO_AF_Set(GPIOH,7,12);    // 添加 SDNE1 和 SDCKE1管脚
   
   
     GPIO_AF_Set(GPIOC,0,12);    //PC0,AF12
     GPIO_AF_Set(GPIOC,2,12);    //PC2,AF12
     GPIO_AF_Set(GPIOC,3,12);    //PC3,AF12
   
     GPIO_AF_Set(GPIOD,0,12);    //PD0,AF12
     GPIO_AF_Set(GPIOD,1,12);    //PD1,AF12
     GPIO_AF_Set(GPIOD,8,12);    //PD8,AF12
     GPIO_AF_Set(GPIOD,9,12);    //PD9,AF12
     GPIO_AF_Set(GPIOD,10,12);    //PD10,AF12  
     GPIO_AF_Set(GPIOD,14,12);    //PD14,AF12
     GPIO_AF_Set(GPIOD,15,12);    //PD15,AF12
   
     GPIO_AF_Set(GPIOE,0,12);    //PE0,AF12
     GPIO_AF_Set(GPIOE,1,12);    //PE1,AF12
     GPIO_AF_Set(GPIOE,7,12);    //PE7,AF12
     GPIO_AF_Set(GPIOE,8,12);    //PE8,AF12
     GPIO_AF_Set(GPIOE,9,12);    //PE9,AF12
     GPIO_AF_Set(GPIOE,10,12);    //PE10,AF12
     GPIO_AF_Set(GPIOE,11,12);    //PE11,AF12
     GPIO_AF_Set(GPIOE,12,12);    //PE12,AF12
     GPIO_AF_Set(GPIOE,13,12);    //PE13,AF12
     GPIO_AF_Set(GPIOE,14,12);    //PE14,AF12
     GPIO_AF_Set(GPIOE,15,12);    //PE15,AF12

     GPIO_AF_Set(GPIOF,0,12);    //PF0,AF12
     GPIO_AF_Set(GPIOF,1,12);    //PF1,AF12
     GPIO_AF_Set(GPIOF,2,12);    //PF2,AF12
     GPIO_AF_Set(GPIOF,3,12);    //PF3,AF12
     GPIO_AF_Set(GPIOF,4,12);    //PF4,AF12
     GPIO_AF_Set(GPIOF,5,12);    //PF5,AF12
     GPIO_AF_Set(GPIOF,11,12);    //PF11,AF12
     GPIO_AF_Set(GPIOF,12,12);    //PF12,AF12
     GPIO_AF_Set(GPIOF,13,12);    //PF13,AF12
     GPIO_AF_Set(GPIOF,14,12);    //PF14,AF12
     GPIO_AF_Set(GPIOF,15,12);    //PF15,AF12
   
     GPIO_AF_Set(GPIOG,0,12);    //PG0,AF12
     GPIO_AF_Set(GPIOG,1,12);    //PG1,AF12
     GPIO_AF_Set(GPIOG,2,12);    //PG2,AF12
     GPIO_AF_Set(GPIOG,4,12);    //PG4,AF12
     GPIO_AF_Set(GPIOG,5,12);    //PG5,AF12  
     GPIO_AF_Set(GPIOG,8,12);    //PG8,AF12
     GPIO_AF_Set(GPIOG,15,12);    //PG15,AF12   
     
     sdctrlreg|=1<<0;                //9位列地址 1
    sdctrlreg|=2<<2;                //13位行地址 2
    sdctrlreg|=1<<4;                //16位数据位宽 1
    sdctrlreg|=1<<6;                //4个内部存区(4 BANKS) 1
    sdctrlreg|=3<<7;                //3个CAS延迟 3
    sdctrlreg|=0<<9;                //允许写访问 0
    sdctrlreg|=2<<10;                //SDRAM时钟=HCLK/2=216M/2=108M=9.3ns 2   -- 18.6ns
    sdctrlreg|=1<<12;                //使能突发访问  1
    sdctrlreg|=0<<13;                //读通道延迟0个HCLK 0
     FMC_Bank5_6->SDCR[0]=sdctrlreg;    //设置FMC BANK5 SDRAM控制寄存器(BANK5和6用于管理SDRAM).
    FMC_Bank5_6->SDCR[1]=sdctrlreg;    //设置FMC BANK5 SDRAM控制寄存器(BANK5和6用于管理SDRAM).

    sdtimereg|=5<<0;                //加载模式寄存器到激活时间的延迟为2个时钟周期 1
    sdtimereg|=12<<4;                //退出自刷新延迟为8个时钟周期  7  TXSR
    sdtimereg|=11<<8;                //自刷新时间为7个时钟周期  6   TRAS
    sdtimereg|=11<<12;                //行循环延迟为7个时钟周期 6  TRC
    sdtimereg|=6<<16;                //恢复延迟为2个时钟周期 1  TWR
    sdtimereg|=6<<20;                //行预充电延迟为2个时钟周期 1  TRP
    sdtimereg|=6<<24;                //行到列延迟为2个时钟周期 1  TRCD
     FMC_Bank5_6->SDTR[0]=sdtimereg;    //设置FMC BANK5 SDRAM时序寄存器   
    FMC_Bank5_6->SDTR[1]=sdtimereg;    //设置FMC BANK5 SDRAM时序寄存器

    SDRAM_Send_Cmd(0,1,0,0);        //时钟配置使能
    SDRAM_Send_Cmd(1,1,0,0);        //时钟配置使能
    delay_us(500);                    //至少延迟200us.
    SDRAM_Send_Cmd(0,2,0,0);        //对所有存储区预充电
    SDRAM_Send_Cmd(1,2,0,0);        //对所有存储区预充电
    SDRAM_Send_Cmd(0,3,8,0);        //设置自刷新次数
    SDRAM_Send_Cmd(1,3,8,0);        //设置自刷新次数
   
    mregval|=3<<0;                    //设置突发长度:8(可以是1/2/4/8)
    mregval|=0<<3;                    //设置突发类型:连续(可以是连续/交错)
    mregval|=3<<4;                    //设置CAS值:3(可以是2/3)
    mregval|=0<<7;                    //设置操作模式:0,标准模式
    mregval|=1<<9;                    //设置突发写模式:1,单点访问
    SDRAM_Send_Cmd(0,4,0,mregval);    //设置SDRAM的模式寄存器
    SDRAM_Send_Cmd(1,4,0,mregval);    //设置SDRAM的模式寄存器
   
    //刷新频率计数器(以SDCLK频率计数),计算方法:
    //COUNT=SDRAM刷新周期/行数-20=SDRAM刷新周期(us)*SDCLK频率(Mhz)/行数
    //我们使用的SDRAM刷新周期为64ms,SDCLK=216/2=108Mhz,行数为8192(2^13).
    //所以,COUNT=64*1000*108/8192-20=824
    FMC_Bank5_6->SDRTR=824<<1;        //设置刷新频率计数器
}


//向SDRAM发送命令
//bankx:0,向BANK5上面的SDRAM发送指令
//      1,向BANK6上面的SDRAM发送指令
//cmd:指令(0,正常模式/1,时钟配置使能/2,预充电所有存储区/3,自动刷新/4,加载模式寄存器/5,自刷新/6,掉电)
//refresh:自刷新次数(cmd=3时有效)
//regval:模式寄存器的定义
//返回值:0,正常;1,失败.
u8 SDRAM_Send_Cmd(u8 bankx,u8 cmd,u8 refresh,u16 regval)
{
    u32 retry=0;
    u32 tempreg=0;
    tempreg|=cmd<<0;            //设置指令
    tempreg|=1<<(4-bankx);        //设置发送指令到bank5还是6
    tempreg|=refresh<<5;        //设置自刷新次数
    tempreg|=regval<<9;            //设置模式寄存器的值
    FMC_Bank5_6->SDCMR=tempreg;    //配置寄存器
    while((FMC_Bank5_6->SDSR&(1<<5)))//等待指令发送完成
    {
        retry++;
        if(retry>0X1FFFFF)return 1;
    }
    return 0;   
}



上面的代码中,绿色部分是对 BANK5 SDRAM进行设置, 红色部分是对BANK6 SDRAM进行设置。

现在测试的结果如下:
1. PCB上焊接有两片SDRAM
2. 若代码中对 BANK5进行设置, 注释掉BANK6代码(保留绿色,注释掉红色)。 通过 FOR循环 对 *(vu8*)(Bank5_SDRAM_ADDR+i)  所有地址进行读写操作 均没问题,也挂载了RGB屏进行 测试。
3. 若代码中对 BANK5和BANK6进行设置(绿色和红色代码共存),通过 FOR循环 对 *(vu8*)(Bank5_SDRAM_ADDR+i) 测试没有问题,但是对 *(vu8*)(Bank6_SDRAM_ADDR+i) 测试 有问题,无法正常工作。
4. 若代码中对 BANK6进行设置, 注释掉BANK5代码(注释掉绿色,保留红色)。 *(vu8*)(Bank6_SDRAM_ADDR+i) 测试 有问题,无法正常工作。

请问ERIC大大,同时挂两片SDRAM,是不是有一些特殊地方的设置? 电路焊接基本排除了,芯片也是同一批次买的。

感谢您的指导!

使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

741

主题

742

帖子

0

粉丝