s3c2440存储控制器详解

从上图可知,外部内存类的设备与存储管理器相连,那么CPU是怎样访问到内存的呢?经过存储管理器。CPU比较单纯,只会按照指令执行,CPU只负责发出地址,怎样找到内存类设备呢?这些都交给存储管理器来管理。linux

s3c2440对外引出的27根地址线ADDR0-ADDR26的访问范围只有128M,那么如何达到1G呢,CPU还对外引出了8条片选线nGCS0-nGCS7,对应于bank0-bank7,当访问BANKX的地址空间时,nGCSx输出低电平选中外部芯片,这样就能达到1G的地址空间。以下图性能

s3c2440做为32位的CPU,可使用的地址理论上是4G,除了存储器管理的1G,还有内部的寄存器占用地址外,其余的地址剩下没用。s3c2440的内部寄存器地址范围是0x48000000-0x5FFFFFFF,各功能部件的功能大致相同。
下图是内部寄存器地址分布:spa

SDRAM内存工做原理
SDRAM的内部是一个存储阵列。阵列就如同表格同样,将数据“填”进去。在数据读写时和表格的检索原理同样,先指定一个行(Row),再指定一个列(Column),咱们就能够准确地找到所须要的单元格,这就是内存芯片寻址的基本原理,如图所示。prototype

这个单元格(存储阵列)就叫逻辑 Bank(Logical Bank,下文简称 L-Bank)。 因为技术、成本等缘由,不可能只作一个全容量的 L-Bank,并且最重要的是,因为SDRAM的工做原理限制,单一的 L-Ban k将会形成很是严重的寻址冲突,大幅下降内存效率。因此人们在 SDRAM内部分割成多个 L-Bank,目前基本都是 4个(这也是SDRAM规范中的最高L-Bank数量),因而可知,在进行寻址时就要先肯定是哪一个 L-Bank,而后在这个选定的 L-Bank中选择相应的行与列进行寻址。所以对内存的访问,一次只能是一个 L-Bank工做。

当对内存进行操做时,先要肯定操做L-Bank,所以要对L-Bank进行选择。在内存芯片的外部管脚上多出了两个管脚BA0, BA1,用来片选4个L-Bank。如前所述, 32位的地址长度因为其存储结构特色,分红了行地址和列地址。经过下面的内存结构图可知,内存外接管脚地址线只有13根地址线A0~A12,它最多只能寻址8M内存空间,到底使用什么机制来实现对64M内存空间进行寻址的呢?SDRAM的行地址线和列地址线是分时复用的,即地址要分两次送出,先送出行地址(nSRAS行有效操做),再送出列地址(nSCAS列有效操做)。这样,能够大幅度减小地址线的数目,提升器件的性能和制做工艺复杂度。但寻址过程也会所以而变得复杂。实际上,如今的SDRAM通常都以L-Bank为基本寻址对象的。由L-Bank地址线BAn控制L-Bank间的选择,行地址线和列地址线贯穿链接全部的L-Bank,每一个L-Bank的数据的宽度和整个存储器的宽度相同,这样,能够加快数据的存储速度。同时,BAn还可使未被选中的L-Bank工做于低功耗的模式下,从而下降器件的功耗。

这些都是内存的原理部分,其实做为工程师,可以正确配置存储管理器的相关的寄存器,就能够对内存进行初始化,可使用了。
下面是配置存储管理器的思路及方法:code

以jz2440为例:对象

一、肯定BA0、BA1的接线
经过阅读s3c2440手册,能够看出CPU ADDR24和ADDR25
解释一下名词:
Bank Size: 外接内存容量大小(HY57561620是4Mbit*16bit*4Bank*2Chips/8=64MB)
Bus Width: 总线宽度 (两片16位HY57561620,并联成32位)
Base Component:单个芯片容量(bit)(256Mb)
Memory Configration:内存配置 ((4M*16*4banks)*2Chips )

使用A[25:24]两根地址线做为Bank片选信号,正好两根接线能够片选每一个存储单元的4个BANKS。
S3C2440提供的两片16位芯片并联链接示意图,An是CPU地址总线,其中A2~A14为内存芯片寻址总线,之因此地址寻址总线从A2开始是由于内存地址都是按字节对齐的,,A24,A25为L-Bank片选信号,Dn为CPU数据总线,其它为对应控制信号线。blog

