Chinaunix首页 | 论坛 | 博客
  • 博客访问: 426229
  • 博文数量: 47
  • 博客积分: 1669
  • 博客等级: 上尉
  • 技术积分: 585
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-04 23:27
文章分类

全部博文(47)

文章存档

2011年(23)

2010年(24)

分类: LINUX

2011-01-16 20:47:48

      理解好存储器的编址、映射和重新映射等问题,对于嵌入式编程和操作系统的理解等都有重大的帮助。所有的把嵌入式系统都可以看成一个“输入输出”系统。信息输入,经过处理,然后输出。那么输入都可以看做读存储单元,这个“存储单元”范围很广,RAM、ROM、寄存器等。可以从SDRAM中读,也可以从FLASH中读,还可以从UART的寄存器中读,有个重要的思想是,把所有设备看成同一性质,即这个设备都有地址,都可以进行读写,这就是统一编程的思想。那么嵌入式编程就可以归结为“读写”问题。

      具体说一下编址。编址也就是给“内存单元”编号,而这个“内存单元”是多大呢?一般是8bit,即一个Byte,如x86和ARM;但也有其它的,如AVR单片机,就是以每2Byte来编址的。地址空间的大小一般取决于地址总线,32位机的地址总线一般是32bit的,2^32=4294967296,也就是说可以用来表示4294967296个Byte,也即4GB的地址空间;如果以2Byte来编址的话,那么就可以表示8GB的地址空间。

      下面结合LPC210x来具体解释一下。我以前有个错误的理解就是boot block是个逻辑上的概念,就是存放bootloader的地方,一般应该在FLASH的起始端。但对于LPC210x来说,不是这样的,它固化 在片内的8K大小的存储区域。PHILIPS在芯片出厂时固化了IAP、ISP和RealMonitor程序在FLASH中,地址为0x7d000~0x7ffff。通常称该空间为boot block。boot程序功能:判断用户代码是否有效,有效执行用户代码;否则运行ISP程序。 (认为出厂时Flash顶端被地址译码为0x7d000~0x7ffff

      存储器映射(Memory Map):ARM处理器产生的地址叫虚拟地址,把这个地址按照某种规则转换到另一个物理地址去的方法称为地址映射。就是把芯片中或芯片外的FLASH,RAM,外设,BOOTBLOCK等进行统一编址。即用地址来表示对象。这个地址绝大多数是由厂家规定好的,用户只能用而不能改。用户只能在挂外部RAM或FLASH的情况下可进行自定义。“映射”这个概念体现了“一一对应”,可以说虚拟地址0x00000000~0x0001ffff到片内FLASH的映射,也可以说片内FLASH被映射到虚拟地址0x00000000~0x0001ffff。下图是LPC210x的存储器映射。

      存储器重新映射(Memory Re-Map):存储器重新映射是将复位后用户可见的存储器中部分区域,再次映射到其他的地址上。对于LPC210x微控制器,存储器重新映射区域一共为64个字节,分别为异常向量区(32字节)和紧随其后的32字节。通俗的讲,就是虚拟地址0x00000000~0x0000003f本来是指向片内FLASH的,重新映射以后,当访问这段地址时,实际访问的就是boot block或者RAM。也就是把boot block或RAM的一部分映射到虚拟地址0x00000000~0x0000003f(异常向量和其后的32字节)。LPC210x存储器重新映射见下图。

      那么为什么要重新映射呢?这得从ARM的7种异常说起,它们会使得ARM进入不同的工作模式,并执行不同特定地址的指令。如下图。

      可以看出,每个异常向量的大小都是4字节,这是因为ARM处理器的ARM指令大小也是4字节,7个异常向量加上一个保留的,共8*4=32个字节,再加上其后的32个字节,就构成了我们要重新映射的区域。要特别注意的是,这里的“异常向量”不同与一般的“中断向量”,一般的中断向量,如UART、Timer中断等是划归到IRQ中断里面处理的,也就是系统进入到IRQ中断服务程序中以后,再跳转到具体的中断服务。这样看来,重新映射都是为了灵活的放置异常向量的物理位置。

       对于第二个图。我们姑且把虚拟地址0x00000000-0x0000003c都称为异常向量表。

      MEMMAP=0:开机默认值,Boot装载模式----异常向量表(0x00000000-0x0000003c)映射的是BootBlock中的0x7FFFE000-0x7FFFF03c中的值;芯片复位时,启动boot装载程序,boot装载程序检查P0.14口的状态和用户的异常向量,判断是进入ISP状态还是启动用户程序,若启动用户程序,则自动设置MEMMAP=1(片内flash启动)或3(片外程序存储器启动)。

      MEMMAP=1:异常向量表就在片内flash中,地址就是0x00000000-0x0000003c,相当于没有映射;

      MEMMAP=2:最为主要的设置,即是重映射的关键之所在,当设置MEMMAP=2 时,异常向量表(0x00000000-0x0000003c)映射的是片内SRAM中的0x40000000-0x4000003c中的值,而因为是SRAM,所以在程序运行的过程中是可以改变的,这样就可以达到重映射的目的啦(异常向量表可以随时修改)。

       MEMMAP=3:异常向量表就在片外flash中,异常向量表(0x00000000-0x0000003c)映射到是片外flash中的0x80000000-0x8000003c中的值;功能上与MEMMAP=1时的差不多,因为一旦程序固化到flash中,即为只读,只是数值映射而已!

存储器映射
2008-11-09 10:44

(2008-10-23 16:17:24)
存储器映射是指把芯片中或芯片外的FLASH,RAM,外设,BOOTBLOCK等进行统一编址。即用地址来表示对象。这个地址绝大多数是由厂家规定好的,用户只能用而不能改。用户只能在挂外部RAM或FLASH的情况下可进行自定义。

ARM7TDMI的存储器映射可以有0X00000000~0XFFFFFFFF的空间,即4G的映射空间,但所有器件加起来肯定是填不满的。一般来说,0X00000000依次开始存放FLASH——0X00000000,SRAM——0X40000000,BOOTBLOCK,外部存储器 0X80000000,VPB(低速外设地址,如GPIO,UART)——0XE0000000,AHB(高速外设:向量中断控制器,外部存储器控制器) ——从0XFFFFFFFF回头。他们都是从固定位置开始编址的,而占用空间又不大,如AHB只占2MB,所以从中间有很大部分是空白区域,用户若使用这些空白区域,或者定义野指针,就可能出现取指令中止或者取数据中止。

由于系统在上电复位时要从0X00000000 开始运行,而第一要运行的就是厂家固化在片子里的BOOTBLOCK,这是判断运行哪个存储器上的程序,检查用户代码是否有效,判断芯片是否加密,芯片是否IAP(在应用编程),芯片是否ISP(在系统编程),所以这个BOOTBLOCK要首先执行。而芯片中的BOOTBLOCK不能放在FLASH的头部,因为那要存放用户的异常向量表的,以便在运行、中断时跳到这来找入口,所以BOOTBLOCK只能放在FLSAH尾部才能好找到,呵呵。而ARM7的各芯片的FLASH大小又不一致,厂家为了BOOTBLOCK在芯片中的位置固定,就在编址的2G靠前编址的位置虚拟划分一个区域作为BOOTBLOCK 区域,这就是重映射,这样访问<2G即<0X80000000的位置时,就可以访问到在FLASH尾部的BOOTBLOCK区了。

BOOTBLOCK运行完就是要运行用户自己写的启动代码了,而启动代码中最重要的就是异常向量表,这个表是放在FLASH的头部首先执行的,而异常向量表中要处理多方面的事情,包括复位、未定义指令、软中断、预取指中止、数据中止、IRQ(中断) ,FIQ (快速中断),而这个异常向量表是总表,还包括许多分散的异常向量表,比如在外部存储器,BOOTBLOCK,SRAM中固化的,不可能都由用户直接定义,所以还是需要重映射把那些异常向量表的地址映到总表中。


1.存储器映射:

处理器产生的地址按其某种规则转移到具体的物理地址;用户可见的,开机后固定不变的。
2.存储器重映射:
重新修改局部(64字节异常向量表);可选操作,稳定运行时由用户需要进行改变(用户程序)。
今天在ZLG的EazyARM板子上,对照着自带的实验册做存储器重映射的实验,需要设置MEMMAP寄存器,此时不是很明白这个MEMMAP寄存器该怎么设置,看了几遍ARM书上的相关章节,终于明白了实验程序的具体原理,也明白了MEMMAP设置的作用:
MEMMAP=0:开机默认值,Boot装载模式----向量表(0x00000000-0x0000003c)映射的是BootBlock中的0x7FFFE000-0x7FFFF03c中的值;芯片复位时,启动boot装载程序,boot装载程序检查P0.14口的状态和用户的异常向量,判断是进入ISP状态还是启动用户程序,若启动用户程序,则自动设置MEMMAP=1(片内flash启动)或3(片外程序存储器启动)。
很奇怪的,我在实验中,当使用无片内flash的LPC2210时即使设置P0.14为高低都没关系,芯片会跳过继而执行片外flash中的代码.
MEMMAP=1:中断向量表就在片内flash中,地址就是0x00000000-0x0000003c,相当于没有映射;
MEMMAP=2:最为主要的设置,即是重映射的关键之所在,当设置MEMMAP=2 时,中断向量表(0x00000000-0x0000003c)映射的是片内SRAM中的0x40000000-0x4000003c中的值,而因为是SRAM,所以在程序运行的过程中是可以改变的,这样就可以达到重映射的目的(中断向量表可以随时修改)
MEMMAP=3:中断向量表就在片外flash中,中断向量表(0x00000000-0x0000003c)映射到是片外flash中的0x80000000-0x8000003c中的值;功能上与MEMMAP=1时的差不多,因为一旦程序固化到flash中,即为只读,只是数值映射而已

(首先分两种情况:1 用户程序代码已经固化到flash,执行用户代码时,memmap=1或3。当复位时为0,执行的是bootblock代码,复位完成后即为1或3,片内或外flash启动,执行用户代码)

2 当用户代码在ram区中时,memmap=2,一般为debug版本,开发过程中使用

阅读(2835) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~