经过了一段时间考试,今天终于把SDRAM这块给学习了。
1、许多单片机像STM32一直是使用片上FLASH和RAM,MDK也是定义好了下载算法,进行简单地配置就可以了,而s3c2440确需要外扩FLASH和SDRAM(小于4K的程序可以不用配置SDRAM),使用前需要对其进行初始化。
S3C2440 有 27 根地址线 ADDR[26:0],2^27= 128Mbyte ,是一个bank的最大容量,有8个bank,bank0-5 for Rom、Sram,bank6-7 for Rom、sram、Sdram,bank6和bank7可配置大小。通过memory controler来配置SDRAM
SDRAM 内部是一个存储阵列。可以把它想象成一个表格。和表格的检索原理一样,先指定行,再指定列,就可以准确找到所需要的存储单元。这个表格称为逻辑BANK。目前的 SDRAM 基本都是 4 个 L-BANK。寻址的流程就是先指定L- BANK 地址,再指定行地址,最后指定列地址。
HY57V561620F这个SDRAM有
13根行地址线 RA0-RA12
9 根列地址线 CA0-CA8
2 根BANK 选择线 BA0-BA1
SDRAM的地址引脚是复用的,在读写SDRAM存储单元时,操作过程是将读写的地址分两次输入到芯片中,每一次都由同一组地址线输入。两次送到芯片上去的地址分别称为行地址和列地址。它们被锁存到芯片内部的行地址锁存器和列地址锁存器。/RAS 是行地址锁存信号,该信号将行地址锁存在芯片内部的行地址锁存器中;/CAS 是列地址锁存信号,该信号将列地址锁存在芯片内部的列地址锁存器中,这样就更容易理解这里只有15个地址总线了。
SDRAM 的A0接S3C2440 的ADDR2。SDRAM 的A0接S3C2440 的哪一根地址线是根据整个SDRAM 的数据位宽来决定的。(因为CPU的寻址空间是以Byte为单位的)。BA0~BA1 代表了SDRAM 的最高2地址位,因此接ADDR24与ADDR25。也可以这样推理:13根行地址线+9根列地址线 = 22根。另外 HY57V561620F 一个存储单元是2 个字节,相当于有了23根地址线。BA0,BA1 是最高地址位,所以应该接在ADDR24,ADDR25上。也就是说SDRAM 的BA0,BA1接S3C2440 的哪几根地址线是根据整个SDRAM 的容量来决定的。
2、下面是使用SDRAM的程序(汇编+C语言)
a、
AREA Init,CODE,READONLY
ENTRY
start
/* close watchdog */
ldr r0,=0x53000000
mov r1,#0
str r1,[r0]
bl initmem
bl copyall
IMPORT xmain
ldr sp,=0x34000000
ldr lr,=endxmain
ldr pc,=xmain
endxmain
ldr r0, =0x56000010
ldr r1, =0x00015400
str r1, [r0]
ldr r0, =0x56000014
ldr r1, =0x0
str r1,[r0]
loop
b loop
/* copy the text */
copyall
IMPORT |Image$$RO$$Base|
IMPORT |Image$$RW$$Limit|
ldr r0, =|Image$$RO$Base|
ldr r1, =|Image$$RW$$Limit|
ldr r2, =0x0
copyallloop
teq r0,r1
beq quitcopyallloop
ldr r3, [r2], #4
str r3, [r0], #4
b copyallloop
quitcopyallloop
mov pc, lr
/* init mem */
initmem
ldr r0, =0x48000000
ldr r1, =0x48000034
adr r2, memdata
initmemloop
ldr r3, [r2], #4
str r3, [r0], #4
teq r0, r1
bne initmemloop
mov pc,lr
memdata<span style="white-space:pre"> </span>//
DCD 0x22000000 //BWSCON
DCD 0x00000700 //BANKCON0
DCD 0x00000700 //BANKCON1
DCD 0x00000700 //BANKCON2
DCD 0x00000700 //BANKCON3
DCD 0x00000700 //BANKCON4
DCD 0x00000700 //BANKCON5
DCD 0x00018005 //BANKCON6
DCD 0x00018005 //BANKCON7
DCD 0x008e07a3 //REFRESH
DCD 0x000000b1 //BANKSIZE
DCD 0x00000030 //MRSRB6
DCD 0x00000030 //MRSRB7
END
编译时出了一些问题,bad instruction,如下图:
试了几次,还是不行,又把程序改成了下面的样子
b、下面的程序编译成功,并且下载到板子上成功
Init.s
.equ MEM_CTL_BASE, 0x48000000
.equ SDRAM_BASE, 0x30000000
.text
.global _start
_start:
bl disable_watchdog
bl memsetup
bl copy_steppingstone_to_sdram
ldr pc,=on_sdram
on_sdram:
/* IMPORT xmain */
ldr sp,=0x34000000
bl xmain
halt_loop:
b halt_loop
/* close watchdog */
disable_watchdog:
ldr r0,=0x53000000
mov r1,#0
str r1,[r0]
mov pc,lr
/* copy the text */
copy_steppingstone_to_sdram:
mov r1,#0
ldr r2,=SDRAM_BASE
mov r3,#4*1024<span style="white-space:pre"> </span>//4K空间
1:<span style="white-space:pre"> </span>//局部标签
ldr r4,[r1],#4
str r4,[r2],#4
cmp r1,r3
bne 1b
mov pc,lr
/* init mem */
memsetup:
mov r1,#MEM_CTL_BASE<span style="white-space:pre"> </span>//<span style="font-family: Arial, Helvetica, sans-serif;">13个相关寄存器的起始地址</span>
adrl r2,memdata
add r3,r1,#52 @13*4<span style="white-space:pre"> </span>//<span style="font-family: Arial, Helvetica, sans-serif;">13个相关寄存器</span><span style="white-space:pre">
</span>
1:
ldr r4,[r2],#4
str r4,[r1],#4
cmp r1,r3
bne 1b
mov pc,lr
.align 4
memdata:<span style="white-space:pre"> </span>//<span style="font-family: Arial, Helvetica, sans-serif;">13个相关寄存器</span>
.long 0x22000000 @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 0x000000b1 @BANKSIZE
.long 0x00000030 @MRSRB6
.long 0x00000030 @MRSRB7
delay.s
@AREA delay,CODE,READONLY
@entry
@code32
@extern delay
@EXPORT delay
.text
.global delay
delay:
sub r0,r0,#1 /* parameter transmission */
cmp r0,#0x0
bne delay
mov pc,lr
main.c (跑马灯)
#define GPBCON (*(volatile unsigned long *)0x56000010)
#define GPBDAT (*(volatile unsigned long *)0x56000014)
#define LEDS (1<<5|1<<6|1<<7|1<<8)
#define DELAYVAL (0x0ffff)
extern int delay(int time);
//int i = 5;
int xmain()
{
GPBCON = 0x00015400;
// while(i > 0)
while(1)
{
GPBDAT=(GPBDAT&(~LEDS)) | (1<<6|1<<7|1<<8);
delay(DELAYVAL);
GPBDAT=(GPBDAT&(~LEDS)) | (1<<5|1<<7|1<<8);
delay(DELAYVAL);
GPBDAT=(GPBDAT&(~LEDS)) | (1<<5|1<<6|1<<8);
delay(DELAYVAL);
GPBDAT=(GPBDAT&(~LEDS)) | (1<<5|1<<6|1<<7);
delay(DELAYVAL);
// i--;
}
return 0;
}
Makefile
sdram.bin:Init.o delay.o main.o
arm-linux-ld -Ttext 0x30000000 -o sdram_led.elf $^
arm-linux-objcopy -O binary -S sdram_led.elf sdram.bin
arm-linux-objdump -D sdram_led.elf > sdram.dis
%.o:%.s<span style="white-space:pre"> </span>//通配符
arm-linux-gcc -o $@ $< -c
%.o:%.c
arm-linux-gcc -o $@ $< -c
clean:
rm *.o sdram_led.elf sdram.bin sdram.dis
新学到的汇编知识:equ,dcd,align,.word,.long,局部标签1和1b以及arm的一些伪指令,写Makefile时的通配符的运用
还是不知道那些出错的bad instruction是为什么
要搞懂从steppingstone跳转到SDRAM的指令,ldr pc,=on_sdram,看反汇编的代码可以理解