S3C2440A为32位CPU,也就是说其数据总线和地址总线宽度都是32位(能够理解为32根线一端链接CPU内部,另一端链接向内存控制器),那么内存数据的输入/输出端也要保证是32位总线,jz2440上采用两片16位宽总线内存芯片并联构成32位总线。其中一个芯片链接到CPU数据总线的低16位,另一个芯片链接到数据总线上的高16位,并联成32位总线,所以两个芯片的输入/输出总线链接到CPU总线上的不一样管脚上。ip

 

1、SDRAM的读操做
SDRAM进行读操做时,先向地址线上送上要读取数据的地址,经过前面的知识了解到,地址被分红3部分,行地址,列地址,L-Bank片选信号。片选(L-Bank的定址)操做和行有效操做能够同时进行。
在CS、L-Bank定址的同时,RAS(nSRAS行地址选通讯号)也处于有效状态。此时 An地址线则发送具体的行地址。A0~A12,共有13根地址线(可表示8192行),A0~A12的不一样数值就肯定了具体的行地址。因为行有效的同时也是相应 L-Bank有效,因此行有效也可称为L-Bank有效。
行地址肯定以后,就要对列地址进行寻址了。可是,地址线仍然是行地址所用的 A0~A12。没错,在SDRAM中,行地址与列地址线是复用的。列地址复用了A0~A8,共9根(可表示512列)。那么,读/写的命令是怎么发出的呢?其实没有一个信号是发送读或写的明确命令的,而是经过芯片的可写状态的控制来达到读/写的目的。显然WE信号(nWE)就是一个关键。WE无效时,固然就是读取命令。有效时,就是写命令。
SDRAM基本操做命令, 经过各类控制/地址信号的组合来完成(H表明高电平,L表明低电平,X表示高,低电平均没有影响)。此表中,除了自刷新命令外,全部命令都是默认CKE(SCKEl输入时钟频率有效)有效。列寻址信号与读写命令是同时发出的。虽然地址线与行寻址共用,但CAS(nSCAS列地址选通讯号)信号则能够区分开行与列寻址的不一样,配合A0~A8,A9~A11来肯定具体的列地址。
读取命令与列地址一块发出(当WE为低电平是即为写命令)然而,在发送列读写命令时必需要与行有效命令有一个间隔,这个间隔被定义为 tRCD,即RAS to CAS Delay(RAS至 CAS延迟),这个很好理解,在地址线上送完行地址以后,要等到行地址稳定定位后再送出列地址,tRCD是SDRAM的一个重要时序参数,相关数值参看对应芯片硬件手册。一般tRCD以时钟周期(tCK,Clock Time)数为单位,好比笔者MINI2440所用内存芯片里面写到tRCD为20nst,若是未来内存工做在100MHz,那么RCD至少要为2个时钟周期, RCD=2。内存

SDRAM读操做时序图资源

在选定列地址后,就已经肯定了具体的存储单元,剩下就是等待数据经过数据 I/O通道(DQ)输出到内存数据总线上了。可是在列地址选通讯号CAS 发出以后,仍要通过必定的时间才能有数据输出,从CAS与读取命令发出到第一笔数据输出的这段时间,被定义为 CL(CAS Latency,CAS潜伏期)。因为CL只在读取时出现,因此CL又被称为读取潜伏期(RL,Read Latency)。CL的单位与tRCD同样,也是时钟周期数,具体耗时由时钟频率决定(笔者官方手册CL=3)。不过,CAS并非在通过CL周期以后才送达存储单元。实际上CAS与RAS同样是瞬间到达的。因为芯片体积的缘由,存储单元中的电容容量很小,因此信号要通过放大来保证其有效的识别性,这个放大/驱动工做由S-AMP负责。但它要有一个准备时间才能保证信号的发送强度,这段时间咱们称之为tAC(Access Time from CLK,时钟触发后的访问时间)。

 2、SDRAM预充电操做
本来逻辑状态为1的电容在读取操做后,会因放电而变为逻辑0。因为SDRAM的寻址具备独占性,因此在进行完读写操做后,若是要对同一L-Bank的另外一行进行寻址,就要将原先操做行关闭,从新发送行/列地址。在对原先操做行进行关闭时,DRAM为了在关闭当前行时保持数据,要对存储体中原有的信息进行重写,这个充电重写和关闭操做行过程叫作预充电,发送预充电信号时,意味着先执行存储体充电,而后关闭当前L-Bank操做行。预充电中重写的操做与刷新操做(后面详细介绍)同样,只不过预充电不是按期的,而只是在读操做之后执行的。

