本帖最后由 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
后边就没有然后了。。。
所以现在可以定位bank5到bank6的修改上有些问题。
有哪位对这块了解的还请赐教,谢谢!
一周热门 更多>