OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4846|回复: 3

STM32F429 官方Discovery SDRAM 配置问题

[复制链接]

3

主题

12

帖子

0

精华

初级会员

Rank: 2

积分
64
金钱
64
注册时间
2017-2-16
在线时间
16 小时
发表于 2017-2-16 14:11:46 | 显示全部楼层 |阅读模式
5金钱
本帖最后由 leejanus 于 2017-2-21 16:54 编辑

按照原子大神的寄存器版本学习。到SDRAM这里,徘徊几天无法通过。
用官方的discovery套件,SDRAM接的bank2,SDRAM型号是IS42S16400J。12行8列,芯片的总容量1Mbitx 16-bit x 4-bank = 67,108,864 bits = 64-Mbit 。硬件连接上不同的是用的是  SDNE1和SDCKE1。官方例程可以跑通,硬件上没什么问题。飞线连到bank1 的 CLKE0和CA0之后也可以跑通,说明时序配置上也没什么问题。但是就是bank2跑不通。

在原子大神寄存器SDRAM例程里面修改了GPIO 配置、SDRAM起始地址,SDRAM命令发送目标bank,时序配置。现在真不知道问题出在哪里了。还请大神指点一下,谢谢了!







sdram.c修改代码如下:


[mw_shl_code=c,true]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;        
}

