打印
[STM32F4]

【STM32F469I试用】+SDRAM的容量测试程序

[复制链接]
2412|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 湛只为无双 于 2016-1-14 14:41 编辑

前段时间见有人讨论F469板子上SDRAM容量的大小问题,根据官方给出的DISCOVERY例程来看,里面的容量大小为8M字节,但是根据原理图推算出来的大小确实16M字节,然后就有了今天这个测试程序,通过实践来验证板载SDRAM大小以及主控可用容量大小。

一、SDRAM硬件电路
首先是要写出SDRAM的底层驱动程序,我个人比较倾向于使用标准库,感觉标准库用起来知道自己都对芯片做了啥,不像HAL库那样对底层不了解,并且觉得使用标准库更符合以前的编程习惯,编出来的代码效率要高一些,当然这个是没有理论依据的。

在SDRAM的原理图里面需要注意的是写入使能引脚为PC0,我参考开发板以前的资料中SDRAM写入使能引脚就不是PC0。除了这个地方需要注意外,SDRAM使用的数据线为32位,提高了总线带宽,这个在大容量数据交互中显得十分重要。
二、SDRAM软件底层设计及其宏定义
根据以上原理图编写初始化程序,如下:
void SDRAM_Init(void)
{
        FMC_SDRAMInitTypeDef  FMC_SDRAMInitStructure;
        FMC_SDRAMTimingInitTypeDef  FMC_SDRAMTimingInitStructure;

        /* GPIO configuration for FMC SDRAM bank */
        SDRAM_GPIOConfig();

        /* Enable FMC clock */
        RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FMC, ENABLE);

        /* FMC Configuration ---------------------------------------------------------*/
        /* FMC SDRAM Bank configuration */
        /* Timing configuration for 90 Mhz of SD clock frequency (180Mhz/2) */
        /* TMRD: 2 Clock cycles */
        FMC_SDRAMTimingInitStructure.FMC_LoadToActiveDelay    = 2;
        /* TXSR: min=70ns (7x11.11ns) */
        FMC_SDRAMTimingInitStructure.FMC_ExitSelfRefreshDelay = 7;
        /* TRAS: min=42ns (4x11.11ns) max=120k (ns) */
        FMC_SDRAMTimingInitStructure.FMC_SelfRefreshTime      = 4;
        /* TRC:  min=70 (7x11.11ns) */
        FMC_SDRAMTimingInitStructure.FMC_RowCycleDelay        = 7;
        /* TWR:  min=1+ 7ns (1+1x11.11ns) */
        FMC_SDRAMTimingInitStructure.FMC_WriteRecoveryTime    = 2;
        /* TRP:  20ns => 2x11.11ns */
        FMC_SDRAMTimingInitStructure.FMC_RPDelay              = 2;
        /* TRCD: 20ns => 2x11.11ns */
        FMC_SDRAMTimingInitStructure.FMC_RCDDelay             = 2;

        /* FMC SDRAM control configuration */
        FMC_SDRAMInitStructure.FMC_Bank               = FMC_Bank1_SDRAM;
        /* Row addressing: [7:0] */
        FMC_SDRAMInitStructure.FMC_ColumnBitsNumber   = FMC_ColumnBits_Number_8b;
        /* Column addressing: [11:0] */
        FMC_SDRAMInitStructure.FMC_RowBitsNumber      = FMC_RowBits_Number_12b;
        FMC_SDRAMInitStructure.FMC_SDMemoryDataWidth  = SDRAM_MEMORY_WIDTH;
        FMC_SDRAMInitStructure.FMC_InternalBankNumber = FMC_InternalBank_Number_4;
        /* CL: Cas Latency = 3 clock cycles */
        FMC_SDRAMInitStructure.FMC_CASLatency         = FMC_CAS_Latency_3;
        FMC_SDRAMInitStructure.FMC_WriteProtection    = FMC_Write_Protection_Disable;
        FMC_SDRAMInitStructure.FMC_SDClockPeriod      = SDCLOCK_PERIOD;
        FMC_SDRAMInitStructure.FMC_ReadBurst          = FMC_Read_Burst_Enable;
        FMC_SDRAMInitStructure.FMC_ReadPipeDelay      = FMC_ReadPipe_Delay_0;
        FMC_SDRAMInitStructure.FMC_SDRAMTimingStruct  = &FMC_SDRAMTimingInitStructure;

        /* FMC SDRAM bank initialization */
        FMC_SDRAMInit(&FMC_SDRAMInitStructure);

        /* FMC SDRAM device initialization sequence */
        SDRAM_InitSequence();

}
在这个初始化程序里面,比较中的部分由行列地址的说明和总线宽度:
 /* Row addressing: [7:0] */
        FMC_SDRAMInitStructure.FMC_ColumnBitsNumber   = FMC_ColumnBits_Number_8b;
        /* Column addressing: [11:0] */
        FMC_SDRAMInitStructure.FMC_RowBitsNumber      = FMC_RowBits_Number_12b;
        FMC_SDRAMInitStructure.FMC_SDMemoryDataWidth  = SDRAM_MEMORY_WIDTH;


