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方法1
    uint32_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方法2
    uint32_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下载交流经验。感谢~!

 

 

  • 8
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值