EDA365电子论坛网

标题: SDRAM操作代码分析 [打印本页]

作者: grand    时间: 2021-11-26 13:28
标题: SDRAM操作代码分析
本帖最后由 grand 于 2021-11-26 15:54 编辑 ( c8 c+ j3 {2 S8 G

6 k( d% [( v; Y" {不多说先放代码:# A' m0 T/ G" o8 D* {1 R! U

3 @$ b, k% X8 g6 |4 k! L9 \' \5 @9 S' P( J
<span style="font-size:18px;"><span style="font-size:14px;">#include <csl.h>
& E* _' f3 r- ^- w  O8 r: u#include <csl_pll.h>
" }( T/ v! m3 U2 k#include <csl_emif.h>
( \* o. k2 \+ |- y% \4 o#include <csl_chip.h>$ Z- F/ \: i3 N( S5 o+ M; v- _" O
#include <stdio.h>
* q+ H* Y5 B- _* g% s5 x
  {; M( M+ w5 P, Y7 FUint16 x;$ d8 ^! G% n% j' h- ?
Uint32 y;
: W7 R5 U3 S1 b6 ]! P$ [CSLBool b;
0 ?* J" h  Q1 E6 @; ?1 f( i6 T! Bunsigned int datacount = 0;3 y: D% u  Z3 ?1 M. G7 o
int databuffer[1000] ={0};
$ v" j' j% ~" I" ~- Q" \int *souraddr,*deminaddr;
6 f. j' \+ ]. \" z4 ~0 M+ h/*锁相环的设置*/
' H; v# g, T& D  \" a& tPLL_Config  myConfig      = {+ ]( i) D- n. G8 Z: g; P& X
  0,    //IAI: the PLL locks using the same process that was underway # g0 y4 E, H( P1 e1 j, h
                //before the idle mode was entered  \! T; M! e6 N8 a3 i
  1,    //IOB: If the PLL indicates a break in the phase lock,
' u" z  m- R- b                //it switches to its bypass mode and restarts the PLL phase-locking
7 Z+ O' p3 {4 ?1 N* k                //sequence
; F# j3 I: H$ h- q6 y3 R  20,    //PLL multiply value; multiply 20 times, H/ e; o) }; K/ z0 G0 B! Y" x
  1             //Divide by 2 PLL divide value; it can be either PLL divide value 2 R; V6 e0 p9 Q
                //(when PLL is enabled), or Bypass-mode divide value
. c% F5 l7 \/ W                //(PLL in bypass mode, if PLL multiply value is set to 1)3 L5 ^. L8 @# h$ B& y5 F
};  s. B+ w- A) V" J& R9 c
/*SDRAM的EMIF设置*/
/ `1 j1 G6 Y' W4 C$ tEMIF_Config emiffig = {0 |1 [+ ]$ Q3 J- w
  0x0021,     //EGCR  : the MEMFREQ = 00,the clock for the memory is equal to cpu frequence
% u1 Q2 b8 Z0 C% o7 R( l- O              //          the WPE = 0 ,forbiden the writing posting when we debug the EMIF
' q( v! D+ S, v              //        the MEMCEN = 1,the memory clock is reflected on the CLKMEM pin
& y) e/ N+ k+ e/ r& m* x. |              //        the NOHOLD = 1,HOLD requests are not recognized by the EMIF
  T# X7 E. K9 {& t" g  0xFFFF,    //EMI_RST: any write to this register resets the EMIF state machine3 H( I9 A  W. e9 v6 @6 p
  0x3FFF,    //CE0_1:  CE0 space control register 13 x3 N  m, {& A
              //        MTYPE = 011,Synchronous DRAM(SDRAM),16-bit data bus width/ o9 p6 I6 ~. }, c! z% `2 L( X
  0xFFFF,   //CE0_2:  CE0 space control register 2
; T8 |% h% u, Z% T  0x00FF,   //CE0_3:  CE0 space control register 3* J  s4 E7 P9 M  L0 ?" r
              //        TIMEOUT = 0xFF;
% z/ [' i( K2 ]5 ~& c1 J# o# y  t  0x7FFF,    //CE1_1:  CE0 space control register 1$ ]7 z* t9 H- G0 h; t: O
  0xFFFF,    //CE1_2:  CE0 space control register 2: b: C9 i0 t7 d# z' v
  0x00FF,    //CE1_3:  CE0 space control register 30 k  h% q1 z! M5 t/ l/ H$ n
  # q: r6 W5 D/ G- l
  0x7FFF,    //CE2_1:  CE0 space control register 19 O) {. N' f3 n1 o# }! l. K( V2 F: y
  0xFFFF,    //CE2_2:  CE0 space control register 2
: [5 Y- \7 Z, b. T: n8 P  0x00FF,    //CE2_3:  CE0 space control register 3
; u. B, `9 M, ^6 u5 L, E6 h/ T  
# ]5 w* D! S$ }' d  0x7FFF,    //CE3_1:  CE0 space control register 1
+ Q1 {! s! p. S1 l2 z' d' Q  0xFFFF,    //CE3_2:  CE0 space control register 24 ^& L6 Z. e2 h( n8 i
  0x00FF,    //CE3_3:  CE0 space control register 3- b! H7 E7 _& [# q; q/ H3 f
  7 b; s* ~/ {! \" E, W+ ?; \
  0x2922,   //SDC1:   SDRAM control register 1! `6 ~# L4 e- N0 G+ x/ _
              //          TRC = 8     
: L& b5 z) A4 _. _- }  O              //        SDSIZE = 0;SDWID = 0
  M8 ~5 l( k5 I" o2 P              //        RFEN = 1
+ G$ S% E. D; s# w# h, g+ ]              //        TRCD = 2* i  w! k2 a& x1 _. _; d
              //        TRP  = 2
" g# x7 P( k2 e% d$ O  0x0410,    //SDPER : SDRAM period register: G4 I' Q/ |- N9 r0 m2 C3 p
              //          7ns *4096
; Y3 _) |' P4 J- z  0x07FF,    //SDINIT: SDRAM initialization register
( l6 t1 t$ }8 a) s* n4 p+ M+ |              //        any write to this register to init the all CE spaces,
$ f; o8 s. I: B3 p, P( \6 F5 |. c              //        do it after hardware reset or power up the C55x device# a$ ^2 F. d2 Q
  0x0131    //SDC2:      SDRAM control register 2- f) K! w. j2 N% O
              //        SDACC = 0;( y  P, T- P4 o$ f7 t
              //        TMRD = 01;0 h; G% {2 d2 e) S; w
              //        TRAS = 0101;
: z) T% H* s4 b& x! t4 K              //        TACTV2ACTV = 0001;                                
2 E; i: Q# a- Z: l. p  };1 L* ?* n! {7 r$ f( P( G  D
& w4 m2 F7 ?" ^" k' Y. B( J
  g7 H( Q5 \3 F) ?, e$ X
main()# X+ c  G  Q  B& E& _6 [
{
! X3 S0 t0 U: B8 l7 |3 P    unsigned int error=0;) ]) N: z  D; V4 x( \
    /*初始化CSL库*/    0 @4 B4 V. p/ Z; w& Z6 o/ [
    CSL_init();
) q$ q0 C1 ~( \4 b, c$ }    : m- I" |! U: f6 I* L& f8 {
    /*EMIF为全EMIF接口*/
$ q8 h) o9 N+ ^- `5 ?    CHIP_RSET(XBSR,0x0a01);5 g( K  `% X5 m4 t0 O% z" X7 p/ y
    ! @- s7 M* v& e. V
    /*设置系统的运行速度为120MHz*/2 y6 ^7 J4 ]6 z/ t* W& \$ Y5 D
    PLL_config(&myConfig);
0 i( g: o# b% w    , p( n/ j6 N% k. _( R0 E. \# a4 x2 k- x3 G& a
    /*初始化DSP的外部SDRAM*/- _) I; a8 U- D( y5 u3 o
    EMIF_config(&emiffig);) d4 \! l& U' r+ W
    /*向SDRAM中写入数据*/
( I3 I% Q8 k3 I& u- {+ L) B
6 ]! _- f7 b5 n) D    souraddr =  (int *)0x40000;
* ?; v9 s/ z3 Z, i0 a# ^! a    deminaddr = (int *)0x41000;4 P9 o+ o) E  h5 }+ R4 b8 C, l) I
    while(souraddr<deminaddr)0 L: i$ @$ Q, a3 T- g; B( A& k
    {9 T5 J4 s5 A* f" J( W
        *souraddr++ = datacount;   
; l+ ]2 b4 C* O4 C5 L        datacount++    ;. J# o0 t& c9 w  H9 o' _8 l4 z
    }
$ d  [: f* i9 w( d    /*读出SDRAM中的数据*/
/ v! N% _: M8 h9 U    souraddr =  (int *)0x40000;
8 Z" @7 n) s) {, _8 H# s    datacount = 0;
+ |( i6 S- }3 G6 w. r+ T$ D    while(souraddr<deminaddr)6 U  N  \' ^, G0 H
    {
- t) R0 R; c  h# s        databuffer[datacount++] = *souraddr++;
$ ^1 R1 x& ^3 ]& w3 V( @% \0 ^' g        if(databuffer[datacount-1]!=(datacount-1))
9 n0 r3 x3 t; s            error++;; j- N! y% Q# ?* C* ?& a
    }& h* ~+ x1 p+ H2 L! u1 c
4 w1 S* g1 T: `0 x3 v" W
    while(1);
6 f8 B% M4 P: ^. M: z& r/ R5 j}
6 }$ O7 Y7 A+ V( e/*************************</span></span># Y2 l# a& D1 B- |  [, C
下面分部分分析:
7 Q5 ^9 T! o7 x1 I* T: D锁相环的设置:PLL_Config结构体是在csl_pllA.H中定义的* q  ?' {9 [$ H+ `  k5 b# @/ }3 B

, I2 p0 D+ L( p' I3 }* r$ r( g% l& t
PLL锁相环的配置寄存器Clock Mode Register (CLKMD)的各位的详细描述 在5509A的datasheet里是没有的,
  u, M; ]* {3 Q
+ s' w$ L* {, i在overview_spru317f.pdf里有详细介绍,想要的发评论留下方式我发给你。
$ O  Z, w/ i1 R2 M$ V) P8 S& l* K! m7 {/ m$ p+ q/ H; K! {' [
IAI:Initialize after idle bit.IAI=0表示The PLL locks using the same process that was underwaybefore the idle 1 ?1 \: r7 E  n9 T9 z

. T0 V# e; ]! S% J% t& ^mode was entered。5 y) g* r* @& s$ p8 G0 t9 c/ c, H9 z
7 u" m+ F' `& Z3 O  Y
翻译过来大致就是在进入空闲模式之前PLL lock使用相同的方式。' {# Z, p0 K. i% d! ~
7 r3 Y; X9 |- p
IOB:Initialize on break bit. IOB=1:时钟发生器选择它的旁路模式并且重启锁相序列。" D6 \: J  ?% r. O7 `8 _% ?
PLL MULT:pll倍频位。pllmult=20,输入时钟频率倍频20倍
5 m! i, e2 p6 A& F% V) oPLL DIVLL分频位。plldiv=1,输入频率分频28 I% V2 D. D! j7 _  p7 p
我的开发板外接频率是12MHZ,倍频20,再分频2以后系统时钟频率就是12*20/2=120MHZ。
$ Q4 D6 ?5 X- KSDRMA的EMIF设置:0 c4 O  Z) h' z1 C% ]" ~; O! M
EMIF_Config结构体在csl_emifA.h中定义3 y$ q* @; \3 x/ {; k
2 a9 t6 h/ R/ K1 j9 E
' q8 s% _3 b% }+ v; f
结构体里每个参数都是寄存器的名字,每个寄存器的具体描述在datasheetemif_spru670.pdf中,
# ~, N2 V: k& l# Q+ Q. v! K+ f6 {, [$ ]7 I3 t2 p. @, q0 X4 c
在5509A的datasheet中并没有具体的描述,只有寄存器的memory map。
1 o) }2 c6 j5 G0 M1 O9 E  I5 r# z4 Z- q8 B, A9 G
5509A的外扩内存映射被分成4个CE片选空间,每个空间可以扩展4Mx16,5 C; B' L% o5 ~- R$ L) Z) d

# V( e4 z% s" y  v$ x) _/ d$ lEMIF Global Control Register (EGCR):MEMFREQ的9-11位是000,CLKMEM的频率就等于
# a% k2 @' a) ?9 f  b  Z5 L$ w' S7 M- A
- U: H2 N/ U' [- U; k0 kcpu的时钟频率(120mhz),
( n" D* [' v2 g% [9 s0 v0 \: Z
- e' C. G8 o5 c: ~+ `, R. D8 ]但是对于5509A芯片来说,如果MEMFREQ=000b,SDRAM控制寄存器3的DIV1位必须设置为1,
) a/ W, t' y7 l3 b1 N' e( o4 c# ~' b) w7 F* h$ w! z
但是结构体中并没有定义SDC3(SDRAM Control Register 3 ),晚上回实验室再补上SDC3的定义试试,应该可以通过。
6 g) F' R3 L3 ~3 q
: ?' E+ }! G( @4 v- JEMIF Global Reset Register (EMIRST):用默认的0xFFFF就行。
5 N( d: ~; g! n3 u
* f+ e  Y( Y0 n- y% e" VCE Space Control Registers (CEn1, CEn2, and CEn3 in Each CE Space):外部的内存memory map 9 L* o9 b( t0 ]; X( M* r8 ?
被分成4个CE空间,
; ^0 ~% h6 B  s6 Q; x* P每个CE空间都3个CE控制寄存器,
2 z: ~' B( q1 Q) J分别是CEn1, CEn2, and CEn3 ,n是表示的4个CE空间,CE0空间寄存器就是CE01,CE02,CE03,以此类推。
  k% `' h4 H+ f3 e  y1 W我的开发板外接的SDRAM是4MX16的,4M是内存大小,16是数据位宽D0-D15,所以CE0的片选空间被完全占用,! o9 S3 M9 c/ A; {& s* y
只用到了CE0的3个寄存器,其他3个CE空间不适用,也是将CEn1寄存器的MTYPE位设置为0x7FFF(只要MTYPE不是00,01,10,11,认识数值都可以,具体描述看手册)。其他的寄存器数值配置按默认的就可以。
( E, @5 F! d! a2 M" X7 s! H* L/ o, D- e$ H; C$ {: _8 Y
* |9 R6 B# r+ y' T9 L
SDRAM寄存器配置:
/ B  l8 S& ~4 t8 ^  s! uSDRAM Control Registers 1 and 2 (SDC1 and SDC2):SDRAM控制寄存器主要就是配置SDRAM的时序,: e( o, l  L) k$ u6 j& S
这要结合SDRAM的厂家提供的时序资料来配置。
' K& L* o6 w9 `( K$ _* `3 m
% n. t7 }( c+ c, q9 x 4 K, C, B6 ?: U; ^3 E
这里就举一个例子,其他的类似。+ C, C8 y8 D; E6 ~
SDC1=0x2911,TRP[3:0]=0010,; y% G0 W& w: ~. y$ y; ]7 q( z
TRP = (tRP/CLKMEM) − 1:
9 M  y5 p. u7 q4 o! r" E' j查看SDRAM的厂家datasheet,查tTP的参考数值,发现,tRP最小值是20ns,CLKMEM的时钟频率就是前面设置的120MHZ,周期t=1/120MHZ=8ns,.tRP=24ns。$ ]9 c* F9 \& Q/ o+ K+ x2 l  M

1 D8 |7 T& S$ i6 J/ B4 r $ N( _* [5 ^+ Y4 i' G$ h7 ]8 v
Main函数分析
0 }9 y7 {9 w. J; B8 Q2 l) Z2 ]CSL_init();使用CSL库必须要用这个函数初始化CSL库,而且只需要初始化一次。, e! F3 h7 x# A4 q$ m4 X
CHIP_RSET(XBSR,0x0a01);配置EMIF为全EMIF接口,XBSR是寄存器External Bus Selection Register简称。
* K7 I) C, l! Q8 Hox0a01就是将EMIF配置成全emif模式。
% Q* I; C! n$ z& w  s souraddr =  (int *)0x40000;是SDRAM起始地址1 m- ^& K: D; V/ k: J, Y
deminaddr = (int *)0x41000;结束地址
! l% C, Q! z& L& B; @接下来的程序就是写,读数据了。
2 f- \: d, x5 ^3 {% {) P+ n
: D3 e5 o" a0 |  p: f0 B/ ^5 l# z8 ?# u& w) |' V

作者: CLBuu    时间: 2021-11-26 15:06
使用CSL库必须要用这个函数初始化CSL库,而且只需要初始化一次
作者: MLXG    时间: 2021-11-26 15:55
ox0a01就是将EMIF配置成全emif模式
作者: muzitongxue    时间: 2021-11-26 15:55
在进入空闲模式之前PLL lock使用相同的方式




欢迎光临 EDA365电子论坛网 (https://bbs.eda365.com/) Powered by Discuz! X3.2