IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> MMU地址空间映射 -> 正文阅读

[嵌入式]MMU地址空间映射

MMU地址空间映射

虚拟地址-物理地址

虚拟地址,和芯片位数相关,对于32位芯片,一个指针的大小为4字节,寻址范围为【0x0000,0000 ~ 0xFFFF,FFFF】,寻址范围为4G,也就是说最多能够访问到4G的内存空间。但是实际情况下缺很尴尬,在早期,内存的真实物理容量都很小,通常只有几百兆,在这种情况下,如何让用户拥有4G的寻址空间呢?虽然这是一个假象。可以通过内存映射的方式,为每一个进程都营造出可以访问到4G内存空间的假象。
为什么要使用虚拟地址呢?在单片机上,没有MMU单元,我们都是直接访问的内存物理地址,这样会存在一些问题:

  • 所有程序的资源都是共享的,如果有一个程序崩溃,会造成整个系统崩溃。
  • 用户可以违法使用非法地址,来破坏系统,在有MPU的单片机上,可以做一些内存保护操作
  • 所有程序都必须在不同的地址上运行,这在编译链接时就必须确定好,如果你的操作系统有成千上万的用户,那你还要为他们分配不同的地址,那工作量简直惨不忍睹,我们希望每个应用程序都可以从0开始链接,而且各自的资源相互独立,不能相互访问,只能通过操作系统提供的接口来提供IPC进程间通信的接口

基于如上,我们需要一套机制来实现内存映射机制,在ARM9上引入了MMU,这是实现内存映射的基本硬件单元。

MMU

MMU为内存管理单元,他提供2个功能可以帮助我们实现内存映射

  • 虚拟地址转换到物理地址
  • 地址空间的权限控制

当我们开启MMU后,CPU读取虚拟地址后,经过MMU单元,会硬件自动转换成物理地址,最后访问内存。注意,这是硬件自动完成的,你只需要设置好TTB的基地址就可以了。
映射流程:

  1. cpu获取虚拟地址VA
  2. 读取CP15中的C13将不同进程的相同虚拟地址转换成MVA,修正后的虚拟地址
  3. 读取CP15寄存器的C2寄存器,得到TTB的基地址,注意TTB是存放在物理地址中,在编译链接时确定。
  4. 通过查找页表,最后得到真实的物理地址

前提:
在映射之前,我们首先要做好映射工作,不然MMU根本无法进行地址转换

  • 根据需要映射的空间地址,设置好页表映射
  • 开启MMU

L1级映射

前提:
我们首先要确定我们要怎么映射。
比如说,我的物理地址是从0x5000,0000开始
我们想把虚拟地址4G空间里的高端内存1G空间规定为内核空间,低端3G空间作为用户空间。
我们先进行内核空间映射,我们想把虚拟地址0xC000,00000xFFFF,FFFF,映射到物理地址0x5000,00000x8FFF,FFFF
我们在编译链接时,就指定内核空间的代码和数据段到0xC000,0000开始

映射规则分为两种:

  • 分段
  • 分页

L1级映射为分段映射,映射规则很简单,把4G空间分为4096个段,每一个段大小为1M。
我们定义页表为:

int page_table[4096];

MVA = 0xC000,0000

index_L1 = MVA >> 20;
得到一级页表描述索引
index_L1 = 0xC00
进而得到一级页表描述地址为

PGD = page_table[index_L1];

PGD结构
在这里插入图片描述

低两位为[1:0],表示直接段映射
映射的真实物理地址为:

// 先右移动再左移动,清除低20位
Phy_addr = base + offset = ((PGD>>20)<<20) + MVA[19:0]

物理地址为0x50000000,右移20位得到0x500;
AP,domain,C,B属性不设置,最终得到一级描述符位:0x12
pgd = ((0x500>>20)<<20)+0x12 = 0x5000,0012
我们将pgd的值写入到page_table[0xC00]里去

若低两位为[0:1],表示还有二级映射,也叫粗页表,PGD的高22位[31:10]表示二级页表的基地址

// 地址为32为,需要把低10位清零
PTE_addr = ((PGD>>10)<<10);

L2级映射

二级页表为256个页,一般二级映射的单元为小页,大小为4K,
我们设置二级页表为:

page_table_L2 = PTE_addr

PTE_addr指向一个page_table_L2

index_L2 = MVA[19:12];

得到二级页表描述地址为

PTE = page_table_L2[index_L2];

PTE结构
在这里插入图片描述

低两位一般为[1:XN],表示页面大小为small page为4K
高20位表示base addr
最中的物理地址为:

base = (PTE>>20)<<20
// 先右移动再左移动,清除低12位
Phy_addr = base + offset = ((PTE>>20)<<20) + MVA[11:0]

要实现0xC000,0000 到 0x5000,0000的映射,那么

pte = (0x5000,0000>>20)<<20 + 0x12 = 0x5000,0012
我们将pte的值写入到page_table_L2[index_L2]里去

映射流程

在这里插入图片描述

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-09-18 10:20:30  更:2021-09-18 10:21:49 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/30 1:34:27-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码