STM32f769I-DISC开发板板载了128Mbit的SDRAM芯片,一直只是了解SDRAM原理,并未进行深入的了解,手头的开发板硬件资源丰富可以有机会研究下。片上SDRAM框图如下: ' L# t- C9 ]- R! ? W% K9 u5 q; w! F8 U, P (, 下载次数: 12) 上传 点击文件名下载附件 : ?% d" n' X) r 从图中可以看出,SDRAM的行地址宽度和列地址宽度分别为12bit和8bit,正好和demo的配置吻合。0 ?3 |- T, l* ^2 c$ @( I hsdram.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_8; ; @* a& p0 c; I, V7 Y' W( S- Chsdram.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_12;复制代码% Q; r* m I" ^8 x% e$ {9 g3 ] 由于技术、成本等原因,不可能只做一个全容量的 L-Bank,而且最重要的是,由于 SDRAM 的工作原理限制,单一的 L-Bank 将会造成非常严重的寻址冲突,大幅降低内存效率。所以人们在 SDRAM 内部分割成多个L-Bank,较早以前是两个,目前基本都是 4 个,这也是 SDRAM 规范中的最高 L-Bank + Z2 Z4 `4 r7 g* z( S* e数量。根据上面的图示可以知道,板子上的Lbank数量为4。( c4 ?: y# X) s+ J( B* W hsdram.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;复制代码以下说明来自《内存终极技术指南》中对SDRAM的操作流程说明(1~4,我们的片上SDRAM只有一个P-Bank)& ` [- _- d- K+ _ 1、 首先,我们知道内存控制器要先确定一个 P-Bank 的芯片集合,然后才对这集合中的芯片进行寻址操作。因此要有一个片选的信号,它一次选择一个 5 c3 I% E! |; u" m3 i! y2 {8 lP-Bank 的芯片集(根据位宽的不同,数量也不同)。被选中的芯片将同时接收或读取数据,所以要有一个片选信号。 * X( T8 r3 Z# W' s' c/ F' u6 @ 2、 接下来是对所有被选中的芯片进行统一的 L-Bank 的寻址,目前 SDRAM中 L-Bank 的数量最高为 4 个,所以需要两个 L-Bank 地址信号(22=4)。 1 b" L. ^# ]3 H. F 3、 最后就是对被选中的芯片进行统一的行/列(存储单元)寻址。地址线数量要根据芯片的组织结构分别设计了。但在相同容量下,行数不变,只有列数会根据位宽的而变化,位宽越大,列数越少,因为所需的存储单元减少了。 2 ^- F; }8 B+ X 4、 找到了存储单元后,被选中的芯片就要进行统一的数据传输,那么肯定要有与位宽相同数量的数据 I/O 通道才行,所以肯定要有相应数量的数据线引脚。 - D6 E' }) A6 b' l; i% l# z7 O $ e+ |) M( y% T: T" v根据上面的芯片框图,芯片的控制引脚大致分为,时钟信号线,地址线,数据线,控制线这三类。0 i- ~6 C" R& q- J+ w8 O 时钟信号线:5 M) U$ [: {# l/ r) g. g, t CLK:时钟信号线# G, o& M' v1 h CKE:时钟使能信号线 ! j6 x8 [/ g4 p$ u: |5 a: A地址线: ( ~/ Q2 t: y! Q( I# H3 _2 IA0-A11 12根地址线# a$ N* v) s* f5 v1 }3 F4 Z BA0,BA1:SDRAM bank选择信号 3 X# T3 B6 n" S h0 T. X数据线: 5 z# V1 R+ t) e" [3 M9 eDQ0-DQ31 32根数据线7 f# \2 g7 r4 q* u2 ? 控制线:' J" F4 I/ k5 {2 q' D3 U CS#:片选信号线' M' z# `; P: M1 A8 ?+ B WE#:SDRAM写使能信号 % D' N- v: }" ~# T2 p: cCAS#:列地址选择信号线9 y6 }6 ]1 m9 y) M T) R RAS#:行地址选择信号线! N+ D: H: I9 J" d9 I DQM0-DQM3:SDRAM输入输出掩码控制信号 ( {, v! x$ q* t2 v: i, c. NFMC结构框图如下: # h7 o* |1 o+ [; k( A5 ? M" y* R( z, }8 i! F; |$ U' H+ o (, 下载次数: 14) 上传 点击文件名下载附件 - T! c# p5 e$ F3 F" a( K" s 硬件连线图: - y5 r' F3 Z$ c* e2 W/ U " S9 a8 N2 t1 N: {0 q/ t (, 下载次数: 11) 上传 点击文件名下载附件 * u5 `/ ]3 q5 H# W4 z- f- Q (, 下载次数: 12) 上传 点击文件名下载附件 + r: h( Y$ T! j ~ (, 下载次数: 13) 上传 点击文件名下载附件 4 A. V) G* N6 F3 e3 l FMC模块使用的时钟为HCLK,试验代码配置200MHZ(The AHB clock (HCLK) is the reference clock for the FMC.) ; z9 w0 Z( f: c$ p$ }7 b2 t: y; O# P( v0 I 硬件相关的初始化如下: . P' M) V/ N& {5 k+ U5 H' x# k" }4 g. s3 U5 w' d0 } /*##-1- Configure the SDRAM device #########################################*/) i* F2 s) x- G1 s0 E /* SDRAM device configuration */ 2 Z/ G& V$ x. w5 d6 j+ t hsdram.Instance = FMC_SDRAM_DEVICE;( M9 Z0 K. @; b! `- @9 J& p" G- } * W% \; a9 y L( ~0 I( `4 u$ ~ SDRAM_Timing.LoadToActiveDelay = 2;! z) ?6 b8 `! v% ^5 P$ S6 C SDRAM_Timing.ExitSelfRefreshDelay = 6; 9 j+ y2 q5 @1 E" M5 p9 U SDRAM_Timing.SelfRefreshTime = 4;) m7 }8 ^- Z" V) {% g: X SDRAM_Timing.RowCycleDelay = 6;! a# l* x6 Z/ ?- m5 x; K4 j4 o SDRAM_Timing.WriteRecoveryTime = 2; / R5 N. e9 D0 }9 q( _0 g, L SDRAM_Timing.RPDelay = 2; - R! ?$ x% P2 c SDRAM_Timing.RCDDelay = 2;! {9 `+ g% Q* A; E2 Q ! ` ~* O% b1 d hsdram.Init.SDBank = FMC_SDRAM_BANK1; 5 E, v" `9 {5 r hsdram.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_8;. I9 e$ X# \8 P8 Z& p7 l hsdram.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_12; / T' k9 H- V! f hsdram.Init.MemoryDataWidth = SDRAM_MEMORY_WIDTH; 7 I0 l/ P. L* Q/ B: M$ L hsdram.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;$ a& T( Y. v0 w. M hsdram.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_2;1 ^3 y, n. K3 T, \9 Q hsdram.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;) [# W! s9 f% H" B) P0 ? hsdram.Init.SDClockPeriod = SDCLOCK_PERIOD; & b! q+ @. M+ y7 y. f& [ hsdram.Init.ReadBurst = FMC_SDRAM_RBURST_ENABLE;- u( v1 J) {0 `. R6 K* ^$ W hsdram.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0;4 j L) {" U: J. H 0 x6 _, `9 _! t1 e+ B" A /* Initialize the SDRAM controller */, V, |( E, y4 T. W! P if(HAL_SDRAM_Init(&hsdram, &SDRAM_Timing) != HAL_OK)* K0 s+ H; Q2 K. ~ {& X$ V" B4 B! ` /* Initialization Error */! |0 {9 d2 S. O1 j. u Error_Handler(); ; J9 ?/ y" e: Y. M }复制代码5 @% ]1 S# w& t7 @7 a9 M SDRAM命令发送方法如下: 2 _; G8 E, @3 V9 y; {- j# v9 v# `5 i# ^2 Q% H: b- Y8 T (, 下载次数: 12) 上传 点击文件名下载附件 * n: J8 s1 ? m0 n) L1 uSDRAM的时钟分频系数设置可设为2和3(SDRAM clock can be HCLK/2 or HCLK/3 ),demo代码设置为2即CLK为100M,周期10ns。2 H* j% Q( d/ P2 F6 {, _ #define SDRAM clock can be HCLK/2 or HCLK/3 # G9 d7 u `+ o f) V+ Phsdram.Init.SDClockPeriod = SDCLOCK_PERIOD; ( ` X: L$ X# C7 Y. C0 H. O4 E1 l5 H0 Y SDRAM相关时间参数的设置: 6 X0 t4 g. P# J* j. S芯片手册上TRCD的时间描述如下,最小值为20ns.% B) ^; H4 ~5 Y R' W (, 下载次数: 11) 上传 点击文件名下载附件 ) C8 r7 e3 a" M/ q( Y (, 下载次数: 12) 上传 点击文件名下载附件 $ B5 f) _0 E1 w$ ^/ B 根据SDRAM Timing registers 寄存器的描述,Bits 27:24 TRCD[3:0]: Row to column delay 此处可以设为1~16来设置最小值,demo设置的为2(30ns) > 最小值20ns符合芯片时序要求。 $ U& f* p- f h8 c( ~SDRAM_Timing.RCDDelay = 2;, \9 } I9 z8 W, M (, 下载次数: 14) 上传 点击文件名下载附件 ) @/ A9 r8 q0 r% `! v& }8 f" z& L; {& b3 w: e5 ~# f( v 芯片手册的TRRD时间最小值为14ns 0 f% v9 @9 z7 S( z$ P+ ?: Q (, 下载次数: 14) 上传 点击文件名下载附件 9 r, v: b+ s5 z7 b & A; ]4 O. v. x: n代码配置为3个时钟周期,30ns满足芯片的最小时间要求。 * S) c+ v: c- WSDRAM_Timing.RPDelay = 2;) o/ ^0 F/ ]+ H8 J* w % A; [; N5 G" n7 ~CAS 根据手册的描述指的是,模式寄存器中的 CASLatency 是指列地址选通延迟,简称 CL。在发出读命令(命令同时包含列地址)后,需要等待几个时钟周期数据线 DQ 才会输出有效数据,,手册上描述支持1,2,3(Supports CAS latency of 1, 2, and 3)个周期,769的FMC控制器支持CAS latency of 1,2,3三种配置,demo中配置的为2。 0 f: s+ U9 o4 e( }+ B1 R& W' w& k4 U J- }! d9 l hsdram.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_2;改参数设置的为SDRAM的模式寄存器的CASLatency位。 ' w' B) }' F- W! U ~ ) }( P! ` r! N; { 7 j6 Z! J! i. S (, 下载次数: 15) 上传 点击文件名下载附件 - g7 h% I; v; [3 \+ c/ w : P' i3 ?3 W) w/ |7 ~7 W' B (, 下载次数: 15) 上传 点击文件名下载附件 ( p7 K5 d( j/ ? (, 下载次数: 12) 上传 点击文件名下载附件 ; e' G6 `4 } N) H. s M% D ' L9 L8 r+ _: w; E9 c, StXSR (These bits define the delay from releasing the Self-refresh command to issuing the Activate command in number of memory clock cycles. )自刷新命令后,可以执行Active command 的时间间隔芯片手册描述最小为(70ns)。 7 q G# }% u+ N+ g / h, R5 h: W5 P6 p8 o& n (, 下载次数: 15) 上传 点击文件名下载附件 % c& d( L7 _) V) v" y4 j7 ? ( j# u* I" D& a9 O Z! eSDRAM_Timing.ExitSelfRefreshDelay = 6; demo中设定为70ns - q; j( I. j6 b3 C" ctRAS (These bits define the minimum Self-refresh period in number of memory clock cycles.)刷新周期,刷新率,手册要求最小值为42ns. a: C9 z* E# i+ @8 @+ p" i* c+ g. u& w' O+ n+ ~1 S* y SDRAM_Timing.SelfRefreshTime = 4;demo中设定为50ns满足要求' l. D; R- q: o+ ?' { tMRD 设定load mode 命令和 active 指令之间的时间间隔,手册上最小值为2个时钟周期 h& c9 o' E: a8 c " o' |8 X3 J2 A# J% j8 E4 pBits 3:0 TMRD[3:0]: Load Mode Register to Active % s! @: k" z4 V; E. JThese bits define the delay between a Load Mode Register command and an Active or Refresh9 ~- V! N" a9 g% x3 Q command in number of memory clock cycles. * \: b7 |( A v% P, G0000: 1 cycle # C8 @( n# J, o" T' S# E0001: 2 cycles+ H$ M, F* K9 }1 O/ X) W: I .... % V" P$ c/ x5 Z) w1111: 16 cycles % Z L. x* s* W) e' g% P' E! J3 t! w; s! j4 u1 l: U# k SDRAM_Timing.LoadToActiveDelay = 2;demo中设置为3个时钟周期满足芯片要求 # u8 c7 E# f m" BtRC(ACTIVE to ACTIVE command period) 芯片手册描述的为70ns,代码中设置为70ns * p6 n* G2 \3 a9 V/ u O' L H; V4 |- N- D5 @) G/ Q9 z9 I SDRAM_Timing.RowCycleDelay = 6;9 @( ]% O, h9 }( K9 y# J, H tWR:WRITE recovery time( Auto precharge mode only )芯片手册描述为1CLK+7ns,针对本demo为17ns,demo代码的SDRAM_Timing.WriteRecoveryTime = 2; 30ns符合要求。 ) L) r& ]+ i& x4 \0 n/ V, k8 y" {6 A& g# A) q7 l4 R1 L# d0 q9 X6 x (, 下载次数: 12) 上传 点击文件名下载附件 # H* k& R. Y9 ^- {769文档上对这个几个时间有此要求:TWR ≥ TRAS - TRCD and TWR ≥TRC - TRCD - TRP 3 f! v4 P& ^7 E* { ( ~- N o) o3 H! P- ?! _; WTWR=30ns ,TRAS = 50ns,TRCD = 30ns,TRC = 70ns ,TRP = 30ns. h" ^! F) M2 Y: N; e8 p . w9 w2 S0 t% A0 q7 Y 2 F0 B1 W) W$ l/ v# O, z6 h时间参数满足上述要求。下图为SDRAM初始化流程图。 4 h5 {& t+ F: Z; w/ Q, @/ c3 g7 i6 q$ h$ u3 M# K (, 下载次数: 14) 上传 点击文件名下载附件 # |% r8 H& A- t 3 @9 ^* h% V# Z 该流程说明如下: 9 R; d/ U) a6 T. \8 s(1) 给 SDRAM 上电,并提供稳定的时钟,至少 100us;* s& C2 I0 k" m1 U3 E' N (2) 发送“空操作” (NOP)命令; # L- {) [( c* {5 s0 C(3) 发送“预充电” (PRECHARGE)命令,控制所有 Bank 进行预充电,并等待 tRP 时间,tRP 表示预充电与其它命令之间的延迟; 2 c5 ~/ ?2 W+ p: a(4) 发送至少 2 个“自动刷新” (AUTO REFRESH)命令,每个命令后需等待 tRFC 时间, tRFC表示自动刷新时间; 3 Z }, b% v4 \$ k" h) p(5) 发送“加载模式寄存器” (LOAD MODE REGISTER)命令,配置 SDRAM 的工作参数,并等待 tMRD时间, tMRD表示加载模式寄存器命令与行有行或刷新命令之间的延迟; % u, c( \0 @1 C0 Z4 ?4 D(6) 初始化流程完毕,可以开始读写数据。 : R- u. H0 n+ D9 L$ x (, 下载次数: 12) 上传 点击文件名下载附件 ! Q) q- h9 y, i7 M/ [6 @# T # \2 p3 o" f6 L1 B(1) 发送“行有效” (ACTIVE)命令,发送命令的同时包含行地址和 Bank 地址,然后等待 tRCD时间, tRCD表示行有效命令与读/写命令之间的延迟;$ M3 I& c- O) x4 u! X6 Q) ]0 w (2) 发送“读/写” (READ/WRITE)命令,在发送命令的同时发送列地址,完成寻址的地址输入。对于读命令,根据模式寄存器的 CL 定义,延迟 CL 个时钟周期后,SDRAM 的数据线 DQ 才输出有效数据,而写命令是没有 CL 延迟的,主机在发送写命令的同时就可以把要写入的数据用 DQ 输入到 SDRAM 中,这是读命令与写命令的时序最主要的区别。图中的读/写命令都通过地址线 A10 控制自动预充电,而 SDRAM 接收到带预充电要求的读/写命令后,并不会立即预充电,而是等待tWR 时间才开始, tWR 表示写命令与预充电之间的延迟; ( r( ]1 w. T& ^* l(3) 执行“预充电” (auto precharge)命令后,需要等待 tRP 时间, tRP 表示预充电与其它命令之间的延迟; : R9 S l) k% I(4) 图中的标号处的 tRAS,表示自刷新周期,即在前一个“行有效”与 “预充电”命令之间的时间;, ]7 e6 l/ N ~: k+ @5 x (5) 发送第二次“行有效” (ACTIVE)命令准备读写下一个数据,在图中的标号处的tRC,表示两个行有效命令或两个刷新命令之间的延迟。 / T# a8 S) Z) P( f/ e其中 tRCD、 tWR、 tRP、 tRAS 以及 tRC 等时间参数跟具体的 SDRAM 有关,可查阅其数据手册获知, STM32 FMC 访问时配置需要这些参数。 / Y9 z# W1 K( X* V, P0 i7 Z( L; |- l3 y9 k =======================参考资料=========================" g7 e7 W" \3 O6 r& u" A( c (, 下载次数: 4) 上传 点击文件名下载附件 ' T3 b0 b5 I0 f* |+ k. K (, 下载次数: 17) 上传 点击文件名下载附件 4 b- g k! v- _# k6 p) M# J7 z ) R( |1 E/ t& ^$ S3 R8 X7 A5 q" q2 B% E0 J% i j 7 D' x+ [: C; p 1 R+ s/ e1 Y9 b$ A# _( B4 g( b* c! x: z6 p 7 N6 R5 r$ A0 O$ V9 h- ^( A* j1 w, G0 o ; v" L5 |+ z! ~8 V X3 T* v % T y# ]2 e0 w: t" q/ W6 }2 L3 a( t' u1 V7 R/ E : A6 D4 W9 s+ _! v+ O5 r, s9 |# H % K0 Q5 T9 H8 K " `* {; H& {9 D ( u2 y. S, u3 P' \& w! H- O |$ r6 u" I- V# [ 4 A3 T3 y+ ~) M! U% z. g ! J8 }9 o" |# Y! R/ K$ u: h% p( n; F, `. \- G" w7 L: E , g+ f# Q9 w2 }/ L . @8 Q0 o( ~& b3 x X. F; f1 X& \( x 9 ^6 U3 W: l0 ?& a( c . Z$ ^5 C) O& y/ B