//SDRAM初始化
void SDRAM_Init(void)
{
        u32 sdctrlreg=0,sdtimereg=0;
        u16 mregval=0;
        
        RCC->AHB3ENR|=1<<0;             //使能FMC时钟  
        RCC->AHB1ENR|=0X3F<<1;                //使能PB/PC/PD/PE/PF/PG时钟  
        
        GPIO_Set(GPIOB,PIN5|PIN6,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);                                //PB5/6
        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(GPIOB,5,12);        //PB5,AF12        SDCKE1
        GPIO_AF_Set(GPIOB,6,12);        //PB6,AF12        SDNE1/CS#
        
        GPIO_AF_Set(GPIOC,0,12);        //PC0,AF12
//        GPIO_AF_Set(GPIOC,2,12);        //PC2,AF12        CS#
//        GPIO_AF_Set(GPIOC,3,12);        //PC3,AF12   FMC_SDCKE0
        
         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        A12
         GPIO_AF_Set(GPIOG,4,12);        //PG4,AF12
         GPIO_AF_Set(GPIOG,5,12);        //PG5,AF12  
         GPIO_AF_Set(GPIOG,8,12);        //PG8,AF12        FMC_SDCKE
         GPIO_AF_Set(GPIOG,15,12);        //PG15,AF12        

         sdctrlreg|=0<<0;                                //8位列地址
        sdctrlreg|=1<<2;                                //12位行地址
        sdctrlreg|=1<<4;                                //16位数据位宽
        sdctrlreg|=1<<6;                                //4个内部存区(4 BANKS)
        sdctrlreg|=3<<7;                                //3个CAS延迟
        sdctrlreg|=0<<9;                                //允许写访问
        sdctrlreg|=2<<10;                                //SDRAM时钟=HCLK/2=192M/2=96M=10.4ns
        sdctrlreg|=1<<12;                                //使能突发访问
        sdctrlreg|=0<<13;                                //读通道延迟0个HCLK
         FMC_Bank5_6->SDCR[1]=sdctrlreg;        //设置FMC BANK5 SDRAM控制寄存器(BANK5和6用于管理SDRAM).

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

        SDRAM_Send_Cmd(1,1,0,0);                //时钟配置使能
        delay_us(500);                                        //至少延迟200us.
        SDRAM_Send_Cmd(1,2,0,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(1,4,0,mregval);        //设置SDRAM的模式寄存器
        
        //刷新频率计数器(以SDCLK频率计数),计算方法:
        //COUNT=SDRAM刷新周期/行数-20=SDRAM刷新周期(us)*SDCLK频率(Mhz)/行数
        //我们使用的SDRAM刷新周期为64ms,SDCLK=192/2=96Mhz,行数为8192(2^13).
        //所以,COUNT=64*1000*96/8192-20=730
        FMC_Bank5_6->SDRTR=1386<<1;                //设置刷新频率计数器
}  [/mw_shl_code]






MAIN.C
[mw_shl_code=applescript,true]u16 testsram[100] __attribute__((at(0XD0000000)));//测试用数组

//SDRAM内存测试            
void fmc_sdram_test(u16 x,u16 y)
{  
        u32 i=0;            
        u32 temp=0;           
        u32 sval=0;        //在地址0读到的数据                                             
        
        
        
        //每隔16K字节,写入一个数据,总共写入2048个数据,刚好是32M字节
        printf("SDRAM test data wr start!\r\n");
        for(i=0;i<(32*1024*256);i+=16*1024)
        {
                *(vu32*)(Bank6_SDRAM_ADDR+i)=temp;
                temp++;
                printf("SDRAM内存测试写入数据temp=:%d\r\n",temp);
        }
        printf("SDRAM test data wr done!\r\n");
        
        
        
        
        
        //依次读出之前写入的数据,进行校验               
        printf("SDRAM test data rd start!\r\n");

        for(i=0;i<(32*1024*256);i+=16*1024)
        {        
                  temp=*(vu32*)(Bank6_SDRAM_ADDR+i);
//                if(i==0)sval=temp;
//                 else if(temp<=sval)break;//后面读出的数据一定要比第一次读到的数据大.                 
                printf("SDRAM内存测试读取数据temp=:%d\r\n",temp);        
//                printf("SDRAM Capacity:%dKB\r\n",(u16)(temp-sval+1)*16);//打印SDRAM容量
         }        
        printf("SDRAM test data rd done!\r\n");
}        



int main(void)
{
        u8 keysta;                 
         u8 i=0;            
        u32 ts=0;


        Stm32_Clock_Init(360,8,2,8);           //设置时钟AHB=180M,APB1=45M,APB1_TIM=90M,APB2=90M,APB2_TIM=180M
        delay_init(180);                                //初始化延时函数
//        LED_Init();                                                //initial LED clk
        uart_init(90,115200);
        KEY_Init();
        printf("System Reset!\r\n");
        
        printf("SDRAM Init Start!\r\n");
        SDRAM_Init();                                //初始化SDRAM
        printf("SDRAM Init finish!\r\n");
        

        printf("预存测试数据start!\r\n");
        for(ts=0;ts<100;ts++)
        {
                testsram[ts]=ts;//预存测试数据         
          }
        printf("预存测试数据done!\r\n");
        
        
        while(1)
        {        
               
                printf("fmc_sdram_test start!\r\n");
                fmc_sdram_test(40,170);//测试SDRAM容量
                printf("fmc_sdram_test done!\r\n");
               
               
                //打印预存测试数据

                for(ts=0;ts<100;ts++)
                {
                        printf("testsram[%d]:%d\r\n",ts,testsram[ts]);
                }
                delay_ms(10);   
                i++;
                if(i==20)//DS0闪烁.
                {
                        i=0;
                        LED_G=!LED_G;
                 }
        }
        

}[/mw_shl_code]



System Reset!
SDRAM Init Start!
SDRAM Init finish!
预存测试数据start!
预存测试数据ts=:0
预存测试数据ts=:1
预存测试数据ts=:2
预存测试数据ts=:3
预存测试数据ts=:4
预存测试数据ts=:5
预存测试数据ts=:6
预存测试数据ts=:7
预存测试数据ts=:8
预存测试数据ts=:9
预存测试数据ts=:10
预存测试数据ts=:11
预存测试数据ts=:12
预存测试数据ts=:13
预存测试数据ts=:14
预存测试数据ts=:15
后边就没有然后了。。。



最佳答案

查看完整内容[请看2#楼]

经过一个一个寄存器排查,自己找到了答案。我在这个问题上浪费了好几天的时间,现在把他贴出来,希望可以帮到有共同问题的同学! SDCR寄存器中CLK配置,在FMC_SDCR2中配置是不生效的!必须到FMC_SDCR1中去配置才行! 位 11:10 SDCLK:SDRAM 时钟配置 (SDRAM clock configuration) 这些位用于定义两个 SDRAM 存储区域的 SDRAM 时钟周期以及在更改频率前禁止时钟。此时,必 须重新初始化 SDRAM。 00:禁止 SDCLK 时钟 01: ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

12

帖子

0

精华

初级会员

Rank: 2

积分
64
金钱
64
注册时间
2017-2-16
在线时间
16 小时
 楼主| 发表于 2017-2-16 14:11:47 | 显示全部楼层

SDRAM bank2 配置问题!

本帖最后由 leejanus 于 2017-2-22 15:21 编辑

经过一个一个寄存器排查,自己找到了答案。我在这个问题上浪费了好几天的时间,现在把他贴出来,希望可以帮到有共同问题的同学!

SDCR寄存器中CLK配置,在FMC_SDCR2中配置是不生效的!必须到FMC_SDCR1中去配置才行!

位 11:10 SDCLK:SDRAM 时钟配置 (SDRAM clock configuration)
这些位用于定义两个 SDRAM 存储区域的 SDRAM 时钟周期以及在更改频率前禁止时钟。此时,必
须重新初始化 SDRAM。
00:禁止 SDCLK 时钟
01:保留
10:SDCLK 周期 = 2 x HCLK 周期
11:SDCLK 周期 = 3 x HCLK 周期
注意: FMC_SDCR2 寄存器中的相应位为无关位。
回复

使用道具 举报

3

主题

12

帖子

0

精华

初级会员

Rank: 2

积分
64
金钱
64
注册时间
2017-2-16
在线时间
16 小时
 楼主| 发表于 2017-2-16 15:52:24 | 显示全部楼层
希望路过的大神提点一下,谢谢了。
回复

使用道具 举报

3

主题

12

帖子

0

精华

初级会员

Rank: 2

积分
64
金钱
64
注册时间
2017-2-16
在线时间
16 小时
 楼主| 发表于 2017-2-17 09:16:47 | 显示全部楼层
飞线把   SDNE1和SDCKE1跳到  DNE0和SDCKE0上,用bank5可以跑通,数据都是对的。

所以现在可以定位bank5到bank6的修改上有些问题。

有哪位对这块了解的还请赐教,谢谢!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-20 05:31

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表