3、SDRAM突发操做
突发(Burst)是指在同一行中相邻的存储单元连续进行数据传输的方式,连续传输所涉及到存储单元(列)数量就是突发长度(Burst Length,简称BL)。
在目前,因为内存控制器一次读/写P-Bank位宽的数据,也就是8个字节,可是在现实中小于8个字节的数据不多见,因此通常都要通过多个周期进行数据的传输,上文写到的读/写操做,都是一次对一个存储单元进行寻址,若是要连续读/写,还要对当前存储单元的下一单元进行寻址,也就是要不断的发送列地址与读/写命令(行地址不变,因此不用再对地寻址)。虽然因为读/写延迟相同可让数据传输在I/O端是连续的,可是它占用了大量的内存控制资源,在数据进行连续传输时没法输入新的命令效率很低。为此,引入了突发传输机制,只要指定起始列地址与突发长度,内存就会依次自动对后面相应长度数据的数据存储单元进行读/写操做而再也不须要控制器连续地提供列地址,这样,除了第一笔数据的传输须要若干个周期(主要是之间的延迟,通常的是tRCD + CL)外,其后每一个数据只需一个周期便可。

SDRAM写操做
SDRAM的基本写操做也须要控制线和地址线相配合地发出一系列命令来完成。先发出芯片有效命令,并锁定相应的L-BANK地址(BA0、BA1给出)和行地址(A0~A12给出)。芯片有效命令发出后必须等待大于tRCD的时间后,发出写命令数据,待写入数据依次送到DQ(数据线)上。在最后一个数据写入后,延迟tWR时间。发出预充电命令,关闭已经激活的页。等待tRP时间后,能够展开下一次操做。写操做能够有突发写和非突发写两种。突发长度同读操做。

写操做时序以下图:

4、SDRAM的刷新

SDRAM之因此成为DRAM就是由于它要不断进行刷新(Refresh)才能保留住数据,所以它是SDRAM最重要的操做。
刷新操做与预充电中重写的操做同样,都是用S-AMP先读再写。但为何有预充电操做还要进行刷新呢?由于预充电是对一个或全部 L-Bank中的工做行操做,而且是不按期的,而刷新则是有固定的周期,依次对全部行进行操做,以保留那些很长时间没经历重写的存储体中的数据。但与全部L-Bank预充电不一样的是,这里的行是指全部L-Bank中地址相同的行,而预充电中各L-Bank中的工做行地址并非必定是相同的。那么要隔多长时间重复一次刷新呢?目前公认的标准是,存储体中电容的数据有效保存期上限是64ms(毫秒,1/1000秒),也就是说每一行刷新的循环周期是64ms。这样刷新时间间隔就是: 64m/行数s。咱们在看内存规格时,常常会看到4096 Refresh Cycles/64ms或8192 Refresh Cycles/64ms的标识,这里的4096与8192就表明这个芯片中每一个L-Bank的行数。刷新命令一次对一行有效,刷新间隔也是随总行数而变化,4096行时为 15.625μs(微秒,1/1000毫秒),8192行时就为 7.8125μs。刷新操做分为两种:Auto Refresh,简称AR与Self Refresh,简称SR。不管是何种刷新方式,都不须要外部提供行地址信息,由于这是一个内部的自动操做。对于 AR,SDRAM内部有一个行地址生成器(也称刷新计数器)用来自动的依次生成行地址。因为刷新是针对一行中的全部存储体进行,因此无需列寻址,或者说CAS在 RAS以前有效。因此,AR又称CBR(CAS Before RAS,列提早于行定位)式刷新。因为刷新涉及到全部L-Bank,所以在刷新过程当中,全部 L-Bank都中止工做,而每次刷新所占用的时间为9个时钟周期(PC133标准),以后就可进入正常的工做状态,也就是说在这9个时钟期间内,全部工做指令只能等待而没法执行。64ms以后则再次对同一行进行刷新,如此周而复始进行循环刷新。显然,刷新操做确定会对SDRAM的性能形成影响,但这是没办法的事情,也是DRAM相对于 SRAM(静态内存,无需刷新仍能保留数据)取得成本优点的同时所付出的代价。SR则主要用于休眠模式低功耗状态下的数据保存,这方面最著名的应用就是 STR(Suspend to RAM,休眠挂起于内存)。在发出AR命令时,将CKE置于无效状态,就进入了SR模式,此时再也不依靠系统时钟工做,而是根据内部的时钟进行刷新操做。在SR期间除了CKE以外的全部外部信号都是无效的(无需外部提供刷新指令),只有从新使CKE有效才能退出自刷新模式并进入正常操做状态。

