欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

存储控制器和SDRAM 实验

程序员文章站 2022-04-03 22:41:23
...

S3C2440 存储控制器(memory controller)提供了访问外部设备所需的信号,这是一种通过总线形式来访问扩展的外设。

S3C2440 的存储器控制器有以下的特性:
支持小字节序、大字节序(通过软件选择)
每个BANK的地址空间为128MB,总共1GB(8 BANKs)
可编程控制的总线位宽(8/16/32 -bit),不过 BANK0 只能选择两种位宽(16/32 -bit)
总共8个BANK, BANK0 ~ BANK5 可以支持外接 ROM,SRAM等,BANK6 ~ BANK7 除可以支持 ROM,SRAM外,还支持SDRAM等;
BANK0 ~ BANK6 共7个BANK的起始地址是固定的;
BANK7 的起始地址是可编程选择;
BANK6、BANK7的地址空间大小是可编程控制的;
每个BANK的访问周期均可编程控制;
可以通过外部的”wait“ 信号延长总线的访问周期;
在外接SDRAM时,支持自刷新(self-refresh)和省电模式(power down mode)。

S3C2440 对外引出的27根地址线 ADDR0 ~ ADDR26 的访问范围只有 128MB,那么如果达到上面所说的1GB的访问空间呢?CPU对外还引出了8根片选信号 nGCS0 ~ nGCS7,对应与 BANK0 ~ BANK7,当访问 BANKx 的地址空间时,nGCSx 引脚输出低电平用来选中外接的设备。这样,每个 nGCSx 对应 128MB 地址空间,8个 nGCSx 信号总共就对应了 1GB 的地址空间。这8个 BANK的地址空间如图:
存储控制器和SDRAM 实验

如图所示,左边对应不使用 NAND Flash 作为启动设备(单板上不接 NAND_BOOT 跳线)时的地址空间布局,右边对应使用 NAND Flash启动设备(单板上接 NAND_BOOT 跳线)时的地址空间布局。
S3C2440 作为32位的CPU,可以使用的地址范围理论上达到 4GB。除去上述用于连接外设的 1GB 地址空间外,还有一部分是 CPU 内部寄存器的地址,剩下的地址空间没有使用。
注意:这里说的是物理地址。

S3C2440 的寄存器地址范围都处于 0x48000000 ~ 0x5FFFFFFF,各功能部件的寄存器大体相同。如图:
存储控制器和SDRAM 实验

源码:
[html] view plain copy
@***************************************************************
@ File:head.S
@ 功能:设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行
@***************************************************************

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

.text
.global _start
_start:
bl disable_watch_dog @ 关闭看门狗
bl memsetup @ 设置存储控制器
bl copy_steppingstone_to_sdram @ 复制代码到SDRAM中
ldr pc, =on_sdram @ 跳到SDRAM中继续执行
on_sdram:
ldr sp,=0x34000000 @ 设置堆栈
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个寄存器的开始地址
adrl r2, mem_cfg_val @ 这13个值的起始存储地址
add r3, r1, #52 @ 13*4 = 52
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 个寄存器的设置值

@ 存储控制器共有 13 个寄存器,   
@ BANK0 ~ BANK5 只需要设置 BWSCON 和 BANKCONx(x为0~5)两个寄存器:   
@ BANK6、BANK7 外接SDRAM时,除 BWSCON 和 BANKCONx(x为6~7)外,还要设置   
@ REFRESH、BANKSIZE、MRSRB6、MRSRB7 等4个寄存器。  

@ 位宽和等待控制寄存器 BWSCON (BUS WIDTH & WAIT CONTROL REGISTER)  
@ BWSCON 中每4位控制一个 BANK,最高4位对应 BANK7、接下来4位对应 BANK6,依此类推  
@ STx:启动/禁止 SDRAM 的数据掩码引脚,对于 SDRAM,此位为0;对于 SRAM,此位为 1  
@ WSx:是否使用存储器的 WAIT 信号,通常设为 0  
@ DWx:使用两位来设置相应 BANK 的位宽, 0b00 对应8位, 0b01 对应16位,0b10 对应32位,0b11表示保留  
@ 比较特殊的是 BANK0,它没有 ST0 和 WS0,DW0([2:1])只读---由硬件跳线决定:  
@ 0b01 对应16位,0b10 对应32位,BANK0 只支持16、32两种宽度  
@ 对于本开发板(JZ2440),可以确定 BWSCON 寄存器的值为: 0x22011110  
.long       0x22011110                          @ BWSCON  

@ BANK 控制寄存器 BANKCONx(BANK CONTROL REGISTER, x 为 0~5)  
@ 这几个寄存器用来控制 BANK0 ~ BANK5 外接设备的访问时序,使用默认的 0x0700 即可  
.long   0x00000700                          @ BANKCON0  
.long   0x00000700                          @ BANKCON1  
.long   0x00000700                          @ BANKCON2  
.long   0x00000700                          @ BANKCON3  
.long   0x00000700                          @ BANKCON4  
.long   0x00000700                          @ BANKCON5  

