S3C2440是32位的处理器理论寻址范围为2^32即4G,S3C2440使用[26:0]作为地址线,寻址范围128M,使用[29:27]作为bank选择信号,所以S3C2440可以连接8个外设,如果全部连接存储器就可以达到1GB的内存。在S3C2440中内存为64MB,它使用了第6和第7个bank连接两片32MB的SDAM。由于外设多种多样其位宽也不尽相同,所以每个bank的数据宽度是可以软件编程控制的。
为什么下载程时要下载到0x30000000地址单元执行,或下载文件到0x30000000地址单元再通过写操作写到NAND FLASH?
因为两片SDARM在bank6和bank7上面连接,通过[29:27]的信号决定选择那块bank,所以bank6的起始地址为0x30000000。
对应关系如下表:
注:bank7的起始地址由bank6的结束地址所决定。
对64MB的SDARM理解:
较大的存储体是由小的存储体进行字扩展和位扩展构成。S3C2440中的64MB(16Mb×32)SDARM实际是由16块4Mb×8的SDARM组成。拥有4个片面内Bank,通过地址线A25,A24进行选择某一个Bank。
存储管理器对内存访问是必须知道其位宽、行地址、列地址、存储周期,对于SDARM还要知道其刷新周期等信息,这都可以通过相应的寄存器设置。
存储管理器的使用:
初始化存储管理器,把ARM的4K代码拷贝到SDARM上执行。
Makefile文件:
led_mempory: start.S led.c
arm-linux-gcc -c start.S -o start.o
arm-linux-gcc -c led.c -o led_mempory.o
arm-linux-ld -Ttext=0x30000000 start.o led_mempory.o -o led_mempory
arm-linux-objcopy -O binary led_mempory led_mempory.bin
arm-linux-objdump -D -m arm led_mempory > led_mempory.dis
clean:
rm -f start.o led_mempory.o led_mempory led_mempory.bin led_mempory.dis *.o
初始化存储管理器、堆栈、关闭看门狗:
@##########################################################
@ 初始化存储器管理器,设置堆栈,调用main函数 #
@##########################################################
.equ sdarm_abs, 0x30000000 @SDAM其实地址
.equ mempory, 0x48000000 @存储管理器寄存器的起始地址
.text
.global _start
_start:
bl WDOG @关闭看门狗
bl setmempory @初始化存储器管理器
bl cp_to_dsarm @拷贝前4K代码到SDARM中
ldr sp, =0x34000000 @初始化堆栈
ldr pc, =main @到SDARM中执行
WDOG:
ldr r0, =0x53000000
mov r1, #0x0
str r1, [r0]
mov pc, lr
setmempory:
ldr r0, =mempory
adrl r2, table
add r1, r0, #52
m_loop:
ldr r4, [r2], #4
str r4, [r0], #4
cmp r1, r0
bne m_loop
mov pc, lr
cp_to_dsarm:
ldr r0, =sdarm_abs
mov r1, #0x0
add r2, r1, #4*1024
loopcopy: @循环拷贝
ldmia r1!, {r3-r10}
stmia r0!, {r3-r10}
cmp r1, r2
bne loopcopy
mov pc, lr
.align 4
table:
.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
点亮LED:
#include "led.h"
void time(unsigned int t)
{
while(t--);
}
int main()
{
GPBCON &= (~(0x3 << 12 | 0x3 << 14 | 0x3 << 16 | 0x3 << 10));
GPBCON |= (0x1 << 12 | 0x1 << 14 | 0x1 << 16 | 0x1 << 10);
while(1)
{
GPBDAT &= (~(0x1 << 5 | 0x1 << 6 | 0x1 << 7 | 0x1 << 8));
time(50000);
GPBDAT |= (0x1 << 5 | 0x1 << 6 | 0x1 << 7 | 0x1 << 8);
time(50000);
}
return 0;
}
#ifndef _LEDD_H_
#define _LEDD_H_
#define GPIO 0x56000000 /*GPIO的基地址*/
#define GPBCON (*(volatile unsigned long *)(GPIO + 0x10))
#define GPBDAT (*(volatile unsigned long *)(GPIO + 0x14))
#endif
链接地址是CPU能够看到的地址,也是程序员编写程序用到的虚拟地址,一般要经过MMU的转换映射到实际的物理地址。CPU对内存的访问一般是CPU发送一个它看到的地址,经过MMU的转化,在通过存储管理器,最终访问到实际的物理地址。本实验的链接地址为0x30000000,并且没有初始化MMU, CPU发出的地址实际就直接对应到实际的物理地址,通过存储 管理器访问内存。这也是本实验能够成功的原因。