为了cpu访问外部设备,ARM提供一个存储管理器部件,提供访问外部设备的所需的信号(对SDRAM、网卡、nor等设备进行初始化,以便存储器管理器配合CPU进行与外设数据通讯)。

  CPU通常读写一个外设仅仅发出地址,它不仔细过问其中的任何过程,地址发出后就交给了存储管理器,存储管理器就会根据地址判断是什么设备,并负责数据操作,把CPU想操作的数据反馈给CPU:

  

  S3C2440对外引出27根地址线ADDR0-ADDR26,因此从地址线数目来看S3C2440对外访问的范围只有128MB,cpu同时还引出了8根片选信号nGCS0-nGCS7,分别对应着BANK0-BANK7,当nGCSx引脚拉低即可选中对应的外接设备。这样S3C2440的寻址空间就有1GB了。S3C2440作为32位的cpu,理论可以寻址范围是4GB,一部分用于访问外设--1GB,一部分是cpu内部寄存器的地址,剩下的地址空间没有使用。(注意:这里是物理地址)

    

  上图是s3c2440的存储控制器地址空间分布图,左侧图对应不使用Nand flash启动时(通过跳线设置),存储器Bank分布图,通常在这种启动方式里选择Norflash启动,将Nor flash焊接在Bank0, 系统上电后,CPU从Bank0的开始地址0x00000000开始取指运行。上图右侧是选择从Nand flash引导启动(通过跳线设置),系统上电后,CPU会自动将Nandflash里前4K的数据复制到S3C2440内部一个4K大小 SRAM类型存储器里(叫做Steppingstone),然后从Steppingstone取指启动。

  其中Bank0~Bank5可以焊接ROM或SRAM类型存储器,Bank6~Bank7可以焊接ROM,SRAM,SDRAM类型存储器,也就是说,S3C2440的SDRAM内存应该焊接在Bank6~Bank7上,最大支持内存256M,Bank0~Bank5通常焊接一些用于引导系统启动小容量ROM,具体焊接什么样存储器,多大容量,根据每个开发板生产商不同而不同,比如s3c2440开发板将2M的Norflash焊接在了Bank0上,用于存放系统引导程序Bootloader,将两片32M,16Bit位宽SDRAM内存焊接在Bank6上(Bank7没有使用),并联形成64M,32位内存。

 

  cpu想访问一个存储芯片需要哪些条件?

   1)地址线

   2)数据线 8/16/32 数据宽度

   3)时钟频率

   4)芯片相关特性(行地址,列地址,bank,刷新周期等等)

 

  下面就SDRAM为例子,cpu想要进行SDRAM的访问,应该怎样的一个过程呢?

 1)cpu发出片选信号nSCS0/nSCS6的有效信号,通过选中存储控制器的BANK6来选中sdram芯片(其中nSCS0与nSCS6是同一个引脚的两种功能,拉低哪一个对引脚效果都是一样的)

   2)使用ADDR24和ADDR25作为L-Bank的选择信号,可以选择SDRAM的L-Bank的四个中任意一个

   3)对选中的芯片进行统一的行和列寻址,根据sdram芯片的列地址线数设置存储管理器的相关寄存器,cpu就会从4GB地址中自动分配L-bank选择信号,行地址信号,列地址信号,然后先后发出行地址信号,列地址信号。L-bank选择信号在发出行地址信号的同时并维持到列地址信号结束。

在下图中可以清楚看到行地址和列地址共用地址线ADDR2-ADDR14(BANK6位宽是32,ADDR0/1没有使用),并用sdram的行地址脉冲选择信号nSRAS和列地址脉冲选择信号nSCAS进行区别。当nSRAS有效时,ADDR2-ADDR14上发出的是行地址信号,对应着32位地址空间的bit[23:11];当nSCAS信号有效时,ADDR2-ADDR10上发出的是列地址信号,对应32位地址空间的bit[10:2]。

  下面进行一个实验,将写的LED流水的程序在SDRAM中进行运行,当然当运行程序较大时由于ARM片内资源中,内存很小(4K),为了能够运行操作系统和大的应用程序,需要在ARM存储接口上进行扩展,如SDRAM,SRAM,ROM,FLASH等。

   源程序:led_loop.c

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

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

    

   #define GPF4_reset (3<<(4*2))

  #define GPF5_reset (3<<(5*2))

   #define GPF6_reset (3<<(6*2))

   #define GPF4_out (1<<(4*2))

   #define GPF5_out (1<<(5*2))

   #define GPF6_out (1<<(6*2))

