您的位置:首页 > 其它

存储控制器SDRAM实验

2013-01-05 22:55 288 查看
今天继续学习韦东山老师的视频教程,这是有关存储控制器以及SDRAM实验的部分。

S3C2440对外引出27根地址线ADDR0-ADDR26,访问范围只有128MB,CPU对外还引出8根片选信号nGCS0-nGCS7,对应BANK0-BANK7,当访问BANKx的地址空间时,nGCSx引脚输出低电平来选中外接设备。

这样每个128MB空间,共8个片选,对应1GB的地址空间。S3C2440是32位CPU,可以使用的地址范围理论达到4GB,除去上面连接外设的1GB空间外,还有一部分是CPU内部寄存器的地址,剩下的地址空间没有使用。

先上源码,head.S文件内容

@*************************************************************************
@ File:head.S
@ 功能:设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行
@*************************************************************************

.equ        MEM_CTL_BASE,       0x48000000
.equ        SDRAM_BASE,         0x30000000

.text
.global _start
_start:
bl  disable_watch_dog               @ 关闭WATCHDOG,否则CPU会不断重启
bl  memsetup                        @ 设置存储控制器
bl  copy_steppingstone_to_sdram     @ 复制代码到SDRAM中
ldr pc, =on_sdram                   @ 跳到SDRAM中继续执行
on_sdram:
ldr sp, =0x34000000                 @ 设置堆栈,0x34000000为SDRAM中bank7的start address
bl  main
halt_loop:
b   halt_loop

disable_watch_dog:
@ 往WATCHDOG寄存器写0即可
mov r1,     #0x53000000
mov r2,     #0x0
str r2,     [r1]
mov pc,     lr      @ 返回

copy_steppingstone_to_sdram:
@ 将Steppingstone的4K数据全部复制到SDRAM中去
@ Steppingstone起始地址为0x00000000,SDRAM中起始地址为0x30000000

mov r1, #0
ldr r2, =SDRAM_BASE
mov r3, #4*1024
1:
ldr r4, [r1],#4     @ 从Steppingstone读取4字节的数据,并让源地址加4
str r4, [r2],#4     @ 将此4字节的数据复制到SDRAM中,并让目地地址加4
cmp r1, r3          @ 判断是否完成:源地址等于Steppingstone的未地址?
bne 1b              @ 若没有复制完,继续
mov pc,     lr      @ 返回

memsetup:
@ 设置存储控制器以便使用SDRAM等外设

mov r1,     #MEM_CTL_BASE       @ 存储控制器的13个寄存器的开始地址,0x48000000为BWSCON的起始地址
adrl    r2, mem_cfg_val         @ 这13个值的起始存储地址
add r3,     r1, #52             @ 13*4 = 54
1:
ldr r4,     [r2], #4            @ 读取设置值,并让r2加4
str r4,     [r1], #4            @ 将此值写入寄存器,并让r1加4
cmp r1,     r3                  @ 判断是否设置完所有13个寄存器
bne 1b                          @ 若没有写成,继续
mov pc,     lr                  @ 返回

.align 4
mem_cfg_val:
@ 存储控制器13个寄存器的设置值
.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//refresh_count=2^11+1-12*7.8125=1955	REFRESH=0x008C0000+1955=0x008C07A3
.long   0x000000B1      @ BANKSIZE
.long   0x00000030      @ MRSRB6
.long   0x00000030      @ MRSRB7


.equ        MEM_CTL_BASE,       0x48000000此处是设置BWSCON寄存器,其地址为0x48000000.

.equ        SDRAM_BASE,         0x30000000BANK6和BANK7外接SDRAM,其中BANK6的起始地址为0x30000000

on_sdram:

    ldr sp, =0x34000000                 @ 设置堆栈,0x34000000为SDRAM中bank7的start address

    bl  main

此处为什么要将sp设置到0x34000000?

关于_start部分,这里涉及到程序的启动过程,具体过程如下:

1)CPU上电后,硬件自动将NAND前4k的内容复制到SRAM,在手册中SRAM称为steppingstone,其地址为0x00000000.

2)这时,程序需要关闭看门狗,若不关闭系统将不断重启。之后初始化存储管理器

3)存储管理器初始化完成后,将代码从SRAM拷贝到SDRAM中,然后程序继续执行。在这里,由于程序大小只有不到4k,所以可以直接拷贝。若程序大于4k,则需要从NandFlash中拷贝余下内容。

以上三步逐步对应此四段代码

bl  disable_watch_dog               @ 关闭WATCHDOG,否则CPU会不断重启
bl  memsetup                        @ 设置存储控制器
bl  copy_steppingstone_to_sdram     @ 复制代码到SDRAM中
ldr pc, =on_sdram                   @ 跳到SDRAM中继续执行


adrl    r2, mem_cfg_val         @ 13个值的起始存储地址

