07-存储管理器实验
S3C2440的存储控制器提供了访问外设所需要的信号,它有如下特性:
支持大/小端字节(通过软件选择);每个BANK的地址空间为128MB,总共1GB(8个BANK);可编程控制的总线宽度(8/16/32bit),BANK0只有两种位宽(16/32bit);总共8个BANK:BANK0-BANK5可以支持外接ROM、SRAM等;BANK6-BANK7除了支持ROM、SRAM外,还支持SDRAM等;BANK0-BANK6七个BANK的起始地址固定;BANK7的起始地址可编程选择;每个BANK的访问周期均可编程控制;通过外部的wait信号延长总线的访问周期;在外接SDRAM时,支持自刷新和省电模式模式。
S3C2440对外引出的27根地址线ADDR0-ADDR26的访问范围只有128MB,而八个片选信号nGCS0-nGCS7对应于BANK0-BANK7,当访问BANKx的地址空间时,nGCSx引脚输出低电平用来选中外接的设备。每个nGCSx对应128MB地址空间,8个nGCSx信号总共对应了1GB。
在TQ2440开发板中BANK6连接SDRAM,CPU对其提供了一组用于SDRAM的信号:
SDRAM时钟有效信号LSCKE;SDRAM时钟信号LSCLK0/LSCLK1;数据掩码信号LnWBE0/LnWBE1/LnWBE2/LnWBE3;SDRAM行地址选通脉冲信号LnSRAS;SDRAM列地址选通脉冲信号LnSCAS;写允许信号LnWE
1、SDRAM介绍
SDRAM的内部是一个存储阵列,如同一个二维表格,将数据填进去。其检索原理和表格相同,先指定一个行地址,再指定一个列地址就可以准确找到所需要的单元格。这个单元格被称为存储单元,而表格则称为逻辑BANK(L-BANK),SDRAM一般有4个L-BANK其逻辑图为上图所示。
访问SDRAM可以分为如下四个步骤:
1、CPU发出的片选信号LnSCS0有效;2、SDRAM中有4个L-BANK,需要两根地址线来选中其中一个,从图中可知使用ADDR24、ADDR25作为L-BANK选择信号;3、对选中的芯片进行统一行/列(存储单元)寻址;4、找到存储单元后,被选中的芯片进行同一的数据传输。
在TQ2440开发板中使用了两片16位的ADRAM芯片并联组成32位的位宽,与CPU的32根数据线(DATA0-DATA31)相连。BANK6的起始地址为0x30000000,所以SDRAM的访问地址为0x30000000-ox33ffffff,共64MB。
2、存储控制器的寄存器使用
在S3C2440中,存储控制器一共有13个寄存器,BANK0-BANK5只需要设置BWSCON和BANKCONx(x为0-5)两个寄存器,BANK6/BANK7外接SDRAM时,除了WSCON和BANKCONx(x为6-7)外,还需要设置REFRESH、BANKSIZE、MRSRB6、MRSRB7等四个寄存器。下面分别说明每个寄存器。
位宽和等待控制寄存器BWSCON
BWSCON | 说明 |
---|---|
STx | 启动/禁止SDRAM的数据掩码引脚,对于SDRAM,此位为0;对于SRAM,此位为1 |
WSx | 是否使用存储器的WAIT信号,通常设为0 |
DWx | 使用两位来设置相应BANK的位宽,0b00对应8位,0b01对应16位,0b10对应32位,0b11保留 |
对于BANK0,它没有ST0和WS0、DW0([2:1]),bank0只支持两种位宽16/32。
BANK控制寄存器BANKCONx(x为0-5),控制BANK0-BANK5外接设备的访问时序,使用默认的0x0700即可满足TQ2440开发板。
BANK控制寄存器BANKCONx(x为6-7),在8个BANK中,只有BANK6和BANK7可以外接SRAM或SDRAM,因此其设置方法有所不同。
BANKCONn | 说明 |
---|---|
MT [16:15] | 用于设置BANK外接的是SRAM或SDRAM,00 = ROM or SRAM,11 = Sync. DRAM |
Trcd [3:2] | RAS to CAS delay,推荐设置0b01 |
SCAN [1:0] | SDRAM的列地址位数,00 = 8-bit 01 = 9-bit 10= 10-bit |
刷新控制寄存器REFRESH
REFRESH | 说明 |
---|---|
REFEN [23] | 0,禁止SDRAM的刷新功能,1,开启SDRAM的刷新功能 |
TREFMD [22] | SDRAM的刷新模式。0 = CBR/Auto Refresh 1 = Self Refresh(一般系统休眠时使用) |
Trp [21:20] | 一般设置为0 |
Tsrc [19:18] | 设为默认值11 |
Refresh Counter [10:0] | SDRAM的刷新值,Refresh period = (211-SDRAM时钟频率(MHX)+1)/sdram刷新周期(us) |
BANKSIZE寄存器
BANKSIZE | 说明 |
---|---|
BURST_EN [7] | 0,禁止ARM核突发传输;1,ARM核支持突发传输 |
SCKE_EN [5] | 0,不使用SCKE信号令SDRAM进入省电模式;1,使用SCKE信号令SDRAM进入省电模式 |
SCLK_EN [4] | 0,时刻发出SCLK信号;1,仅在访问SDRAM期间发出SCLE信号 |
BK76MAP [2:0] | 配置BANK大小 |
SDRAM模式设置寄存器MRSRBx(6-7)
MRSRBx | 说明 |
---|---|
CL [6:4] | SDRAM时序的时间参数设置 |
3、存储控制器实验;点亮LED灯
从NAND Flash启动CPU时,CPU会通过内部的硬件将NAND Flash开始的4KB数据复制到称为Steppingstone的4KB的内部RAM中(起始地址为0),然后跳转到地址0开始执行。
本实验先使用汇编语言设置好存储控制器,使外接的SDRAM可用,然后把程序本身从Steppingstone复制到SDRAM,最后跳转到SDRAM中执行。
首先在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 @ 设置堆栈 bl mainhalt_loop: b halt_loopdisable_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*10241: 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 = 541: ldr r4, [r2], #4 @ 读取设置值,并让r2加4 str r4, [r1], #4 @ 将此值写入寄存器,并让r1加4 cmp r1, r3 @ 判断是否设置完所有13个寄存器 bne 1b @ 若没有写成,继续 mov pc, lr @ 返回.align 4mem_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 .long 0x000000B1 @ BANKSIZE .long 0x00000030 @ MRSRB6 .long 0x00000030 @ MRSRB7
在leds.c文件中,完成led循环闪烁的实验:
#define GPBCON (*(volatile unsigned long *)0x56000010)#define GPBDAT (*(volatile unsigned long *)0x56000014)/* * LED1,LED2,LED4对应GPB5、GPB6、GPB7、GPB8 */#define GPB5_out (1<<(5*2))#define GPB6_out (1<<(6*2))#define GPB7_out (1<<(7*2))#define GPB8_out (1<<(8*2))void wait(volatile unsigned long dly){ for(; dly > 0; dly--);}int main(void){ unsigned long i = 0; // LED1,LED2,LED3,LED4对应的4根引脚设为输出 GPBCON = GPB5_out | GPB6_out | GPB7_out | GPB8_out; while(1){ wait(30000); GPBDAT = (~(i<<5)); // 根据i的值,点亮LED1,2,3,4 if(++i == 16) 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 #链接代码段的起始地址为0x30000000 arm-linux-objcopy -O binary -S sdram_elf sdram.bin arm-linux-objdump -D -m arm sdram_elf > sdram.disclean: rm -f sdram.dis sdram.bin sdram_elf *.o
代码的具体流程图为:
实验结果:
相比于直接在内部SRAM运行结果,可以发现在外部SDRAM运行的LED点灯程序,LED闪烁变慢 。本程序只能将内部SRAM的4KB程序复制到外部SDRAM,当程序大于4KB时,要复制4KB后的代码,就需要使用NAND Flash控制器。
实验代码