void Delay_ms(volatile unsigned long ms);

   int main()

{

  GPFCON &=~(GPF4_reset | GPF5_reset | GPF6_reset);

  GPFDAT |=  GPF4_out | GPF5_out | GPF6_out; //输出

 while(1)

{

    GPFDAT &=~(1<<4);

    Delay_ms(30000);

    GPFDAT |=(1<<4);

    GPFDAT &=~(1<<5);

    Delay_ms(30000);

    GPFDAT |=(1<<5);

    GPFDAT &=~(1<<6);

    Delay_ms(30000);

    GPFDAT |=(1<<6);

 }

   return 0;

}

void Delay_ms(volatile unsigned long ms)//延时函数

{

    for(; ms>0; ms--);

}

  配置文件:crt.S

  .equ    MEM_BASE    0x48000000   @存储管理器寄存器首地址

  .text   SDRAM_BASE  0x30000000   @sdram首地址

  .global _start

  _start:

      bl disable_watch_dog      @关看门狗

      bl setup_mem              @配置存储管理器

          bl sram_to_sdram          @到sdram中进行运行

      ldr pc, =on_sdram

on_sdram:

      ldr sp, =34000000

      bl main

halt_loop:

      b halt_loop

disable_watch_dog:

      ldr r0,=0x53000000

      mov r1,#0x00000000

      str r1, [r0]

      mov pc,lr

setup_mem:

      ldr r0,=MEM_BASE

          adrl r1,mem_con_val

      add r3,r0,#(13*4)

1:

         ldr r4,[r1],#4

      str r4,[r0],#4 

      cmp r0,r3

     bne 1b

      mov pc,lr

sram_to_sdram:

      ldr r0,=0x00000000

      ldr r1,=SDRAM_BASE

      mov r3,#1024*4

1:

      ldr r4,[r0],#4

      str r4,[r1],#4

          cmp r0,r3

      bne 1b

      mov pc,lr

.align 4

mem_con_val:

    .long  0x220111110 @位宽

    .long  0x00000700 @bank0访问时序

    .long  0x00000700 @bank1。。。。

    .long  0x00000700 @bank2。。。。

    .long  0x00000700 @bank3。。。。

    .long  0x00000700 @bank4。。。。

    .long  0x00000700 @bank5。。。。

    .long  0x00018005 @bank6。。。。

    .long  0x00018005 @bank7。。。。

    .long  0x008C07A3 @刷新周期

    .long  0x000000B1 @banksize

    .long  0x00000030 @sdram模式设置--MRSRB6

    .long  0x00000030 @sdram模式设置--MRSRB7   

  Makefile:

led_loop.bin: crt.S  led_loop.c

    arm-linux-gcc -g -c -o crt.o crt.S

    arm-linux-gcc -g -c -o led_loop.o led_loop.c

    arm-linux-ld -Ttext 0x30000000 -g crt.o led_loop.o -o led_loop_elf

    arm-linux-objcopy -O binary -S led_loop_elf led_loop.bin

    arm-linux-objdump -D -m arm led_loop_elf > led_loop.dis

clean:

    rm -f led_loop_elf led_loop.dis led_loop.bin *.o

 执行make后生成的可执行的文件进行烧录,发现在SDRAM中进行运行LED进行流水的速度较慢,这是由于SDRAM和SRAM相比,SDRAM的性能较差:

    SRAM:速度快,价格贵,不需要进行刷新

    SDRAM:速度慢,价格便宜,访问复杂,需要不断刷新(否则数据会丢失)

 

 在学习过程中遇到了两个问题:

  1)2440与SDRAM的连接方式--根据不同的存储器件(SDRAM)的位宽,2440的地址线要进行左移一位,即:

      SDRAM的位宽是32位(4byte)时,2440与SDRAM进行连接时   --------------A0,A1不进行连接

SDRAM的位宽是16位(2byte)时,2440与SDRAM进行连接时   --------------仅仅A0不进行连接