@ BANK 控制寄存器 BANKCONx(BANK CONTROL REGISTER, x 为 6~7)  
@ 在8个BANK中,只有BANK6和BANK7可以外接SRAM或SDRAM,  
@ 所以BANKCON6 ~ BANKCON7 与 BANKCON0 ~ BANKCON5 有点不同  
@ MT([16:15]) 用于设置本 BANK 外接的是 ROM/SRAM 还是 SDRAM。  
@ MT=0b00 时,此寄存器与 BANKCON0 ~ BANKCON5 类似。(外接SRAM)  
@ MT=0b11 时,此寄存器其它值如下设置。(外接SDRAM)  
@ Trcd([3:2]) RAS to CAS delay,设置推荐值为 0b01  
@ SCAN([1:0]) SDRAM  的列地址位数。对于本开发板使用的 SDRAM K4S561632,  
@ 列地址位数为 9, 所以 SCAN = 0b01。如果使用其他型号的 SDRAM, 需要查看其数据手册来决定 SCAN 的取值。  
@ 0b00 表示8位, 0b01 表示9位, 0b10 表示10位  
@ 综上所述,本开发板中 BANKCON6/7 均设为 0x00018005  
.long   0x00018005                          @ BANKCON6  
.long   0x00018005                          @ BANKCON7  

@ 刷新控制寄存器 REFRESH(REFRESH CONTROL REGISTER): 设为 0x008C0000 + R_CNT  
@ REFEN([23])   0 = 禁止 SDRAM 的刷新功能, 1 = 开启 SDRAM 的刷新功能  
@ TREFMD([22]) SDRAM 的刷新模式。0 = CBR/Auto Refresh, 1 = Self Refresh(一般在系统休眠时使用)  
@ Trp([21:20]) 设为 0 即可。  
@ Tsrc([19:18]) 设为默认值 0b11 即可。  
@ Refresh Counter([10:0]) 即上述的 R_CNT  
@ R_CNT 可如下计算 (SDRAM 时钟频率就是 HCLK)  
@ R_CNT = 2 ^ 11 + 1 - SDRAM 时钟频率(MHz) * SDRAM 刷新周期 (uS)  
@ SDRAM 的刷新周期在 SDRAM 的数据手册上有标明,在本开发板使用的 SDRAM K4S561632 的数据手册上,  
@ 可看见这么一行 "64 ms refresh period (8K Cycle)"  
@ 所以,刷新周期 = 64ms/8192 = 7.8125 us  
@ 在未使用 PLL 时, SDRAM 时钟频率等于晶振频率 12 MHz  
@ 现在可以计算: R_CNT = 2 ^ 11 + 1 - 12 * 7.8125 = 1955  
@ 所以,在末使用 PLL 时, REFRESH = 0x008C0000 + 1955 = 0x008C07A3  
.long   0x008C07A3                          @ REFRESH  

@ BANKSIZE 寄存器 REFRESH (BANKSIZE REGISTER)  
@ 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 的大小  
@ BANK6/7 对应的地址空间与 BANK0~5 不同。 BANK0~5 的地址空间大小都是固定的 128MB,  
@ 地址返回是 (x*128M) 到 (x+1)*128M-1。 x表示 0 到 5。BANK6/7 的大小是可变的,  
@ 以保持这两个空间的地址连续,即 BANK7 的其实地址会随它们的大小变化。BK76MAP 的取值意义如下:  
@ 0b010 = 128M/128M  
@ 0b001 = 64MB/64MB  
@ 0b000 = 32MB/32MB  
@ 0b111 = 16MB/16MB  
@ 0b110 = 8MB/8MB  
@ 0b101 = 4M/4M  
@ 0b100 = 2M/2M  
@ 本开发板 BANK6 外接64MB的 SDRAM, 令[2:0]=0b001 (64MB/64MB)  
@ 表示 BANK6/7 的容量都是64MB,虽然 BANK7 没有使用  
@ 综上所述,本开发板 BANKSIZE 寄存器的值可算得 0xB1  
.long   0x000000B1                          @ BANKSIZE  

@ SDRAM 模式设置寄存器 MRSRBx (SDRAM MODE REGISTER SET REGISTER, x为6~7)  
@ 能修改的只有位 CL([6:4]),这是 SDRAM 时序的一个时间参数:  
@ 0b000 = 1 clocks, 0b010 = 2 clocks, 0b011 = 3 clocks  
@ SDRAM K4S561632 不支持 CL = 1的情况,所以位[6:4]取值为 0b010 或 0b011 。  
@ 本开发板取最保守的值 0b011, 所以 MRSRB6/7 的值为 0x30  
.long   0x00000030                          @ MRSRB6  
.long   0x00000030                          @ MRSRB7  

[html] view plain copy
// 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;  

}

[html] view plain copy

Makefile

sdram.bin : head.S leds.c
arm-linux-gcc -g -c -o head.o head.S
arm-linux-gcc -g -c -o leds.o leds.c
arm-linux-ld -Ttext 0x30000000 -g 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.dis *.o

相关标签: 存储