第6课,SDRAM
注:以下内容学习于韦东山老师arm裸机第一期****
如果想要完全了解SDRAM,参考: 高手进阶,终极内存技术指南-完整/进阶版
一.SDRAM的访问方法
1.1 SDRAM结构图
a.由4个BANK组成,可以看作是表格
b.里面的每个格子有16位数据(2440接有两片SDRAM,每一片提供16位数据)
c.访问时,需要先发出片选信号选中SDRAM,然后发出BANK信号选中哪个BANK,最后发出行地址和列地址(这些信号都是由内存控制器发出)
1.2 内存控制器执行流程
假设当CPU执行 ldr r0, =0x30000000
ldr r1, [r0] /* 读内存的数据 */
1.2.1 CPU将地址发送给内存控制器
1.2.2 内存控制器根据地址发出片选信号nGCS6
1.2.3 根据接的类型是SDRAM,拆分地址
a.BANK地址
b.发出行地址
c.发出列地址
(需要去设置每个地址有多少地址条,设置内存控制器中的相关寄存器)
1.2.4 读取数据
二.内存控制器中相关寄存器的设置
2.1 设置BWSCON寄存器,如下图 (最终设置为0x22000000)
我们只需要设置BANK6
2.1.1 DW6 [25:24] Determines data bus width for bank 6(决定bank6的位宽)
00 = 8-bit 01 = 16-bit, 10 = 32-bit 11 = reserved
我们使用两个16位的芯片拼接成32位的,因此设置为10
2.1.2 WS6 [26] Determines WAIT status for bank 6.(决定bank6的等待信号)
0 = WAIT disable, 1 = WAIT enable
假设CPU的读写速度很慢,CPU发出读写命令后,内存芯片没有在规定时间准备好数据,可以向CPU发出wait信号,请求CPU宽限一点时间,我们用不到设置为0
2.1.3 ST6 [27] Determines SRAM for using UB/LB for bank 6.(决定SRAM是否使用UB/LB引脚)
0 = Not using UB/LB (The pins are dedicated nWBE[3:0)(nWBE表示写某个字节的时候是否真正写进去)
1 = Using UB/LB (The pins are dedicated nBE[3:0])(读/写字节的时候都可以使用nBE[3:0]这个引脚来决定是否使用这个byte)
我们的内存是32位的,如果我们想要修改某个字节,仍然需要提供4个字节的数据,这时便需要通过nWBE[3:0](SDRAM中的L_nWBE[3:0])
当想要读一个字节的时候,仍然会读到32位的数据,会从中挑出需要的字节(具体方法在上一节中提到过).因此不需要nBE来屏蔽某一个字节
因此对于SDRAM,我们选择为0
2.2 设置BANKCON6寄存器,如下图 (最终设置为0x18001)
设置该寄存器对照时序图如下:
2.2.1 MT [16:15] Determine the memory type for bank6 and bank7.(决定bank6,bank7外面接的是ROM还是RAM还是SDRAM,如果是SDRAM就会将地址拆分)
00 = ROM or SRAM 01 = Reserved (Do not use)
10 = Reserved (Do not use) 11 = Sync. DRAM
我们外接的SDRAM,设置为11
Memory Type = ROM or SRAM [MT=00] (15-bit)
下面的15位是为ROM或者SRAM准备的,可以跳过
2.2.2 Tacs [14:13] Address set-up time before nGCS (地址信号发出多久之后发出片选信号)
00 = 0 clock 01 = 1 clock 10 = 2 clocks 11 = 4 clocks
2.2.3 Tcos [12:11] Chip selection set-up time before nOE (片选信号发出多久之后发出读信号)
00 = 0 clock 01 = 1 clock 10 = 2 clocks 11 = 4 clocks
2.2.4 Tacc [10:8] Access cycle(读一个周期消耗的时间)
000 = 1 clock 001 = 2 clocks
010 = 3 clocks 011 = 4 clocks
100 = 6 clocks 101 = 8 clocks
110 = 10 clocks 111 = 14 clocks
2.2.5 Tcoh [7:6] Chip selection hold time after nOE(读信号失效后片选信号持续多长时间)
00 = 0 clock 01 = 1 clock
10 = 2 clocks 11 = 4 clocks
2.2.6 Tcah [5:4] Address hold time after nGCSn(片选信号失效后地址信号持续多长时间)
00 = 0 clock 01 = 1clock 10 = 2 clocks 11 = 4 clocks
2.2.7 Tacp [3:2] Page mode access cycle @ Page mode(页模式读一个周期消耗的时间)
00 = 2 clocks 01 = 3 clocks
10 = 4 clocks 11 = 6 clocks
PMC [1:0] Page mode configuration(页模式的配置)
00 = normal (1 data) 01 = 4 consecutive accesses
10 = 8 consecutive accesses 11 = 16 consecutive accesses
Memory Type = SDRAM [MT=11] (4-bit)(下面的4位是为SDRAM准备的,我们只需要设置这4位)
Trcd [3:2] RAS to CAS delay(RAS->CAS,内存控制器先发出行地址再发出列地址,两个地址的间隔delay)
00 = 2 clocks 01 = 3 clocks 10 = 4 clocks
根据芯片手册来设置,搜索Trcd,找到下图
可以设置为20ns,2440的HCLK=100MHZ,t = 10ns,因此可以设置为2clocks,设置为00
SCAN [1:0] Column address number(设置列地址占据多少位,bank有4个肯定占据2位,剩下的就是行地址)
00 = 8-bit 01 = 9-bit 10= 10-bit
根据芯片手册来选择,在芯片手册上说明A0-A8表示列地址,9位,如下图:
,因此设置为01
2.3 设置REFRESH寄存器(在使用过程中需要不断的刷新SDRAM,否则数据会丢失),如下图: 最终设置为0x8404f5
SCAN [1:0] Column address number(设置列地址占据多少位,bank有4个肯定占据2位,剩下的就是行地址)
00 = 8-bit 01 = 9-bit 10= 10-bit
设置为1,使能SMRAM的刷新
2.3.2 TREFMD [22] SDRAM Refresh Mode(SDRAM刷新模式)
0 = CBR/Auto Refresh
1 = Self Refresh
In self-refresh time, the SDRAM control signals are driven to the
appropriate level.
设置为0,自动刷新
2.3.3 Trp [21:20] SDRAM RAS pre-charge Time(行地址信号的冲电时间)
00 = 2 clocks 01 = 3 clocks 10 = 4 clocks 11 = Not support
在芯片手册搜索Trp中有如下图:
我们设置为trp >= 20ns即可,2440的HCLK=100MHZ,t = 10ns,因此可以设置为2clocks,设置为00
2.3.4 Tsrc [19:18] SDRAM Semi Row cycle time(SDRAM行周期时间)
00 = 4 clocks 01 = 5 clocks 10 = 6 clocks 11 = 7 clocks
SDRAM Row cycle time: Trc=Tsrc+Trp
If Trp = 3clocks & Tsrc = 7clocks, Trc = 3+7=10clocks.
在芯片手册中搜索不到Tsrc,但是给了一个公式Trc=Tsrc+Trp,因此在芯片手册中搜索Trc,如下图:
我们可以取63ns,Tsrc = Trp - Trc = 63 - 20 = 43ns
因此我们可以设置为01,表示5clocks
2.3.5 Reserved [17:16] Not used 00
Reserved [15:11] Not used 0000
2.3.6 Refresh Counter [10:0] SDRAM refresh count value.(刷新周期值)
Refer to chapter 6 SDRAM refresh controller bus priority section.(参见芯片手册第6章SDRAM刷新控制器总线优先级部分)
Refresh period = (211-refresh_count+1)/HCLK (刷新周期 = 211 - refresh_count+1 ==>refresh_count = 211 + 1 - 刷新周期)
Ex) If refresh period is 7.8 us and HCLK is 100MHz,(假设刷新周期=7.8us,HCLK=100MHZ)
the refresh count is as follows:
Refresh count = 211 + 1 - 100x7.8 = 1269
在芯片手册中找到下图:
指明了64ms刷新8192次,因此刷新周期= 64 / 8192 = 7.8,因此Refresh count = 211 + 1 - 100x7.8 = 1269
2.4 设置BANKSIZE寄存器,如下图: 最终设置为0xb1
2.4.1 BURST_EN [7] ARM core burst operation enable.(ARM核突发操作使能,即一次访问多个字节)
0 = Disable burst operation.
1 = Enable burst operation.
设置为1,使能
2.4.1 BURST_EN [7] ARM core burst operation enable.(ARM核突发操作使能,即一次访问多个字节)
0 = Disable burst operation.
1 = Enable burst operation.
设置为1,使能SDRAM休眠模式
2.4.4 SCLK_EN [4] SCLK is enabled only during SDRAM access cycle for reducing
power consumption. When SDRAM is not accessed, SCLK
becomes 'L' level.
0 = SCLK is always active.
1 = SCLK is active only during the access (recommended).
1是推荐值,设置为1,可以减少SDRAM的功耗
2.4.5 Reserved [3] Not used
2.4.6 BK76MAP [2:0] BANK6/7 memory map(BANK6/7内存映射)
010 = 128MB/128MB 001 = 64MB/64MB
000 = 32M/32M 111 = 16M/16M
110 = 8M/8M 101 = 4M/4M
100 = 2M/2M
我们接了两个SDRAM,组成了64M的内存,因此要设置为001,64MB
2.5 设置MRSRB6寄存器,如下图: 最终设置为0x20
2.5.1 Reserved [11:10] Not used
2.5.2 WBL [9] Write burst length(突发访问长度)
0: Burst (Fixed)
1: Reserved
设置为0,固定的突发访问的长度 2.5.3 TM [8:7] Test mode
00: Mode register set (Fixed)
01, 10 and 11: Reserved
设置为00 2.5.4 CL [6:4] CAS latency
000 = 1 clock, 010 = 2 clocks, 011=3 clocks
Others: reserved
内存控制器读SDRAM,发出BANK地址,行地址,列地址,对于SDRAM需要等一会才有数据在芯片手册上有下图:
需要等待2或者3个clocks,我们可以选择第2个或者第三个clocks,这个值会发给SDRAM,这个值会保存在SDRAM中的MR(Mode Register)中,
以后就会在收到列地址后等待这些时间再向2440返回数据
2.5.5 BT [3] Burst type
0: Sequential (Fixed)
1: Reserved
设置为0
2.5.6 BL [2:0] Burst length
000: 1 (Fixed)
Others: Reserved
设置为0
三.SDRAM程序编写
#include "s3c2440_soc.h"
void SdramInit(void)
{
/* BWSCON = (0x2 << 24) | (0x2 << 28)*/
BWSCON = 0x22000000;
/* BANKCON6 = (0x3 << 15) | (0x1 << 0) */
BANKCON6 = 0x18001;
/* BANKCON6 = (0x3 << 15) | (0x1 << 0) */
BANKCON7 = 0x18001;
/* REFRESH = (1 << 23) | (1 << 18) | (1269 << 0) */
REFRESH = 0x8404f5;
/* BANKSIZE = (1 << 7) | (1 << 5) | (1 << 4) | (1 << 0) */
BANKSIZE = 0xb1;
/* MRSRB6 = (2 << 4) */
MRSRB6 = 0x20;
}
int SdramTest(void)
{
int i;
volatile unsigned char *p = (volatile unsigned char *)0x30000000;
for (i = 0; i < 250; i++)
p[i] = 55;
for (i = 0; i < 250; i++)
{
if (p[i] == 55)
return 0;
}
return -1;
}
上一篇: Stm32学习(七)外部中断