STM32F429-DISCO SDRAM学习和速度测试

/ 9评 / 2

有了F4这个开发板之后,又看到了F7和F429两种,虽然他们都已经被很多人下了枪毙判决书,但用户就是那个多啊!偶然撸到一个F429的板子,二手板子啊,便宜,先测试一下SDRAM速度.
当然,也是在学习SDRAM的使用.其中SDRAM实验.板子上使用速度等级是-7的片子.不算特别快.要看ELECTRICAL CHARACTERISTICS 就能查看配置参数了.看官方配置,再对照就不难了.

/* FMC Configuration ---------------------------------------------------------*/
/* FMC SDRAM Bank configuration */
  /* Timing configuration for 90 Mhz of SD clock frequency (180Mhz/2) */ /* 1 5 1 4 1 1 1 */
  /* 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;

他已经标明了,这是TMRD,TXSR等等.按照配置就可以做的.首先是TMRD.
QQ截图20151112202036
然后其他参数都是如此,直接填写进去,就可以了,因为是90MHz,所以是11.11ns周期,所以按照比例乘一下.手册地址可以从这里查:http://www.issi.com/WW/pdf/42-45S16400J.pdf
初始化分为初始化IO,时序,以及指令初始化,指令初始化相对不是特别难.官方测试例程里面已经有介绍.所有的SDRAM都是这样的.

void SDRAM_InitSequence(void)
{
  FMC_SDRAMCommandTypeDef FMC_SDRAMCommandStructure;
  uint32_t tmpr = 0;
/* Step 3 --------------------------------------------------------------------*/
  /* Configure a clock configuration enable command */
  FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_CLK_Enabled;
  FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank2;
  FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1;
  FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
  /* Wait until the SDRAM controller is ready */
  while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET)
  {
  }
  /* Send the command */
  FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
/* Step 4 --------------------------------------------------------------------*/
  /* Insert 100 ms delay */
  __Delay(10);
/* Step 5 --------------------------------------------------------------------*/
  /* Configure a PALL (precharge all) command */
  FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_PALL;
  FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank2;
  FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1;
  FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
  /* Wait until the SDRAM controller is ready */
  while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET)
  {
  }
  /* Send the command */
  FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
/* Step 6 --------------------------------------------------------------------*/
  /* Configure a Auto-Refresh command */
  FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_AutoRefresh;
  FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank2;
  FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 4;
  FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
  /* Wait until the SDRAM controller is ready */
  while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET)
  {
  }
  /* Send the  first command */
  FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
  /* Wait until the SDRAM controller is ready */
  while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET)
  {
  }
  /* Send the second command */
  FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
/* Step 7 --------------------------------------------------------------------*/
  /* Program the external memory mode register */
  tmpr = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_2          |
                   SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL   |
                   SDRAM_MODEREG_CAS_LATENCY_3           |
                   SDRAM_MODEREG_OPERATING_MODE_STANDARD |
                   SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
  /* Configure a load Mode register command*/
  FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_LoadMode;
  FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank2;
  FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1;
  FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = tmpr;
  /* Wait until the SDRAM controller is ready */
  while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET)
  {
  }
  /* Send the command */
  FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
/* Step 8 --------------------------------------------------------------------*/
  /* Set the refresh rate counter */
  /* (15.62 us x Freq) - 20 */
  /* Set the device refresh counter */
  FMC_SetRefreshCount(1386);
  /* Wait until the SDRAM controller is ready */
  while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET)
  {
  }
}

然后可以当普通RAM一样使用,因为是16B的RAM,所以访问16B的时候效率会高一些,但是程序一般优化得很好地前提下,不会有太大的差别,我们可以测试一下速度,就用测试的例子.先用STM_EVAL_LEDInit初始化LED3,然后让他置低,然后高低翻转测试速度,估算出值,因为数值读取不只是一个寄存器,所以速度可能会慢一些.但更接近实际情况.首先是上升沿到下降沿,是擦除.

  for (counter = 0x00; counter < IS42S16400J_SIZE; counter++)
  {
    *(__IO uint8_t*) (SDRAM_BANK_ADDR + counter) = (uint8_t)0x0;
  }

这段时间0.1631s,大约速度是49.05MByte/s,而等待上升沿是普通写入,花了相同的时间,速度自然也差不多.但是读取就慢了,花了0.4693s,这也是因为读取再存到变量里面导致的,折合速度只有17.05MByte/s,再来一次上升沿可以抵消这个时间,写入内部SRAM大约还有90ms,微不足道.内部SRAM速度是88.68MByte/s呢.

/* Turn Off Leds */
STM_EVAL_LEDOn(LED3);
/* Erase SDRAM memory */
for (counter = 0x00; counter < IS42S16400J_SIZE; counter++)
{
    *(__IO uint8_t *) (SDRAM_BANK_ADDR + counter) = (uint8_t)0x0;
}
STM_EVAL_LEDOff(LED3);
/* Write data value to all SDRAM memory */
for (counter = 0; counter < IS42S16400J_SIZE; counter++)
{
    *(__IO uint8_t *) (SDRAM_BANK_ADDR + counter) = (uint8_t)(ubWritedata_8b + counter);
}
STM_EVAL_LEDOn(LED3);
/* Write data value to all SDRAM memory */
for (counter = 0; counter < IS42S16400J_SIZE; counter++)
{
    ubReaddata_8b = *(__IO uint8_t *)(SDRAM_BANK_ADDR + counter);
}
STM_EVAL_LEDOff(LED3);
/* Write data value to all SDRAM memory */
for (counter = 0; counter < IS42S16400J_SIZE; counter++)
{
    ubReaddata_8b = 0x00;
}
STM_EVAL_LEDOn(LED3);
while(1);

测试程序如上面,以及产生的时序图在下面:QQ截图20151112202036只要把uint8_t改成uint16_t,就是16位方式访问了.测试16B下,差别不会特别大.当然,在有LCD时候,带宽可能会降低一些.这一点是我对ST比较不满的地方,好像NXP就不会怎么降带宽.我们可以直接用官方例程测试,带LCD的情况.

  LCD_Init();
  LCD_LayerInit();
  LTDC_Cmd(ENABLE);
  LCD_SetLayer(LCD_FOREGROUND_LAYER);
  LCD_Clear(LCD_COLOR_WHITE);
  LCD_SetTransparency(200);
  LTDC_ReloadConfig(LTDC_IMReload);

发现0.2161s完成清空,后面的时序,也是按1.3倍左右变慢,就是速度可能只有37MByte/s了,足足占了12MByte的带宽呢.F4最大的特色就是支持SDRAM和LCD了,当然,这么大的RAM,或许可以干点别的东西.但是觉得LCD和SDRAM都占这么多IO,信心不足啊.

  1. 梁家伟说道:

    您好:
    我最近在做用ADC采样做FFT的工程,但是由于采样数据比较大,所以存储空间不足,想用SRAM来做,我的ADC采样率是1.11M,两路同时采,我感觉SRAM实时存储好像不太够?另外能不能把您的工程发我一份做参考?我找了好久没找到一个合适的工程。
    谢谢!

  2. 欧林华说道:

    测试程序如上面,以及产生的时序图在下面–

    这个时序图是外接的逻辑分析仪产生的吗?还是别的工具?

  3. loyal说道:

    图片显示看不清啊。单独打开才行。

  4. loyal说道:

    怎么才能搞个这样的博客?CSDN广告太多了。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注