剩下的事情就是配置寄存器

(1)BWSCON寄存器(BUS WIDTH & WAIT CONTROL REGISTER)

根据开发板的存储器配置和芯片型号,设置每一个BANK焊接芯片的位宽和等待状态,BWSCON,每4位对应一个BANK,这4位分别表示:

 STx:启动/禁止SDRAM的数据掩码引脚(UB/LB),SDRAM没有高低位掩码引脚,此位为0,SRAM链接有UB/LB管脚,设置为1
 注:UB/LB数据掩码引脚用来控制芯片读取/写入的高字节和低字节(对比硬件手册SDRAM和SRAM的接线图)
 WSx:是否使用存储器的WAIT信号,一般设为0
DWx:设置焊接存储器芯片的位宽,笔者开发板使用两片容量为32M,位宽为16的SDRAM组成64M,32位存储器,所以DW7,DW6位设置为0b10,其它BANK不用设置采用默认值便可。
BANK0对应的是系统引导BANK,这4位比较特殊,它的设置是由硬件跳线决定的,所以不用设置
BWSCON设置结果:0x22000000

2)BANKCON0~BANKCON5 (BANK CONTROL REGISTER)

这6个寄存器用来设置对应BANK0~BANK5的访问时序,采用默认值0x700便可

(3)BANKCON6~BANKCON7 (BANK CONTROL REGISTER)

因为内存都焊接在这两个BANK上,所以内存驱动主要是对这两个寄存器进行设置
MT:设置BANK6~BANK7的存储器类型,
00=ROM or SRAM 01=保留
10=保留         11=SDRAM
内存为SDRAM,设置为0b11,对应的应该设置Trcd和SCAN位,其它位和SDRAM无关
Trcd:RAS to CAS Delay行地址选通到列地址选通延迟,这个参数请看后面的内存工做原理扩展部分解释,笔者内存芯片为HY57V561620,由其芯片手册可知其Trcd为最少 20ns,若是内存工做在100MHz,则该值至少要为2个时钟周期,一般设置为3个时钟周期,所以设置为0b01
SCAN:SDRAM Column Address Number SDRAM的列地址数,笔者内存芯片为HY57V561620,列地址数为9,设置为0b01
BANK6,BANK7设置结果为:0x18005

(4)REFRESH (REFRESH CONTROL REGISTER)

刷新频率设置寄存器(REFRESH)
SDRAM的刷新有效,刷新频率设置寄存器(刷新)
REFEN:开启/关闭刷新功能,设置为1,开启刷新
TREFMD:SDRAM刷新模式,0=CBR/AutoRefresh,  1=Self Refresh,设置为0,自动刷新

Trp:行地址选通预充电时间,通常设置为0b00便可
Tsrc:单行刷新时间,设置为0b11便可。
Refresh Counter:内存存储单元刷新数,它经过下面公式计算出:
Refresh Counter = 2^11 + 1 – SDRAM时钟频率(MHz)* SDRAM刷新周期(uS)
SDRAM的刷新周期,也就是内存存储单元间隔须要多久进行一次刷新,前面内存工做原理分析可知电容数据保存上限为64ms,笔者使用内存芯片每一个L-Bank共有8192行,所以每次刷新最大间隔为:64ms/8192 = 7.8125uS,若是内存工做在外部晶振频率12MHz下,Refresh Counter = 1955,若是内存工做在100MHz下,那么Refresh Counter = 1269(取大整数)
 REFRESH寄存器设置为:
0x8e0000 + 1269 = 0x008e04f5(HCLK = 100MHz)
0x8e0000 + 1955 = 0x008e07a3(HCLK = 12MHz)

(5)BANKSIZE寄存器(BANKSIZE REGISTER)

 BANKSIZE寄存器(BANKSIZE)
 设置内存的突发传输模式,省电模式和内存容量。