SDRAM的位宽是8位(1byte)时, 2440与SDRAM进行连接时   --------------全部地址线进行连接

  

 原因在于:

   从软件和CPU的角度而言,一个地址对应一个字节,就是8位数据。对于具体器件而言,它的位宽是一定的,所谓位宽,指的是“读/写操作时,最小的数据单元”──别说最小单元是“位”,一般设备上没有单独的“位操作”,修改位时通过把整个字节、字或双字读出来、修改,再回写。  CPU的地址线(A0-A20)对应的最小数据单元是字节,即8位;而位宽为16的NOR FLASH的地址线(A0-A19)对应的最小数据单元是16位。

  这两个怎么对应起来?
  如果说外设的位宽是16,难道我们写程序时会“特意”以16位进行操作吗?不用的,我们写程序时根本不用管外设位宽是8、16还是32。
  仔细想想,其实是可以想通的:既然CPU、外设NOR FLASH的最小读/写单元已经固定,那么肯定就是CPU与NORFLASH之间有个中间层,它来做处理:
这个中间层被称为“Memory Controller”,CPU要进行读写操作时,“Memory Controller”根据NOR FLASH的位宽,每次总是读/写16位数据。
以读操作为例:
CPU想进行8位操作时,它选择其中的8位返回给CPU;
CPU想进行16位操作时,它直接把这16位数据返回给CPU;
CPU想进行32位操作时,它发起2次读/写,把结果组合成32位返回给CPU。

 

  假如现在CPU执行了以下的汇编指令:
  MOV R0, #3 
  LDRB R1, [R0]  
  汇编含义:先让R0=3,然后去R0所表示的地址读取1byte放在R1中。
  其中LDRB中的B是byte之意,从存储器中将一个8位的字节数据传送到目的寄存器中,同理的还有LDR指令对32位的字数据操作,LDRH指令对16位的半字数据操作。
即,以上汇编就是  从地址3处,读出1byte数据。

CPU发出指令后,交给内存控制器,内存控制器发出地址3,即A0、A1都为1。
  对于8bitROM ,8bit是一次读写的最小单位,如图:即0地址是第一个8bit,1地址是第二个8bit;
内存控制器发出的 A0和A1都为1,8bitROM的A0和A1收到的也都是1,于是找到了ROM上地址为3的8bit数据,就是我们需要的数据,内存控制器返回给CPU。

对于16bitROM ,16bit是一次读写的最小单位,如图:即0地址是第一个16bit,里面有两个8bit数据;
内存控制器发出的 A0和A1都为1,16bitROM的A0和A1分别收到的是1和0,于是找到了ROM上地址为1的16bit数据,包含了我们需要的数据,最后内存控制器根据”A0=1”,挑出低8bit数据,  即我们刚好需要的数据,返回给CPU。。

对于32bitROM ,32bit是一次读写的最小单位,如图:即0地址是第一个32bit,里面有四个8bit数据;
内存控制器发出的 A0和A1都为1,但32bitROM的A0和A1收到的都是0,于是找到了ROM上地址为0的32bit数据,包含了我们需要的数据,最后内存控制器根据”A0=1 A1=1”,相应8bit数据,  即我们刚好需要的数据,返回给CPU。。

 参考链接:http://www.100ask.org/bbs/forum.php?mod=viewthread&tid=19770

           http://blog.csdn.net/thisway_diy/article/details/78113879

  2)SDRAM的寻址范围:

           2^13×2^9×4×32bit=64M

