对于2440的存储器来说,他的结构是这样的:
存储管理器作用:
2440可以外接SDRAM、网卡,CPU怎么访问这些外设,就是通过存储管理器来访问它们的,
比如CPU想从0X3000,0000 读四个字节的地址,CPU只要执行: MOV R1 0X30000000 , ldr R0 ,[R1];这两条指令即可,存储管理器根据内部的配置信息:1,发出片选信息
2,发出bank选择信号
3,发出列地址
4,发出行地址;
存储管理器根据内部的配置信息去访问具体的外设。那它里面具体有哪些配置信息呢?
具有的配置信号如下图所示:
想访问一个芯片,需要哪些条件?
想访问一个芯片,首先需要地址(线)、数据(线),其中数据线的位数(8、16、32),又叫数据宽度;时钟/频率;芯片相关的一些特性,比如SDARM里面有列地址有多少位、行地址有多少位、bank;
SDARM存储结构的逻辑图:
SDARM先发出一个bank确定是哪一个bank,然后发出行地址、再发出列地址。
只有配置好了2440的存储管理器,才知道怎么去访问外部的设备。
需要的配置信息如下图所示:
2440的SDARM原理图如下所示:
进一步对应的芯片手册可以知道行地址13位,列地址9位,如图:
刷新周期为:
注意:位宽是看2440的原理图来的,而列、行地址宽度,时钟是从存储器的芯片手册当中查询来的。bank怎么接,需要看原理图:
从图中可以看出芯片地址总线的第24、25位分别接到 bank0,bank1.
2440的地址单位是字节(8位),如果内存的芯片是32位、16位、8位。这几种情况下的接线图如下图所示:
目的:访问、使用SDRAM。
1,先配置存储管理器。所谓的配置,也就是向相应的寄存器写入相应的值。怎么写,我们要查看2440的芯片手册。
2440支持的内存有:SARM,SDARM。SARM价格高、使用简单,直接发地址即可。SDARM价格低,使用比较复杂,需要发送bank,列,行地址,并且还要不断的刷新,否则数据会丢失。
2440可以接多少个像SDARM的外设?可以接8个外设。即8条片选信号。
从原理可知,每个bank的寻址空间是128MB。
怎么用代码初始化存储被处理器?
首先看一下初始化文件的汇编代码:
@*************************************************************************
@ File:head.S
@ 功能:设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行
@*************************************************************************
.equ MEM_CTL_BASE, 0x48000000
.equ SDRAM_BASE, 0x30000000
.text
.global _start
_start:
bl disable_watch_dog @ 首先用bl指令跳到disable_watch_dog去关闭WATCHDOG,否则CPU会不断重启; bl 指令会把返回的地址存到lr寄存器中
bl memsetup @ 然后得用bl指令跳转到memsetup去设置存储控制(管理)器
bl copy_steppingstone_to_sdram @ 复制代码到SDRAM中 把代码从片内存拷贝到SDARM中,把前面4K完完全全拷贝过去
ldr pc, =on_sdram @ 跳到SDRAM中继续执行;执行完这一条指令以后,CPU就会片内的SDRAM中取址,就不会再从SARM中去取。
on_sdram:
ldr sp, =0x34000000 @ 设置堆栈 准备调用C语言的main函数
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 @DRAM的地址
mov r3, #4*1024 @ 4K地址
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个寄存器的开始地址;其中MEM_CTL_BASE是寄存器的起始地址,是从原理图中得到的
adrl r2, mem_cfg_val @ 这13个值的起始存储地址; 即把mem_cfg_val这一块内存赋给r2;
add r3, r1, #52 @ 13*4 = 54;因为mem_cfg_val共有13个寄存器
1:
ldr r4, [r2], #4 @ 读取设置值,并让r2加4
str r4, [r1], #4 @ 将此值写入寄存器,并让r1加4
cmp r1, r3 @ 判断是否设置完所有13个寄存器; 循环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
2440的启动方式:NOR Flash启动、Nand Flash启动;
2440内部有4K的SARM,这4K的SARM是一个性能非常好,但价格非常高的存储器。
NOR Flash启动的时候,CPU的起始地址指向0地址,即bank0,CPU从这个地址读取指令并执行;
Nand Flash启动的时候,bank0无法访问,失效。
如果2440同时接有NOR Flash、Nand Flash,采用Nand Flash方式启动的时候,NOR Flash将无法使用;
0地址指向片内的SRAM;
一上电的时候,硬件会自动把Nand前4K完完全全的复制到片内的SRAM,然后从0地址开始执行。
2440还外接有SDRAM;
总结一下程序的启动过程:
1,一上电,Nand前4K被复制到片内的SRAM,从0地址开始;
2,程序关看门狗、初始化存储管理器。
3,把SRAM中的代码拷贝到SDARM中去。(steppinstone). 拷完之后继续执行。
如果程序很大的时候,我们首先要在SRAM中的4K中关看门狗、初始化存储管理器,然后把4K拷贝到SDRAM中,再然后利用SRAM中的4K把Nand Flash的大片内存拷贝到SDARM中去。
然后看一下C语言程序代码:
#define GPFCON (*(volatile unsigned long *)0x56000050)
#define GPFDAT (*(volatile unsigned long *)0x56000054)
#define GPF4_out (1<<(4*2))
#define GPF5_out (1<<(5*2))
#define GPF6_out (1<<(6*2))
void wait(volatile unsigned long dly)
{
for(; dly > 0; dly--);
}
int main(void)
{
unsigned long i = 0;
GPFCON = GPF4_out|GPF5_out|GPF6_out; // 将LED1,2,4对应的GPF4/5/6三个引脚设为输出
while(1){
wait(30000);
GPFDAT = (~(i<<4)); // 根据i的值,点亮LED1,2,4
if(++i == 8)
i = 0;
}
return 0;
}
然后看一下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
其中链接的时候,指定代码段的链接地址为:0x30000000。意义就是说程序正常运行时,应该放在SDARM中的0x30000000开始运行。
链接地址:运行时,程序“应该”位于哪里。