s3c2440的SDRAM裸机程序

时间:2021-12-12 12:44:01

1.CPU读取数据是通过存储管理器来实现的。
2.对于SDRAM的操作,需要注意的是:
(1)位宽
(2)行/列地址
(3)刷新周期
(4)Bank地址
3.2440对外能够接8个SDRAM类的芯片,因为内部分为8个bank,有8个片选信号线。
4.SRAM和SDRAM对比
SRAM:价格比较贵,访问简单,只需要发出地址信号即可。
SRAM是英文Static RAM的缩写,即静态随机存储器。它是一种具有静止存取功能的内存,不需要刷新电路即能保存它内部存储的数据。
常见的应用方式:如高速缓存(cache)

SDRAM:价格比较便宜,访问相对复杂,需要发出bank地址,行/列地址等。
SDRAM:Synchronous Dynamic Random Access Memory,同步动态随机存储器,同步是指 Memory工作需要同步时钟,内部的命令的发送与数据的传输都以它为基准;动态是指存储阵列需要不断的刷新来保证数据不丢失;随机是指数据不是线性依次存储,而是*指定地址进行数据读写。
常见应用方式:计算机中的内存
5.SDRAM实验对应的启动文件(汇编代码)

@*************************************************************************
@ 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                 @ 设置堆栈
    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 = 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
    .long   0x000000B1      @ BANKSIZE
    .long   0x00000030      @ MRSRB6
    .long   0x00000030      @ MRSRB7

分析:

(1)一条ARM指令占4个字节的空间,从_start:标号开始的4条bl指令将从0x0000 0000到0x0000 000c的空间占据。在启动文件执行的时候系统已经将看门狗以及SDRAM控制寄存器设置好,最后跳转到后续的设置栈的指令处去执行。

(2)该例程总大小小于4K,所以在从SRAM向SDRAM拷贝数据的过程中设置拷贝的大小为4K。

(3)@符号是GNU汇编的规范,就是注释,';' 有另外的用途。

(4)在arm汇编指令中,pc的值为当前指令的地址加8。解释:这是因为arm处理器内部的流水线技术有关,可以简单的理解为当前指令在执行时,下一条指令其实已经取走在做执行前的一些操作,所以pc的值并不是加4,而是加了两条指令的所占的大小也就是8字节。

(5)ldr pc, =on_sdram这一句话为什么就能保证pc跳转到SDRAM的on_sdram标号处,而不是SRAM中on_sdram标号处?

答:因为在下面的makefile中用-Ttext指定了程序编译之后RO的实际起始地址是0x3000 0000,所以虽然前4K的代码被拷贝到SRAM中执行,但是它们的地址都是以0x3000 0000为基址的,所以标号赋值的时候是按基址算起的。

该实验的C文件代码:

#define GPBCON  (*(volatile unsigned long *)0x56000010)
#define GPBDAT  (*(volatile unsigned long *)0x56000014)

#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(unsigned long dly)
{
 for(; dly > 0; dly--);
}

int main(void)
{
 unsigned long i = 0;
 
 GPBCON = GPB5_out|GPB6_out|GPB7_out|GPB8_out;  // 将LED1-4对应的GPB5/6/7/8四个引脚设为输出

 while(1){
  wait(30000);
  GPBDAT = (~(i<<5));   // 根据i的值,点亮LED1-4
  if(++i == 16)
   i = 0;
 }

 return 0;
}

分析:由于该代码功能比较简单,不做过多的分析。

6.该实验的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
分析:

(1)链接地址:运行时,程序应该“位于”哪里,所以在这个实验的饿makefile中-Ttext后面的参数为0x30000000。