i.MX8MM处理器采用了先进的14LPCFinFET工艺,提供更快的速度和更高的电源效率;四核Cortex-A53,单核Cortex-M4,多达五个内核 ,主频高达1.8GHz,2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT、4G模块、CAN、RS485等接口一应俱全。H264、VP8视频硬编码,H.264、H.265、VP8、VP9视频硬解码,并提供相关历程,支持8路PDM接口、5路SAI接口、2路Speaker。系统支持Android9.0(支持获取root限)Linux4.14.78+Qt5.10.1、Yocto、Ubuntu20、Debian9系统。适用于智能充电桩,物联网,工业控制,医疗,智能交通等,可用于任何通用工业和物联网应用、
【公众号】迅为电子
【粉丝群】258811263(加群获取驱动文档+例程)
第 四十一 章 物理地址 与 虚拟地址
本章导读
本章讲解了在裸机程序中操作寄存器方式和Linux系统中使用MMU。讲解了在Linux系统中物理地址到虚拟地址的转换。
本章内容对应视频讲解链接(在线观看):
linux物理地址到虚拟地址映射 → https://www.bilibili.com/video/BV1Vy4y1B7ta?p=12
目前,大多数嵌入式微控制器(如ARM、PowerPC等)中并不提供I/O空间,而仅存在内存空间。内
存空间可以直接通过地址、指针来访问,程序及在程序运行中使用的变量和其他数据都存在于内存空间中。
内存地址可以直接由C语言指针操作,例如,操作一个寄存器,可以定义一个指针来操作寄存器,如下所示:
unsighted int *p = 0x12345678;
*p=0x87654321;
以上程序的意义是在绝对地址0x12345678(ARM、PowerPC)中写入0x87654321。
高性能处理器一般会提供一个内存管理单元(MMU),该单元辅助操作系统进行内存管理,提供虚
拟地址和物理地址的映射、内存访问权限保护和Cache缓存控制等硬件支持。操作系统内核借助MMU可以
让用户感觉到程序好像可以使用非常大的内存空间,从而使得编程人员在写程序时不用考虑计算机中物理
内存的实际容量。
MMU具有虚拟地址和物理地址转换、内存访问权限保护等功能,这将使得Linux操作系统能单独为系
统的每个用户进程分配独立的内存空间并保证用户空间不能访问内核空间的地址,为操作系统的虚拟内存
管理模块提供硬件基础。上层应用看到的内存都是虚拟内存,应用就不能直接访问硬件,所以这样就保证了系统安全。
对于包含MMU的处理器而言,Linux系统提供了复杂的存储管理系统,使得进程所能访问的内存达到
4GB。在Linux系统中,进程的4GB内存空间被分为两个部分------用户空间与内核空间。用户空间的地址一
般分布为0~3GB(即PAGE_OFFSET,在0x86中它等于0xC0000000),这样,剩下的3~4GB为内核空间,如下图所示。用户进程通常只能访问用户空间的虚拟地址,不能访问内核空间的虚拟地址。用户进程只有通过系统调用(代表用户进程在内核态执行)等方式才可以访问到内核空间。
每个进程的用户空间都是完全独立、互不相干的,用户进程各自有不同的页表。而内核空间是由内核
负责映射,它并不会跟着进程改变,是固定的。内核空间的虚拟地址到物理地址映射是被所有进程共享的,内核的虚拟空间独立于其他程序。
MMU非常复杂,那么我们如何完成物理地址到虚拟地址的转换呢?内核给我们提供了相关的函数,我们先来了解下这些函数。函数定义在内核源码目录include/asm-generic/io.h
cpp
ioremap: 把物理地址转换成虚拟地址
iounmap: 释放掉ioremap映射的地址
|----------------------|-----------------------------------------------------------------------|
| 函数 | 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 | 要取消映射的虚拟地址的首地址 |
| 参数size_t size | 要映射多大的内存空间 |
| 功能 | 释放掉ioremap映射的地址 |
注意: 物理地址只能被映射一次,多次映射会失败。如何查看哪些物理地址被映射过了呢?可以使用以下命令来查看。
cat /proc/iomem