【JZ2440笔记】裸机实验使用SDRAM

 

一、前言

S3C2440选择Nand启动模式之后,会将Nand Flash的块0前4KB的数据拷贝到片内的4KB SRAM中去,然后PC指针指到SRAM的0地址去顺序向下取指令执行,但是4KB的代码运行空间太小了,所以SRAM的这4KB空间只用来做启动前的一些必要初始化,更大型的代码需要从Nand Flash的其他块中读出来,然后写入到外部的SDRAM中去,PC指针再从片内的SRAM跳到外部SDRAM中去运行程序。JZ2440开发板上的SDRAM是16Mx16bit的,有两片,总共是64MB容量。

 

二、实验目标

在SRAM中完成关闭看门狗、初始化SDRAM、将main.c代码拷贝到SDRAM中;然后跳到SDRAM中去执行main函数的代码使LED闪烁。

 

三、硬件连线

SDRAM有数据总线和地址总线,由于有两片SDRAM,1片SDRAM位宽时16位的,两片并行组合起来使用,相当于位宽有32位,所以数据总线第一片连LDATA0到15,第二片连LDATA16到31;地址总线需要错开两位连接,即LADDR0和LADDR1是用不上的,因为两片SDRAM组合之后寻址是4字节对齐的,所以最低两位地址线没有意义。

S3C2440有专门的存储器控制器来操作SDRAM,和STM32单片机的FSMC模块原理是类似的,就是划分了许多段虚拟的内存空间,这些内存空间映射到要控制的存储器内存,我们往这些虚拟的内存地址上面进行数据读写,S3C2440的存储控制器自动完成对外部设备对应的读写操作。

S3C2440的存储器控制器划分为8个Bank,每个Bank映射空间为128MB,8个Bank都可以控制ROM和SRAM类型的存储器,但是只有Bank 6和7可以控制SDRAM。该实验中用Bank 6完成对两个SDRAM的控制。存储控制器涉及到的寄存器如下:

 

四、程序设计

本实验包含5个源文件,分别如下:

head.S:启动文件,关闭看门狗,初始化SDRAM,拷贝SRAM中的main函数代码到SDRAM中运行。

init.c:包含关闭看门狗,初始化SDRAM和SRAM拷贝数据到SDRAM的C函数代码。

main.c:循环闪烁LED。

sdram.lds:链接脚本,划分代码在bin文件中的存放位置。

Makefile:编译代码。

各个文件内容具体如下:

head.S

@*************************************************************************
@ File:head.S
@ 功能:设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行
@*************************************************************************       
.text
.global _start
_start:

	ldr	    sp, =4096               @设置堆栈,因为要调用C语言函数 
	bl	    disable_watch_dog       @关WATCH DOG
	bl	    memsetup                @初始化SDRAM
    bl	    copy_steppingstone_to_sdram     @ 复制代码到SDRAM中
    ldr     sp, =0x34000000         @设置栈
    ldr     lr, =halt_loop          @设置返回地址
    ldr     pc, =main               @b指令和bl指令只能前后跳转32M的范围,所以这里使用向pc赋值的方法进行跳转
halt_loop:
    b       halt_loop


init.c


/* WOTCH DOG register */
#define WTCON               (*(volatile unsigned long *)0x53000000)

/* SDRAM regisers */
#define REG_BWSCON              (*(volatile unsigned long *)0x48000000)
#define REG_BANKCON6            (*(volatile unsigned long *)0x4800001C)
#define REG_REFRESH             (*(volatile unsigned long *)0x48000024)
#define REG_BANKSIZE            (*(volatile unsigned long *)0x48000028)
#define REG_MRSRB6              (*(volatile unsigned long *)0x4800002C)

/* SDRAM Start Addr*/
#define SDRAM_START_ADDR    0x30000000

/* main function offset*/
#define MAIN_FUNC_OFFSET    2048
 
void disable_watch_dog();
void memsetup();
void copy_steppingstone_to_sdram();

/*上电后,WATCH DOG默认是开着的,要把它关掉 */
void disable_watch_dog()
{
	WTCON	= 0;
}

/* 设置控制SDRAM的寄存器 */
void memsetup()
{
    REG_BWSCON = 0x22011110;
    REG_BANKCON6 = 0x00018005;
    REG_REFRESH = 0x008C07A3;
    REG_BANKSIZE = 0x000000B1;
    REG_MRSRB6 = 0x00000030;
}

