F429 FMC SDRAM 数据写入惊现诡异现象 , 困扰多日,求原子大神及路过大神援助!

2019-07-20 16:28发布



在SDRAM里面定义的数组写入数据的时候,
0xD0000000总是与0xD00000008联动
0xD0000002总是与0xD0000000A联动
。。。。。以此类推。
写入0xD0000000的时候,0xD00000008也会同步写入。等写到0xD00000008的时候,0xD0000000也会发生改变。不论定义的数据类型是字、字节或者是双字,非常奇怪!


在调试窗口下,可以看到数据改变:
如果定义的是U16的数组,则数据如下:
0xD0000000  :  04  00
0xD0000002  :  05  00
0xD0000004  :  06  00
0xD0000006  :  07  00
0xD0000008  :  04  00
0xD000000A  :  05  00
0xD000000C  :  06  00
0xD000000E  :  07  00
0xD0000010  :  0C  00
。。。。。


如果定义的是U32的数组,则数据如下:
0xD0000000  :  02  00  00  00
0xD0000004  :  03  00  00  00
0xD0000008  :  02  00  00  00
0xD000000C  :  03  00  00  00
0xD0000010  :  06  00  00  00
。。。。。





本人用的SDRAM型号是IS42S16400J,接的bank2。
硬件上是没有问题的,因为用ST官方的库函数版本同样的方式定义数组,读写数组,都OK。
时序配置上也是没有问题的,用单步调试模式,查看过SDRAM所有的寄存器配置,SDCR1/2、SDTR1/2、SDCMR(初始化过程中5次命令都已对比无异常)、SDRTR。这些寄存器都与官方库函数在程序运行时仔细对比过,已改为全部一致!
降低工作频率也于事无补!
另外试过把SDRAM的CKE1/NE1跳线到 CKE0/NE0上,用原子大神的寄存器源程序(稍作时序修改)也是有同样的问题!
实在找不到问题的原因,非常诡异!还求原子大神与路过的大神指点!!


SDRAM.C


[mw_shl_code=applescript,true]#include "sdram.h"
#include "delay.h"
#include "usart.h"




//向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;       
}

//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       
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,0X3B<<0|0X1F<<11,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);        //PG0/1/3/4/5/11~15       
GPIO_Set(GPIOG,3<<0|3<<4|PIN8|PIN15,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);        //PF0~1/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);        //PC0,AF12 SDNE0
//        GPIO_AF_Set(GPIOC,3,12);        //PC0,AF12        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,4,12);        //PG4,AF12
GPIO_AF_Set(GPIOG,5,12);        //PG5,AF12
GPIO_AF_Set(GPIOG,8,12);        //PG8,AF12        FMC_SDCLK
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|=1<<13;        //读通道延迟0个HCLK
//        FMC_Bank5_6->SDCR[0]=sdctrlreg;        //设置FMC BANK5 SDRAM控制寄存器(BANK5和6用于管理SDRAM).在FMC_SDCR2中配置是不生效的!必须到FMC_SDCR1中去配置才行!
//        FMC_Bank5_6->SDCR[1]=sdctrlreg;        //设置FMC BANK5 SDRAM控制寄存器(BANK5和6用于管理SDRAM).
FMC_Bank5_6->SDCR[0]=0x00002800;
FMC_Bank5_6->SDCR[1]=0x000001D4;

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


SDRAM_Send_Cmd(1,1,0,0);        //时钟配置使能
delay_us(200);        //至少延迟100us.
SDRAM_Send_Cmd(1,2,0,0);        //对所有存储区预充电
SDRAM_Send_Cmd(1,3,3,0);        //设置自刷新次数 第一次
SDRAM_Send_Cmd(1,3,3,0);        //设置自刷新次数 第二次
mregval|=1<<0;        //设置突发长度:2(可以是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的模式寄存器

FMC_Bank5_6->SDRTR=1386<<1;        //设置刷新频率计数器
//        FMC_Bank5_6->SDRTR=0x00000AD4;

}
[/mw_shl_code]



MAIN.C

[mw_shl_code=applescript,true]u32 testsram[100] __attribute__((at(0XD0000000)));

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

Stm32_Clock_Init(360,8,2,8); //设置时钟AHB=180M,APB1=45M,APB1_TIM=90M,APB2=90M,APB2_TIM=180M
delay_init(180);       
SDRAM_Init();       
for(ts=0;ts<100;ts++)
{
testsram[ts]=ts;
}

while(1)
{}

}[/mw_shl_code]





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