存储器重映射

存储器重映射

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

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

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

bootblock最开始有自己特有的中断向量表,也就是说在执行bootblock的时候可以响应中断,并执行自己的中断服务函数

注意:存储器重映射并不是对映射单元的内容进行了复制,而只是将多个地址指向了同一个存储单元,这种效果是通过芯片内部的存储器管理部件实现的。


BOOTBLOCK运行完就是要运行用户自己写的启动代码了(BootLoader,如果你的应用程序被编译在RAM空间运行,也需要Bootloader把它从诸如SD卡等存储介质加载到RAM并启动它。),而启动代码中最重要的就是异常向量表,这个表是放在FLASH的头部首先执行的,而异常向量表中要处理多方面的事情,包括复位、未定义指令、软中断、预取指中止、数据中止、IRQ(中断) ,FIQ (快速中断),而这个异常向量表是总表,还包括许多分散的异常向量表,比如在外部存储器,BOOTBLOCKSRAM中固化的,不可能都由用户直接定义,所以还是需要重映射把那些异常向量表的地址映到总表中。

当逻辑地址0x00000000映射到物理地址0x00000000,相当于没有LPC-MMU(存储管理单元)!这就是说,如果你设计的Bootloader是从LPC2200系列ARM的内部FLASH启动的,那么就没有什么特殊性,和其他ARM一样就是了!

   如果你的Bootloader是从外部FLASH启动的(也就是物理地址0x80000000开始的空间),那么就需要我这里所说的内容了。

   很简单,你只要把异常向量代码和常量池(共64字节)写成如下形式即可!不过这样的话该Bootloader只能在0x80000000的地址启动了。此外,Bootloader需要把自己的RO段、RW段拷贝到RAM,并设置ZI段。而这些代码都不在其编译时设置的空间运行,所以都需要使用相对当前PC寻址的指令来实现,有一定的技巧性。最后,Bootloader还需要把自己的PC以及返回地址LR都转移到正确的运行时地址去,Bootloader从此走上阳关大道。

;//*****************************************************************************

;//64字节的映射空间开始 

ResetEntry

;//32字节异常向量

   LDR     PC, Reset_Addr      ;//复位异常入口(进入SVR32模式)

   LDR     PC, Undefined_Addr ;//未定义指令异常入口(进入UNDF32模式)

   LDR     PC,SWI_Addr        ;//软件中断异常入口(进入SVR32模式)

   LDR     PC, Prefetch_Addr   ;//预取中止异常入口(进入ABT32模式)

   LDR     PC, DataAbort_Addr ;//数据中止异常入口(进入ABT32模式)

   DCD    0xb9205f80          ;//保留的矢量,对于LPC系列ARM的内部FLASH有特殊作用

   LDR     PC, [PC, #-0xff0]   ;//中断异常入口(进入IRQ32模式)

   LDR     PC,FIQ_Addr        ;//快中断异常入口(进入FIQ32模式)

;//32字节常量池

Reset_Addr

   DCD    0x80000040          ;//注意这里原来是Reset_Handler

Undefined_Addr     

   DCD     Undefined_Handler

SWI_Addr           

   DCD     SWI_Handler

Prefetch_Addr      

   DCD     Prefetch_Handler

DataAbort_Addr     

   DCD     DataAbort_Handler

Reserve_Addr

   DCD     0

IRQ_Addr           

   DCD     IRQ_Handler

FIQ_Addr           

   DCD     FIQ_Handler

;//64字节的映射空间结束

;//*****************************************************************************

;//以下开始是系统复位处理程序

Reset_Handler

   ...

   ...

;//*****************************************************************************

;//启动代码结束

   END



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

                       

      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,所以在程序运行的过程中是可以改变的,这样就可以达到重映射的目的啦(异常向量表可以随时修改),当用户代码在ram区中时,memmap=2,一般为debug版本,开发过程中使用

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


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

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值