重点分析s3c2410复位后的内存映射,及其应用。
|
|
|
寄存器来访问的,在上电后,NAND Flash开始的4k数据被自动地复制到芯片内部一个被称为“Steppingstone”的RAM上。Steppingstone被映射为地址0,上面的4k程序完成必要的初始化;SDRAM使用BANK6,它的物理起始地址6*128M=0x30000000。
|
LDFLAGS := -Ttext 0x30000000 //ld的链接选项,表示在链接时将整个工程的代码段也就是Text段加载到0x30000000
OBJS += $(patsubst %.c, %.o, $(wildcard init/*.c))
$(LD) $(LDFLAGS) $^ -o $@.o //将所有的.o文件也就是目标文件全部链接到sdram.o文件中
$(OBJDUMP) -D $@.o >$@_s //将链接成的目标文件sdram.o中的符号地址全部输出到sdram_s中
$(OBJCOPY) -O binary -S $@.o $@ //利用objcopy将目标文件sdram.o转化为二进制的格式sdram
clean:
find . -name "*.o" | xargs rm -f
$(RM) sdram*
@echo "OBJS: $(OBJS)"
%.o: %.s
$(CC) $(CFLAGS) -c $< -o $@
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
.equ WDTCON, 0x53000000
@ Memory Control Register Base Address
.equ MEM_CTL_BASE, 0x48000000
@ Sdram Base Address
.equ SDRAM_BASE, 0x30000000
@ Stack top address
.equ stack_top, 0x34000000
@ start
@
.global _start
@ disable watch dog timer
mov r0, #WDTCON
mov r1, #0x0
str r1, [r0]
bl memsetup
bl copy_steppingston_to_sdram
ldr pc, =setup_stack //为什么将setup_stack标号的地址赋给pc,就能跳转到SDRAM中执行,因为在前面利用copy_steppingston_to_sdram已经将程序从steppingstone复制到了SDRAM中来,所以当前语句的下一句也就是在SDRAM中要执行的下一句
ldr sp, =stack_top //设置堆栈,一般将堆栈设置在BANK7中最大只能为4K
b stop
@ sub routines
@
@ r2: dst base address
@ r3: data block length
mov r1, #0x00000000 //基地址也就是steppingstone的地址
ldr r2, =SDRAM_BASE //目的地址也就是sdram的地址
mov r3, #4096 //复制的字节数也就是4KB
1:
@ auto-indexing
@ first transfer, and then write back to the base register r1
ldr r4, [r1], #4 //每次复制4个字节
str r4, [r2], #4
@ r1 is equal to counter
cmp r1, r3
bne 1b
@ r2: memory control register table address
@ r3: r1+13 words(because there is 13 registers)
mov r1, #MEM_CTL_BASE //与SDRAM相关的寄存器是从0x48000000地址开始的,每个寄存器占4个字节
adrl r2, mem_cfg_val //adrl中等范围的地址读取,将mem_cfg_val标号表示的地址值读取到r2寄存器中来
add r3, r1, #13*4 //因为总共有13个寄存器,每个寄存器占4个字节,r3作为循环的结束条件
1:
@ write initial values to registers
ldr r4, [r2], #4 //取出r2寄存器中的地址值对应的值赋给r4,然后r2加上4,指向下一个初始值
str r4, [r1], #4 //将r4的值赋值给r1对应的寄存器,然后将r1加上4,指向下一个寄存器
cmp r1, r3
bne 1b
mem_cfg_val://相当于定义一个寄存器初值表,将每个寄存器的初始值通过一个标号全部定义在一起,因为每个寄存器的地址是规律的也就是相差4个字节所以可以很方便的通过查表来赋值
.long 0x22111110 @ 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 0x008e07a3 @ REFRESH
.long 0x000000b2 @ BANKSIZE
.long 0x00000030 @ MRSRB6
.long 0x00000030 @ MRSRB7
a.STx:启动/禁止SDRAM的数据掩码引脚,对于SDRAM,此位为0;对于
SRAM,此位为1。
b.WSx:是否使用存储器的WAIT信号,通常设为0
c.DWx:使用两位来设置存储器的位宽:00-8位,01-16位,10-32位,
11-保留。
d.比较特殊的是BANK0对应的4位,它们由硬件跳线决定,只读。 对于本开发板,使用两片容量为32Mbyte、位宽为16的SDRAM组成容量为64Mbyte、位宽为32的存储器,所以其BWSCON相应位为:0010。对于本开发板,BWSCON可设为0x22111110:其实我们只需要将BANK6对应的4位设为0010即可,其它的是什么值没什么影响,这个值是参考手册上给出的。
a.MT([16:15]):用于设置本BANK外接的是SRAM还是SDRAM:SRAM-00,SDRAM-11
b.当MT=11时,还需要设置两个参数:
Trcd([3:2]):RAS to CAS delay,设为推荐值01,因为在这里我们知道RAS是0:12也就是13位,而CAS是0:8也就是9位,所以delay就是3
SCAN([1:0]):SDRAM的列地址位数,对于本开发板使用的SDRAM HY57V561620CT-H,列地址位数为9,所以SCAN=01。如果使用其他型号的SDRAM,您需要查看它的数据手册来决定SCAN的取值:00-8位,01-9位,10-10位。
在未使用PLL时,SDRAM时钟频率等于晶振频率12MHz;SDRAM的刷新周期在SDRAM的数据手册上有标明,在本开发板使用的SDRAM HY57V561620CT-H的数据手册上,可看见这么一行“8192 refresh cycles / 64ms”:所以,刷新周期=64ms/8192 = 7.8125 uS。 对于本实验,R_CNT = 2^11 + 1 – 12 * 7.8125 = 1955, REFRESH=0x008e0000 + 1955 = 0x008e07a3.
位[7]=1:Enable burst operation
位[5]=1:SDRAM power down mode enable
位[4]=1:SCLK is active only during the access (recommended)
位[2:1]=010:BANK6、BANK7对应的地址空间与BANK0-5不同。BANK0-5的地址空间都是固定的128M,地址范围是(x*128M)到(x+1)*128M-1,x表示0到5。但是BANK7的起始地址是可变的,您可以从S3C2410数据手册第5章“Table 5-1. Bank 6/7 Addresses”中了解到BANK6、7的地址范围与地址空间的关系。本开发板仅使用BANK6的64M空间,我们可以令位
[2:1]=010(128M/128M)或001(64M/64M):这没关系,多出来的空间程序会检测出来,不会发生使用不存在的内存的情况——后面介绍到的bootloader和linux内核都会作内存检测,位[6]、位[3]没有使用。
能让我们修改的只有位[6:4](CL),SDRAM HY57V561620CT-H不支持CL=1的情况,所以位[6:4]取值为010(CL=2)或011(CL=3)。
SRAM只有4k大小,如果我们的程序大于4k,那么就不能指望利用内部SRAM来运行了。所以得想办法把存储在NAND Flash中的代码,复制到SDRAM中去。对于NAND Flash中的前4k,芯片自动把它复制到内部SRAM中,我们可以很轻松地再把它复制到SDRAM中(实验五中函数copy_steppingstone_to_sdram就做这事)。但是对于4k之后的代码,复制它就不那么轻松了,这就是nand flash之后的问题啦。
|
|