侧边栏壁纸
博主头像
thinkTV博主等级

喜爱动漫的二刺螈一枚,摩托车云爱好者(快要有车了)。 懂一点技术的在读生物医学工程研究生( •̀ ω •́ )✧,多多指教。

  • 累计撰写 127 篇文章
  • 累计创建 17 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

STM32-SDRAM

thinkTV
2023-07-03 / 0 评论 / 0 点赞 / 198 阅读 / 1,772 字 / 正在检测是否收录...

1. SDRAM介绍

存储器类型

图片-1688366358136

1.1 SDRAM简介

  • Synchronous Dynamic Random Access Memory(同步动态随机访问存储器)

  • 同步:内存工作需要同步时钟,内部的命令的发送与数据的传输都以它为基准

  • 动态:存储阵列 需要不断的刷新来保证数据不丢失

  • 随机:数据不是线性依次存储,而是自由指定地址进行数据读写

  • 优点:容量大、读写速度快、价格相对便宜

  • 缺点:控制逻辑复杂

图片-1688367568944

图片-1688368295107

定位存储单元

图片-1688368335602

  • 存储空间被划分为4个Bank
  • 容量:81925124*16 = 32 MB
  • SDRAM寻址:
    • 指定BANK
    • 该BANK中选择对应行与列

SDRAM寻址

图片-1688369120580

SDRAM存储单元

图片-1688369159338

  • SDRAM存储数据是利用电容的充放电特性以及保持电荷的能力。需要周期性刷新。
  • 行地址与列地址选通使得存储电容与数据线导通,从而可进行放电(读取)与充电(写入)操作。

1.2 SDRAM 操作命令

图片-1688369248027

  • CS引脚为高电平,表示“命令禁止”(COMMAND INHIBIT)
  • 其中,H表示高电平,L表示低电平,X表示任意电平

NO-Operation

  • 空操作命令,用于选中SDRAM,防止SDRAM接受错误的命令,为接下来的命令发送做准备。

Active(用于存储单位寻址)

  • 激活命令,该命令必须在读写操作之前被发送,用于设置所需要的BANK和行地址(同时设置),BANK地址由BS0(BA0),BS1(BA1)决定,行地址由A0~12决定。

图片-1688370307137

  • ① 通过指令线发送行有效命令,其中RAS线为低电平
  • ② 通过BA线和A线决定发送的BANK地址和行地址

Read / Write

  • 读 / 写命令,在发送完激活命令后, 再发送列地址就可以完成对SDRAM的寻址,并进行读写操作。读/写命令和列地址的发送,是通过一次传输完成的。

图片-1688370629133

  • ① 通过指令线发送读/写命令,WE信号控制读(高)/写(低)命令,CAS线为低电平
  • ② 通过A线决定发送的列地址,使用到A[8:0],A10线用于控制预充电(高电平使能,低电平关闭)
  • 注意:DQM线表示有效的DQ数据线

Precharge

  • 预充电指令,用于关闭BANK中所打开的行地址,准备打开新行。
  • 进行完读写操作后,要对同一BANK的另一行进行寻址,就要将原来有效(打开)的行关闭,重新发送行/列地址。

Refresh

刷新指令,用于刷新一行数据,可以依次对所有的行进行刷新操作。

有两种方式(发送Refresh命令时,由CKE引脚决定):
① 自动刷新(Auto Refresh)高电平
② 自我刷新(Self Refresh) 低电平

自动刷新:

  • 依靠刷新计数器(行地址生成器)自动依次生成要刷新的行地址。
  • 刷新周期(完成一次所有行的刷新所需要的时间):64ms
  • 刷新过程中,所有Bank停止工作
  • 刷新时间:9个CLK

自我刷新:

  • 用于休眠低功耗状态下的数据保存。(发出AR命令后,将CKE至于无效状态(低电平))
  • 进入自我刷新模式后,不再依靠系统时钟工作,根据内部时钟进行刷新操作。
  • CKE高电平时退出自刷新模式进入正常操作模式

Mode Register Set

设置模式寄存器。SDRAM芯片内部有一个逻辑控制单元,控制单元的相关参数由模式寄存器提供。该命令在每次对SDRAM进行初始化时都需要用到。

图片-1688373925980

1.3 SDRAM工作流程介绍

SDRAM初始化

图片-1688374391378

写操作
单次写并自动预充电

