第六节、物理地址到虚拟地址映射
本节用于介绍物理地址到虚拟地址映射
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以后有什么好处呢?
- 让虚拟地址成了可能
- 可以让系统更加安全,因为有了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