STM32F429 官方Discovery SDRAM 配置问题

2019-07-20 16:45发布

本帖最后由 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! ");
        for(i=0;i<(32*1024*256);i+=16*1024)
        {
                *(vu32*)(Bank6_SDRAM_ADDR+i)=temp;
                temp++;
                printf("SDRAM内存测试写入数据temp=:%d ",temp);
        }
        printf("SDRAM test data wr done! ");
        
        
        
        
        
        //依次读出之前写入的数据,进行校验               
        printf("SDRAM test data rd start! ");

        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 ",temp);        
//                printf("SDRAM Capacity:%dKB ",(u16)(temp-sval+1)*16);//打印SDRAM容量
         }        
        printf("SDRAM test data rd done! ");
}        



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! ");
        
        printf("SDRAM Init Start! ");
        SDRAM_Init();                                //初始化SDRAM
        printf("SDRAM Init finish! ");
        

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

                for(ts=0;ts<100;ts++)
                {
                        printf("testsram[%d]:%d ",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
后边就没有然后了。。。



友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。