图片-1688374628460

读操作
单次读并自动预充电

图片-1688374655073

2. FMC介绍

FMC,灵活的存储控制器,能驱动SRAM、NOR/NAND Flash以及SDRAM等存储器

SDRAM控制器特点:

  • 两个SDRAM存储区域,可独立配置
  • 支持8/16/32位数据总线宽度
  • 支持13位行地址,11位列地址,4个内部存储区域
  • 支持字、半字和字节访问
  • 自动进行行和存储区域边界管理
  • 多存储区域乒乓访问
  • 可编程时序参数
  • 支持自动刷新操作,可编程刷新速率
  • 自刷新模式
  • 读FIFO可缓存

2.1 FMC-SDRAM 引脚说明介绍

图片-1688432575666

2.2 外部器件地址映射

使用FMC外接存储器,其存储单元是映射到STM32的内部寻址空间的。
FMC有两个存储块用来连接SDRAM器件(每个存储区域一个器件).

2.3 SDRAM相关寄存器

图片-1688433403287

控制寄存器(FMC_SDCRx)

包含每个SDRAM存储区域的控制参数(F429)

图片-1688433595139

时序寄存器(FMC_SDTRx)

包含每个SDRAM存储区域的时序参数,时钟周期指的是SDRAM时钟周期,F429为11.1ns

图片-1688433705337

命令模式寄存器(FMC_SDCMR)

包含访问SDRAM设备时所发出的命令

图片-1688433746116

刷新定时器寄存器(FMC_SDRTR)

用来设置刷新循环之间的刷新速率

图片-1688433947441

SDRAM接收读请求后若出现内部刷新请求,必须将刷新速率增加20个SDRAM时钟周期,获得充足余量。

2.4 FMC SDRAM 相关HAL驱动

图片-1688433994042

FMC SDRAM HAL库相关结构体:

SDRAM_HandleTypeDef

typedef struct 
{ 
	FMC_SDRAM_TypeDef 			*Instance; 	/* 寄存器基地址*/ 
	FMC_SDRAM_InitTypeDef 		Init; 			/* SDRAM初始化结构体 */ 	
	__IO HAL_SDRAM_StateTypeDef 	State; 		/* SDRAM访问状态 */ 	
	HAL_LockTypeDef 				Lock; 		/* SDRAM锁对象 */
	DMA_HandleTypeDef 			*hdma;		/* DMA控制结构体 */
} SDRAM_HandleTypeDef;

图片-1688435225544

FMC_SDRAM_TimingTypeDef

typedef struct 
{ 
	uint32_t		LoadToActiveDelay; 	/* TMRD 加载模式寄存器命令或刷新命令后的延迟*/ 
	uint32_t		ExitSelfRefreshDelay; 	/* TXSR 自刷新命令到发出激活命令之间的延迟 */ 	
	uint32_t 		SelfRefreshTime; 		/* TRAS 自刷新周期 */ 	
	uint32_t 		RowCycleDelay; 		/* TRC (刷新和激活/两个相邻刷新)命令之间的延迟 */
	uint32_t		WriteRecoveryTime;	/* TWR 写命令和预充电命令之间的延迟 */
	uint32_t 		RPDelay; 				/* TRP 预充电命令与其他命令之间的延迟 */
	uint32_t		RCDDelay;			/* TRCD 激活命令与读写命令之间的延迟 */
} FMC_SDRAM_TimingTypeDef;

FMC_SDRAM_CommandTypeDef

typedef struct 
{ 
	uint32_t		CommandMode; 			/* 命令类型(7种) */ 
	uint32_t		CommandTarget; 			/* 目标SDRAM存储区域 */ 	
	uint32_t 		AutoRefreshNumber; 		/* 自刷新次数(发送自动刷新命令才有效) */ 
	uint32_t		ModeRegisterDefinition; 	/* SDRAM模式寄存器内容(发送MRS命令) */
} FMC_SDRAM_CommandTypeDef;

  • 设置自刷新时,AutoRefreshNumber要设置为8
  • 设置模式寄存器,ModeRegisterDefinition要设置为

3. SDRAM驱动步骤

图片-1688435515563

直接指定变量存储到SDRAM空间

uint16_t g_test_buffer[250000] __attribute__((at(SDRAM_BASE_ADDR)));
g_test_buffer[i] = i;
0

评论区