其中总线宽度的宏定义为:
/**
  * [url=home.php?mod=space&uid=247401]@brief[/url]  FMC SDRAM Memory Width
  */
#define SDRAM_MEMORY_WIDTH    FMC_SDMemory_Width_32b


这样就完成了主要参数的初始化,当然里面还包括了GPIO初始换和SDRAM矩阵的初始化,具体的参考楼下给出的源代码,可以自行下载编译查看现象。
根据以上设置参数就可以得到SDRAM内存映射到芯片内部的地址和存储空间大小,如下:
/**
  * [url=home.php?mod=space&uid=247401]@brief[/url]  FMC SDRAM Bank address
  */
#define SDRAM_BANK_ADDR     ((uint32_t)0xC0000000)

/**
  * [url=home.php?mod=space&uid=247401]@brief[/url]  FMC SDRAM Device size
  */
#define SDRAM_DEVICE_SIZE  ((uint32_t)0x1000000)
三、基于大容量SDRAM的测试程序开发
针对以上软件和硬件设计可以知道,SDRAM的起始地址为0xc0000000,大小为0x1000000(16M字节),那么我们可以采取对SDRAM写入数据,然后读取数据并与原始数据比较的方式,来验证SDRAM的大小。
本设计使用了STM32F469内部集成的随机数发生器,来产生10000个4字节的随机数,并将随机数循环写入SDRAM,然后读取SDRAM并与原始随机数比较,来验证写入与读取的数据是否相同,从而达到验证SDRAM容量大小的目的。
①定义随机数存储数组,并生成随机数
u32 RadomBuffer[10000];

RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG,ENABLE);
RNG_Cmd(ENABLE);

for(count=0;count<10000;count++)
{
        while(RNG_GetFlagStatus(RNG_FLAG_DRDY) == RESET);
        RadomBuffer[count]=RNG->DR;
}
通过等待随机数生成,然后依次赋值于随机数存储数组RadomBuffer方式,完成测试数组序列。


②将测试序列依次写入SDRAM
pSDRAM=(u32*)SDRAM_BANK_ADDR;
count=0;

for(sdram_count=0;sdram_count<SDRAM_SIZE;sdram_count++)
{
        *pSDRAM=RadomBuffer[count];
        count++;
        pSDRAM++;
        if(count>=10000)
        {
                count=0;
        }
}
在设计中使用指向SDRAM起始地址指针的方式,向SDRAM依次写入数据,由于写入的数据为4字节,而SDRAM总字数为SDRAM_DEVICE_SIZE,故测试用的SDRAM_SIZE大小为SDRAM_DEVICE_SIZE/4。

③读取SDRAM并与原始测试序列逐个比较
pSDRAM=(u32*)SDRAM_BANK_ADDR;
sdram_count=0;
for(;sdram_count<SDRAM_SIZE;sdram_count++)
{
        if(*pSDRAM != RadomBuffer[count])
        {
                break;
        }
        count++;
        pSDRAM++;
        if(count>=10000)
        {
                count=0;
        }
}
在与原始序列逐个比较的过程中,如果出现数据与原始测试序列不符的情况,马上停止比较,说明SDRAM容量大小不对。


④根据测试结果点亮LED灯
为了能够看到测试比较的结果,通过程序设置点亮不同的LED灯来说明最后测试结果,程序设计如下:
if(sdram_count == SDRAM_SIZE)
{
        LED1=0;
}
else
{
        LED2=0;
}


四、主文件总体设计
为了能够看到程序的运行过程,以及知道程序的在运行中的具体情况,引入串口向电脑发送数据的方式来增强对程序的了解。
故主文件程序设计如下:
#include "stm32f4xx.h"
#include "LED.h"
#include "USART3.h"
#include "delay.h"
#include "DISCO_SDRAM.h"

