有了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.
然后其他参数都是如此,直接填写进去,就可以了,因为是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);
测试程序如上面,以及产生的时序图在下面:只要把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,信心不足啊.
您好:
我最近在做用ADC采样做FFT的工程,但是由于采样数据比较大,所以存储空间不足,想用SRAM来做,我的ADC采样率是1.11M,两路同时采,我感觉SRAM实时存储好像不太够?另外能不能把您的工程发我一份做参考?我找了好久没找到一个合适的工程。
谢谢!
@梁家伟 这个是官方例程里面改的,看你计算啊,256x应该是对于429是够用的.
测试程序如上面,以及产生的时序图在下面–
这个时序图是外接的逻辑分析仪产生的吗?还是别的工具?
@欧林华 山寨淘宝的山寨分析仪
@TaterLi 嗯嗯,这个效果也不错的!
图片显示看不清啊。单独打开才行。
@loyal 太早期的内容了,期间换过很多次主题就没兼容好.
怎么才能搞个这样的博客?CSDN广告太多了。
@loyal 国内买服务器,1年1K-2K,工信部备案,公安局备案,学习Linux知识,然后自己搭建.