ADRL 指令将基于PC或基于寄存器的地址值读取到寄存器中。ADRL伪指令比ADR伪指令可以读取更大范围的地址。ADRL伪指令在汇编时被编译器替换成两条指令,即使一条指令可以完成该伪指令的功能。 语法格式 ADRL{cond} register,expr
bne 1b                          @ 若没有写成,继续

bne里的1b是向后跳转到局部标签1处执行,b表示backward 

对应的还有bne 1f(向前跳到局部标签1处执行) 如:
1: ;A 

cmp r0, #0 

beq 1f ; r0==0那么向前跳转到B处执行 

bne 1b ; 否则向后跳转到A处执行 

1: ;B 

1b,1f里的b和f表示backward和forward,1表示局部标签1 

刚意识到这里出现了.align,经查,该指令为:对指令或者数据的地址进行对齐,关于该指令的详细介绍:http://blog.csdn.net/cs1275/article/details/8487468

存储控制器各寄存器值设定的说明:

1)位宽和等待控制寄存器BWSCON





BWSCON中每四位控制一个BANK,最高4位对应BANK7、接下来4位对应BANK6,依次类推。
STx:启动/禁止SDRAM的数据掩码引脚
WSx:是否使用存储器的WAIT信号
DWx:设置对应BANK的位宽,0b00对应8位,0b01对应16位,0b10对应32位,0b11表示保留

比较特殊的是BANK0,它没事ST0和WS0,DW0只读,由硬件跳线决定,0b01表示16位,0b10表示32位,BANK0只支持16、32两种位宽
所以可以确定BWSCON寄存器值为:0x22011110

2)BANK控制寄存器BANKCONx(x为0-5)



这些寄存器用来控制BANK0-BANK5外接设备的访问时序,使用默认0x0700即可

3)BANK控制寄存器BANKCONx(x为6-7)



MT[16:15]:设置BANK外接ROM/SRAM还是SDRAM,00=ROM/SRAM,01=保留,10=保留,11=SDRAM

MT=0b00时,与BANKCON0-BANKCON5类似
MT=0b11时,Trcd[3:2]:RAS to CAS delay,设为推荐值0b01
SCAN[1:0]:SDRAM的列地址数,本开发板使用的SDRAM列地址数为9,0b00=8位,0b01=9位,0b10=10位
所以本开发板,BANKCON6/7均设为0x00018005

4)刷新控制寄存器REFRESH



 REFEN[23]: 0=禁止SDRAM的刷新功能,1=开启SDRAM的刷新功能

TREFMD[22]: SDRAM的刷新模式,0=CBR/Auto Refresh,1=SelfRefresh

Trp[21:20]: SDRAM RAS预充电时间 00=2 clocks,01=3clocks,10=4clocks,11=不支持

Tsrc[19:18]: SDRAM半行周期时间 00=4clocks,01=5clocks,10=6clocks,11=7clocks,SDRAM行周期时间Trc=Tsrc+Trp

Refresh Counter[10:0]: SDRAM刷新计数,刷新时间=(2^11+1-refresh_count)/HCLK,在未使用PLL时,HCLK=晶振频率12MHz,刷新周期为7.8125us
refresh_count=2^11+1-12*7.8125=1955

REFRESH=0x008C0000+1955=0x008C07A3

5)BANKSIZE寄存器



BURST_EN[7]: 0=ARM核禁止突发传输,1=ARM核支持突发传输

SCKE_EN[5]: 0=不使用SCKE信号令SDRAM进入省电模式,1=使用SCKE信号令SDRAM进入省电模式

SCLK_EN[4]: 0=时刻发出SCLK信号,1=仅在方位SDRAM期间发出SCLK信号

BK76MAP[2:0]: 设置BANK6/7的大小,0b010=128MB/128MB,0b001=64MB/64MB,0b000=32M/32M,0b111=16M/16M,0b110=8M/8M,0b101=4M/4M,0b100=2M/2M
本开发板外接64MB的SDRAM
则本开发板BANKSIZE设为0xB1

6)SDRAM模式设置寄存器MRSRBx(x为6-7)



CL[6:4]: 0b000=1clocks,0b010=2clocks,0b011=3clocks
本开发板取0b011,所以MRSRB6/7取值为0x30

leds.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  wait(volatile unsigned long dly)
{
for(; dly > 0; dly--);
}

int main(void)
{
unsigned long i = 0;

GPFCON = GPF4_out|GPF5_out|GPF6_out;		// 将LED1,2,4对应的GPF4/5/6三个引脚设为输出

while(1){
wait(30000);
GPFDAT = (~(i<<4));	 	// 根据i的值,点亮LED1,2,4
if(++i == 8)
i = 0;
}

return 0;
}


Makefile文件

sdram.bin : head.S  leds.c
arm-linux-gcc  -c -o head.o head.S
arm-linux-gcc -c -o leds.o leds.c
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
arm-linux-ld -Ttext 0x30000000 head.o leds.o -o sdram_elf中-Ttext0x30000000为代码段的起始地址,此地址也是SDRAM的起始地址,更确切的说也是BANK6的起始地址。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息