“映射”一词首先是在数学中接触到的,在认识存储器映射或存储器重映射前先回顾一下数学中对映射一词的解释。
映射的定义:如果集合A中的每个元素在对应法则f的作用下,在集合B中都有唯一的一个元素与它对应,那么集合A,B及对应法则f称为集合A到集合B的一个映射,记作f : A→B。
在映射f : A→B中,与A中的元素a对应的B中的元素b叫做a的象,a叫做b的原象。对应法则f、集合A及集合B称为映射的三要素。
从映射的定义可以看出,映射是“一对一”或“多对一”的对应关系。微机中的“多对一”关系就是重映射。
从数学中映射的定义可以看出,要弄清楚存储器的映射或重映射前,需要找出存储器映射的三要素:
存储器本身并没有地址信息,它的地址是由芯片厂商分配好的,一般不可修改。给存储器编址的过程(CPU对芯片中或芯片外的FLASH、RAM、外设、BOOTBLOCK等进行编址,地址统一编入存储器中)称为存储器映射,也称为存储器地址映射。其中,映射到端口寄存器的存储器单元(或存储器空间)称为存储器映射寄存器,其地址(或地址空间)称为存储器映射寄存器地址(或存储器映射寄存器地址空间)。
所以,对应法则f是存储器映射寄存器地址,集合A是存储器,集合B是外设寄存器。(外设有私有外设、片上外设及片外设备这三种外设,其中,片上外设有GPIO端口 、ADC、 TIM、 SPI、 USART、CAN、I2C等,私有外设有NVIC等。CPU通过存储器映射方式对这些功能模块进行统一编址,使得CPU通过访问内存单元达到对外设寄存器的访问)。所以它们构成的映射为:存储器映射寄存器地址:存储器存储单元→外设寄存器(或 存储器映射寄存器地址空间:存储器存储空间→外设寄存器),即存储器到外设寄存器的映射。
那么,重映射就是CPU将外设寄存器重复编址到存储器的过程,也就是某一个外设寄存器在存储器里被映射了多个地址空间。
实际上,真实的外设寄存器在物理上不属于存储器。由于真实的外设寄存器与其对应的存储器映射寄存器是通过线路相互连接的,所以,逻辑上外设寄存器属于存储器。并且,真实的外设寄存器中的内容与存储器映射寄存器中的内容在任何时候都是相同的。
用片上外设中的IO端口寄存器举个例子:一个IO端口的端口位x在存储器中有2个被映射的存储单元A和B,存储单元A的地址为m,存储单元B的地址为n。这样,通过地址m访问A可以达到访问B,最终实现访问IO端口位x。同样地,通过地址n访问B可以达到访问A的目的,最终实现访问IO端口位x。也就是说存储单元A的内容变化了,那么存储单元B和端口位x的内容也就跟随着A变化成相同的值,同样地,A和端口位x也会跟随着B变化而变化,并且A、B及端口位x中的内容始终相同。
在一些内核处理器预定义的存储器映射中,如Cortex-M3/M4内核,有两个内核预定义存储空间“位带区和位带别名区”就是存储器的重映射的结果。由于通过位带操作访问位带别名区来访问位带区的单个数据位,所以,常常将它们相互映射关系称为“位带别名区到位带区的映射”。
存储器映射的意义:I/O端口有两种编址方式,即I/O端口与存储器统一编址和I/O端口与存储器独立编址。I/O地址空间和存储器地址空间是两个不同的物理空间,C/C++等高等语言中没有访问IO端口的指令(除非有专门的访问IO的汇编内核指令或者编译器提供的专门访问IO的函数),不过C/C++语言具有对绝对地址(或物理地址)的单元内容读写的能力,也就是说具有直接访问物理地址的能力,它是以指针方式访问物理地址单元内容的。所以,若采用I/O端口与存储器统一编址的方式,将存储器空间映射给IO空间,那么就可以通过访问存储器实现对IO的访问。
注:物理地址/绝对地址指对存储器编址后存储单元的地址。