本文主要是介绍STM32HAL库--SDRAM实验(速记版),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
STM32F429IGT6 自带了 256K 字节的 SRAM,对一般应用来说,已经足够了,不过在一些对内存要求高的场合, STM32F429 自带的这些内存就不够用了。比如使用 LTDC 驱动RGB 屏、跑算法或者跑 GUI 等,就可能不太够用,所以阿波罗 STM32F429 开发板板载了一颗 32M 字节容量的 SDRAM 芯片:W9825G6KH,满足大内存使用的需求。
1.1 SDRAM简介
SDRAM,英文名是: Synchronous Dynamic Random Access Memory,即同步动态随机存储器,相较于 SRAM(静态存储器),SDRAM 具有:容量大和价格便宜的特点。 STM32F429 支持 SDRAM,因此,我们可以外挂 SDRAM,从而大大降低外扩内存的成本。
阿波罗板载的 SDRAM 型号为:W9825G6KH,其内部结构框图如图所示。
(1) SDRAM 信号线
(2) 存储单元
SDRAM 的存储单元(称之为:BANK)是以阵列的形式排列的,如图所示:
对于这个存储阵列,我们可以将其看成是一个表格,只需要给定行地址和列地址,就可以确定其唯一位置,这就是 SDRAM 寻址的基本原理。而一个 SDRAM 芯片内部,一般又有 4 个这样的存储单元( BANK),所以,在 SDRAM 内部寻址的时候,先指定 BANK 号和行地址,然后再指定列地址,就可以查找到目标地址。
SDRAM 的存储结构示意图,如图 25.1.1.3 所示,寻址的时候,首先 RAS 信号为低电平,选通行地址,地址线 A0~A12 所表示的地址,会被传输并锁存到行地址译码器里面,最为行地址,同时 BANK 地址线上面的 BS0,BS1 所表示的 BANK 地址,也会被锁存,选中对应的BANK,然后, CAS 信号为低电平,选通列地址,地址线A0~A12 所表示的地址,会被传输并锁存到列地址译码器里面,作为列地址,这样,就完成了一次寻址。W9825G6KH 的存储结构为:行地址:8192 个;列地址:512 个; BANK 数: 4 个;位宽:16 位;这样,整个芯片的容量为:8192*512*4*16=32M 字节。
(3) 数据传输
在完成寻址以后,数据线 DQ0~DQ15 上面的数据会通过图 25.1.1.1 中所示的数据控制逻辑写入(或读出)存储阵列。特别注意:因为 SDRAM 的位宽,可以达到 32 位,也就是最多有 32 条数据线,在实际使用的时候,我们可能会以:8 位、16 位、24 位和 32 位等宽度来读写数据,这样的话,并不是每条数据线,都会被使用到,未被用到的数据线上面的数据,必须被忽略,这个时候就需要用到数据掩码( DQM)线来控制了,每一个数据掩码线,对应 8 个位的数据,低电平表示对应数据位有效,高电平表示对应数据位无效。以 W9825G6KH 为例,假设以 8 位数据访问, 我们只需要 DQ0~DQ7 的数据,而DQ8~DQ15 的数据需要忽略,此时,我们只需要设置LDQM 为低电平, UDQM 为高电平,就可以了
(4) 控制命令
SDRAM的驱动需要用到一些命令,我们列出几个常用的命令给大家做讲解,如表25.1.1.2所示:
1, NO-Operation
NO-Operation,即空操作命令,用于选中 SDRAM,防止 SDRAM 接受错误的命令,为接下来的命令发送做准备。
2, Active
Active,即激活命令,该命令必须在读写操作之前被发送,用于设置所需要的Bank和行地
址(同时设置这 2 个地址),Bank 地址由 BS0,BS1(也写作 BA0,BA1,下同)指定,行地
址由 A0~A12 指定。
3, Read/Write
Read/Write,即读/写命令,在发送完激活命令后,再发送列地址就可以完成对 SDRAM 的寻址,并进行读写操作了,读/写命令和列地址的发送,是通过一次传输完成的。
列地址由 A0~A9 指定,WE 信号控制读/写命令,高电平表示读命令,低电平表示写命令,各条信号线的状态,在 CLK 的上升沿被锁存到芯片内部。
4, Percharge
Percharge,即预充电指令,用于关闭 Bank 中所打开的行地址。由于 SDRAM 的寻址具有独占性,所以在进行完读写操作后,如果要对同一 Bank 的另一行进行寻址,就要将原来有效(打开)的行关闭,重新发送行/列地址。Bank 关闭现有行,准备打开新行的操作就叫做预充电(Percharge)。
预充电命令可以独立发送也可以在每次发送读/写命令的时候发送,使用地址线A10可以设置自动预充电。在发送读/写命令的时候,当 A10=1,则使能所有 Bank 的预充电,在读/写操作完成后,会自动进行预充电使Bank关闭现有行准备打开新行。
5, Refresh
Refresh,即刷新命令,用于刷新一行数据。SDRAM 里面存储的数据,需要不断的进行刷新操作才能保留住,因此刷新命令对于 SDRAM 来说,尤为重要。预充电命令和刷新命令,都可以实现对 SDRAM 数据的刷新,不过预充电仅对当前打开的行有效(仅刷新当前行),而刷新命令,则可以依次对所有的行进行刷新操作。
总共有两种刷新操作:自动刷新( Auto Refresh)和自我刷新( Self Refresh)。
在发送Refresh 命令时,如果 CKE 有效(高电平),则使用自动刷新模式,否则使用自我刷新模式。不论是何种刷新方式,都不需要外部提供行地址信息,因为这是一个内部的自动操作。刷新按照逐行进行,无需列寻址,刷新过程中所有Bank停止工作,需等待 9 个时钟周期,一般 64 ns。DRAM 相对于 SRAM(静态内存,无需刷新仍能保留数据)取得成本优势的同时所付出的代价。
自我刷新:主要用于休眠模式低功耗状态下的数据保存,在发出刷新命令时,将CKE 无效状态(低电平),就进入了自我刷新模式,此时不再依靠系统时钟工作,而是根据内部的时钟进行刷新操作。在自我刷新期间除了 CKE 之外的所有外部信号都是无效的(无需外部提供刷新指令),只有重新使 CKE 有效(高电平)才能退出自刷新模式并进入正常操作状态。
6, Mode Register Set
Mode Register Set,即设置模式寄存器。 SDRAM 芯片内部有一个逻辑控制单元,控制单
元的相关参数由模式寄存器提供,我们通过设置模式寄存器命令,来完成对模式寄存器的设置,
这个命令在每次对 SDRAM 进行初始化的时候,都需要用到。
发送该命令时,通过地址线来传输模式寄存器的值,W9825G6KH 的模式寄存器描述如图25.1.1.7 所示:
由图可知,模式寄存器的配置分为几个部分:
Burst Length,即突发长度(简称 BL),通过 A0~A2 设置, 是指在同一行中相邻的存储单元连续进行数据传输的方式,连续传输所涉及到存储单元(列)的数量就是突发长度。突发传输计数解决连续发送读写命令和列地址进行选址存在的效率问题,指定起始地址和突发长度,内存依次对后面相应数量的存储单元进行读写操作。
非突发连续读取模式:不采用突发传输而是依次单独寻址,此时可等效于 BL=1。虽然可以让数据是连续的传输,但每次都要发送列地址与命令信息,控制资源占用极大。
突发连续读取模式:只要指定起始列地址与突发长度,寻址与数据的读取自动进行。两段突发读取命令的间隔周期需要和突发长度(BL)相同,且 BL 的数值要在初始化时通过模式寄存器命令进行设置。目前可用的选项是 1、 2、 4、 8、全页( Full Page),常见的设定是 4 和 8。 若传输长度小于突发长度,则需要发送 Burst Stop(停止突发)命令,结束突发传输。
Addressing Mode,即突发访问的地址模式,通过 A3 设置,可以设置为: Sequential(顺序)或 Interleave(交错)。顺序方式,地址连续访问,而交错模式则地址是乱序的,一般选择连续模式。
CAS Latency,即列地址选通延迟(简称 CL)。在读命令(同时发送列地址)发送完之后,需要等待几个时钟周期, DQ 数据线上的数据,才会有效,这个延迟时间,就叫 CL,一般设置为 2/3 个时钟周期。仅读命令需要列地址选通延迟,写命令不需要。
Write Mode,即写模式,用于设置单次写的模式,可以选择突发写入或者单次写入。
(5) 初始化
SDRAM 上电后,必须进行初始化,才可以正常使用。
初始化过程分为五步:
① 上电
此步,给 SDRAM 供电,使能 CLK 时钟,并发送 NOP(No Operation 命令)选中 SDRAM,注意,上电后,要等待最少 200us,再发送其他指令。
② 发送预充电命令
第二步,就是发送预充电命令,给所有 Bank 预充电。
③ 发送自动刷新命令
这一步,至少要发送 8 次自刷新命令,每一个自刷新命令之间的间隔时间为 tRC。
④ 设置模式寄存器
这一步,发送模式寄存器的值,配置 SDRAM 的工作参数。配置完成后,需要等待 tMRD(也叫 tRSC),使模式寄存器的配置生效,才能发送其他命令。
⑤ 完成
经过前面四步的操作,SDRAM 的初始化就完成了,接下来就可以发送激活命令和读/写命
令,进行数据的读/写了。这里提到的 tRC、tMRD 和 tRSC 见 SDRAM 的芯片数据手册。
(6) 写操作
在完成对 SDRAM 的初始化后,我们就可以对 SDRAM 进行读写操作了。
SDRAM 的写流程如下:
① 发送激活命令
此命令同时设置行地址和 BANK 地址,发送该命令后,需要等待 tRCD 时间,才可以发送写命令。
② 发送写命令
在发送完激活命令,并等待 tRCD 后,发送写命令,该命令同时设置列地址,完成对 SDRAM 的寻址。同时,将数据通过 DQ 数据线,存入 SDRAM。
③ 使能自动预充电
在发送写命令的同时,拉高 A10 地址线,使能自动预充电,以提高读写效率。
④ 执行预充电
预充电在发送激活命令的 tRAS 时间后启动,并且需要等待 tRP 时间,来完成。
⑤ 完成一次数据写入
最后,发送第二个激活命令,启动下一次数据传输。这样,就完成了一次数据的写入。
(7) 读操作
① 发送激活命令
此命令同时设置行地址和 BANK 地址,发送该命令后,需要等待 tRCD 时间,才可以发送读命令。
② 发送写命令
在发送完激活命令,并等待 tRCD 后,发送读命令,该命令同时设置列地址,完成对 SDRAM 的寻址。读操作还有一个 CL 延迟( CAS Latency),所以需要等待给定的 CL 延迟( 2 个或 3 个 CLK)后,再从 DQ 数据线上读取数据。
③ 使能自动预充电
在发送读命令的同时,拉高 A10 地址线,使能自动预充电,以提高读写效率。
④ 执行预充电
预充电在发送激活命令的 tRAS 时间后启动,并且需要等待 tRP 时间来完成。
⑤ 完成一次数据写入
最后,发送第二个激活命令,启动下一次数据传输。这样就完成了一次数据的读取。
1.2 FMC SDRAM 接口简介
·两个 SDRAM 存储区域,可独立配置
·支持 8 位、16 位和 32 位数据总线宽度
· 支 持 13 位 行 地 址 ,11 位 列 地 址 ,4 个 内 部 存 储 区 域 :
4*16M*32bit(256MB)、4*16M*16bit(128MB)、4*16M*8bit(64MB)
·支持字、半字和字节访问
·自动进行行和存储区域边界管理
·多存储区域乒乓访问
·可编程时序参数
·支持自动刷新操作,可编程刷新速率
·自刷新模式
·读 FIFO 可缓存,支持 6 行*32 位深度(6*14 位地址标记)
控制寄存器 SDCRx
该寄存器只有低 15 位有效,且都需要进行配置:
NC:这两个位定义列地址的位数(00~11,表示 8~11 位),W9825G6KH 有 9 位列地址,
所以,这里应该设置为 01。
NR:这两个位定义行地址的位数(00~10,表示 11~13 位),W9825G6KH 有 13 位行地址,所以,这里设置为 10。
MWID:这两个位定义存储器数据总线位宽( 00~10,表示 8~32 位),W9825G6KH 数据位宽为 16 位,所以这里设置为 01。
NB: 该 位 用 于 设 置 SDRAM 内部存储区域(BANK) 数 量 (0=2 个 ,1=4 个 )。W9825G6KH 内部有 4 个 BANK,所以,这里设置为:1。
CAS:这两个位可设置 SDRAM 的 CAS 延迟,按存储器时钟周期计( 01~11,表示 1~3 个)。W9825G6KH 可以设置为 2,也可以设置为 3,我们设置为 11。CAS延迟指的是传输列地址到读取数据之间间隔的时钟周期单位,时钟周期时钟震荡一次时间,us或ps。Column Address Strobe,行地址触发信号延迟。
WP:该位用于写保护设置(0=写使能,1=写保护),我们需要用到写操作,所以这里设
置为 1 即可。
SDCLK:这两个位用于配置 SDRAM 的时钟(10=HCLK/2,11=HCLK/3),需要在禁止SDRAM 时钟的前提下配置。 W9825G6KH 最快可以到 200M(@CL=3),为了较快的速度,我们设置为 10。
RBURST:此位用于使能突发读模式(0=禁止,1=使能)。这里我们设置为 1,使能突发
读。
RPIPE:这两个位可定义在 CAS 延迟后延后多少个 HCLK 时钟周期读取数据(00~10,表示 0~2 个)。这里,我们设置为 00 即可。
时序寄存器 SDTRx
接下来,我们介绍 SDRAM 的时序寄存器 SDTRx:
FMC_SDTRx,x=1/2,该寄存器各位描述如图 25.1.2.2 所示:
该寄存器用于控制 SDRAM 的时序,非常重要,接下来我们分别介绍各个参数:
TMRD:这四个位定义自刷新时间间隔,W9825G6KH 的 tRSC 值为 2 个时钟,所以我们设置为 1 即可( 2 个时钟周期,这里的时钟周期是指 SDRAM 的时钟周期,下同)。tMRD:两次自刷新之间的时间间隔。
TXSR:这四个位定义从发出自刷新命令到发出激活命令之间的延迟。W9825G6KH 的这个时间为 72ns,我们设置 STM32F429 的时钟频率为 180Mhz,那么一个 SDRAM 的时钟频率为 90M,一个周期为 11.1ns,设置 TXSR 为 6,即 7 个时钟周期即可。
TRAS:这四个位用于设置自刷新周期。 W9825G6KH 的自刷新周期为 60ns,我们设置
TRAS 为 5,即 6 个时钟周期即可。
TRC: 这四个位定义刷新命令和激活命令之间的延迟,以及两个相邻刷新命令之间的延迟。W9825G6KH 的这个时间同样是 60ns,我们设置 TRC 为 5,即 6 个时钟周期即可。
TWR: 这四个位定义写命令和预充电命令之间的延迟。 W9825G6KH 的这个时间为 2 个时钟周期,所以,我们设置 TWR=1 即可。
TRP:这四个位定义预充电命令与其它命令之间的延迟。W9825G6KH 的这个时间为 15ns,所以,我们设置 TRP=1 即可。
TRCD:这四个位定义激活命令与读/写命令之间的延迟。W9825G6KH 的这个时间为15ns,所以,我们设置 TRP=1 即可。
命令模式寄存器 SDCMR
接下来,我们介绍 SDRAM 的命令模式寄存器:FMC_SDCMR,该寄存器各位描述如图:
该寄存器用于发送控制 SDRAM 的命令,以及 SDRAM 控制器的工作模式时序,非常重要。
接下来我们分别介绍各个参数:
MODE: 这三个位定义发送到 SDRAM 存储器的命令。000:正常模式;001:时钟配置使能;010:预充电所有存储区;011:自刷新命令;100:配置模式寄存器;101:自刷新命令;110:掉电命令; 111:保留。加粗部分的命令,我们配置的时候需要用到。CTB2/CTB1:这两个位用于指定命令所发送的目标存储器,因为 SDRAM 控制器可以外挂 2 个 SDRAM,发送命令的时候,需要通过 CTB1/CTB2 指定命令发送给哪个存储器。我们使用的是第一个存储器( SDNE0),所以设置 CTB1 即可。NRFS:这四个位定义在MODE=011 时 ,所发出的连续自刷新命令的个数。 0000~1110,表示 1~15 个自刷新命令。 W9825G6KH 在初始化的时候,至少需要连续发送 8 个自刷新命令。
MRD:这十三个位,定义 SDRAM 模式寄存器的内容(通过地址线发送),在 MODE=100 的时候,需要配置。
模式寄存器
用来设置突发长度BL(A0,A1)、突发访问的地址模式(A3 顺序还是乱序)、列地址选通延迟CL等
刷新定时器寄存器 SDRTR
该寄存器通过配置刷新定时器计数值来设置刷新一行要多少时钟周期,按 SDRAM 的时钟周期计数。计算公式为:
而如果 SDRAM 在接受读请求后,出现内部刷新请求,则必须将刷新速率增加 20 个 SDRAM 时钟周期,以获得充足的余量,所以,实际设计的 COUNT 值应该是:COUNT-20=730。所以,我们设置 FMC_SDRTR 的 COUNT=730,就可以完成对该寄存器的配置。
MDK 并没有将寄存器定义成 FMC_SDCR1/2 的形式,而是定义成: FMC_SDCR[0]/[1],对应的就是 FMC_SDCR1/2,其他几个寄存器类似,使用的时候注意一下。
阿波罗 STM32F429 核心板板载的 W9825G6KH 芯片挂在 FMC SDRAM 的控制器 1 上面(SDNE0),其原理图如图 25.1.2.5 所示:
1.3 FMC驱动SDRAM配置步骤(总结)
最后,我们来看看使用 HAL 库实现对 W9825G6KH 的驱动,需要对 FMC 进行哪些配置。对 于 SDRAM 配 置 , 我 们 要 新 引 入 的 HAL 库 文 件 为 stm32f4xx_hal_sdram.c 和stm32f4xx_hal_sdram.h。具体步骤如下:
1) 使能 FMC 时钟,并配置 FMC 相关的 IO 及其时钟使能。
2) 通过控制寄存器 SDCR1 来设置地址线位数、数据线位数、BANK区数量、CAS延迟 、SDRAM时钟、突发模式使能,通过 时序寄存器 FMC_SDTR1 初始化各个命令之间的延迟,比如自刷新时间间隔、自刷新时间周期、激活命令和预充电命令之间的间隔、激活和读写命令之间的间隔等等。寄存器都有类似HAL_SDRAM_Init之类的函数来设置,都有初始化回调函数MSPInit。
3) 发送 SDRAM 初始化序列给命令模式寄存器 SDCMR。 包括
1. 使能CLK时钟来上电,并发送NOP命令来选中 SDRAM,同时要等待 200us。
2. 发送预充电命令给所有BANK预充电。
3. 发送自刷新命令。
4. 设置模式寄存器的值来配置 SDRAM 的工作参数,并等待 tMRD 时间。
发送初始化序列主要是向 SRAM 发送命令,HAL_SDRAM_SendCommand函数,传SDRAM句柄传命令结构体传过期时间。命令结构体CommandTypeDef里面属性成员有7种命令类型、外挂的目标SDRAM区域(, 发 送 命 令 的 时 候 , 需 要 指 定 命 令 发 送 给 哪 个 存 储 器 取 值 范 围 为 :FMC_SDRAM_CMD_TARGET_BANK1,FMC_SDRAM_CMD_TARGET_BANK2 和FMC_SDRAM_CMD_TARGET_BANK1_2),自刷新次数,模式寄存器的值。
4) 通过刷新定时器寄存器 FMC_ SDRTR 设置刷新频率。
这篇关于STM32HAL库--SDRAM实验(速记版)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!