s3c2440 存储管理实验
s3c2440存储控制器映射图:
2440的存储控制器共有30根地址线,对外引出27根(剩下的三根我想应该是用于三八译码器了,正好出来nGCS0~nGCS7),正好能寻址128MB空间,8个bank分别由nGCSx(低电平bank有效)控制线控制,总共能寻址1GB空间。作为一个32位的cpu最大寻址是4GB,剩下的空间有一部分是内部寄存器地址,还用一部分没有使用。
SDRAM(Synchronous Dynamic Random Access Memory,同步动态随机存储器)也就是通常所说的内存,其内部是一个存储阵列,如下图所示。就像一个“”“表格”一样,存储数据时只要选中其中一个L-Bank,然后在提供行地址、列地址,就找到了存储数据的位置。
SDRAM引脚接线及分析
(1)确定启动方式
我们选择从nand flash启动,也就是OM1为高电平,OM0为低电平。
(2)确定SDRAM各个引脚的接线
引脚描述:
接线图:
我们选择2片16位32MB的SDRAM芯片并联,则总线宽度为32位,总芯片的大小为64MB,片选信号接在nGCS6上,也就是接在存储控制器的bank6上,起始地址为0x30000000。
BA0和BA1的接法如下图所示:
其中64MB代表总内存大小,x32代表数据总线宽度,256Mb代表一片芯片容量(bit),4M(单个芯片每个blank寻址范围)x16(数据总线宽度)x4(4个blank)x2(总共2片芯片).
UDQM和LDQM分别表示16bit数据的高、低八位是否能被读取。
地址线的接法比较特殊,2440的ADDR2与SDRAM的ADDR0连接在一起,2440的ADDR3与SDRAM的ADDR1连接在一起,以此类推。这是因为cpu访问外设是通过一个地址,而这个地址里面存储的是1个字节的数据,例如发出0x30000000,0x30000001,0x30000002,0x30000004,而这个4个数据都在SDRAM的“0”地址里面,每四个地址里的数据对应SDRAM里面的一个地址存的数据。存储的数据关系如图:
(更加详细的解释:http://www.100ask.org/bbs/forum.php?mod=viewthread&tid=11544&fromuid=5490)
存储控制寄存器配置:
1.BWSCON:位宽与等待控制寄存器
STx:是否用掩码引脚,SDRAM没有高低位掩码,不用,设置为0
WSx:是否用等待信号,一般不启用
DWx:数据总线宽度,我们的是32位
SDRAM接在bank6上,bank7没有使用,设置.BWSCON为0x22000000
2.BANK CONTROL REGISTER:BANK 控制寄存器
BANKCON0~BANKCON5为默认值0x700。
MT:决定bank6和bank7存储类型,选11
trcd:行地址发出后到列地址发出直接的延时,通过查看SDRAM手册至少是20ns,如果sdram工作在100MHZ的时,正好是2个clock,通常设置为3个clock
SCAN:列地址数,通过引脚描述可知列地址为a0~a8为9-bit。
BANKCON6=BANKCON7=0x18005
3.REFRESH:刷新控制寄存器
REFEN:刷新允许位,为1
TREFMD:刷新模式,选择0自动刷新,1一般在睡眠状态下使用
TRP:行选通欲充电时间,一般设置为2clock,即00
tsrc:单行刷新时间,一般设置为11
Refresh Counter=2^11 + 1 – SDRAM时钟频率(MHz)* SDRAM刷新周期(uS)
在SDRAM数据手册上有:64ms refresh period (8K Cycle),则一行刷新周期为64ms/8192 = 7.8125uS,未使用pll时
SDRAM时钟频率为12MHZ
Refresh Counter=2^11 + 1 –12*7.8125=1955
REFRESH=0x8c0000+1955=0x8c07a3
4.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
5.mrsr:模式和设置寄存器能修改的只有BL位,设置cas潜伏期,为011
代码:
head.s
.equ MEM_CTL_START_ADDR, 0x48000000
.equ SDRAM_START_ADDR, 0x30000000
.text
.global _start
_start:
bl disable_watch_dog @关闭看门狗
bl set_up_mem_ctl @设置存储控制器
bl cp_steppingston_to_sdram @将steppingston中的4k内容全部复制到SDRAM
ldr pc, =on_sdram @跳转到SDRAM中执行(b和bl只能跳转前后32M范围的内容)
on_sdram:
ldr sp, =0x34000000 @设置堆栈
bl main
halt_loop:
b halt_loop
disable_watch_dog:
ldr r0, =0x53000000
mov r1, #0x00
str r1, [r0]
mov pc, lr
set_up_mem_ctl:
ldr r0, =MEM_CTL_START_ADDR
adrl r1, mem_ctl_value
add r2, r1, #13*4
1:
ldr r3,[r1],#4
str r3,[r0],#4
cmp r2, r1
bne 1b
mov pc, lr
cp_steppingston_to_sdram:
ldr r0, =SDRAM_START_ADDR
mov r1, #0
add r2, r1, #4096
1:
ldr r3, [r1],#4
str r3, [r0],#4
cmp r1, r2
bne 1b
mov pc, lr
.align @四字节对齐
mem_ctl_value:
.long 0x22000000 @BWSCON
.long 0x0700 @BANKCON0
.long 0x0700 @BANKCON1
.long 0x0700 @BANKCON2
.long 0x0700 @BANKCON3
.long 0x0700 @BANKCON4
.long 0x0700 @BANKCON5
.long 0x18001 @BANKCON6
.long 0x18001 @BANKCON7
.long 0x008C07A3 @ REFRESH
.long 0x00b1 @BANKSIZE
.long 0x0030 @MRSRB6
.long 0x0030 @MRSRB7
Makefile:
sdram.bin:head.s leds.c
arm-linux-gcc -c -g head.s -o head.o
arm-linux-gcc -c -g leds.c -o leds.o
arm-linux-ld -Ttext 0x30000000 head.o leds.o -o sdram_elf
arm-linux-objcopy -O binary -S sdram_elf sdram.bin
arm-linux-objdump -D -m arm sdram_elf > sdram.dis
clean:
rm -f sdram.dis sdram.bin sdram_elf *.o
程序从steppingstone跳转到SDRAM反汇编分析
文件反汇编:
sdram_elf: file format elf32-littlearm
Disassembly of section .text:
30000000 <_start>:
30000000: eb000005 bl 3000001c <disable_watch_dog>
30000004: eb000008 bl 3000002c <set_up_mem_ctl>
30000008: eb000010 bl 30000050 <cp_steppingston_to_sdram>
3000000c: e59ff090 ldr pc, [pc, #144] ; 300000a4 <mem_ctl_value+0x34>
30000010 <on_sdram>:
30000010: e3a0d30d mov sp, #872415232 ; 0x34000000
30000014: eb000030 bl 300000dc <main>
.
.
.
30000070 <mem_ctl_value>:
30000070: 22000000 andcs r0, r0, #0 ; 0x0
30000074: 00000700 andeq r0, r0, r0, lsl #14
30000078: 00000700 andeq r0, r0, r0, lsl #14
3000007c: 00000700 andeq r0, r0, r0, lsl #14
30000080: 00000700 andeq r0, r0, r0, lsl #14
30000084: 00000700 andeq r0, r0, r0, lsl #14
30000088: 00000700 andeq r0, r0, r0, lsl #14
3000008c: 00018001 andeq r8, r1, r1
30000090: 00018001 andeq r8, r1, r1
30000094: 008c07a3 addeq r0, ip, r3, lsr #15
30000098: 000000b1 streqh r0, [r0], -r1
3000009c: 00000030 andeq r0, r0, r0, lsr r0
300000a0: 00000030 andeq r0, r0, r0, lsr r0
300000a4: 30000010 andcc r0, r0, r0, lsl r0
3000000c: e59ff090 ldr pc, [pc, #144]
; 300000a4 <mem_ctl_value+0x34>
在汇编程序中pc值等于当前pc值加8,则pc=0x3000000c+8+144=300000a4,在去30000010
处执行,完成了程序的跳转