u32 RadomBuffer[10000];
u32 ReadBuffer[10000];
#define SDRAM_SIZE (SDRAM_DEVICE_SIZE/4)
u32 *pSDRAM;
long long count=0,sdram_count=0;
int main(void)
{
        LED_Init();
        USART3_Init(115200);
        SDRAM_Init();
        
        RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG,ENABLE);
        RNG_Cmd(ENABLE);
        u3_printf("*******************************\r\n");
        u3_printf("中国电子网技术论坛_bbs.21ic.com\r\n");
        u3_printf("*********SDRAM测试程序**********\r\n");
        u3_printf("*******************************\r\n");
        u3_printf("开始生成10000个SDRAM测试随机数\r\n");
        for(count=0;count<10000;count++)
        {
                while(RNG_GetFlagStatus(RNG_FLAG_DRDY) == RESET);
                RadomBuffer[count]=RNG->DR;
        }
        u3_printf("10000个SDRAM测试随机数生成完毕\r\n");
        
        pSDRAM=(u32*)SDRAM_BANK_ADDR;
        count=0;
        u3_printf("开始写入SDRAM\r\n");
        for(sdram_count=0;sdram_count<SDRAM_SIZE;sdram_count++)
        {
                *pSDRAM=RadomBuffer[count];
                count++;
                pSDRAM++;
                if(count>=10000)
                {
                        count=0;
                }
        }
        u3_printf("写入总字节数:%d\r\n",(u32)pSDRAM-SDRAM_BANK_ADDR);
        
        count=0;
        pSDRAM=(u32*)SDRAM_BANK_ADDR;
        u3_printf("开始读取SDRAM并与原随机数比较\r\n");
        sdram_count=0;
        for(;sdram_count<SDRAM_SIZE;sdram_count++)
        {
                if(*pSDRAM != RadomBuffer[count])
                {
                        u3_printf("数据比较错误——退出~\r\n");
                        break;
                }
                count++;
                pSDRAM++;
                if(count>=10000)
                {
                        count=0;
                }
        }
        u3_printf("比较通过总字节数:%d\r\n",(u32)pSDRAM-SDRAM_BANK_ADDR);
        
        if(sdram_count == SDRAM_SIZE)
        {
                LED1=0;
                u3_printf("SDRAM测试成功\r\n");
        }
        else
        {
                LED2=0;
                u3_printf("SDRAM测试失败\r\n");
        }
        u3_printf("中国电子网技术论坛_bbs.21ic.com\r\n");
        while(1)
        {
                LED3^=1;
               
                delay_ms(500);
        }
}

通过开启串口调试助手,可以很清晰看到程序的运行过程和运行结果。

五、测试结果
将以上程序设计编译后下载至DISCOVERY板,打开串口调试助手查看运行结果,得到如下所示的结果。

通过板子的实际运行情况可以看到,LED1被点亮,证明程序测试通过,容量大小测试通过。

同样的,根据串口接收到的数据表明,SDRAM测试通过,测试通过的字节数为16777216,换算成以M为单位,大小为16M字节。
由以上可知,DISCOVERY板上板载SDRAM容量大小16M,芯片可访问大小也为16M。
最后,祝大家平安夜平安,圣诞节快乐。





沙发
湛只为无双|  楼主 | 2015-12-24 21:12 | 只看该作者
本帖最后由 湛只为无双 于 2015-12-24 21:57 编辑

这一层楼用于放置测试用工程,基于keil5.15的IDE开发平台。 STM32F469_SDRAM_Test.zip (686.11 KB)

使用特权

评论回复
板凳
湛只为无双|  楼主 | 2015-12-24 21:13 | 只看该作者
占楼 等待编辑 编辑。。。。。。。

使用特权

评论回复
地板
天灵灵地灵灵| | 2015-12-24 22:48 | 只看该作者
DISCOVERY板上板载SDRAM容量大小16M,芯片可访问大小也为16M.
可以存好多内容啊。

使用特权

评论回复
5
zhangbin_abc| | 2015-12-24 23:58 | 只看该作者
楼主,你好,请你有空试一下PC6和PC7所在的USART6串口打印测试,我测试时程序一直停在发送完成标志的循环检测上,不知道啥问题,向你请教一下,谢谢。

使用特权

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

本版积分规则

15

主题

171

帖子

9

粉丝