Yuhang Zheng

第六节、物理地址到虚拟地址映射

N 人看过

本节用于介绍物理地址到虚拟地址映射

1、在单片机和裸机中我们操作硬件是怎么操作的?

我们可以这样来操作我们的寄存器

unsigned int*p=0x12345678;

*p=0x87654321;

但是在Linux上不行,在Linux上,如果要想操作硬件,需要先把物理地址转换成虚拟地址。因为Linux使能了MMU,所以我们在Linux上不能直接操作物理地址。

内存管理单元(英语:memory management unit,缩写为MMU),有时称作分页内存管理单元(英语:paged memory management unit,缩写为PMMU)。它是一种负责处理中央处理器(CPU)的内存访问请求的计算机硬件。它的功能包括虚拟地址物理地址的转换(即虚拟内存管理)[1]内存保护、中央处理器高速缓存的控制,在较为简单的计算机体系结构中,负责总线仲裁以及存储体切换(bank switching,尤其是在8位的系统上)。

2、使能了MMU以后有什么好处呢?

  1. 让虚拟地址成了可能
  2. 可以让系统更加安全,因为有了MMU,我们上层应用看到的内存都是虚拟内存,我们的应用就不能直接访问硬件,所以这样就保证了系统安全。

3、MMU非常复杂,那么我们如何完成物理地址到虚拟地址的转换呢?

ioremap,iounmap

ioremap:把物理地址转换成虚拟地址

iounmap:释放掉ioremap映射的地址。

文件位置路径:include/linux/io.h

static inline void __iomem *ioremap(phys_addr_t offset, size_t size)
//参数
//phys_addr_t offset:映射物理地址的起始地址
//size_t size:要映射多大的内存空间,单位是字节
//返回值
//成功:返回虚拟地址的首地址
//失败:返回NULL
static inline void iounmap(void __iomem *addr)
//参数
//*addr:要取消映射的内存地址的首地址
#include <linux/io.h>

#define GPDIR_1 0x02310000

p = ioremap(GPDIR_1, 4);
if(p != NULL)
{
    ...
}
iounmap((volatile void *)GPDIR_1);

注意:物理地址只能被映射一次,多次映射会失败

4、如何查看哪些物理地址被映射过了呢?

通过命令:cat /proc/iomem

root@localhost:~# cat /proc/iomem
01550000-0155ffff : QuadSPI
01560000-0156ffff : /soc/esdhc@1560000
01571000-01571fff : /soc/msi-controller1@1571000
01572000-01572fff : /soc/msi-controller2@1572000
01573000-01573fff : /soc/msi-controller3@1573000
01ee0000-01ee0fff : /soc/dcfg@1ee0000
02180000-0218ffff : /soc/i2c@2180000
021a0000-021affff : /soc/i2c@21a0000
021b0000-021bffff : /soc/i2c@21b0000
021c0500-021c05ff : serial
021c0600-021c06ff : serial
021d0500-021d05ff : serial
021d0600-021d06ff : serial
02a30000-02a30fff : /pwm@2a30000
02ad0000-02adffff : /soc/wdog@2ad0000
02c00000-02c0ffff : /soc/edma@2c00000
02c10000-02c1ffff : /soc/edma@2c00000
02c20000-02c2ffff : /soc/edma@2c00000
02f00000-02f07fff : /soc/usb3@2f00000
  02f00000-02f07fff : /soc/usb3@2f00000
02f0c100-02f0ffff : /soc/usb3@2f00000
03000000-03007fff : /soc/usb3@3000000
  03000000-03007fff : /soc/usb3@3000000
0300c100-0300ffff : /soc/usb3@3000000
03100000-03107fff : /soc/usb3@3100000
  03100000-03107fff : /soc/usb3@3100000
0310c100-0310ffff : /soc/usb3@3100000
03200000-0320ffff : ahci
03500000-035fffff : regs
03600000-036fffff : regs
20140520-20140523 : sata-ecc
40000000-43ffffff : QuadSPI-memory
80000000-f7ffffff : System RAM
  81080000-8227ffff : Kernel code
  823b0000-82612fff : Kernel data
fb000000-fb7fffff : System RAM
fbc00000-fbdfffff : System RAM
4840000000-487fffffff : MEM
  4840000000-48400fffff : PCI Bus 0000:01
    4840000000-4840001fff : 0000:01:00.0
      4840000000-4840001fff : iwlwifi
  4840100000-48401007ff : 0000:00:00.0
5040000000-507fffffff : MEM
  5040000000-50400007ff : 0001:00:00.0