本文介绍了用IS42S16400J给stm32的ram增加8M字节扩容
文章目录
前言
随着现代电子设备复杂度的不断增加,对于内存的需求也日益增长。STM32微控制器提供了多种方式来连接外部存储器,以满足不同的应用场景和性能需求。其中,FMC接口是一个能够支持SRAM、NOR Flash、PSRAM、NAND Flash和SDRAM等不同类型存储器的强大工具。特别是对于需要大量数据缓存或快速读写操作的应用,如图像处理、音频播放或复杂的图形用户界面(GUI),SDRAM以其高速度和大容量成为了理想的选择。
在这里,我们将深入探讨STM32系列微控制器中一个非常强大的外设——FMC(Flexible Memory Controller),以及它在SDRAM(同步动态随机存取存储器)扩展中的应用。
一、SDRAM介绍
1.在相关博客推荐处看到的这一篇,看了确实会对sdram的配置有一个基础的了解。
高手进阶,终极内存技术指南——完整/进阶版 I
那篇博客也贴在这里
STM32F429驱动SDRAM(IS42S16400J)详解
2. IS42S16400J-7
IS42S16400J是一种高速同步动态随机存储器(SDRAM),有4个bank,每个bank有12根行地址线(A0-A11),8根列地址线(A0-A7),总线宽度为16位,所以它的容量为4*212*28*16=64M bit=8M Byte。
后续的文章我会讲解stm32H743上使用fmc->W9825G6KH和lcd/dma2d的使用。
二、sdram时钟
查找图中的时间都能找到
三、cubemx配置
这里根据手册选择bank1应该也是可以的。
四、sdram初始化
在配置好了fmc接口之后,需要对sdram进行初始化流程
总结流程为
1.上电
2.初始化时钟延迟至少100us
3.在一个无效命令或空操作后执行执行预充电延迟至少100us,所有bank都需要被预充电
4.执行两个自动刷新周期
5.配置模式寄存器
/************************************************************************
* * *@brief 对SDRAM芯片进行初始化配置
* * *
************************************************************************/
void SDRAM_InitSequence(void)
{
uint32_t tmpr = 0;
/* 配置命令:开启提供给SDRAM的时钟 */
Command.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
Command.CommandTarget = FMC_COMMAND_TARGET_BANK;
Command.AutoRefreshNumber = 1;
Command.ModeRegisterDefinition = 0;
/* Send the command */
HAL_SDRAM_SendCommand(&sdramHandle, &Command, SDRAM_TIMEOUT);
/* Step 2: Insert 100 us minimum delay */
/* Inserted delay is equal to 1 ms due to systick time base unit (ms) */
HAL_Delay(1);
/* Step 5 --------------------------------------------------------------------*/
/* 配置命令:对所有的bank预充电 */
Command.CommandMode = FMC_SDRAM_CMD_PALL;
Command.CommandTarget = FMC_COMMAND_TARGET_BANK;
Command.AutoRefreshNumber = 1;
Command.ModeRegisterDefinition = 0;
/* Send the command */
HAL_SDRAM_SendCommand(&sdramHandle, &Command, SDRAM_TIMEOUT);
/* Step 6 --------------------------------------------------------------------*/
/* 配置命令:自动刷新 */
Command.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
Command.CommandTarget = FMC_COMMAND_TARGET_BANK;
Command.AutoRefreshNumber = 4;
Command.ModeRegisterDefinition = 0;
/* Send the command */
HAL_SDRAM_SendCommand(&sdramHandle, &Command, SDRAM_TIMEOUT);
/* Step 7 --------------------------------------------------------------------*/
/* 设置sdram寄存器配置 */
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;
/* 配置命令:设置SDRAM寄存器 */
Command.CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
Command.CommandTarget = FMC_COMMAND_TARGET_BANK;
Command.AutoRefreshNumber = 1;
Command.ModeRegisterDefinition = tmpr;
/* Send the command */
HAL_SDRAM_SendCommand(&sdramHandle, &Command, SDRAM_TIMEOUT);
/* Step 8 --------------------------------------------------------------------*/
/* 设置刷新计数器 */
/* (15.62 us x Freq) - 20 */
/* Step 6: Set the refresh rate counter */
/* Set the device refresh rate */
HAL_SDRAM_ProgramRefreshRate(&sdramHandle, 1386);
}
五、测试
在配置和初始化之后,我们使用sdram就可以像使用内部ram一样,直接使用地址访问,这就是fmc的魅力啊。
sdram.c
#include "sdram.h"
#include "fmc.h"
#include "sdram_bsp.h"
#include "rng.h"
#include "usart.h"
#define MAX_SDRAM_TEST_SIZE 10000
#define SDRAM_SIZE (IS42S16400J_SIZE / 4)
static uint32_t RadomBuffer[MAX_SDRAM_TEST_SIZE];
//static uint32_t ReadBuffer[MAX_SDRAM_TEST_SIZE];
uint32_t *pSDRAM;
/************************************************************************
* * *@brief rng buff填充
* * *
************************************************************************/
void rng_padding(void)
{
printf("开始生成10000个SDRAM测试随机数\n");
for (uint16_t i = 0; i < MAX_SDRAM_TEST_SIZE; i++)
{
RadomBuffer[i] = HAL_RNG_GetRandomNumber(&hrng);
}
}
/************************************************************************
* * *@brief sdram检测
* * *
************************************************************************/
void SDRAM_Check(void)
{
pSDRAM = (uint32_t *)SDRAM_BANK_ADDR;
long long count = 0;
long long sdram_count = 0;
printf("开始写入SDRAM\n");
for (sdram_count = 0; sdram_count < SDRAM_SIZE; sdram_count++)
{
*pSDRAM = RadomBuffer[count];
count++;
pSDRAM++;
if (count >= MAX_SDRAM_TEST_SIZE)
{
count = 0;
}
}
printf("写入总字节数:%d\n", (uint32_t)pSDRAM - SDRAM_BANK_ADDR);
count = 0;
pSDRAM = (uint32_t *)SDRAM_BANK_ADDR;
printf("开始读取SDRAM并与原随机数比较\n");
sdram_count = 0;
for (; sdram_count < SDRAM_SIZE; sdram_count++)
{
if (*pSDRAM != RadomBuffer[count])
{
printf("数据比较错误——退出~\n");
break;
}
count++;
pSDRAM++;
if (count >= MAX_SDRAM_TEST_SIZE)
{
count = 0;
}
}
printf("比较通过总字节数:%d\n", (uint32_t)pSDRAM - SDRAM_BANK_ADDR);
if (sdram_count == SDRAM_SIZE)
{
// LED_GREEN;
printf("SDRAM测试成功\n");
}
else
{
// LED_RED;
printf("SDRAM测试失败\n");
}
}
sdram.h
#pragma once
#include "stm32f4xx.h"
#include <stdio.h>
#define IS42S16400J_SIZE 0x800000 //400000*16bits = 0x800000 ,8M字节
/*SDRAM 的bank选择*/
#define FMC_BANK_SDRAM FMC_Bank2_SDRAM
#define FMC_COMMAND_TARGET_BANK FMC_SDRAM_CMD_TARGET_BANK2
/**
* @brief FMC SDRAM 数据基地址
*/
#define SDRAM_BANK_ADDR ((uint32_t)0xD0000000)//如果使用bank1,0xC0000000
/**
* @brief FMC SDRAM 数据宽度
*/
#define SDRAM_MEMORY_WIDTH FMC_SDRAM_MEM_BUS_WIDTH_16
#define SDRAM_TIMEOUT ((uint32_t)0xFFFF)
#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)
void SDRAM_WriteBuffer(uint32_t* pBuffer, uint32_t uwWriteAddress, uint32_t uwBufferSize);
void SDRAM_ReadBuffer(uint32_t* pBuffer, uint32_t uwReadAddress, uint32_t uwBufferSize);
void SDRAM_InitSequence(void);
引用
相关博客
STM32 FMC篇-SDRAM(IS42S16400J)
STM32F429DISC开发板SDRAM(IS42S16400J)实验—基于STM32cubeMX HAL库
STM32F429驱动SDRAM(IS42S16400J)详解