JZ2440存储管理器--SDRAM的更多相关文章

  1. 二、存储管理器--SDRAM

    2.1 硬件结构 2.1.1 硬件框图 CPU 通过存储管理器来读取 SDRAM 网卡 等外部设备,CPU不管外部设备是怎么样的,只是读存储管理器中的地址 CPU从0x30000000地址读取数据. ...

  2. jz2440存储管理实验【学习笔记】

    平台:jz2440 作者:庄泽彬(欢迎转载,请注明作者) 说明:韦东山一期视频学习笔记 简介:先来简单的说明一下这次的实验,看看下图,我们的程序通过烧录器下载到nandflash当中去,之后在启动的时 ...

  3. 存储管理器 S3C2440A

    CPU通过存储管理器来控制外部设备 SDRAM存储结构 S3C2440A内存控制器 原理图 HY57V561620(L)T 4Banks x 4M x 16Bit Synchronous DRAM S ...

  4. 微软Azure 存储管理器的简单介绍

    Windows Azure存储用户经常希望能够在“管理器”中查看他们的数据,管理器指的是一款可用于显示存储帐户数据的工具.我们之前提供了我们所知的存储管理器列表.在本文中,我们将对此列表进行更新,使其 ...

  5. Windows Azure 存储管理器 (2014)

     Windows Azure存储用户经常希望能够在"管理器"中查看他们的数据,管理器指的是一款可用于显示存储帐户数据的工具.我们之前提供了我们所知的存储管理器列表.在本文中,我 ...

  6. 1-16-2 LVM管理和ssm存储管理器使用&磁盘配额

    ssm存储管理器使用&磁盘配额 ssm存储管理器使用 系统存储管理器的使用 系统存储管理器(又称ssm,即system-storage-manager),是RHEL7/CentOS7新增的功能 ...

  7. 第十五章 LVM管理和ssm存储管理器使用 随堂笔记

    第十五章 LVM管理和ssm存储管理器使用 本节所讲内容: 15.1 LVM的工作原理 15.2 创建LVM的基本步骤 15.3 实战-使用SSM工具为公司的邮件服务器创建可动态扩容的存储池 LVM的 ...

  8. 1-18-2 LVM管理和ssm存储管理器使用&磁盘配额 (二)

    LVM管理和ssm存储管理器使用&磁盘配额  (二) 内容如下: ü  LVM快照 ü  ssm存储管理器的使用 ü  磁盘配额 第1章 LVM快照 lvm快照:为了保持系统的一致性,我们先做 ...

  9. 1-18-1 LVM管理和ssm存储管理器使用&磁盘配额(一)

    LVM管理和ssm存储管理器使用&磁盘配额(一) LVM逻辑卷的管理 问题:对于生产环境下的服务器来说,如果存储数据的分区磁盘空间不够了怎么办? 因为如果要把一个分区的内容都拷贝到另一个分区上 ...

随机推荐

  1. 【Scala学习之一】 Scala基础语法

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk1.8 scala-2.10.4(依赖jdk1.8) spark ...

  2. MySql 查询表中字段的数据类型

    [1]MySQL中查询某表中字段的数据类型 (1)DESC 表名: (2)DESCRIBE 表名: (3)SHOW COLUMNS FROM 表名: 应用示例: DESC cfg_acct_free_ ...

  3. OBO文件格式1.2

    该文件每一行都是一个键值对,基本格式为:    键: 值!注释 总体结构:    文件头    !包含若干行总体说明    词条1    ![词条类型]占第一行,后跟若干行说明    词条2    ! ...

  4. hive 将一个分区表数据全部插入另外一个分区表

    假如现在hive有个分区表A,分区字段为dt 需求是:需要将A表中的数据全部插入到分区表B中 具体步骤如下: 1.create B like A: 2.插入数据 set hive.exec.dynam ...

  5. Django ORM 操作 必知必会13条 单表查询

    ORM 操作 必知必会13条 import os # if __name__ == '__main__': # 当前文件下执行 os.environ.setdefault('DJANGO_SETTIN ...

  6. .NET 常用ORM之Nbear

    NBear是一个基于.Net 2.0.C#2.0开放全部源代码的的软件开发框架类库.NBear的设计目标是尽最大努力减少开发人员的工作量,最大程度提升开发效率,同时兼顾性能及可伸缩性. 一.新建项目并 ...

  7. SSM的理解

    SSM(Spring+SpringMVC+MyBatis)框架集由Spring.SpringMVC.MyBatis三个开源框架整合而成,常作为数据源较简单的web项目的框架.其中spring是一个轻量 ...

  8. Python+OpenCV图像处理(十一)—— 图像金字塔

    简介:图像金字塔是图像中多尺度表达的一种,最主要用于图像的分割,是一种以多分辨率来解释图像的有效但概念简单的结构.简单来说,图像金字塔就是用来进行图像缩放的. 进行图像缩放可以用图像金字塔,也可以使用 ...

  9. 一款用于对 WiFi 接入点安全进行渗透测试的工具

    越来越多的设备通过无线传输的方式连接到互联网,以及,大范围可用的 WiFi 接入点为攻击者攻击用户提供了很多机会.通过欺骗用户连接到虚假的 WiFi 接入点,攻击者可以完全控制用户的网络连接,这将使得 ...

  10. 导弹拦截 p1020

    第一问就是求最长不上升子序列的长度,要写O(nlogn)的算法.... 对于这种nlogn的算法,只能求出长度,不能求出具体的序列.这种算法实现过程如下: 我们定义len为到目前为止最长不上升子序列的 ...