BURST_EN:是否开启突发模式, 0 = ARM内核禁止突发传输 1 = 开启突发传输,设置为1,开启突发传输
SCKE_EN:是否使用SCKE信号做为省电模式控制信号, 0 = 不使用SCKE信号做为省电模式控制信号 1 = 使用SCKE信号做为省电模式控制信号,一般设置为1
SCLK_EN: 设置向存储器输入工做频率,0 = 一直输入SCLK频率,即便没有内存操做也会输入, 1 = 仅当进行内存数据操做时才输入SCLK频率,一般设置为1
BK76MAP:设置Bank6/7的内存容量,笔者使用开发板内存为两片32M内存芯片并联成64M,它们所有都外接到Bank6上,所以选择0b001
BANKSIZE寄存器设置为:0xb1

(6)SDRAM模式设置寄存器MRSRx (SDRAM MODE REGISTER SET REGISTER)

SDRAM模式设置寄存器(MRSRx)
该寄存器用于设置CAS潜伏周期,能够手动设置的位只有CL[6:4]位,经过前面内存工做原理可知,笔者使用开发板CL=3,即0b011
MRSR6,MRSR7设置为:0x00000030

内存实验:

设置该工程加载时运行时地址为0x30000000

ctr.S

.equ    MEM_CTL_BASE,   0x48000000  
.equ    SDRAM_BASE,     0x30000000  
  
.text  
.global _start  
_start:  
        bl close_watchdog  
        bl memsetup  
        bl copy_steppingstone_to_sdram  
        ldr pc, =on_sdram  
on_sdram:  
        ldr sp,=0x34000000  
        bl main  
continue:  
        b continue  
  
close_watchdog:  
        mov r1,#0x53000000  
        mov r2,#0x0  
        str r2,[r1]  
        mov pc,lr  
          
copy_steppingstone_to_sdram:  
        mov r1,#0  
        ldr r2,=SDRAM_BASE  
        mov r3,#4*1024  
1:  
        ldr r4,[r1],#4  
        str r4,[r2],#4  
        cmp r1,r3  
        bne 1b  
        mov pc,lr  
  
memsetup:  
    mov r1,#MEM_CTL_BASE  
    adrl r2,mem_cfg_val  
    add r3,r1,#52  
1:  
    ldr r4,[r2],#4  
    str r4,[r1],#4  
    cmp r1,r3  
    bne 1b  
    mov pc,lr  
      
.align 4  
mem_cfg_val:  
    .long   0x22011110      @ BWSCON  
    .long   0x00000700      @ BANKCON0  
    .long   0x00000700      @ BANKCON1  
    .long   0x00000700      @ BANKCON2  
    .long   0x00000700      @ BANKCON3    
    .long   0x00000700      @ BANKCON4  
    .long   0x00000700      @ BANKCON5  
    .long   0x00018005      @ BANKCON6  
    .long   0x00018005      @ BANKCON7  
    .long   0x008C07A3      @ REFRESH  
    .long   0x000000B1      @ BANKSIZE  
    .long   0x00000030      @ MRSRB6  
    .long   0x00000030      @ MRSRB7  

main.c

#define GPFCON  (*(volatile unsigned long *)0x56000050)  
#define GPFDAT  (*(volatile unsigned long *)0x56000054)  
#define GPF4_out ( 1 << 4*2 )  
#define GPF5_out ( 1 << 5*2 )  
#define GPF6_out ( 1 << 6*2 )  
void   
delay(volatile unsigned long dly)  
{  
    for(;dly > 0;dly--);  
}  
int  
main()  
{  
    unsigned i = 1;  
      
    GPFCON = GPF4_out | GPF5_out | GPF6_out;  
    while(1)  
    {  
        GPFDAT = ( ~( i << 4 ) );  
        i *=2;  
        if( i == 8)  
        {  
            i = 1;  
        }  
        delay(30000);  
  
          
    }  
      
      
    return 0;  
}  

Makefile

CFLAGS := -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -ffreestanding  
led_on.bin:ctr.S main.c  
    arm-linux-gcc $(CFLAGS) -c -o ctr.o ctr.S  
    arm-linux-gcc $(CFLAGS) -c -o main.o main.c  
    arm-linux-ld -Ttext 0x30000000 ctr.o main.o -o led_on.elf  
    arm-linux-objcopy -O binary -S led_on.elf led_on.bin  
    arm-linux-objdump -D -m arm led_on.elf>led_on.dis  
clean:  
    rm -f led_on.bin led_on.elf *.o led_on.dis  
相关文章
相关标签/搜索