本文主要是介绍STM32CbueMX之SDRAM,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
SRAM(静态随机存取存储器)
静态随机存取存储器(Static Random-Access Memory,SRAM)是随机存取存储器的一种。所谓的“静态”,是指这种存储器只要保持通电,里面储存的数据就可以恒常保持。相对之下,动态随机存取存储器(DRAM)里面所储存的数据就需要周期性地更新。然而,当电力供应停止时,SRAM储存的数据还是会消失(被称为volatile memory),这与在断电后还能储存资料的ROM或闪存是不同的。
SDRAM(同步动态随机存取内存)
同步动态随机存取内存(synchronous dynamic random-access memory,简称SDRAM)需要不断的刷新,才能保存数据。而且是行列地址复用的,许多都有页模式。SDRAM之所以成为DRAM就是因为它要不断进行刷新(Refresh)才能保留住数据,因为刷新(Refresh)是DRAM最重要的操作。那么要隔多长时间重复一次刷新,目前公认的标准是,存储体中电容的数据有效保存期上限是64ms(毫秒,1/1000秒),也就是说每一行刷新的循环周期是64ms。
硬件:
F429 + W9825G6KH-6
W9825G6KH-6手册:
内部有4个bank。W9825G6KH-6大小 = 4 M x 4 BANKS x 16 BITS = 256Mb = 32MB
配置CAS Latency: 2 或者 3
W9825G6KH-6 :行地址:A0~A12(13bits)。 列地址:A0~A8(9bits)。
STM32CbueMX配置:
时钟树配置:外部晶振25MHz + 配置最大180MHz
1、Bank:由硬件决定;选择SDRAM bank 1
2、Number of column address bits:芯片决定9bits,列地址:A0~A8(9bits)
3、Number of row address bits:芯片决定13bits,行地址:A0~A12(13bits)
4、CAS latency:表示CAS潜伏期,即上面说的CL,该配置需要与之后的SDRAM模式寄存器的配置相同。
和SDRAM工作时钟选择有关,这里选2 memory clock cycles,133MHz,单个时钟周期为最小7.5ns。
5、Write protection 写保护,配置为Disabled
6、SDRAM common clock SDRAM 时钟配置,选择失能、2分频、3分频。从HCLK时钟分频,HCLK时钟最大是180MHz, 故SDCLK最大时钟就是90MHz.单个时钟周期为1s / 90MHz = 11.1ns,所以上面SDRAM 的时钟选择最低133MHz就可以了。
7、SDRAM common burst read 突发读,选择使能。
8、SDRAM common read pipe delay :CAS后延时多少个CLK读数据,一般配置成0;
9、Load mode register to active delay :加载模式寄存器到激活时间的延迟 tMRD / tRSD,最小15ns,F429一个周期是11.1ns,
故15 / 11 = 1......4,考虑到PCB走线等误差, 一般向上取,所以设置是2SDCLK
10、Exit self-refresh delay:退出自刷新延迟 tXSR = 72ns,72 / 11.1向上取整,7SDCLK
11、Self-refresh time:自刷新时间 tRAS = 42ns,故4SDCLK
12、SDRAM common row cycle delay:行循环延迟 tRC = 60ns,故6SDCLK
13、Write recovery time:等待延迟 tWR = 2tCK = 2SDCLK
14、SDRAM common row precharge delay:行预充电延迟 tRP = 15ns = 2SDCLK
15、Row to column delay:行到列延迟 tRCD = 15ns = 2SDCLK
最后生成代码。
SDRAM初始化过程:
SDRAM初始化过程,图片来源于《高手进阶,终极内存技术指南——完整》(这个初始化过程SDRAM通用)
初始化过程分为五步:
① 上电
此步,给SDRAM供电,使能CLK时钟,并发送NOP(No Operation命令)等待最少200us。
② 发送预充电命令
第二步,就是发送预充电命令,给所有Bank预充电。
③ 发送自动刷新命令
这一步,至少要发送发送8次自刷新命令。
④ 设置模式寄存器
这一步,发送模式寄存器的值,配置SDRAM的工作参数。
最后一步设置:SDRAM刷新定时器(图片来源于STM32F4XX中文参考手册)
W9825G6KH-6 行地址:A0~A12(13bits),即有8192(2^13)行,F429的SDRAM时钟是90MHz。
刷新速率 = 64ms / 8192行 = 7.81us。
SDRAM 的刷新周期 = 7.81us * 90Mhz - 20 = 682.9,取683
减20是为了有足够的时钟周期留个刷新。
#define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001)
#define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002)
#define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0004)
#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008)
#define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020)
#define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030)
#define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200)/*** @brief Perform the SDRAM exernal memory inialization sequence* @param hsdram: SDRAM handle* @param Command: Pointer to SDRAM command structure* @retval None*/
static void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram)
{__IO uint32_t tmpmrd = 0;FMC_SDRAM_CommandTypeDef Command;/* Configure a clock configuration enable command */Command.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;Command.AutoRefreshNumber = 1;Command.ModeRegisterDefinition = 0;/* Send the command */HAL_SDRAM_SendCommand(hsdram, &Command, 0x1000);/* Insert 10 ms delay */HAL_Delay(10);/* Configure a PALL (precharge all) command */Command.CommandMode = FMC_SDRAM_CMD_PALL;Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;Command.AutoRefreshNumber = 1;Command.ModeRegisterDefinition = 0;/* Send the command */HAL_SDRAM_SendCommand(hsdram, &Command, 0x1000);/* Configure a Auto-Refresh command */Command.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;Command.AutoRefreshNumber = 8;Command.ModeRegisterDefinition = 0;/* Send the command */HAL_SDRAM_SendCommand(hsdram, &Command, 0x1000);/* Program the external memory mode register */tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_8|SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |SDRAM_MODEREG_CAS_LATENCY_2 |SDRAM_MODEREG_OPERATING_MODE_STANDARD |SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;Command.CommandMode = FMC_SDRAM_CMD_LOAD_MODE;Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;Command.AutoRefreshNumber = 1;Command.ModeRegisterDefinition = tmpmrd;/* Send the command */HAL_SDRAM_SendCommand(hsdram, &Command, 0x1000);/* Set the refresh rate counter *//* (7.81us x Freq) - 20 *//* Set the device refresh counter */HAL_SDRAM_ProgramRefreshRate(hsdram, 683);
}
最后说一下STM32 FMC地址映射关系,我使用的是SDRAM挂载在SDRAM Bank 1,所以开始地址是0xC0000000.
main.c
int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_FMC_Init();MX_USART1_UART_Init();SDRAM_Initialization_Sequence(&hsdram1);printf("sudaroot\r\n");//使用SDRAM方法1uint32_t i = 0;uint16_t sdramtest[10] __attribute__((at(0XC0000000)));for(i = 0; i < 10; i++){sdramtest[i] = i; }for(i = 0; i < 10; i++){printf("sdramtest[%d]:%d\r\n", i, sdramtest[i]);}//使用SDRAM方法2uint32_t temp = 100;*(__IO uint32_t*)(0XC0000400) = temp;temp = 0;temp = *(__IO uint32_t*)(0XC0000400);printf("temp = %u\r\n", temp);while (1){}
}
现象:
全篇完。
本人是一个嵌入式未入门小白,博客仅仅代表我个人主观见解,记录成长笔记。
笔记是以最简单的方式,只展示最核心的原理。
若有与 大神大大 见解有歧义,我绝对坚信 大神大大 见解是对的,我的是错的。
若无积分等无法下载源码,可加入QQ群657407920下载交流经验。感谢~!
这篇关于STM32CbueMX之SDRAM的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!