一、前言
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 8: eb00000a bl 38 c: eb00001a bl 7c 10: e3a0d30d mov sp, #872415232 ; 0x34000000 14: e59fe004 ldr lr, [pc, #4] ; 20 18: e59ff004 ldr pc, [pc, #4] ; 24 0000001c 1c: eafffffe b 1c 20: 0000001c andeq r0, r0, ip, lsl r0 24: 30000034 andcc r0, r0, r4, lsr r0 00000028 28: e3a02000 mov r2, #0 ; 0x0 2c: e3a03453 mov r3, #1392508928 ; 0x53000000 30: e5832000 str r2, [r3] 34: e1a0f00e mov pc, lr 00000038 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 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 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 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 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 3000002c: e28dd004 add sp, sp, #4 ; 0x4 30000030: e1a0f00e mov pc, lr 30000034 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 30000060: e3a00c75 mov r0, #29952 ; 0x7500 30000064: e2800030 add r0, r0, #48 ; 0x30 30000068: e5845054 str r5, [r4, #84] 3000006c: ebffffe3 bl 30000000 30000070: eafffff6 b 30000050 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 0000001c 1c: eafffffe b 1c 20: 0000001c andeq r0, r0, ip, lsl r0 24: 30000034 andcc r0, r0, r4, lsr r0 经过代码烧录到开发板之后,看到三个LED灯在闪烁,实验成功!
上一篇:【JZ2440笔记】裸机实验使用NandFlash
下一篇:【JZ2440笔记】裸机实验点亮LED
推荐阅读最新更新时间:2024-10-30 10:52
设计资源 培训 开发板 精华推荐
- BLHleli电调
- 使用 MikroElektronika 的 BH1790GLC-E2 的参考设计
- 使用 Analog Devices 的 LT3091HDE 的参考设计
- 无需芯片,QC调诱骗器,支持调压
- LTC1550 的典型应用 - 低噪声、开关电容调节型电压逆变器
- BB-BONE-DVID-02,BeagleBone DVI-D with Audio Cape,BeagleBone 的附加板
- VN7007ALH评估板
- 基于arduino的机械臂程序
- STUSB1602 USB Type-C和带有NUCLEO-F072RB的电力传输核软件包
- 使用 Microchip Technology 的 MAQ5282 的参考设计
- elexcon 2023 报名推广
- 【EEWORLD第三十八届】2012年05月社区明星人物揭晓!
- 有奖看视频|2022台北国际电脑展——美光主题演讲精选
- CadenceLIVE China 2022中国线上用户大会 报名中!
- Microchip直播|如何在ADAS系统中解决精密授时挑战
- 【EEWORLD第四十三届】2012年10月社区明星人物揭晓!
- 报名有礼| Arm Tech Symposia 年度技术大会报名开启!
- Follow me第二季第1期来啦!与得捷一起解锁【Adafruit Circuit Playground Express】超能力!
- PI LYTSwitch™-6系列IC 让你了解不知道的秘密看专题赢好礼!