void copy_steppingstone_to_sdram()
{
    int i;
    unsigned long *p = (unsigned long *)SDRAM_START_ADDR;
    unsigned long *pSrc = (unsigned long *)MAIN_FUNC_OFFSET;

    for(i = 0; i < (2048 / sizeof(unsigned long)); i++)
    {
        p[i] = pSrc[i];
    }
}

main.c

#define	GPFCON		(*(volatile unsigned long *)0x56000050)
#define	GPFDAT		(*(volatile unsigned long *)0x56000054)

void  wait(volatile unsigned long dly)
{
	for(; dly > 0; dly--);
}

int main(void)
{
	GPFCON = 0x00001500;  //将GPF4、GPF5、GPF6设置为输出模式
	
	while(1)
	{		
		GPFDAT = 0x00000000;  //亮灯
		wait(30000);
		GPFDAT = 0x00000070;  //灭灯
		wait(30000);
	}
	
	return 0;
}

sdram.lds

SECTIONS { 
  firtst  	0x00000000 : { head.o init.o}
  second 	0x30000000 : AT(2048) { main.o }
} 
 

该链接脚本指定了将main.c编译的指令代码放到bin文件的2048地址处,main.c中的代码链接地址是0x30000000,表示main.c中的代码运行的时候应该是位于0x30000000地址处的,也就是SDRAM的起始地址。拷贝main函数是从SRAM的2048地址处拷贝2048个字节到SDRAM的开头处。

Makefile

objs := head.o init.o main.o

sdram.bin : $(objs)
	arm-linux-ld -Tsdram.lds	-o sdram_elf $^
	arm-linux-objcopy -O binary -S sdram_elf $@
	arm-linux-objdump -D -m arm  sdram_elf > sdram.dis

%.o:%.c
	arm-linux-gcc -Wall -c -O2 -o $@ $<

%.o:%.S
	arm-linux-gcc -Wall -c -O2 -o $@ $<

clean:
	rm -f  sdram.dis sdram.bin sdram_elf *.o

执行make后得到的反汇编文件sdram.dis如下:

sdram.dis


sdram_elf:     file format elf32-littlearm

Disassembly of section firtst:

