一、Mini2440地址空间
1.1 存储器控制器介绍
在之前的文章中,我们已经介绍过S3C2440自带4KB SRAM和2MB的NOR FALSH。片内4KB的内存其实是很小,为了能够运行操作系统和更大的应用程序,需要在处理器存储接口上进行扩展,如SDRAM、SRAM、ROM、FLASH等。ARM提供一个存储管理器部件,为访问外部存储设备提供存储地址信号和控制信号,即存储器控制器。
1.2 存储器控制器作用
CPU在执行指令时候,CPU只会发出指令从某个地址读数据,此时存储器控制器会根据地址判断时什么设备,并负责数据操作,把CPU想操作的数据反馈给CPU。
比如指令:
COUNT ADDR 0x30000000
MOV R1,=ADDR ;R0=0x30000000
LDR R0,[R1] ;R0=*R1 加载到寄存器
从内存地址0x30000000处读取4个字节的值,写入寄存器R0。存储器控制器根据地址0x30000000知道这是片内SDRAM,然后发出nGCS6片选信号。
访问一个存储芯片,正来说需要具备以下条件:
- 地址线;
- 数据线;
- 时钟频率;
- 芯片相关特性;
1.3 地址空间分布
S3C2440对外引出了27位地址线ADDR0~ADDR26,32位数据线,最多能够寻址128MB。而S3C2440的寻址空间可以达到1GB,这是由于S3C2440将1GB的地址空间分成了8个BANKS(Bank0~Bank7),其中每一个BANK对应一根片选信号线nGCS0~nGCS7,当访问BANKx的时候,nGCSx管脚电平拉低,用来选中外接设备, S3C2440通过8根选信号线和27根地址线,就可以访问1GB。CPU系统上电将从bank0开始执行。
空间分布图如下: Bank0-Bank7的地址范围如下:
- 0x00000000-0x3FFFFFFF:Bank0-Bank7;
- 0x4000 0000-0x47FF FFFF :根据启动方式不同,作用不同;
- 0x4800 0000-0x5FFF FFFF:特殊功能寄存器;
- 0x6000 0000-0xFFFF FFFF;未被使用;
S3C2440是32位CPU,可以使用的地址范围理论达到4GB,除去上面连接外设的1GB空间外,还有一部分是CPU内部寄存器的地址,剩下的地址空间没有使用。
1.4 SDRAM工作原理
我们观察S3C2440内存空间分布图,我们可以发现Bank0~Bank5可以焊接ROM或SRAM类型存储器,Bank6~Bank7可以焊接ROM,SRAM,SDRAM类型存储器,也就是说,S3C2440的SDRAM内存应该焊接在Bank6~Bank7上,最大支持内存256M,Bank0~Bank5通常焊接一些用于引导系统启动小容量ROM,具体焊接什么样存储器,多大容量,根据每个开发板生产商不同而不同。
SDRAM的内部是一个存储阵列。阵列就如同表格一样,将数据“填”进去。在数据读写时和表格的检索原理一样,先指定一个行(Row),再指定一个列(Column),我们就可以准确地找到所需要的单元格,这就是内存芯片寻址的基本原理,如图所示。
这个单元格(存储阵列)就叫逻辑 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位的地址长度由于其存储结构特点,分成了行地址和列地址。以Mini2440开发板为例:将两片32MB,16位宽SDRAM内存(型号HY57V561620FTP)焊接在Bank6,并联形成64M,32位内存。通过下面的内存原理图可知:
内存外接管脚地址线只有13根地址线A0~A12,它最多只能寻址8M内存空间,到底使用什么机制来实现对64M内存空间进行寻址的呢?
SDRAM的行地址线和列地址线是分时复用的,即地址要分两次送出,两次送到芯片上去的地址分别称为行地址和列地址。它们被锁存到芯片内部的行地址锁存器和列地址锁存器。这样,可以大幅度减少地址线的数目,提高器件的性能和制作工艺复杂度。
- 先送出行地址,行地址使用A0~A12(13条)(nSRAS是行地址锁存信号,该信号将行地址锁存在芯片内部的行地址锁存器中);
- 再送出列地址,列地址使用A0~A8(9条)(nSCAS是列地址锁存信号,该信号将列地址锁存在芯片内部的列地址锁存器中);
实际上,现在的SDRAM一般都以L-Bank为基本寻址对象的。由L-Bank地址线BA1~BA0控制L-Bank间的选择:
- BA0-BA1是bank选择引脚。(Bank选择与行地址(row address)同时下发,在列地址下发时,有其他用途)。
13+9+2=24,相当于24个地址,每个地址2个字节,内存大小2^25=32MB。
需要注意的是LADDR2接的引脚是A0,这是因为一个地址对应4个字节,32位数据位宽。
BA0,BA1接ADDR24,ADDR25,为什么用这两根地址线呢?
-
BA0~BA1代表了SDRAM的最高地址位。因为CPU的寻址空间是以字节(byte)为单位的,本系统SDRAM容量为64MB,那就需要A25~A0(64M=2^26)地址线来寻址,所以BA1~BA0地址线应该接到S3C2440的ADDR25~ADDR24引脚上。
左侧DQ0~DQ15接接LDATA0~LDATA15,右侧DQ0~DQ15接接LDATA16~LDATA31,共计数据宽度为32位。
当地址线发出地址位0x33FFFFFC,二进制位0011 0011 1111 1111 1111 1111 1111 1100,存储器控制器会发出nGCS6(与nGCS0同一引脚)片选信号,
nGCS6片选 | ADDR27 | ADDR26 | ADDR25 | ADDR24 | ADDR23 | ADDR22 | ADDR21 | ADDR20 | ADDR19 | ADDR18 | ADDR17 | ADDR16 | ||||||
0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | |||
BA1 | BA0 | A12 | A11 | A10 | A9 | A8 | A7 | A6 | A5 |
ADDR15 | ADDR14 | ADDR13 | ADDR12 | ADDR11 | ADDR10 | ADDR9 | ADDR8 | ADDR7 | ADDR6 | ADDR5 | ADDR4 | ADDR3 | ADDR2 | ADDR1 | ADDR0 | ||||
1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | ||||
A4 | A3 | A2 | A1 | A0 | A8 | A7 | A6 | A5 | A4 | A3 | A2 | A1 | A0 |
所以当行地址A0~A12全部位1,列地址A0~A8全部位1,BA0~BA1可以访问SDRAM最高内存地址,一次取出32位数据,对应0x33FFFFFC~0x33FFFFFF。
SDRAM地址空间:0x30000000~0x33FFFFFF;
二、SDRAM读写操作
2.1 SDRAM读操作
- CPU发出片选信号nSCS0(与nGCS6是同一引脚)有效,选中SDRAM芯片;
-
对被选中的芯片进行同一的行/列(存储单元)寻址:
- 根据SDRAM芯片的列地址线数目设置CPU相关寄存器后,CPU会从32位地址中自动分出L-BANK选择信号、行地址信号、列地址信号,然后先后发出行地址信号、列地址信号。
- 确定Bank,通过ADDR24、ADDR25信号线选定,总共4个Bank;
- 确定行地址:A0~A12地址线发送具体的行地址,共有13根地址线(可表示8192行),A0~A12的不同数值就确定了具体的行地址;
- 确定列地址:行地址确定之后,就要对列地址进行寻址了,行地址与列地址线是复用的。列地址复用了A0~A8,共9根(可表示512列);
- 找到存储单元后,被选中的芯片就要进行统一的数据传输;
在地址线上送完行地址之后,要等到行地址稳定定位后再送出列地址,这个间隔被定义为 tRCD,即RAS to CAS Delay(RAS至 CAS延迟),tRCD是SDRAM的一个重要时序参数,相关数值参看对应芯片硬件手册。通常tRCD以时钟周期(tCK,Clock Time)数为单位,比如Mini2440所用内存芯片里面写到tRCD为20ns,如果内存工作在100MHz,那么RCD至少要为2个时钟周期, RCD=2。
在列地址选通信号CAS 发出之后,仍要经过一定的时间才能有数据输出,从CAS与到第一笔数据输出的这段时间,被定义为 CL(CAS Latency,CAS潜伏期)。
三、寄存器
存储控制器一共有13个寄存器,6种寄存器,对BANK0~BANK5进行访问时,只需要配置BWSCON和BANKCONx寄存器,但是对SDRAM访问,不仅仅需要对这俩个寄存器进行配置,还需要额外配置4个寄存器。
3.1 总线宽度和等待控制寄存器(BWSCON)
寄存器信息:
寄存器 | 地址 | R/W | 描述 | 复位值 |
BWSCON | 0x48000000 | R/W | 总线宽度和等待控制寄存器 | 0x000000 |
寄存器位信息:
BWSCON | 位 | 描述 | 初始状态 |
ST7 | [31] |
决定SRAM 是否对Bank 7 使用UB/LB 0 = 未使用UB/LB(引脚对应nWBE[3:0]) 1 = 使用UB/LB(引脚对应nBE[3:0]) |
0 |
WS7 | [30] |
决定Bank 7 的WAIT 状态 0 = WAIT 禁止 1 = WAIT 使能 |
0 |
DW7 | [29:28] |
决定Bank 7 的数据总线宽度 00 = 8 位 01 = 16 位 10 = 32 位 11 = 保留 |
0 |
ST6 | [27] |
决定SRAM 是否对Bank 6 使用UB/LB 0 = 未使用UB/LB(引脚对应nWBE[3:0]) 1 = 使用UB/LB(引脚对应nBE[3:0]) |
0 |
WS6 | [26] |
决定Bank 6 的WAIT 状态 0 = WAIT 禁止 1 = WAIT 使能 |
0 |
DW6 | [25:24] |
决定Bank 6 的数据总线宽度 00 = 8 位 01 = 16 位 10 = 32 位 11 = 保留 |
0 |
ST5 |
[23] |
决定SRAM 是否对Bank 5 使用UB/LB 0 = 未使用UB/LB(引脚对应nWBE[3:0]) 1 = 使用UB/LB(引脚对应nBE[3:0]) |
0
|
WS5 | [22] |
决定Bank 5 的WAIT 状态
0 = WAIT 禁止 1 = WAIT 使能 |
0 |
DW5 | [21:20] |
决定Bank 5 的数据总线宽度
00 = 8 位 01 = 16 位 10 = 32 位 11 = 保留 |
0 |
ST4 |
[19] |
决定SRAM 是否对Bank 4 使用UB/LB
0 = 未使用UB/LB(引脚对应nWBE[3:0]) 1 = 使用UB/LB(引脚对应nBE[3:0]) |
0 |
WS4 |
[18] |
决定Bank 4 的WAIT 状态
0 = WAIT 禁止 1 = WAIT 使能 |
0 |
DW4 | [17:16] |
决定Bank 4 的数据总线宽度
00 = 8 位 01 = 16 位 10 = 32 位 11 = 保留 |
0 |
ST3 | [15] |
决定SRAM 是否对Bank 3 使用UB/LB
0 = 未使用UB/LB(引脚对应nWBE[3:0]) 1 = 使用UB/LB(引脚对应nBE[3:0]) |
0 |
WS3 | [14] |
决定Bank 3 的WAIT 状态
0 = WAIT 禁止 1 = WAIT 使能 |
0 |
DW3 | [13:12] |
决定Bank 3 的数据总线宽度
00 = 8 位 01 = 16 位 10 = 32 位 11 = 保留 |
0 |
ST2 | [11] |
决定SRAM 是否对Bank 2使用UB/LB
0 = 未使用UB/LB(引脚对应nWBE[3:0]) 1 = 使用UB/LB(引脚对应nBE[3:0]) |
0 |
WS2 | [10] |
决定Bank 2 的WAIT 状态
0 = WAIT 禁止 1 = WAIT 使能 |
0 |
DW2 | [9:8] |
决定Bank 2 的数据总线宽度
00 = 8 位 01 = 16 位 10 = 32 位 11 = 保留 |
0 |
ST1 | [7] |
决定SRAM 是否对Bank 1使用UB/LB
0 = 未使用UB/LB(引脚对应nWBE[3:0]) 1 = 使用UB/LB(引脚对应nBE[3:0]) |
0 |
WS1 | [6] |
决定Bank 1 的WAIT 状态
0 = WAIT 禁止 1 = WAIT 使能 |
0 |
DW1 | [5:4] |
决定Bank 1 的数据总线宽度
00 = 8 位 01 = 16 位 10 = 32 位 11 = 保留 |
0 |
DW0 | [2:1] |
表明Bank 1 的数据总线宽度(只读) 01 = 16位 10 =32位 该状态由OM[1:0]引脚决定 |
- |
保留 | [0] | 保留为0 | 0 |
- ST6:决定是否使用SDRAM的数据掩码,对SDRAM时为0,对SRAM时为1。
- WS6:决定是否使用WAIT信号,一般不使用。(WAIT信号就是在SDRAM没准备好的时候,由SDRAM发给CPU,请求延迟一段时间)
- DW6:决定BANK位宽,自然是32位。
所以,BWSCON寄存器要或运算的值为:0x02000000。
3.2 BANK 控制寄存器(BANKCONn:nGCS0 至nGCS5)
寄存器信息:
寄存器 | 地址 | R/W | 描述 | 复位值 |
BANKCON0 | 0x48000004 | R/W | Bank0 控制寄存器 | 0x0700 |
BANKCON1 | 0x48000008 | R/W | Bank1 控制寄存器 | 0x0700 |
BANKCON2 | 0x4800000C | R/W | Bank2 控制寄存器 | 0x0700 |
BANKCON3 | 0x48000010 | R/W | Bank3 控制寄存器 | 0x0700 |
BANKCON4 | 0x48000014 | R/W | Bank4 控制寄存器 | 0x0700 |
BANKCON5 | 0x48000018 | R/W | Bank5 控制寄存器 | 0x0700 |
寄存器位信息:
BANKCONn | 位 | 描述 | 初始状态 |
Tacs | [14:13] |
nGCSn 前的地址建立时间 00 = 0 个时钟 01 = 1个时钟 |
00 |
Tcos | [12:11] |
nOE 前的片选建立时间 00 = 0 个时钟 01 = 1个时钟 |
00 |
Tacc | [10:8] |
访问周期 000 = 1 个时钟 001 = 2 个时钟 注意:当使用nWAIT 信号时,Tacc ≥ 4 个时钟 |
111 |
Tcoh | [7:6] |
nOE 后的片选保持时间 00 = 0 个时钟 01 = 1个时钟 |
00 |
Tcah | [5:4] |
nGCSn 后的地址保持时间 00 = 0 个时钟 01 = 1个时钟 |
00 |
Tacp | [3:2] |
Page 模式下的Page 模式访问周期 00 = 0 个时钟 01 = 1个时钟 |
00 |
PMC |
[1:0] |
Page 模式配置 00 = 正常(1个数据) 01 = 4个数据 |
00
|
3.3 BANK 控制寄存器(BANKCONn:nGCS6 至nGCS7)
寄存器信息:
寄存器 | 地址 | R/W | 描述 | 复位值 |
BANKCON6 | 0x4800001C | R/W | Bank6 控制寄存器 | 0x18008 |
BANKCON7 | 0x48000020 | R/W | Bank7 控制寄存器 | 0x18008 |
寄存器位信息:
BANKCONn | 位 | 描述 | 初始状态 |
MT | [16:15] |
决定Bank6 和Bank7 的存储器类型 00 = ROM或SRAM 01 = 保留(不要使用) |
11 |
存储器类型 = ROM 或SRAM [MT=00] |
|||
Tacs | [14:13] |
nGCSn 前的地址建立时间 00 = 0 个时钟 01 = 1个时钟 |
00 |
Tcos | [12:11] |
nOE 前的片选建立时间 00 = 0 个时钟 01 = 1个时钟 |
00 |
Tacc | [10:8] |
访问周期 000 = 1 个时钟 001 = 2 个时钟 |
111 |
Tcoh | [7:6] |
nOE 后的片选保持时间 00 = 0 个时钟 01 = 1个时钟 |
00 |
Tcah | [5:4] |
nGCSn 后的地址保持时间 00 = 0 个时钟 01 = 1个时钟 |
00 |
Tacp | [3:2] |
Page 模式下的Page 模式访问周期 00 = 2 个时钟 01 = 3个时钟 |
00 |
PMC | [1:0] |
Page 模式配置 00 = 正常(1个数据) 01 = 4个数据 |
00 |
存储器类型 = SDRAM [MT=11] | |||
Trcd | [3:2] |
RAS 到CAS 的延迟 00 = 2 个时钟 01 = 3 个时钟 10 = 4 个时钟 |
00 |
SCAN |
[1:0] |
列地址数 00 = 8 位 01 = 9 位 10 = 10 位 |
00
|
对于SDRAM的访问,我们需要配置的就是图中蓝色标注地方:
-
MT:决定BANK外接的是SDRAM还是SRAM,SDRAM选择11;
-
Trcd:行列信号之间的延迟时间,根据芯片手册得知最小为20ns,而我们的HCLK时钟为100MHz,一个clock 10ns,所以保险起见选择01,3个时钟;
- SCAN:设置列地址位,这里使用的SDRAM列地址一共9位,所以为:01;
所以,BANKCON6寄存器要或运算的值为:0x00018005。
3.4 刷新控制寄存器
刷新控制寄存器,用来控制SDRAM的刷新模式和刷新频率。我们知道,SDRAM中的存储阵列需要不断的刷新来保证数据不丢失,所以就要配置刷新控制寄存器。
寄存器信息:
寄存器 | 地址 | R/W | 描述 | 复位值 |
REFRESH | 0x48000024 | R/W | SDRAM 刷新控制寄存器 | 0xAC0000 |
寄存器位信息:
REFRESH | 位 | 描述 | 初始状态 |
REFEN | [23] |
SDRAM 刷新使能 0 = 禁止 1 = 使能(自或CBR/自动刷新) |
1 |
TREFMD | [22] |
SDRAM 刷新模式 在自刷新期间,驱动SDRAM 控制信号为适当电平 |
0 |
Trp | [21:20] |
SDRAM RAS 预充电时间 00 = 2 个时钟 01 = 3 个时钟 |
10 |
Tsrc | [19:18] |
SDRAM 半行周期时间 00 = 4 个时钟 01 = 5 个时钟 |
11 |
保留 | [17:16] |
未使用 |
00 |
保留 | [15:11] | 未使用 | 0000 |
刷新计数器 | [10:0] |
SDRAM刷新计数值。 参阅第6 章SDRAM刷新控制器总线优先级部分。
$$refresh_period = (2^11 - refrest_count + 1) / HCLK$$ |
0 |
- REFEN:决定使能刷新功能,当然是开启了,值为:1;
- TREFMD:刷新的模式,一般自动刷新,值为:0;
- Trp:根据芯片手册得知20ns,对应2个时钟,值为:00;
- Tsrc:默认即可;
- Refresh Counter:刷新计数的值,查SDRAM的手册可得8192个刷新周期为64ms,则每一个刷新周期为$64*10^6/8192/1000=7.8125μs$,如果内存工作在100MHz下,那么通过公式计算可得:
$$refrest\_count =2^{11}+1-100*7.8125=1269(取大整数)$$
所以,REFRESH寄存器要或运算的值为:0x8e0000 + 1269 = 0x008e04f5(HCLK = 100MHz)
3.5 Bank 大小寄存器
寄存器信息:
寄存器 | 地址 | R/W | 描述 | 复位值 |
BANKSIZE | 0x48000028 | R/W | 可变Bank 大小寄存器 | 0x00 |
寄存器位信息:
BANKSIZE | 位 | 描述 | 初始状态 |
BURST_EN | [7] |
ARM 核突发(Burst)操作使能 0 = 禁止突发操作 1 = 使能突发操作 |
0 |
保留 | [6] |
未使用 |
0 |
SCKE_EN | [5] |
SDRAM 省电模式使能SCKE 控制 0 = 禁止SDRAM省电模式 1 = 使能SDRAM省电模式 |
0 |
SCLK_EN | [4] |
只在SDRAM访问周期期间SCLK使能,以降低功耗。当未访问SDRAM,SCLK变为低电平 0 = SCLK一直有效 1 = SCLK 只在访问期间有效(推荐) |
0 |
保留 | [3] |
未使用 |
0 |
BK76MAP | [2:0] |
Bank6/7 存储器映射 010 = 128MB/128MB 001 = 64MB/64MB 100 = 2M/2M |
010 |
设置内存的突发传输模式,省电模式和内存容量。
- BURST_EN:决定是否允许突发操作,值为:1;
- SCKE_EN:决定是否使用SCKE信号来决定省电模式,值为:1;
- SCLK_EN:决定SCLK时钟信号的产生模式,值为:1;
- BK76MAP:决定BANK6、BANK7的大小,这里SDRAM是64M,所以值为:001;
所以,BANKSIZE寄存器要或运算的值为:0x000000b1
3.6 SDRAM 模式 寄存器组寄存器(MRSR)
寄存器信息:
寄存器 | 地址 | R/W | 描述 | 复位值 |
MRSRB6 | 0x4800002C | R/W | 模式寄存器组寄存器Bank6 | xxx |
MRSRB7 | 0x48000030 | R/W | 模式寄存器组寄存器Bank7 | xxx |
寄存器位信息:
MRSR | 位 | 描述 | 初始状态 |
保留 | [11:10] |
未使用 |
- |
WBL | [9] |
写突发长度 0 = 突发(固定) 1 = 保留 |
x |
TM | [8:7] |
测试模式 |
xx |
CL | [6:4] |
CAS 等待时间(latency) |
xxx |
BT | [3] |
突发类型 |
x |
BL | [2:1] |
突发长度
000 = 1(固定) 其它 = 保留 |
xxx |
注意:
- 当代码在SDRAM 中运行时一定不要改变MRSR 寄存器。
重要注意:
- 睡眠模式中,SDRAM 必须使能SDRAM 自刷新模式。
参考文章