本帖最后由 湛只为无双 于 2016-1-14 14:41 编辑
前段时间见有人讨论F469板子上SDRAM容量的大小问题,根据官方给出的DISCOVERY例程来看,里面的容量大小为8M字节,但是根据原理图推算出来的大小确实16M字节,然后就有了今天这个测试程序,通过实践来验证板载SDRAM大小以及主控可用容量大小。
一、SDRAM硬件电路
首先是要写出SDRAM的底层驱动程序,我个人比较倾向于使用标准库,感觉标准库用起来知道自己都对芯片做了啥,不像HAL库那样对底层不了解,并且觉得使用标准库更符合以前的编程习惯,编出来的代码效率要高一些,当然这个是没有理论依据的。
SDRAM原理图
在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并与原始测试序列逐个比较
|