00000000 <_start>:
   0:	e3a0da01 	mov	sp, #4096	; 0x1000
   4:	eb000007 	bl	28 <disable_watch_dog>
   8:	eb00000a 	bl	38 <memsetup>
   c:	eb00001a 	bl	7c <copy_steppingstone_to_sdram>
  10:	e3a0d30d 	mov	sp, #872415232	; 0x34000000
  14:	e59fe004 	ldr	lr, [pc, #4]	; 20 <firtst+0x20>
  18:	e59ff004 	ldr	pc, [pc, #4]	; 24 <firtst+0x24>

0000001c <halt_loop>:
  1c:	eafffffe 	b	1c <halt_loop>
  20:	0000001c 	andeq	r0, r0, ip, lsl r0
  24:	30000034 	andcc	r0, r0, r4, lsr r0

00000028 <disable_watch_dog>:
  28:	e3a02000 	mov	r2, #0	; 0x0
  2c:	e3a03453 	mov	r3, #1392508928	; 0x53000000
  30:	e5832000 	str	r2, [r3]
  34:	e1a0f00e 	mov	pc, lr

00000038 <memsetup>:
  38:	e3a03422 	mov	r3, #570425344	; 0x22000000
  3c:	e3a00723 	mov	r0, #9175040	; 0x8c0000
  40:	e2833a11 	add	r3, r3, #69632	; 0x11000
  44:	e3a02906 	mov	r2, #98304	; 0x18000
  48:	e3a01312 	mov	r1, #1207959552	; 0x48000000
  4c:	e2833e11 	add	r3, r3, #272	; 0x110
  50:	e2822005 	add	r2, r2, #5	; 0x5
  54:	e2800e7a 	add	r0, r0, #1952	; 0x7a0
  58:	e5813000 	str	r3, [r1]
  5c:	e2800003 	add	r0, r0, #3	; 0x3
  60:	e3a030b1 	mov	r3, #177	; 0xb1
  64:	e581201c 	str	r2, [r1, #28]
  68:	e3a02030 	mov	r2, #48	; 0x30
  6c:	e5810024 	str	r0, [r1, #36]
  70:	e5813028 	str	r3, [r1, #40]
  74:	e581202c 	str	r2, [r1, #44]
  78:	e1a0f00e 	mov	pc, lr

0000007c <copy_steppingstone_to_sdram>:
  7c:	e3a01f7f 	mov	r1, #508	; 0x1fc
  80:	e2811003 	add	r1, r1, #3	; 0x3
  84:	e3a0c203 	mov	ip, #805306368	; 0x30000000
  88:	e3a00b02 	mov	r0, #2048	; 0x800
  8c:	e3a02000 	mov	r2, #0	; 0x0
  90:	e7903102 	ldr	r3, [r0, r2, lsl #2]
  94:	e78c3102 	str	r3, [ip, r2, lsl #2]
  98:	e2822001 	add	r2, r2, #1	; 0x1
  9c:	e1520001 	cmp	r2, r1
  a0:	9afffffa 	bls	90 <copy_steppingstone_to_sdram+0x14>
  a4:	e1a0f00e 	mov	pc, lr
  a8:	43434700 	cmpmi	r3, #0	; 0x0
  ac:	4728203a 	undefined
  b0:	2029554e 	eorcs	r5, r9, lr, asr #10
  b4:	2e342e33 	mrccs	14, 1, r2, cr4, cr3, {1}
  b8:	00000035 	andeq	r0, r0, r5, lsr r0
Disassembly of section second:

30000000 <wait>:
30000000:	e24dd004 	sub	sp, sp, #4	; 0x4
30000004:	e58d0000 	str	r0, [sp]
30000008:	e59d3000 	ldr	r3, [sp]
3000000c:	e3530000 	cmp	r3, #0	; 0x0
30000010:	0a000005 	beq	3000002c <wait+0x2c>
30000014:	e59d3000 	ldr	r3, [sp]
30000018:	e2433001 	sub	r3, r3, #1	; 0x1
3000001c:	e58d3000 	str	r3, [sp]
30000020:	e59d2000 	ldr	r2, [sp]
30000024:	e3520000 	cmp	r2, #0	; 0x0
30000028:	1afffff9 	bne	30000014 <wait+0x14>
3000002c:	e28dd004 	add	sp, sp, #4	; 0x4
30000030:	e1a0f00e 	mov	pc, lr

30000034 <main>:
30000034:	e3a02456 	mov	r2, #1442840576	; 0x56000000
30000038:	e3a03c15 	mov	r3, #5376	; 0x1500
3000003c:	e92d4070 	stmdb	sp!, {r4, r5, r6, lr}
30000040:	e1a04002 	mov	r4, r2
30000044:	e3a06000 	mov	r6, #0	; 0x0
30000048:	e3a05070 	mov	r5, #112	; 0x70
3000004c:	e5823050 	str	r3, [r2, #80]
30000050:	e3a00c75 	mov	r0, #29952	; 0x7500
30000054:	e2800030 	add	r0, r0, #48	; 0x30
30000058:	e5846054 	str	r6, [r4, #84]
3000005c:	ebffffe7 	bl	30000000 <wait>
30000060:	e3a00c75 	mov	r0, #29952	; 0x7500
30000064:	e2800030 	add	r0, r0, #48	; 0x30
30000068:	e5845054 	str	r5, [r4, #84]
3000006c:	ebffffe3 	bl	30000000 <wait>
30000070:	eafffff6 	b	30000050 <main+0x1c>
30000074:	43434700 	cmpmi	r3, #0	; 0x0
30000078:	4728203a 	undefined
3000007c:	2029554e 	eorcs	r5, r9, lr, asr #10
30000080:	2e342e33 	mrccs	14, 1, r2, cr4, cr3, {1}
30000084:	00000035 	andeq	r0, r0, r5, lsr r0

从反汇编得到的sdram.dis文件中可以看出main函数的链接地址是0x30000034,位于SDRAM区域,wait函数链接地址是30000000也是位于SDRAM区域。在head.S的开头一段汇编代码可以得知,在一系列初始化之后,最终PC被放入了0x30000034这个值,也就是跳到了main函数的开始地址去执行main函数了。
  18:    e59ff004     ldr    pc, [pc, #4]    ; 24 <firtst+0x24>

0000001c <halt_loop>:
  1c:    eafffffe     b    1c <halt_loop>
  20:    0000001c     andeq    r0, r0, ip, lsl r0
  24:    30000034     andcc    r0, r0, r4, lsr r0

经过代码烧录到开发板之后,看到三个LED灯在闪烁,实验成功!

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值