本节用于介绍物理地址到虚拟地址映射
1、在单片机和裸机中我们操作硬件是怎么操作的?
我们可以这样来操作我们的寄存器
1 2 3
| 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
1 2 3 4 5 6 7
| static inline void __iomem *ioremap(phys_addr_t offset, size_t size)
|
1 2 3
| static inline void iounmap(void __iomem *addr)
|
1 2 3 4 5 6 7 8 9 10
| #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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| 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
|